1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2009 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/ioctl.h>
21 #include <sys/uio.h>
22 
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <time.h>
28 #include <unistd.h>
29 
30 #include "tmux.h"
31 
32 static void         server_client_free(int, short, void *);
33 static void         server_client_check_pane_resize(struct window_pane *);
34 static void         server_client_check_pane_buffer(struct window_pane *);
35 static void         server_client_check_window_resize(struct window *);
36 static key_code     server_client_check_mouse(struct client *, struct key_event *);
37 static void         server_client_repeat_timer(int, short, void *);
38 static void         server_client_click_timer(int, short, void *);
39 static void         server_client_check_exit(struct client *);
40 static void         server_client_check_redraw(struct client *);
41 static void         server_client_check_modes(struct client *);
42 static void         server_client_set_title(struct client *);
43 static void         server_client_set_path(struct client *);
44 static void         server_client_reset_state(struct client *);
45 static int          server_client_is_bracket_pasting(struct client *, key_code);
46 static int          server_client_assume_paste(struct session *);
47 static void         server_client_update_latest(struct client *);
48 
49 static void         server_client_dispatch(struct imsg *, void *);
50 static void         server_client_dispatch_command(struct client *, struct imsg *);
51 static void         server_client_dispatch_identify(struct client *, struct imsg *);
52 static void         server_client_dispatch_shell(struct client *);
53 
54 /* Compare client windows. */
55 static int
server_client_window_cmp(struct client_window * cw1,struct client_window * cw2)56 server_client_window_cmp(struct client_window *cw1,
57     struct client_window *cw2)
58 {
59           if (cw1->window < cw2->window)
60                     return (-1);
61           if (cw1->window > cw2->window)
62                     return (1);
63           return (0);
64 }
65 RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp);
66 
67 /* Number of attached clients. */
68 u_int
server_client_how_many(void)69 server_client_how_many(void)
70 {
71           struct client       *c;
72           u_int                n;
73 
74           n = 0;
75           TAILQ_FOREACH(c, &clients, entry) {
76                     if (c->session != NULL && (~c->flags & CLIENT_UNATTACHEDFLAGS))
77                               n++;
78           }
79           return (n);
80 }
81 
82 /* Overlay timer callback. */
83 static void
server_client_overlay_timer(__unused int fd,__unused short events,void * data)84 server_client_overlay_timer(__unused int fd, __unused short events, void *data)
85 {
86           server_client_clear_overlay(data);
87 }
88 
89 /* Set an overlay on client. */
90 void
server_client_set_overlay(struct client * c,u_int delay,overlay_check_cb checkcb,overlay_mode_cb modecb,overlay_draw_cb drawcb,overlay_key_cb keycb,overlay_free_cb freecb,overlay_resize_cb resizecb,void * data)91 server_client_set_overlay(struct client *c, u_int delay,
92     overlay_check_cb checkcb, overlay_mode_cb modecb,
93     overlay_draw_cb drawcb, overlay_key_cb keycb, overlay_free_cb freecb,
94     overlay_resize_cb resizecb, void *data)
95 {
96           struct timeval      tv;
97 
98           if (c->overlay_draw != NULL)
99                     server_client_clear_overlay(c);
100 
101           tv.tv_sec = delay / 1000;
102           tv.tv_usec = (delay % 1000) * 1000L;
103 
104           if (event_initialized(&c->overlay_timer))
105                     evtimer_del(&c->overlay_timer);
106           evtimer_set(&c->overlay_timer, server_client_overlay_timer, c);
107           if (delay != 0)
108                     evtimer_add(&c->overlay_timer, &tv);
109 
110           c->overlay_check = checkcb;
111           c->overlay_mode = modecb;
112           c->overlay_draw = drawcb;
113           c->overlay_key = keycb;
114           c->overlay_free = freecb;
115           c->overlay_resize = resizecb;
116           c->overlay_data = data;
117 
118           if (c->overlay_check == NULL)
119                     c->tty.flags |= TTY_FREEZE;
120           if (c->overlay_mode == NULL)
121                     c->tty.flags |= TTY_NOCURSOR;
122           server_redraw_client(c);
123 }
124 
125 /* Clear overlay mode on client. */
126 void
server_client_clear_overlay(struct client * c)127 server_client_clear_overlay(struct client *c)
128 {
129           if (c->overlay_draw == NULL)
130                     return;
131 
132           if (event_initialized(&c->overlay_timer))
133                     evtimer_del(&c->overlay_timer);
134 
135           if (c->overlay_free != NULL)
136                     c->overlay_free(c, c->overlay_data);
137 
138           c->overlay_check = NULL;
139           c->overlay_mode = NULL;
140           c->overlay_draw = NULL;
141           c->overlay_key = NULL;
142           c->overlay_free = NULL;
143           c->overlay_data = NULL;
144 
145           c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
146           server_redraw_client(c);
147 }
148 
149 /*
150  * Given overlay position and dimensions, return parts of the input range which
151  * are visible.
152  */
153 void
server_client_overlay_range(u_int x,u_int y,u_int sx,u_int sy,u_int px,u_int py,u_int nx,struct overlay_ranges * r)154 server_client_overlay_range(u_int x, u_int y, u_int sx, u_int sy, u_int px,
155     u_int py, u_int nx, struct overlay_ranges *r)
156 {
157           u_int     ox, onx;
158 
159           /* Return up to 2 ranges. */
160           r->px[2] = 0;
161           r->nx[2] = 0;
162 
163           /* Trivial case of no overlap in the y direction. */
164           if (py < y || py > y + sy - 1) {
165                     r->px[0] = px;
166                     r->nx[0] = nx;
167                     r->px[1] = 0;
168                     r->nx[1] = 0;
169                     return;
170           }
171 
172           /* Visible bit to the left of the popup. */
173           if (px < x) {
174                     r->px[0] = px;
175                     r->nx[0] = x - px;
176                     if (r->nx[0] > nx)
177                               r->nx[0] = nx;
178           } else {
179                     r->px[0] = 0;
180                     r->nx[0] = 0;
181           }
182 
183           /* Visible bit to the right of the popup. */
184           ox = x + sx;
185           if (px > ox)
186                     ox = px;
187           onx = px + nx;
188           if (onx > ox) {
189                     r->px[1] = ox;
190                     r->nx[1] = onx - ox;
191           } else {
192                     r->px[1] = 0;
193                     r->nx[1] = 0;
194           }
195 }
196 
197 /* Check if this client is inside this server. */
198 int
server_client_check_nested(struct client * c)199 server_client_check_nested(struct client *c)
200 {
201           struct environ_entry          *envent;
202           struct window_pane  *wp;
203 
204           envent = environ_find(c->environ, "TMUX");
205           if (envent == NULL || *envent->value == '\0')
206                     return (0);
207 
208           RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
209                     if (strcmp(wp->tty, c->ttyname) == 0)
210                               return (1);
211           }
212           return (0);
213 }
214 
215 /* Set client key table. */
216 void
server_client_set_key_table(struct client * c,const char * name)217 server_client_set_key_table(struct client *c, const char *name)
218 {
219           if (name == NULL)
220                     name = server_client_get_key_table(c);
221 
222           key_bindings_unref_table(c->keytable);
223           c->keytable = key_bindings_get_table(name, 1);
224           c->keytable->references++;
225           if (gettimeofday(&c->keytable->activity_time, NULL) != 0)
226                     fatal("gettimeofday failed");
227 }
228 
229 static uint64_t
server_client_key_table_activity_diff(struct client * c)230 server_client_key_table_activity_diff(struct client *c)
231 {
232           struct timeval      diff;
233 
234           timersub(&c->activity_time, &c->keytable->activity_time, &diff);
235           return ((diff.tv_sec * 1000ULL) + (diff.tv_usec / 1000ULL));
236 }
237 
238 /* Get default key table. */
239 const char *
server_client_get_key_table(struct client * c)240 server_client_get_key_table(struct client *c)
241 {
242           struct session      *s = c->session;
243           const char          *name;
244 
245           if (s == NULL)
246                     return ("root");
247 
248           name = options_get_string(s->options, "key-table");
249           if (*name == '\0')
250                     return ("root");
251           return (name);
252 }
253 
254 /* Is this table the default key table? */
255 static int
server_client_is_default_key_table(struct client * c,struct key_table * table)256 server_client_is_default_key_table(struct client *c, struct key_table *table)
257 {
258           return (strcmp(table->name, server_client_get_key_table(c)) == 0);
259 }
260 
261 /* Create a new client. */
262 struct client *
server_client_create(int fd)263 server_client_create(int fd)
264 {
265           struct client       *c;
266 
267           setblocking(fd, 0);
268 
269           c = xcalloc(1, sizeof *c);
270           c->references = 1;
271           c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c);
272 
273           if (gettimeofday(&c->creation_time, NULL) != 0)
274                     fatal("gettimeofday failed");
275           memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
276 
277           c->environ = environ_create();
278 
279           c->fd = -1;
280           c->out_fd = -1;
281 
282           c->queue = cmdq_new();
283           RB_INIT(&c->windows);
284           RB_INIT(&c->files);
285 
286           c->tty.sx = 80;
287           c->tty.sy = 24;
288 
289           status_init(c);
290           c->flags |= CLIENT_FOCUSED;
291 
292           c->keytable = key_bindings_get_table("root", 1);
293           c->keytable->references++;
294 
295           evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
296           evtimer_set(&c->click_timer, server_client_click_timer, c);
297 
298           TAILQ_INSERT_TAIL(&clients, c, entry);
299           log_debug("new client %p", c);
300           return (c);
301 }
302 
303 /* Open client terminal if needed. */
304 int
server_client_open(struct client * c,char ** cause)305 server_client_open(struct client *c, char **cause)
306 {
307           const char          *ttynam = _PATH_TTY;
308 
309           if (c->flags & CLIENT_CONTROL)
310                     return (0);
311 
312           if (strcmp(c->ttyname, ttynam) == 0||
313               ((isatty(STDIN_FILENO) &&
314               (ttynam = ttyname(STDIN_FILENO)) != NULL &&
315               strcmp(c->ttyname, ttynam) == 0) ||
316               (isatty(STDOUT_FILENO) &&
317               (ttynam = ttyname(STDOUT_FILENO)) != NULL &&
318               strcmp(c->ttyname, ttynam) == 0) ||
319               (isatty(STDERR_FILENO) &&
320               (ttynam = ttyname(STDERR_FILENO)) != NULL &&
321               strcmp(c->ttyname, ttynam) == 0))) {
322                     xasprintf(cause, "can't use %s", c->ttyname);
323                     return (-1);
324           }
325 
326           if (!(c->flags & CLIENT_TERMINAL)) {
327                     *cause = xstrdup("not a terminal");
328                     return (-1);
329           }
330 
331           if (tty_open(&c->tty, cause) != 0)
332                     return (-1);
333 
334           return (0);
335 }
336 
337 /* Lost an attached client. */
338 static void
server_client_attached_lost(struct client * c)339 server_client_attached_lost(struct client *c)
340 {
341           struct session      *s;
342           struct window       *w;
343           struct client       *loop;
344           struct client       *found;
345 
346           log_debug("lost attached client %p", c);
347 
348           /*
349            * By this point the session in the client has been cleared so walk all
350            * windows to find any with this client as the latest.
351            */
352           RB_FOREACH(w, windows, &windows) {
353                     if (w->latest != c)
354                               continue;
355 
356                     found = NULL;
357                     TAILQ_FOREACH(loop, &clients, entry) {
358                               s = loop->session;
359                               if (loop == c || s == NULL || s->curw->window != w)
360                                         continue;
361                               if (found == NULL || timercmp(&loop->activity_time,
362                                   &found->activity_time, >))
363                                         found = loop;
364                     }
365                     if (found != NULL)
366                               server_client_update_latest(found);
367           }
368 }
369 
370 /* Set client session. */
371 void
server_client_set_session(struct client * c,struct session * s)372 server_client_set_session(struct client *c, struct session *s)
373 {
374           struct session      *old = c->session;
375 
376           if (s != NULL && c->session != NULL && c->session != s)
377                     c->last_session = c->session;
378           else if (s == NULL)
379                     c->last_session = NULL;
380           c->session = s;
381           c->flags |= CLIENT_FOCUSED;
382 
383           if (old != NULL && old->curw != NULL)
384                     window_update_focus(old->curw->window);
385           if (s != NULL) {
386                     recalculate_sizes();
387                     window_update_focus(s->curw->window);
388                     session_update_activity(s, NULL);
389                     gettimeofday(&s->last_attached_time, NULL);
390                     s->curw->flags &= ~WINLINK_ALERTFLAGS;
391                     s->curw->window->latest = c;
392                     alerts_check_session(s);
393                     tty_update_client_offset(c);
394                     status_timer_start(c);
395                     notify_client("client-session-changed", c);
396                     server_redraw_client(c);
397           }
398 
399           server_check_unattached();
400           server_update_socket();
401 }
402 
403 /* Lost a client. */
404 void
server_client_lost(struct client * c)405 server_client_lost(struct client *c)
406 {
407           struct client_file  *cf, *cf1;
408           struct client_window          *cw, *cw1;
409 
410           c->flags |= CLIENT_DEAD;
411 
412           server_client_clear_overlay(c);
413           status_prompt_clear(c);
414           status_message_clear(c);
415 
416           RB_FOREACH_SAFE(cf, client_files, &c->files, cf1) {
417                     cf->error = EINTR;
418                     file_fire_done(cf);
419           }
420           RB_FOREACH_SAFE(cw, client_windows, &c->windows, cw1) {
421                     RB_REMOVE(client_windows, &c->windows, cw);
422                     free(cw);
423           }
424 
425           TAILQ_REMOVE(&clients, c, entry);
426           log_debug("lost client %p", c);
427 
428           if (c->flags & CLIENT_ATTACHED) {
429                     server_client_attached_lost(c);
430                     notify_client("client-detached", c);
431           }
432 
433           if (c->flags & CLIENT_CONTROL)
434                     control_stop(c);
435           if (c->flags & CLIENT_TERMINAL)
436                     tty_free(&c->tty);
437           free(c->ttyname);
438           free(c->clipboard_panes);
439 
440           free(c->term_name);
441           free(c->term_type);
442           tty_term_free_list(c->term_caps, c->term_ncaps);
443 
444           status_free(c);
445 
446           free(c->title);
447           free(__UNCONST(c->cwd));
448 
449           evtimer_del(&c->repeat_timer);
450           evtimer_del(&c->click_timer);
451 
452           key_bindings_unref_table(c->keytable);
453 
454           free(c->message_string);
455           if (event_initialized(&c->message_timer))
456                     evtimer_del(&c->message_timer);
457 
458           free(c->prompt_saved);
459           free(c->prompt_string);
460           free(c->prompt_buffer);
461 
462           format_lost_client(c);
463           environ_free(c->environ);
464 
465           proc_remove_peer(c->peer);
466           c->peer = NULL;
467 
468           if (c->out_fd != -1)
469                     close(c->out_fd);
470           if (c->fd != -1) {
471                     close(c->fd);
472                     c->fd = -1;
473           }
474           server_client_unref(c);
475 
476           server_add_accept(0); /* may be more file descriptors now */
477 
478           recalculate_sizes();
479           server_check_unattached();
480           server_update_socket();
481 }
482 
483 /* Remove reference from a client. */
484 void
server_client_unref(struct client * c)485 server_client_unref(struct client *c)
486 {
487           log_debug("unref client %p (%d references)", c, c->references);
488 
489           c->references--;
490           if (c->references == 0)
491                     event_once(-1, EV_TIMEOUT, server_client_free, c, NULL);
492 }
493 
494 /* Free dead client. */
495 static void
server_client_free(__unused int fd,__unused short events,void * arg)496 server_client_free(__unused int fd, __unused short events, void *arg)
497 {
498           struct client       *c = arg;
499 
500           log_debug("free client %p (%d references)", c, c->references);
501 
502           cmdq_free(c->queue);
503 
504           if (c->references == 0) {
505                     free(__UNCONST(c->name));
506                     free(c);
507           }
508 }
509 
510 /* Suspend a client. */
511 void
server_client_suspend(struct client * c)512 server_client_suspend(struct client *c)
513 {
514           struct session      *s = c->session;
515 
516           if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
517                     return;
518 
519           tty_stop_tty(&c->tty);
520           c->flags |= CLIENT_SUSPENDED;
521           proc_send(c->peer, MSG_SUSPEND, -1, NULL, 0);
522 }
523 
524 /* Detach a client. */
525 void
server_client_detach(struct client * c,enum msgtype msgtype)526 server_client_detach(struct client *c, enum msgtype msgtype)
527 {
528           struct session      *s = c->session;
529 
530           if (s == NULL || (c->flags & CLIENT_NODETACHFLAGS))
531                     return;
532 
533           c->flags |= CLIENT_EXIT;
534 
535           c->exit_type = CLIENT_EXIT_DETACH;
536           c->exit_msgtype = msgtype;
537           c->exit_session = xstrdup(s->name);
538 }
539 
540 /* Execute command to replace a client. */
541 void
server_client_exec(struct client * c,const char * cmd)542 server_client_exec(struct client *c, const char *cmd)
543 {
544           struct session      *s = c->session;
545           char                *msg;
546           const char          *shell;
547           size_t               cmdsize, shellsize;
548 
549           if (*cmd == '\0')
550                     return;
551           cmdsize = strlen(cmd) + 1;
552 
553           if (s != NULL)
554                     shell = options_get_string(s->options, "default-shell");
555           else
556                     shell = options_get_string(global_s_options, "default-shell");
557           if (!checkshell(shell))
558                     shell = _PATH_BSHELL;
559           shellsize = strlen(shell) + 1;
560 
561           msg = xmalloc(cmdsize + shellsize);
562           memcpy(msg, cmd, cmdsize);
563           memcpy(msg + cmdsize, shell, shellsize);
564 
565           proc_send(c->peer, MSG_EXEC, -1, msg, cmdsize + shellsize);
566           free(msg);
567 }
568 
569 /* Check for mouse keys. */
570 static key_code
server_client_check_mouse(struct client * c,struct key_event * event)571 server_client_check_mouse(struct client *c, struct key_event *event)
572 {
573           struct mouse_event  *m = &event->m;
574           struct session                *s = c->session, *fs;
575           struct winlink                *fwl;
576           struct window_pane  *wp, *fwp;
577           u_int                          x, y, b, sx, sy, px, py;
578           int                            ignore = 0;
579           key_code             key;
580           struct timeval                 tv;
581           struct style_range  *sr;
582           enum { NOTYPE,
583                  MOVE,
584                  DOWN,
585                  UP,
586                  DRAG,
587                  WHEEL,
588                  SECOND,
589                  DOUBLE,
590                  TRIPLE } type = NOTYPE;
591           enum { NOWHERE,
592                  PANE,
593                  STATUS,
594                  STATUS_LEFT,
595                  STATUS_RIGHT,
596                  STATUS_DEFAULT,
597                  BORDER } where = NOWHERE;
598 
599           log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c->name, m->b,
600               m->x, m->y, m->lx, m->ly, c->tty.mouse_drag_flag);
601 
602           /* What type of event is this? */
603           if (event->key == KEYC_DOUBLECLICK) {
604                     type = DOUBLE;
605                     x = m->x, y = m->y, b = m->b;
606                     ignore = 1;
607                     log_debug("double-click at %u,%u", x, y);
608           } else if ((m->sgr_type != ' ' &&
609               MOUSE_DRAG(m->sgr_b) &&
610               MOUSE_RELEASE(m->sgr_b)) ||
611               (m->sgr_type == ' ' &&
612               MOUSE_DRAG(m->b) &&
613               MOUSE_RELEASE(m->b) &&
614               MOUSE_RELEASE(m->lb))) {
615                     type = MOVE;
616                     x = m->x, y = m->y, b = 0;
617                     log_debug("move at %u,%u", x, y);
618           } else if (MOUSE_DRAG(m->b)) {
619                     type = DRAG;
620                     if (c->tty.mouse_drag_flag) {
621                               x = m->x, y = m->y, b = m->b;
622                               if (x == m->lx && y == m->ly)
623                                         return (KEYC_UNKNOWN);
624                               log_debug("drag update at %u,%u", x, y);
625                     } else {
626                               x = m->lx, y = m->ly, b = m->lb;
627                               log_debug("drag start at %u,%u", x, y);
628                     }
629           } else if (MOUSE_WHEEL(m->b)) {
630                     type = WHEEL;
631                     x = m->x, y = m->y, b = m->b;
632                     log_debug("wheel at %u,%u", x, y);
633           } else if (MOUSE_RELEASE(m->b)) {
634                     type = UP;
635                     x = m->x, y = m->y, b = m->lb;
636                     if (m->sgr_type == 'm')
637                               b = m->sgr_b;
638                     log_debug("up at %u,%u", x, y);
639           } else {
640                     if (c->flags & CLIENT_DOUBLECLICK) {
641                               evtimer_del(&c->click_timer);
642                               c->flags &= ~CLIENT_DOUBLECLICK;
643                               if (m->b == c->click_button) {
644                                         type = SECOND;
645                                         x = m->x, y = m->y, b = m->b;
646                                         log_debug("second-click at %u,%u", x, y);
647                                         c->flags |= CLIENT_TRIPLECLICK;
648                               }
649                     } else if (c->flags & CLIENT_TRIPLECLICK) {
650                               evtimer_del(&c->click_timer);
651                               c->flags &= ~CLIENT_TRIPLECLICK;
652                               if (m->b == c->click_button) {
653                                         type = TRIPLE;
654                                         x = m->x, y = m->y, b = m->b;
655                                         log_debug("triple-click at %u,%u", x, y);
656                                         goto have_event;
657                               }
658                     }
659 
660                     /* DOWN is the only remaining event type. */
661                     if (type == NOTYPE) {
662                               type = DOWN;
663                               x = m->x, y = m->y, b = m->b;
664                               log_debug("down at %u,%u", x, y);
665                               c->flags |= CLIENT_DOUBLECLICK;
666                     }
667 
668                     if (KEYC_CLICK_TIMEOUT != 0) {
669                               memcpy(&c->click_event, m, sizeof c->click_event);
670                               c->click_button = m->b;
671 
672                               log_debug("click timer started");
673                               tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
674                               tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
675                               evtimer_del(&c->click_timer);
676                               evtimer_add(&c->click_timer, &tv);
677                     }
678           }
679 
680 have_event:
681           if (type == NOTYPE)
682                     return (KEYC_UNKNOWN);
683 
684           /* Save the session. */
685           m->s = s->id;
686           m->w = -1;
687           m->wp = -1;
688           m->ignore = ignore;
689 
690           /* Is this on the status line? */
691           m->statusat = status_at_line(c);
692           m->statuslines = status_line_size(c);
693           if (m->statusat != -1 &&
694               y >= (u_int)m->statusat &&
695               y < m->statusat + m->statuslines) {
696                     sr = status_get_range(c, x, y - m->statusat);
697                     if (sr == NULL) {
698                               where = STATUS_DEFAULT;
699                     } else {
700                               switch (sr->type) {
701                               case STYLE_RANGE_NONE:
702                                         return (KEYC_UNKNOWN);
703                               case STYLE_RANGE_LEFT:
704                                         log_debug("mouse range: left");
705                                         where = STATUS_LEFT;
706                                         break;
707                               case STYLE_RANGE_RIGHT:
708                                         log_debug("mouse range: right");
709                                         where = STATUS_RIGHT;
710                                         break;
711                               case STYLE_RANGE_PANE:
712                                         fwp = window_pane_find_by_id(sr->argument);
713                                         if (fwp == NULL)
714                                                   return (KEYC_UNKNOWN);
715                                         m->wp = sr->argument;
716 
717                                         log_debug("mouse range: pane %%%u", m->wp);
718                                         where = STATUS;
719                                         break;
720                               case STYLE_RANGE_WINDOW:
721                                         fwl = winlink_find_by_index(&s->windows,
722                                             sr->argument);
723                                         if (fwl == NULL)
724                                                   return (KEYC_UNKNOWN);
725                                         m->w = fwl->window->id;
726 
727                                         log_debug("mouse range: window @%u", m->w);
728                                         where = STATUS;
729                                         break;
730                               case STYLE_RANGE_SESSION:
731                                         fs = session_find_by_id(sr->argument);
732                                         if (fs == NULL)
733                                                   return (KEYC_UNKNOWN);
734                                         m->s = sr->argument;
735 
736                                         log_debug("mouse range: session $%u", m->s);
737                                         where = STATUS;
738                                         break;
739                               case STYLE_RANGE_USER:
740                                         where = STATUS;
741                                         break;
742                               }
743                     }
744           }
745 
746           /* Not on status line. Adjust position and check for border or pane. */
747           if (where == NOWHERE) {
748                     px = x;
749                     if (m->statusat == 0 && y >= m->statuslines)
750                               py = y - m->statuslines;
751                     else if (m->statusat > 0 && y >= (u_int)m->statusat)
752                               py = m->statusat - 1;
753                     else
754                               py = y;
755 
756                     tty_window_offset(&c->tty, &m->ox, &m->oy, &sx, &sy);
757                     log_debug("mouse window @%u at %u,%u (%ux%u)",
758                         s->curw->window->id, m->ox, m->oy, sx, sy);
759                     if (px > sx || py > sy)
760                               return (KEYC_UNKNOWN);
761                     px = px + m->ox;
762                     py = py + m->oy;
763 
764                     /* Try the pane borders if not zoomed. */
765                     if (~s->curw->window->flags & WINDOW_ZOOMED) {
766                               TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
767                                         if ((wp->xoff + wp->sx == px &&
768                                             wp->yoff <= 1 + py &&
769                                             wp->yoff + wp->sy >= py) ||
770                                             (wp->yoff + wp->sy == py &&
771                                             wp->xoff <= 1 + px &&
772                                             wp->xoff + wp->sx >= px))
773                                                   break;
774                               }
775                               if (wp != NULL)
776                                         where = BORDER;
777                     }
778 
779                     /* Otherwise try inside the pane. */
780                     if (where == NOWHERE) {
781                               wp = window_get_active_at(s->curw->window, px, py);
782                               if (wp != NULL)
783                                         where = PANE;
784                               else
785                                         return (KEYC_UNKNOWN);
786                     }
787                     if (where == PANE)
788                               log_debug("mouse %u,%u on pane %%%u", x, y, wp->id);
789                     else if (where == BORDER)
790                               log_debug("mouse on pane %%%u border", wp->id);
791                     m->wp = wp->id;
792                     m->w = wp->window->id;
793           }
794 
795           /* Stop dragging if needed. */
796           if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag != 0) {
797                     if (c->tty.mouse_drag_release != NULL)
798                               c->tty.mouse_drag_release(c, m);
799 
800                     c->tty.mouse_drag_update = NULL;
801                     c->tty.mouse_drag_release = NULL;
802 
803                     /*
804                      * End a mouse drag by passing a MouseDragEnd key corresponding
805                      * to the button that started the drag.
806                      */
807                     switch (c->tty.mouse_drag_flag - 1) {
808                     case MOUSE_BUTTON_1:
809                               if (where == PANE)
810                                         key = KEYC_MOUSEDRAGEND1_PANE;
811                               if (where == STATUS)
812                                         key = KEYC_MOUSEDRAGEND1_STATUS;
813                               if (where == STATUS_LEFT)
814                                         key = KEYC_MOUSEDRAGEND1_STATUS_LEFT;
815                               if (where == STATUS_RIGHT)
816                                         key = KEYC_MOUSEDRAGEND1_STATUS_RIGHT;
817                               if (where == STATUS_DEFAULT)
818                                         key = KEYC_MOUSEDRAGEND1_STATUS_DEFAULT;
819                               if (where == BORDER)
820                                         key = KEYC_MOUSEDRAGEND1_BORDER;
821                               break;
822                     case MOUSE_BUTTON_2:
823                               if (where == PANE)
824                                         key = KEYC_MOUSEDRAGEND2_PANE;
825                               if (where == STATUS)
826                                         key = KEYC_MOUSEDRAGEND2_STATUS;
827                               if (where == STATUS_LEFT)
828                                         key = KEYC_MOUSEDRAGEND2_STATUS_LEFT;
829                               if (where == STATUS_RIGHT)
830                                         key = KEYC_MOUSEDRAGEND2_STATUS_RIGHT;
831                               if (where == STATUS_DEFAULT)
832                                         key = KEYC_MOUSEDRAGEND2_STATUS_DEFAULT;
833                               if (where == BORDER)
834                                         key = KEYC_MOUSEDRAGEND2_BORDER;
835                               break;
836                     case MOUSE_BUTTON_3:
837                               if (where == PANE)
838                                         key = KEYC_MOUSEDRAGEND3_PANE;
839                               if (where == STATUS)
840                                         key = KEYC_MOUSEDRAGEND3_STATUS;
841                               if (where == STATUS_LEFT)
842                                         key = KEYC_MOUSEDRAGEND3_STATUS_LEFT;
843                               if (where == STATUS_RIGHT)
844                                         key = KEYC_MOUSEDRAGEND3_STATUS_RIGHT;
845                               if (where == STATUS_DEFAULT)
846                                         key = KEYC_MOUSEDRAGEND3_STATUS_DEFAULT;
847                               if (where == BORDER)
848                                         key = KEYC_MOUSEDRAGEND3_BORDER;
849                               break;
850                     case MOUSE_BUTTON_6:
851                               if (where == PANE)
852                                         key = KEYC_MOUSEDRAGEND6_PANE;
853                               if (where == STATUS)
854                                         key = KEYC_MOUSEDRAGEND6_STATUS;
855                               if (where == STATUS_LEFT)
856                                         key = KEYC_MOUSEDRAGEND6_STATUS_LEFT;
857                               if (where == STATUS_RIGHT)
858                                         key = KEYC_MOUSEDRAGEND6_STATUS_RIGHT;
859                               if (where == STATUS_DEFAULT)
860                                         key = KEYC_MOUSEDRAGEND6_STATUS_DEFAULT;
861                               if (where == BORDER)
862                                         key = KEYC_MOUSEDRAGEND6_BORDER;
863                               break;
864                     case MOUSE_BUTTON_7:
865                               if (where == PANE)
866                                         key = KEYC_MOUSEDRAGEND7_PANE;
867                               if (where == STATUS)
868                                         key = KEYC_MOUSEDRAGEND7_STATUS;
869                               if (where == STATUS_LEFT)
870                                         key = KEYC_MOUSEDRAGEND7_STATUS_LEFT;
871                               if (where == STATUS_RIGHT)
872                                         key = KEYC_MOUSEDRAGEND7_STATUS_RIGHT;
873                               if (where == STATUS_DEFAULT)
874                                         key = KEYC_MOUSEDRAGEND7_STATUS_DEFAULT;
875                               if (where == BORDER)
876                                         key = KEYC_MOUSEDRAGEND7_BORDER;
877                               break;
878                     case MOUSE_BUTTON_8:
879                               if (where == PANE)
880                                         key = KEYC_MOUSEDRAGEND8_PANE;
881                               if (where == STATUS)
882                                         key = KEYC_MOUSEDRAGEND8_STATUS;
883                               if (where == STATUS_LEFT)
884                                         key = KEYC_MOUSEDRAGEND8_STATUS_LEFT;
885                               if (where == STATUS_RIGHT)
886                                         key = KEYC_MOUSEDRAGEND8_STATUS_RIGHT;
887                               if (where == STATUS_DEFAULT)
888                                         key = KEYC_MOUSEDRAGEND8_STATUS_DEFAULT;
889                               if (where == BORDER)
890                                         key = KEYC_MOUSEDRAGEND8_BORDER;
891                               break;
892                     case MOUSE_BUTTON_9:
893                               if (where == PANE)
894                                         key = KEYC_MOUSEDRAGEND9_PANE;
895                               if (where == STATUS)
896                                         key = KEYC_MOUSEDRAGEND9_STATUS;
897                               if (where == STATUS_LEFT)
898                                         key = KEYC_MOUSEDRAGEND9_STATUS_LEFT;
899                               if (where == STATUS_RIGHT)
900                                         key = KEYC_MOUSEDRAGEND9_STATUS_RIGHT;
901                               if (where == STATUS_DEFAULT)
902                                         key = KEYC_MOUSEDRAGEND9_STATUS_DEFAULT;
903                               if (where == BORDER)
904                                         key = KEYC_MOUSEDRAGEND9_BORDER;
905                               break;
906                     case MOUSE_BUTTON_10:
907                               if (where == PANE)
908                                         key = KEYC_MOUSEDRAGEND10_PANE;
909                               if (where == STATUS)
910                                         key = KEYC_MOUSEDRAGEND10_STATUS;
911                               if (where == STATUS_LEFT)
912                                         key = KEYC_MOUSEDRAGEND10_STATUS_LEFT;
913                               if (where == STATUS_RIGHT)
914                                         key = KEYC_MOUSEDRAGEND10_STATUS_RIGHT;
915                               if (where == STATUS_DEFAULT)
916                                         key = KEYC_MOUSEDRAGEND10_STATUS_DEFAULT;
917                               if (where == BORDER)
918                                         key = KEYC_MOUSEDRAGEND10_BORDER;
919                               break;
920                     case MOUSE_BUTTON_11:
921                               if (where == PANE)
922                                         key = KEYC_MOUSEDRAGEND11_PANE;
923                               if (where == STATUS)
924                                         key = KEYC_MOUSEDRAGEND11_STATUS;
925                               if (where == STATUS_LEFT)
926                                         key = KEYC_MOUSEDRAGEND11_STATUS_LEFT;
927                               if (where == STATUS_RIGHT)
928                                         key = KEYC_MOUSEDRAGEND11_STATUS_RIGHT;
929                               if (where == STATUS_DEFAULT)
930                                         key = KEYC_MOUSEDRAGEND11_STATUS_DEFAULT;
931                               if (where == BORDER)
932                                         key = KEYC_MOUSEDRAGEND11_BORDER;
933                               break;
934                     default:
935                               key = KEYC_MOUSE;
936                               break;
937                     }
938                     c->tty.mouse_drag_flag = 0;
939                     goto out;
940           }
941 
942           /* Convert to a key binding. */
943           key = KEYC_UNKNOWN;
944           switch (type) {
945           case NOTYPE:
946                     break;
947           case MOVE:
948                     if (where == PANE)
949                               key = KEYC_MOUSEMOVE_PANE;
950                     if (where == STATUS)
951                               key = KEYC_MOUSEMOVE_STATUS;
952                     if (where == STATUS_LEFT)
953                               key = KEYC_MOUSEMOVE_STATUS_LEFT;
954                     if (where == STATUS_RIGHT)
955                               key = KEYC_MOUSEMOVE_STATUS_RIGHT;
956                     if (where == STATUS_DEFAULT)
957                               key = KEYC_MOUSEMOVE_STATUS_DEFAULT;
958                     if (where == BORDER)
959                               key = KEYC_MOUSEMOVE_BORDER;
960                     break;
961           case DRAG:
962                     if (c->tty.mouse_drag_update != NULL)
963                               key = KEYC_DRAGGING;
964                     else {
965                               switch (MOUSE_BUTTONS(b)) {
966                               case MOUSE_BUTTON_1:
967                                         if (where == PANE)
968                                                   key = KEYC_MOUSEDRAG1_PANE;
969                                         if (where == STATUS)
970                                                   key = KEYC_MOUSEDRAG1_STATUS;
971                                         if (where == STATUS_LEFT)
972                                                   key = KEYC_MOUSEDRAG1_STATUS_LEFT;
973                                         if (where == STATUS_RIGHT)
974                                                   key = KEYC_MOUSEDRAG1_STATUS_RIGHT;
975                                         if (where == STATUS_DEFAULT)
976                                                   key = KEYC_MOUSEDRAG1_STATUS_DEFAULT;
977                                         if (where == BORDER)
978                                                   key = KEYC_MOUSEDRAG1_BORDER;
979                                         break;
980                               case MOUSE_BUTTON_2:
981                                         if (where == PANE)
982                                                   key = KEYC_MOUSEDRAG2_PANE;
983                                         if (where == STATUS)
984                                                   key = KEYC_MOUSEDRAG2_STATUS;
985                                         if (where == STATUS_LEFT)
986                                                   key = KEYC_MOUSEDRAG2_STATUS_LEFT;
987                                         if (where == STATUS_RIGHT)
988                                                   key = KEYC_MOUSEDRAG2_STATUS_RIGHT;
989                                         if (where == STATUS_DEFAULT)
990                                                   key = KEYC_MOUSEDRAG2_STATUS_DEFAULT;
991                                         if (where == BORDER)
992                                                   key = KEYC_MOUSEDRAG2_BORDER;
993                                         break;
994                               case MOUSE_BUTTON_3:
995                                         if (where == PANE)
996                                                   key = KEYC_MOUSEDRAG3_PANE;
997                                         if (where == STATUS)
998                                                   key = KEYC_MOUSEDRAG3_STATUS;
999                                         if (where == STATUS_LEFT)
1000                                                   key = KEYC_MOUSEDRAG3_STATUS_LEFT;
1001                                         if (where == STATUS_RIGHT)
1002                                                   key = KEYC_MOUSEDRAG3_STATUS_RIGHT;
1003                                         if (where == STATUS_DEFAULT)
1004                                                   key = KEYC_MOUSEDRAG3_STATUS_DEFAULT;
1005                                         if (where == BORDER)
1006                                                   key = KEYC_MOUSEDRAG3_BORDER;
1007                                         break;
1008                               case MOUSE_BUTTON_6:
1009                                         if (where == PANE)
1010                                                   key = KEYC_MOUSEDRAG6_PANE;
1011                                         if (where == STATUS)
1012                                                   key = KEYC_MOUSEDRAG6_STATUS;
1013                                         if (where == STATUS_LEFT)
1014                                                   key = KEYC_MOUSEDRAG6_STATUS_LEFT;
1015                                         if (where == STATUS_RIGHT)
1016                                                   key = KEYC_MOUSEDRAG6_STATUS_RIGHT;
1017                                         if (where == STATUS_DEFAULT)
1018                                                   key = KEYC_MOUSEDRAG6_STATUS_DEFAULT;
1019                                         if (where == BORDER)
1020                                                   key = KEYC_MOUSEDRAG6_BORDER;
1021                                         break;
1022                               case MOUSE_BUTTON_7:
1023                                         if (where == PANE)
1024                                                   key = KEYC_MOUSEDRAG7_PANE;
1025                                         if (where == STATUS)
1026                                                   key = KEYC_MOUSEDRAG7_STATUS;
1027                                         if (where == STATUS_LEFT)
1028                                                   key = KEYC_MOUSEDRAG7_STATUS_LEFT;
1029                                         if (where == STATUS_RIGHT)
1030                                                   key = KEYC_MOUSEDRAG7_STATUS_RIGHT;
1031                                         if (where == STATUS_DEFAULT)
1032                                                   key = KEYC_MOUSEDRAG7_STATUS_DEFAULT;
1033                                         if (where == BORDER)
1034                                                   key = KEYC_MOUSEDRAG7_BORDER;
1035                                         break;
1036                               case MOUSE_BUTTON_8:
1037                                         if (where == PANE)
1038                                                   key = KEYC_MOUSEDRAG8_PANE;
1039                                         if (where == STATUS)
1040                                                   key = KEYC_MOUSEDRAG8_STATUS;
1041                                         if (where == STATUS_LEFT)
1042                                                   key = KEYC_MOUSEDRAG8_STATUS_LEFT;
1043                                         if (where == STATUS_RIGHT)
1044                                                   key = KEYC_MOUSEDRAG8_STATUS_RIGHT;
1045                                         if (where == STATUS_DEFAULT)
1046                                                   key = KEYC_MOUSEDRAG8_STATUS_DEFAULT;
1047                                         if (where == BORDER)
1048                                                   key = KEYC_MOUSEDRAG8_BORDER;
1049                                         break;
1050                               case MOUSE_BUTTON_9:
1051                                         if (where == PANE)
1052                                                   key = KEYC_MOUSEDRAG9_PANE;
1053                                         if (where == STATUS)
1054                                                   key = KEYC_MOUSEDRAG9_STATUS;
1055                                         if (where == STATUS_LEFT)
1056                                                   key = KEYC_MOUSEDRAG9_STATUS_LEFT;
1057                                         if (where == STATUS_RIGHT)
1058                                                   key = KEYC_MOUSEDRAG9_STATUS_RIGHT;
1059                                         if (where == STATUS_DEFAULT)
1060                                                   key = KEYC_MOUSEDRAG9_STATUS_DEFAULT;
1061                                         if (where == BORDER)
1062                                                   key = KEYC_MOUSEDRAG9_BORDER;
1063                                         break;
1064                               case MOUSE_BUTTON_10:
1065                                         if (where == PANE)
1066                                                   key = KEYC_MOUSEDRAG10_PANE;
1067                                         if (where == STATUS)
1068                                                   key = KEYC_MOUSEDRAG10_STATUS;
1069                                         if (where == STATUS_LEFT)
1070                                                   key = KEYC_MOUSEDRAG10_STATUS_LEFT;
1071                                         if (where == STATUS_RIGHT)
1072                                                   key = KEYC_MOUSEDRAG10_STATUS_RIGHT;
1073                                         if (where == STATUS_DEFAULT)
1074                                                   key = KEYC_MOUSEDRAG10_STATUS_DEFAULT;
1075                                         if (where == BORDER)
1076                                                   key = KEYC_MOUSEDRAG10_BORDER;
1077                                         break;
1078                               case MOUSE_BUTTON_11:
1079                                         if (where == PANE)
1080                                                   key = KEYC_MOUSEDRAG11_PANE;
1081                                         if (where == STATUS)
1082                                                   key = KEYC_MOUSEDRAG11_STATUS;
1083                                         if (where == STATUS_LEFT)
1084                                                   key = KEYC_MOUSEDRAG11_STATUS_LEFT;
1085                                         if (where == STATUS_RIGHT)
1086                                                   key = KEYC_MOUSEDRAG11_STATUS_RIGHT;
1087                                         if (where == STATUS_DEFAULT)
1088                                                   key = KEYC_MOUSEDRAG11_STATUS_DEFAULT;
1089                                         if (where == BORDER)
1090                                                   key = KEYC_MOUSEDRAG11_BORDER;
1091                                         break;
1092                               }
1093                     }
1094 
1095                     /*
1096                      * Begin a drag by setting the flag to a non-zero value that
1097                      * corresponds to the mouse button in use.
1098                      */
1099                     c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
1100                     break;
1101           case WHEEL:
1102                     if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) {
1103                               if (where == PANE)
1104                                         key = KEYC_WHEELUP_PANE;
1105                               if (where == STATUS)
1106                                         key = KEYC_WHEELUP_STATUS;
1107                               if (where == STATUS_LEFT)
1108                                         key = KEYC_WHEELUP_STATUS_LEFT;
1109                               if (where == STATUS_RIGHT)
1110                                         key = KEYC_WHEELUP_STATUS_RIGHT;
1111                               if (where == STATUS_DEFAULT)
1112                                         key = KEYC_WHEELUP_STATUS_DEFAULT;
1113                               if (where == BORDER)
1114                                         key = KEYC_WHEELUP_BORDER;
1115                     } else {
1116                               if (where == PANE)
1117                                         key = KEYC_WHEELDOWN_PANE;
1118                               if (where == STATUS)
1119                                         key = KEYC_WHEELDOWN_STATUS;
1120                               if (where == STATUS_LEFT)
1121                                         key = KEYC_WHEELDOWN_STATUS_LEFT;
1122                               if (where == STATUS_RIGHT)
1123                                         key = KEYC_WHEELDOWN_STATUS_RIGHT;
1124                               if (where == STATUS_DEFAULT)
1125                                         key = KEYC_WHEELDOWN_STATUS_DEFAULT;
1126                               if (where == BORDER)
1127                                         key = KEYC_WHEELDOWN_BORDER;
1128                     }
1129                     break;
1130           case UP:
1131                     switch (MOUSE_BUTTONS(b)) {
1132                     case MOUSE_BUTTON_1:
1133                               if (where == PANE)
1134                                         key = KEYC_MOUSEUP1_PANE;
1135                               if (where == STATUS)
1136                                         key = KEYC_MOUSEUP1_STATUS;
1137                               if (where == STATUS_LEFT)
1138                                         key = KEYC_MOUSEUP1_STATUS_LEFT;
1139                               if (where == STATUS_RIGHT)
1140                                         key = KEYC_MOUSEUP1_STATUS_RIGHT;
1141                               if (where == STATUS_DEFAULT)
1142                                         key = KEYC_MOUSEUP1_STATUS_DEFAULT;
1143                               if (where == BORDER)
1144                                         key = KEYC_MOUSEUP1_BORDER;
1145                               break;
1146                     case MOUSE_BUTTON_2:
1147                               if (where == PANE)
1148                                         key = KEYC_MOUSEUP2_PANE;
1149                               if (where == STATUS)
1150                                         key = KEYC_MOUSEUP2_STATUS;
1151                               if (where == STATUS_LEFT)
1152                                         key = KEYC_MOUSEUP2_STATUS_LEFT;
1153                               if (where == STATUS_RIGHT)
1154                                         key = KEYC_MOUSEUP2_STATUS_RIGHT;
1155                               if (where == STATUS_DEFAULT)
1156                                         key = KEYC_MOUSEUP2_STATUS_DEFAULT;
1157                               if (where == BORDER)
1158                                         key = KEYC_MOUSEUP2_BORDER;
1159                               break;
1160                     case MOUSE_BUTTON_3:
1161                               if (where == PANE)
1162                                         key = KEYC_MOUSEUP3_PANE;
1163                               if (where == STATUS)
1164                                         key = KEYC_MOUSEUP3_STATUS;
1165                               if (where == STATUS_LEFT)
1166                                         key = KEYC_MOUSEUP3_STATUS_LEFT;
1167                               if (where == STATUS_RIGHT)
1168                                         key = KEYC_MOUSEUP3_STATUS_RIGHT;
1169                               if (where == STATUS_DEFAULT)
1170                                         key = KEYC_MOUSEUP3_STATUS_DEFAULT;
1171                               if (where == BORDER)
1172                                         key = KEYC_MOUSEUP3_BORDER;
1173                               break;
1174                     case MOUSE_BUTTON_6:
1175                               if (where == PANE)
1176                                         key = KEYC_MOUSEUP6_PANE;
1177                               if (where == STATUS)
1178                                         key = KEYC_MOUSEUP6_STATUS;
1179                               if (where == STATUS_LEFT)
1180                                         key = KEYC_MOUSEUP6_STATUS_LEFT;
1181                               if (where == STATUS_RIGHT)
1182                                         key = KEYC_MOUSEUP6_STATUS_RIGHT;
1183                               if (where == STATUS_DEFAULT)
1184                                         key = KEYC_MOUSEUP6_STATUS_DEFAULT;
1185                               if (where == BORDER)
1186                                         key = KEYC_MOUSEUP6_BORDER;
1187                               break;
1188                     case MOUSE_BUTTON_7:
1189                               if (where == PANE)
1190                                         key = KEYC_MOUSEUP7_PANE;
1191                               if (where == STATUS)
1192                                         key = KEYC_MOUSEUP7_STATUS;
1193                               if (where == STATUS_LEFT)
1194                                         key = KEYC_MOUSEUP7_STATUS_LEFT;
1195                               if (where == STATUS_RIGHT)
1196                                         key = KEYC_MOUSEUP7_STATUS_RIGHT;
1197                               if (where == STATUS_DEFAULT)
1198                                         key = KEYC_MOUSEUP7_STATUS_DEFAULT;
1199                               if (where == BORDER)
1200                                         key = KEYC_MOUSEUP7_BORDER;
1201                               break;
1202                     case MOUSE_BUTTON_8:
1203                               if (where == PANE)
1204                                         key = KEYC_MOUSEUP8_PANE;
1205                               if (where == STATUS)
1206                                         key = KEYC_MOUSEUP8_STATUS;
1207                               if (where == STATUS_LEFT)
1208                                         key = KEYC_MOUSEUP8_STATUS_LEFT;
1209                               if (where == STATUS_RIGHT)
1210                                         key = KEYC_MOUSEUP8_STATUS_RIGHT;
1211                               if (where == STATUS_DEFAULT)
1212                                         key = KEYC_MOUSEUP8_STATUS_DEFAULT;
1213                               if (where == BORDER)
1214                                         key = KEYC_MOUSEUP8_BORDER;
1215                               break;
1216                     case MOUSE_BUTTON_9:
1217                               if (where == PANE)
1218                                         key = KEYC_MOUSEUP9_PANE;
1219                               if (where == STATUS)
1220                                         key = KEYC_MOUSEUP9_STATUS;
1221                               if (where == STATUS_LEFT)
1222                                         key = KEYC_MOUSEUP9_STATUS_LEFT;
1223                               if (where == STATUS_RIGHT)
1224                                         key = KEYC_MOUSEUP9_STATUS_RIGHT;
1225                               if (where == STATUS_DEFAULT)
1226                                         key = KEYC_MOUSEUP9_STATUS_DEFAULT;
1227                               if (where == BORDER)
1228                                         key = KEYC_MOUSEUP9_BORDER;
1229                               break;
1230                     case MOUSE_BUTTON_10:
1231                               if (where == PANE)
1232                                         key = KEYC_MOUSEUP1_PANE;
1233                               if (where == STATUS)
1234                                         key = KEYC_MOUSEUP1_STATUS;
1235                               if (where == STATUS_LEFT)
1236                                         key = KEYC_MOUSEUP1_STATUS_LEFT;
1237                               if (where == STATUS_RIGHT)
1238                                         key = KEYC_MOUSEUP1_STATUS_RIGHT;
1239                               if (where == STATUS_DEFAULT)
1240                                         key = KEYC_MOUSEUP1_STATUS_DEFAULT;
1241                               if (where == BORDER)
1242                                         key = KEYC_MOUSEUP1_BORDER;
1243                               break;
1244                     case MOUSE_BUTTON_11:
1245                               if (where == PANE)
1246                                         key = KEYC_MOUSEUP11_PANE;
1247                               if (where == STATUS)
1248                                         key = KEYC_MOUSEUP11_STATUS;
1249                               if (where == STATUS_LEFT)
1250                                         key = KEYC_MOUSEUP11_STATUS_LEFT;
1251                               if (where == STATUS_RIGHT)
1252                                         key = KEYC_MOUSEUP11_STATUS_RIGHT;
1253                               if (where == STATUS_DEFAULT)
1254                                         key = KEYC_MOUSEUP11_STATUS_DEFAULT;
1255                               if (where == BORDER)
1256                                         key = KEYC_MOUSEUP11_BORDER;
1257                               break;
1258                     }
1259                     break;
1260           case DOWN:
1261                     switch (MOUSE_BUTTONS(b)) {
1262                     case MOUSE_BUTTON_1:
1263                               if (where == PANE)
1264                                         key = KEYC_MOUSEDOWN1_PANE;
1265                               if (where == STATUS)
1266                                         key = KEYC_MOUSEDOWN1_STATUS;
1267                               if (where == STATUS_LEFT)
1268                                         key = KEYC_MOUSEDOWN1_STATUS_LEFT;
1269                               if (where == STATUS_RIGHT)
1270                                         key = KEYC_MOUSEDOWN1_STATUS_RIGHT;
1271                               if (where == STATUS_DEFAULT)
1272                                         key = KEYC_MOUSEDOWN1_STATUS_DEFAULT;
1273                               if (where == BORDER)
1274                                         key = KEYC_MOUSEDOWN1_BORDER;
1275                               break;
1276                     case MOUSE_BUTTON_2:
1277                               if (where == PANE)
1278                                         key = KEYC_MOUSEDOWN2_PANE;
1279                               if (where == STATUS)
1280                                         key = KEYC_MOUSEDOWN2_STATUS;
1281                               if (where == STATUS_LEFT)
1282                                         key = KEYC_MOUSEDOWN2_STATUS_LEFT;
1283                               if (where == STATUS_RIGHT)
1284                                         key = KEYC_MOUSEDOWN2_STATUS_RIGHT;
1285                               if (where == STATUS_DEFAULT)
1286                                         key = KEYC_MOUSEDOWN2_STATUS_DEFAULT;
1287                               if (where == BORDER)
1288                                         key = KEYC_MOUSEDOWN2_BORDER;
1289                               break;
1290                     case MOUSE_BUTTON_3:
1291                               if (where == PANE)
1292                                         key = KEYC_MOUSEDOWN3_PANE;
1293                               if (where == STATUS)
1294                                         key = KEYC_MOUSEDOWN3_STATUS;
1295                               if (where == STATUS_LEFT)
1296                                         key = KEYC_MOUSEDOWN3_STATUS_LEFT;
1297                               if (where == STATUS_RIGHT)
1298                                         key = KEYC_MOUSEDOWN3_STATUS_RIGHT;
1299                               if (where == STATUS_DEFAULT)
1300                                         key = KEYC_MOUSEDOWN3_STATUS_DEFAULT;
1301                               if (where == BORDER)
1302                                         key = KEYC_MOUSEDOWN3_BORDER;
1303                               break;
1304                     case MOUSE_BUTTON_6:
1305                               if (where == PANE)
1306                                         key = KEYC_MOUSEDOWN6_PANE;
1307                               if (where == STATUS)
1308                                         key = KEYC_MOUSEDOWN6_STATUS;
1309                               if (where == STATUS_LEFT)
1310                                         key = KEYC_MOUSEDOWN6_STATUS_LEFT;
1311                               if (where == STATUS_RIGHT)
1312                                         key = KEYC_MOUSEDOWN6_STATUS_RIGHT;
1313                               if (where == STATUS_DEFAULT)
1314                                         key = KEYC_MOUSEDOWN6_STATUS_DEFAULT;
1315                               if (where == BORDER)
1316                                         key = KEYC_MOUSEDOWN6_BORDER;
1317                               break;
1318                     case MOUSE_BUTTON_7:
1319                               if (where == PANE)
1320                                         key = KEYC_MOUSEDOWN7_PANE;
1321                               if (where == STATUS)
1322                                         key = KEYC_MOUSEDOWN7_STATUS;
1323                               if (where == STATUS_LEFT)
1324                                         key = KEYC_MOUSEDOWN7_STATUS_LEFT;
1325                               if (where == STATUS_RIGHT)
1326                                         key = KEYC_MOUSEDOWN7_STATUS_RIGHT;
1327                               if (where == STATUS_DEFAULT)
1328                                         key = KEYC_MOUSEDOWN7_STATUS_DEFAULT;
1329                               if (where == BORDER)
1330                                         key = KEYC_MOUSEDOWN7_BORDER;
1331                               break;
1332                     case MOUSE_BUTTON_8:
1333                               if (where == PANE)
1334                                         key = KEYC_MOUSEDOWN8_PANE;
1335                               if (where == STATUS)
1336                                         key = KEYC_MOUSEDOWN8_STATUS;
1337                               if (where == STATUS_LEFT)
1338                                         key = KEYC_MOUSEDOWN8_STATUS_LEFT;
1339                               if (where == STATUS_RIGHT)
1340                                         key = KEYC_MOUSEDOWN8_STATUS_RIGHT;
1341                               if (where == STATUS_DEFAULT)
1342                                         key = KEYC_MOUSEDOWN8_STATUS_DEFAULT;
1343                               if (where == BORDER)
1344                                         key = KEYC_MOUSEDOWN8_BORDER;
1345                               break;
1346                     case MOUSE_BUTTON_9:
1347                               if (where == PANE)
1348                                         key = KEYC_MOUSEDOWN9_PANE;
1349                               if (where == STATUS)
1350                                         key = KEYC_MOUSEDOWN9_STATUS;
1351                               if (where == STATUS_LEFT)
1352                                         key = KEYC_MOUSEDOWN9_STATUS_LEFT;
1353                               if (where == STATUS_RIGHT)
1354                                         key = KEYC_MOUSEDOWN9_STATUS_RIGHT;
1355                               if (where == STATUS_DEFAULT)
1356                                         key = KEYC_MOUSEDOWN9_STATUS_DEFAULT;
1357                               if (where == BORDER)
1358                                         key = KEYC_MOUSEDOWN9_BORDER;
1359                               break;
1360                     case MOUSE_BUTTON_10:
1361                               if (where == PANE)
1362                                         key = KEYC_MOUSEDOWN10_PANE;
1363                               if (where == STATUS)
1364                                         key = KEYC_MOUSEDOWN10_STATUS;
1365                               if (where == STATUS_LEFT)
1366                                         key = KEYC_MOUSEDOWN10_STATUS_LEFT;
1367                               if (where == STATUS_RIGHT)
1368                                         key = KEYC_MOUSEDOWN10_STATUS_RIGHT;
1369                               if (where == STATUS_DEFAULT)
1370                                         key = KEYC_MOUSEDOWN10_STATUS_DEFAULT;
1371                               if (where == BORDER)
1372                                         key = KEYC_MOUSEDOWN10_BORDER;
1373                               break;
1374                     case MOUSE_BUTTON_11:
1375                               if (where == PANE)
1376                                         key = KEYC_MOUSEDOWN11_PANE;
1377                               if (where == STATUS)
1378                                         key = KEYC_MOUSEDOWN11_STATUS;
1379                               if (where == STATUS_LEFT)
1380                                         key = KEYC_MOUSEDOWN11_STATUS_LEFT;
1381                               if (where == STATUS_RIGHT)
1382                                         key = KEYC_MOUSEDOWN11_STATUS_RIGHT;
1383                               if (where == STATUS_DEFAULT)
1384                                         key = KEYC_MOUSEDOWN11_STATUS_DEFAULT;
1385                               if (where == BORDER)
1386                                         key = KEYC_MOUSEDOWN11_BORDER;
1387                               break;
1388                     }
1389                     break;
1390           case SECOND:
1391                     switch (MOUSE_BUTTONS(b)) {
1392                     case MOUSE_BUTTON_1:
1393                               if (where == PANE)
1394                                         key = KEYC_SECONDCLICK1_PANE;
1395                               if (where == STATUS)
1396                                         key = KEYC_SECONDCLICK1_STATUS;
1397                               if (where == STATUS_LEFT)
1398                                         key = KEYC_SECONDCLICK1_STATUS_LEFT;
1399                               if (where == STATUS_RIGHT)
1400                                         key = KEYC_SECONDCLICK1_STATUS_RIGHT;
1401                               if (where == STATUS_DEFAULT)
1402                                         key = KEYC_SECONDCLICK1_STATUS_DEFAULT;
1403                               if (where == BORDER)
1404                                         key = KEYC_SECONDCLICK1_BORDER;
1405                               break;
1406                     case MOUSE_BUTTON_2:
1407                               if (where == PANE)
1408                                         key = KEYC_SECONDCLICK2_PANE;
1409                               if (where == STATUS)
1410                                         key = KEYC_SECONDCLICK2_STATUS;
1411                               if (where == STATUS_LEFT)
1412                                         key = KEYC_SECONDCLICK2_STATUS_LEFT;
1413                               if (where == STATUS_RIGHT)
1414                                         key = KEYC_SECONDCLICK2_STATUS_RIGHT;
1415                               if (where == STATUS_DEFAULT)
1416                                         key = KEYC_SECONDCLICK2_STATUS_DEFAULT;
1417                               if (where == BORDER)
1418                                         key = KEYC_SECONDCLICK2_BORDER;
1419                               break;
1420                     case MOUSE_BUTTON_3:
1421                               if (where == PANE)
1422                                         key = KEYC_SECONDCLICK3_PANE;
1423                               if (where == STATUS)
1424                                         key = KEYC_SECONDCLICK3_STATUS;
1425                               if (where == STATUS_LEFT)
1426                                         key = KEYC_SECONDCLICK3_STATUS_LEFT;
1427                               if (where == STATUS_RIGHT)
1428                                         key = KEYC_SECONDCLICK3_STATUS_RIGHT;
1429                               if (where == STATUS_DEFAULT)
1430                                         key = KEYC_SECONDCLICK3_STATUS_DEFAULT;
1431                               if (where == BORDER)
1432                                         key = KEYC_SECONDCLICK3_BORDER;
1433                               break;
1434                     case MOUSE_BUTTON_6:
1435                               if (where == PANE)
1436                                         key = KEYC_SECONDCLICK6_PANE;
1437                               if (where == STATUS)
1438                                         key = KEYC_SECONDCLICK6_STATUS;
1439                               if (where == STATUS_LEFT)
1440                                         key = KEYC_SECONDCLICK6_STATUS_LEFT;
1441                               if (where == STATUS_RIGHT)
1442                                         key = KEYC_SECONDCLICK6_STATUS_RIGHT;
1443                               if (where == STATUS_DEFAULT)
1444                                         key = KEYC_SECONDCLICK6_STATUS_DEFAULT;
1445                               if (where == BORDER)
1446                                         key = KEYC_SECONDCLICK6_BORDER;
1447                               break;
1448                     case MOUSE_BUTTON_7:
1449                               if (where == PANE)
1450                                         key = KEYC_SECONDCLICK7_PANE;
1451                               if (where == STATUS)
1452                                         key = KEYC_SECONDCLICK7_STATUS;
1453                               if (where == STATUS_LEFT)
1454                                         key = KEYC_SECONDCLICK7_STATUS_LEFT;
1455                               if (where == STATUS_RIGHT)
1456                                         key = KEYC_SECONDCLICK7_STATUS_RIGHT;
1457                               if (where == STATUS_DEFAULT)
1458                                         key = KEYC_SECONDCLICK7_STATUS_DEFAULT;
1459                               if (where == BORDER)
1460                                         key = KEYC_SECONDCLICK7_BORDER;
1461                               break;
1462                     case MOUSE_BUTTON_8:
1463                               if (where == PANE)
1464                                         key = KEYC_SECONDCLICK8_PANE;
1465                               if (where == STATUS)
1466                                         key = KEYC_SECONDCLICK8_STATUS;
1467                               if (where == STATUS_LEFT)
1468                                         key = KEYC_SECONDCLICK8_STATUS_LEFT;
1469                               if (where == STATUS_RIGHT)
1470                                         key = KEYC_SECONDCLICK8_STATUS_RIGHT;
1471                               if (where == STATUS_DEFAULT)
1472                                         key = KEYC_SECONDCLICK8_STATUS_DEFAULT;
1473                               if (where == BORDER)
1474                                         key = KEYC_SECONDCLICK8_BORDER;
1475                               break;
1476                     case MOUSE_BUTTON_9:
1477                               if (where == PANE)
1478                                         key = KEYC_SECONDCLICK9_PANE;
1479                               if (where == STATUS)
1480                                         key = KEYC_SECONDCLICK9_STATUS;
1481                               if (where == STATUS_LEFT)
1482                                         key = KEYC_SECONDCLICK9_STATUS_LEFT;
1483                               if (where == STATUS_RIGHT)
1484                                         key = KEYC_SECONDCLICK9_STATUS_RIGHT;
1485                               if (where == STATUS_DEFAULT)
1486                                         key = KEYC_SECONDCLICK9_STATUS_DEFAULT;
1487                               if (where == BORDER)
1488                                         key = KEYC_SECONDCLICK9_BORDER;
1489                               break;
1490                     case MOUSE_BUTTON_10:
1491                               if (where == PANE)
1492                                         key = KEYC_SECONDCLICK10_PANE;
1493                               if (where == STATUS)
1494                                         key = KEYC_SECONDCLICK10_STATUS;
1495                               if (where == STATUS_LEFT)
1496                                         key = KEYC_SECONDCLICK10_STATUS_LEFT;
1497                               if (where == STATUS_RIGHT)
1498                                         key = KEYC_SECONDCLICK10_STATUS_RIGHT;
1499                               if (where == STATUS_DEFAULT)
1500                                         key = KEYC_SECONDCLICK10_STATUS_DEFAULT;
1501                               if (where == BORDER)
1502                                         key = KEYC_SECONDCLICK10_BORDER;
1503                               break;
1504                     case MOUSE_BUTTON_11:
1505                               if (where == PANE)
1506                                         key = KEYC_SECONDCLICK11_PANE;
1507                               if (where == STATUS)
1508                                         key = KEYC_SECONDCLICK11_STATUS;
1509                               if (where == STATUS_LEFT)
1510                                         key = KEYC_SECONDCLICK11_STATUS_LEFT;
1511                               if (where == STATUS_RIGHT)
1512                                         key = KEYC_SECONDCLICK11_STATUS_RIGHT;
1513                               if (where == STATUS_DEFAULT)
1514                                         key = KEYC_SECONDCLICK11_STATUS_DEFAULT;
1515                               if (where == BORDER)
1516                                         key = KEYC_SECONDCLICK11_BORDER;
1517                               break;
1518                     }
1519                     break;
1520           case DOUBLE:
1521                     switch (MOUSE_BUTTONS(b)) {
1522                     case MOUSE_BUTTON_1:
1523                               if (where == PANE)
1524                                         key = KEYC_DOUBLECLICK1_PANE;
1525                               if (where == STATUS)
1526                                         key = KEYC_DOUBLECLICK1_STATUS;
1527                               if (where == STATUS_LEFT)
1528                                         key = KEYC_DOUBLECLICK1_STATUS_LEFT;
1529                               if (where == STATUS_RIGHT)
1530                                         key = KEYC_DOUBLECLICK1_STATUS_RIGHT;
1531                               if (where == STATUS_DEFAULT)
1532                                         key = KEYC_DOUBLECLICK1_STATUS_DEFAULT;
1533                               if (where == BORDER)
1534                                         key = KEYC_DOUBLECLICK1_BORDER;
1535                               break;
1536                     case MOUSE_BUTTON_2:
1537                               if (where == PANE)
1538                                         key = KEYC_DOUBLECLICK2_PANE;
1539                               if (where == STATUS)
1540                                         key = KEYC_DOUBLECLICK2_STATUS;
1541                               if (where == STATUS_LEFT)
1542                                         key = KEYC_DOUBLECLICK2_STATUS_LEFT;
1543                               if (where == STATUS_RIGHT)
1544                                         key = KEYC_DOUBLECLICK2_STATUS_RIGHT;
1545                               if (where == STATUS_DEFAULT)
1546                                         key = KEYC_DOUBLECLICK2_STATUS_DEFAULT;
1547                               if (where == BORDER)
1548                                         key = KEYC_DOUBLECLICK2_BORDER;
1549                               break;
1550                     case MOUSE_BUTTON_3:
1551                               if (where == PANE)
1552                                         key = KEYC_DOUBLECLICK3_PANE;
1553                               if (where == STATUS)
1554                                         key = KEYC_DOUBLECLICK3_STATUS;
1555                               if (where == STATUS_LEFT)
1556                                         key = KEYC_DOUBLECLICK3_STATUS_LEFT;
1557                               if (where == STATUS_RIGHT)
1558                                         key = KEYC_DOUBLECLICK3_STATUS_RIGHT;
1559                               if (where == STATUS_DEFAULT)
1560                                         key = KEYC_DOUBLECLICK3_STATUS_DEFAULT;
1561                               if (where == BORDER)
1562                                         key = KEYC_DOUBLECLICK3_BORDER;
1563                               break;
1564                     case MOUSE_BUTTON_6:
1565                               if (where == PANE)
1566                                         key = KEYC_DOUBLECLICK6_PANE;
1567                               if (where == STATUS)
1568                                         key = KEYC_DOUBLECLICK6_STATUS;
1569                               if (where == STATUS_LEFT)
1570                                         key = KEYC_DOUBLECLICK6_STATUS_LEFT;
1571                               if (where == STATUS_RIGHT)
1572                                         key = KEYC_DOUBLECLICK6_STATUS_RIGHT;
1573                               if (where == STATUS_DEFAULT)
1574                                         key = KEYC_DOUBLECLICK6_STATUS_DEFAULT;
1575                               if (where == BORDER)
1576                                         key = KEYC_DOUBLECLICK6_BORDER;
1577                               break;
1578                     case MOUSE_BUTTON_7:
1579                               if (where == PANE)
1580                                         key = KEYC_DOUBLECLICK7_PANE;
1581                               if (where == STATUS)
1582                                         key = KEYC_DOUBLECLICK7_STATUS;
1583                               if (where == STATUS_LEFT)
1584                                         key = KEYC_DOUBLECLICK7_STATUS_LEFT;
1585                               if (where == STATUS_RIGHT)
1586                                         key = KEYC_DOUBLECLICK7_STATUS_RIGHT;
1587                               if (where == STATUS_DEFAULT)
1588                                         key = KEYC_DOUBLECLICK7_STATUS_DEFAULT;
1589                               if (where == BORDER)
1590                                         key = KEYC_DOUBLECLICK7_BORDER;
1591                               break;
1592                     case MOUSE_BUTTON_8:
1593                               if (where == PANE)
1594                                         key = KEYC_DOUBLECLICK8_PANE;
1595                               if (where == STATUS)
1596                                         key = KEYC_DOUBLECLICK8_STATUS;
1597                               if (where == STATUS_LEFT)
1598                                         key = KEYC_DOUBLECLICK8_STATUS_LEFT;
1599                               if (where == STATUS_RIGHT)
1600                                         key = KEYC_DOUBLECLICK8_STATUS_RIGHT;
1601                               if (where == STATUS_DEFAULT)
1602                                         key = KEYC_DOUBLECLICK8_STATUS_DEFAULT;
1603                               if (where == BORDER)
1604                                         key = KEYC_DOUBLECLICK8_BORDER;
1605                               break;
1606                     case MOUSE_BUTTON_9:
1607                               if (where == PANE)
1608                                         key = KEYC_DOUBLECLICK9_PANE;
1609                               if (where == STATUS)
1610                                         key = KEYC_DOUBLECLICK9_STATUS;
1611                               if (where == STATUS_LEFT)
1612                                         key = KEYC_DOUBLECLICK9_STATUS_LEFT;
1613                               if (where == STATUS_RIGHT)
1614                                         key = KEYC_DOUBLECLICK9_STATUS_RIGHT;
1615                               if (where == STATUS_DEFAULT)
1616                                         key = KEYC_DOUBLECLICK9_STATUS_DEFAULT;
1617                               if (where == BORDER)
1618                                         key = KEYC_DOUBLECLICK9_BORDER;
1619                               break;
1620                     case MOUSE_BUTTON_10:
1621                               if (where == PANE)
1622                                         key = KEYC_DOUBLECLICK10_PANE;
1623                               if (where == STATUS)
1624                                         key = KEYC_DOUBLECLICK10_STATUS;
1625                               if (where == STATUS_LEFT)
1626                                         key = KEYC_DOUBLECLICK10_STATUS_LEFT;
1627                               if (where == STATUS_RIGHT)
1628                                         key = KEYC_DOUBLECLICK10_STATUS_RIGHT;
1629                               if (where == STATUS_DEFAULT)
1630                                         key = KEYC_DOUBLECLICK10_STATUS_DEFAULT;
1631                               if (where == BORDER)
1632                                         key = KEYC_DOUBLECLICK10_BORDER;
1633                               break;
1634                     case MOUSE_BUTTON_11:
1635                               if (where == PANE)
1636                                         key = KEYC_DOUBLECLICK11_PANE;
1637                               if (where == STATUS)
1638                                         key = KEYC_DOUBLECLICK11_STATUS;
1639                               if (where == STATUS_LEFT)
1640                                         key = KEYC_DOUBLECLICK11_STATUS_LEFT;
1641                               if (where == STATUS_RIGHT)
1642                                         key = KEYC_DOUBLECLICK11_STATUS_RIGHT;
1643                               if (where == STATUS_DEFAULT)
1644                                         key = KEYC_DOUBLECLICK11_STATUS_DEFAULT;
1645                               if (where == BORDER)
1646                                         key = KEYC_DOUBLECLICK11_BORDER;
1647                               break;
1648                     }
1649                     break;
1650           case TRIPLE:
1651                     switch (MOUSE_BUTTONS(b)) {
1652                     case MOUSE_BUTTON_1:
1653                               if (where == PANE)
1654                                         key = KEYC_TRIPLECLICK1_PANE;
1655                               if (where == STATUS)
1656                                         key = KEYC_TRIPLECLICK1_STATUS;
1657                               if (where == STATUS_LEFT)
1658                                         key = KEYC_TRIPLECLICK1_STATUS_LEFT;
1659                               if (where == STATUS_RIGHT)
1660                                         key = KEYC_TRIPLECLICK1_STATUS_RIGHT;
1661                               if (where == STATUS_DEFAULT)
1662                                         key = KEYC_TRIPLECLICK1_STATUS_DEFAULT;
1663                               if (where == BORDER)
1664                                         key = KEYC_TRIPLECLICK1_BORDER;
1665                               break;
1666                     case MOUSE_BUTTON_2:
1667                               if (where == PANE)
1668                                         key = KEYC_TRIPLECLICK2_PANE;
1669                               if (where == STATUS)
1670                                         key = KEYC_TRIPLECLICK2_STATUS;
1671                               if (where == STATUS_LEFT)
1672                                         key = KEYC_TRIPLECLICK2_STATUS_LEFT;
1673                               if (where == STATUS_RIGHT)
1674                                         key = KEYC_TRIPLECLICK2_STATUS_RIGHT;
1675                               if (where == STATUS_DEFAULT)
1676                                         key = KEYC_TRIPLECLICK2_STATUS_DEFAULT;
1677                               if (where == BORDER)
1678                                         key = KEYC_TRIPLECLICK2_BORDER;
1679                               break;
1680                     case MOUSE_BUTTON_3:
1681                               if (where == PANE)
1682                                         key = KEYC_TRIPLECLICK3_PANE;
1683                               if (where == STATUS)
1684                                         key = KEYC_TRIPLECLICK3_STATUS;
1685                               if (where == STATUS_LEFT)
1686                                         key = KEYC_TRIPLECLICK3_STATUS_LEFT;
1687                               if (where == STATUS_RIGHT)
1688                                         key = KEYC_TRIPLECLICK3_STATUS_RIGHT;
1689                               if (where == STATUS_DEFAULT)
1690                                         key = KEYC_TRIPLECLICK3_STATUS_DEFAULT;
1691                               if (where == BORDER)
1692                                         key = KEYC_TRIPLECLICK3_BORDER;
1693                               break;
1694                     case MOUSE_BUTTON_6:
1695                               if (where == PANE)
1696                                         key = KEYC_TRIPLECLICK6_PANE;
1697                               if (where == STATUS)
1698                                         key = KEYC_TRIPLECLICK6_STATUS;
1699                               if (where == STATUS_LEFT)
1700                                         key = KEYC_TRIPLECLICK6_STATUS_LEFT;
1701                               if (where == STATUS_RIGHT)
1702                                         key = KEYC_TRIPLECLICK6_STATUS_RIGHT;
1703                               if (where == STATUS_DEFAULT)
1704                                         key = KEYC_TRIPLECLICK6_STATUS_DEFAULT;
1705                               if (where == BORDER)
1706                                         key = KEYC_TRIPLECLICK6_BORDER;
1707                               break;
1708                     case MOUSE_BUTTON_7:
1709                               if (where == PANE)
1710                                         key = KEYC_TRIPLECLICK7_PANE;
1711                               if (where == STATUS)
1712                                         key = KEYC_TRIPLECLICK7_STATUS;
1713                               if (where == STATUS_LEFT)
1714                                         key = KEYC_TRIPLECLICK7_STATUS_LEFT;
1715                               if (where == STATUS_RIGHT)
1716                                         key = KEYC_TRIPLECLICK7_STATUS_RIGHT;
1717                               if (where == STATUS_DEFAULT)
1718                                         key = KEYC_TRIPLECLICK7_STATUS_DEFAULT;
1719                               if (where == BORDER)
1720                                         key = KEYC_TRIPLECLICK7_BORDER;
1721                               break;
1722                     case MOUSE_BUTTON_8:
1723                               if (where == PANE)
1724                                         key = KEYC_TRIPLECLICK8_PANE;
1725                               if (where == STATUS)
1726                                         key = KEYC_TRIPLECLICK8_STATUS;
1727                               if (where == STATUS_LEFT)
1728                                         key = KEYC_TRIPLECLICK8_STATUS_LEFT;
1729                               if (where == STATUS_RIGHT)
1730                                         key = KEYC_TRIPLECLICK8_STATUS_RIGHT;
1731                               if (where == STATUS_DEFAULT)
1732                                         key = KEYC_TRIPLECLICK8_STATUS_DEFAULT;
1733                               if (where == BORDER)
1734                                         key = KEYC_TRIPLECLICK8_BORDER;
1735                               break;
1736                     case MOUSE_BUTTON_9:
1737                               if (where == PANE)
1738                                         key = KEYC_TRIPLECLICK9_PANE;
1739                               if (where == STATUS)
1740                                         key = KEYC_TRIPLECLICK9_STATUS;
1741                               if (where == STATUS_LEFT)
1742                                         key = KEYC_TRIPLECLICK9_STATUS_LEFT;
1743                               if (where == STATUS_RIGHT)
1744                                         key = KEYC_TRIPLECLICK9_STATUS_RIGHT;
1745                               if (where == STATUS_DEFAULT)
1746                                         key = KEYC_TRIPLECLICK9_STATUS_DEFAULT;
1747                               if (where == BORDER)
1748                                         key = KEYC_TRIPLECLICK9_BORDER;
1749                               break;
1750                     case MOUSE_BUTTON_10:
1751                               if (where == PANE)
1752                                         key = KEYC_TRIPLECLICK10_PANE;
1753                               if (where == STATUS)
1754                                         key = KEYC_TRIPLECLICK10_STATUS;
1755                               if (where == STATUS_LEFT)
1756                                         key = KEYC_TRIPLECLICK10_STATUS_LEFT;
1757                               if (where == STATUS_RIGHT)
1758                                         key = KEYC_TRIPLECLICK10_STATUS_RIGHT;
1759                               if (where == STATUS_DEFAULT)
1760                                         key = KEYC_TRIPLECLICK10_STATUS_DEFAULT;
1761                               if (where == BORDER)
1762                                         key = KEYC_TRIPLECLICK10_BORDER;
1763                               break;
1764                     case MOUSE_BUTTON_11:
1765                               if (where == PANE)
1766                                         key = KEYC_TRIPLECLICK11_PANE;
1767                               if (where == STATUS)
1768                                         key = KEYC_TRIPLECLICK11_STATUS;
1769                               if (where == STATUS_LEFT)
1770                                         key = KEYC_TRIPLECLICK11_STATUS_LEFT;
1771                               if (where == STATUS_RIGHT)
1772                                         key = KEYC_TRIPLECLICK11_STATUS_RIGHT;
1773                               if (where == STATUS_DEFAULT)
1774                                         key = KEYC_TRIPLECLICK11_STATUS_DEFAULT;
1775                               if (where == BORDER)
1776                                         key = KEYC_TRIPLECLICK11_BORDER;
1777                               break;
1778                     }
1779                     break;
1780           }
1781           if (key == KEYC_UNKNOWN)
1782                     return (KEYC_UNKNOWN);
1783 
1784 out:
1785           /* Apply modifiers if any. */
1786           if (b & MOUSE_MASK_META)
1787                     key |= KEYC_META;
1788           if (b & MOUSE_MASK_CTRL)
1789                     key |= KEYC_CTRL;
1790           if (b & MOUSE_MASK_SHIFT)
1791                     key |= KEYC_SHIFT;
1792 
1793           if (log_get_level() != 0)
1794                     log_debug("mouse key is %s", key_string_lookup_key (key, 1));
1795           return (key);
1796 }
1797 
1798 /* Is this a bracket paste key? */
1799 static int
server_client_is_bracket_pasting(struct client * c,key_code key)1800 server_client_is_bracket_pasting(struct client *c, key_code key)
1801 {
1802           if (key == KEYC_PASTE_START) {
1803                     c->flags |= CLIENT_BRACKETPASTING;
1804                     log_debug("%s: bracket paste on", c->name);
1805                     return (1);
1806           }
1807 
1808           if (key == KEYC_PASTE_END) {
1809                     c->flags &= ~CLIENT_BRACKETPASTING;
1810                     log_debug("%s: bracket paste off", c->name);
1811                     return (1);
1812           }
1813 
1814           return !!(c->flags & CLIENT_BRACKETPASTING);
1815 }
1816 
1817 /* Is this fast enough to probably be a paste? */
1818 static int
server_client_assume_paste(struct session * s)1819 server_client_assume_paste(struct session *s)
1820 {
1821           struct timeval      tv;
1822           int                 t;
1823 
1824           if ((t = options_get_number(s->options, "assume-paste-time")) == 0)
1825                     return (0);
1826 
1827           timersub(&s->activity_time, &s->last_activity_time, &tv);
1828           if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) {
1829                     log_debug("session %s pasting (flag %d)", s->name,
1830                         !!(s->flags & SESSION_PASTING));
1831                     if (s->flags & SESSION_PASTING)
1832                               return (1);
1833                     s->flags |= SESSION_PASTING;
1834                     return (0);
1835           }
1836           log_debug("session %s not pasting", s->name);
1837           s->flags &= ~SESSION_PASTING;
1838           return (0);
1839 }
1840 
1841 /* Has the latest client changed? */
1842 static void
server_client_update_latest(struct client * c)1843 server_client_update_latest(struct client *c)
1844 {
1845           struct window       *w;
1846 
1847           if (c->session == NULL)
1848                     return;
1849           w = c->session->curw->window;
1850 
1851           if (w->latest == c)
1852                     return;
1853           w->latest = c;
1854 
1855           if (options_get_number(w->options, "window-size") == WINDOW_SIZE_LATEST)
1856                     recalculate_size(w, 0);
1857 
1858           notify_client("client-active", c);
1859 }
1860 
1861 /*
1862  * Handle data key input from client. This owns and can modify the key event it
1863  * is given and is responsible for freeing it.
1864  */
1865 static enum cmd_retval
server_client_key_callback(struct cmdq_item * item,void * data)1866 server_client_key_callback(struct cmdq_item *item, void *data)
1867 {
1868           struct client                           *c = cmdq_get_client(item);
1869           struct key_event              *event = data;
1870           key_code                       key = event->key;
1871           struct mouse_event            *m = &event->m;
1872           struct session                          *s = c->session;
1873           struct winlink                          *wl;
1874           struct window_pane            *wp;
1875           struct window_mode_entry      *wme;
1876           struct timeval                           tv;
1877           struct key_table              *table, *first;
1878           struct key_binding            *bd;
1879           int                                      xtimeout;
1880           uint64_t                       flags, prefix_delay;
1881           struct cmd_find_state                    fs;
1882           key_code                       key0, prefix, prefix2;
1883 
1884           /* Check the client is good to accept input. */
1885           if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
1886                     goto out;
1887           wl = s->curw;
1888 
1889           /* Update the activity timer. */
1890           if (gettimeofday(&c->activity_time, NULL) != 0)
1891                     fatal("gettimeofday failed");
1892           session_update_activity(s, &c->activity_time);
1893 
1894           /* Check for mouse keys. */
1895           m->valid = 0;
1896           if (key == KEYC_MOUSE || key == KEYC_DOUBLECLICK) {
1897                     if (c->flags & CLIENT_READONLY)
1898                               goto out;
1899                     key = server_client_check_mouse(c, event);
1900                     if (key == KEYC_UNKNOWN)
1901                               goto out;
1902 
1903                     m->valid = 1;
1904                     m->key = key;
1905 
1906                     /*
1907                      * Mouse drag is in progress, so fire the callback (now that
1908                      * the mouse event is valid).
1909                      */
1910                     if ((key & KEYC_MASK_KEY) == KEYC_DRAGGING) {
1911                               c->tty.mouse_drag_update(c, m);
1912                               goto out;
1913                     }
1914                     event->key = key;
1915           }
1916 
1917           /* Find affected pane. */
1918           if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0)
1919                     cmd_find_from_client(&fs, c, 0);
1920           wp = fs.wp;
1921 
1922           /* Forward mouse keys if disabled. */
1923           if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
1924                     goto forward_key;
1925 
1926           /* Forward if bracket pasting. */
1927           if (server_client_is_bracket_pasting(c, key))
1928                     goto forward_key;
1929 
1930           /* Treat everything as a regular key when pasting is detected. */
1931           if (!KEYC_IS_MOUSE(key) &&
1932               (~key & KEYC_SENT) &&
1933               server_client_assume_paste(s))
1934                     goto forward_key;
1935 
1936           /*
1937            * Work out the current key table. If the pane is in a mode, use
1938            * the mode table instead of the default key table.
1939            */
1940           if (server_client_is_default_key_table(c, c->keytable) &&
1941               wp != NULL &&
1942               (wme = TAILQ_FIRST(&wp->modes)) != NULL &&
1943               wme->mode->key_table != NULL)
1944                     table = key_bindings_get_table(wme->mode->key_table(wme), 1);
1945           else
1946                     table = c->keytable;
1947           first = table;
1948 
1949 table_changed:
1950           /*
1951            * The prefix always takes precedence and forces a switch to the prefix
1952            * table, unless we are already there.
1953            */
1954           prefix = (key_code)options_get_number(s->options, "prefix");
1955           prefix2 = (key_code)options_get_number(s->options, "prefix2");
1956           key0 = (key & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS));
1957           if ((key0 == (prefix & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS)) ||
1958               key0 == (prefix2 & (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS))) &&
1959               strcmp(table->name, "prefix") != 0) {
1960                     server_client_set_key_table(c, "prefix");
1961                     server_status_client(c);
1962                     goto out;
1963           }
1964           flags = c->flags;
1965 
1966 try_again:
1967           /* Log key table. */
1968           if (wp == NULL)
1969                     log_debug("key table %s (no pane)", table->name);
1970           else
1971                     log_debug("key table %s (pane %%%u)", table->name, wp->id);
1972           if (c->flags & CLIENT_REPEAT)
1973                     log_debug("currently repeating");
1974 
1975           bd = key_bindings_get(table, key0);
1976 
1977           /*
1978            * If prefix-timeout is enabled and we're in the prefix table, see if
1979            * the timeout has been exceeded. Revert to the root table if so.
1980            */
1981           prefix_delay = options_get_number(global_options, "prefix-timeout");
1982           if (prefix_delay > 0 &&
1983               strcmp(table->name, "prefix") == 0 &&
1984               server_client_key_table_activity_diff(c) > prefix_delay) {
1985                     /*
1986                      * If repeating is active and this is a repeating binding,
1987                      * ignore the timeout.
1988                      */
1989                     if (bd != NULL &&
1990                         (c->flags & CLIENT_REPEAT) &&
1991                         (bd->flags & KEY_BINDING_REPEAT)) {
1992                               log_debug("prefix timeout ignored, repeat is active");
1993                     } else {
1994                               log_debug("prefix timeout exceeded");
1995                               server_client_set_key_table(c, NULL);
1996                               first = table = c->keytable;
1997                               server_status_client(c);
1998                               goto table_changed;
1999                     }
2000           }
2001 
2002           /* Try to see if there is a key binding in the current table. */
2003           if (bd != NULL) {
2004                     /*
2005                      * Key was matched in this table. If currently repeating but a
2006                      * non-repeating binding was found, stop repeating and try
2007                      * again in the root table.
2008                      */
2009                     if ((c->flags & CLIENT_REPEAT) &&
2010                         (~bd->flags & KEY_BINDING_REPEAT)) {
2011                               log_debug("found in key table %s (not repeating)",
2012                                   table->name);
2013                               server_client_set_key_table(c, NULL);
2014                               first = table = c->keytable;
2015                               c->flags &= ~CLIENT_REPEAT;
2016                               server_status_client(c);
2017                               goto table_changed;
2018                     }
2019                     log_debug("found in key table %s", table->name);
2020 
2021                     /*
2022                      * Take a reference to this table to make sure the key binding
2023                      * doesn't disappear.
2024                      */
2025                     table->references++;
2026 
2027                     /*
2028                      * If this is a repeating key, start the timer. Otherwise reset
2029                      * the client back to the root table.
2030                      */
2031                     xtimeout = options_get_number(s->options, "repeat-time");
2032                     if (xtimeout != 0 && (bd->flags & KEY_BINDING_REPEAT)) {
2033                               c->flags |= CLIENT_REPEAT;
2034 
2035                               tv.tv_sec = xtimeout / 1000;
2036                               tv.tv_usec = (xtimeout % 1000) * 1000L;
2037                               evtimer_del(&c->repeat_timer);
2038                               evtimer_add(&c->repeat_timer, &tv);
2039                     } else {
2040                               c->flags &= ~CLIENT_REPEAT;
2041                               server_client_set_key_table(c, NULL);
2042                     }
2043                     server_status_client(c);
2044 
2045                     /* Execute the key binding. */
2046                     key_bindings_dispatch(bd, item, c, event, &fs);
2047                     key_bindings_unref_table(table);
2048                     goto out;
2049           }
2050 
2051           /*
2052            * No match, try the ANY key.
2053            */
2054           if (key0 != KEYC_ANY) {
2055                     key0 = KEYC_ANY;
2056                     goto try_again;
2057           }
2058 
2059           /*
2060            * Binding movement keys is useless since we only turn them on when the
2061            * application requests, so don't let them exit the prefix table.
2062            */
2063           if (key == KEYC_MOUSEMOVE_PANE ||
2064               key == KEYC_MOUSEMOVE_STATUS ||
2065               key == KEYC_MOUSEMOVE_STATUS_LEFT ||
2066               key == KEYC_MOUSEMOVE_STATUS_RIGHT ||
2067               key == KEYC_MOUSEMOVE_STATUS_DEFAULT ||
2068               key == KEYC_MOUSEMOVE_BORDER)
2069                     goto forward_key;
2070 
2071           /*
2072            * No match in this table. If not in the root table or if repeating
2073            * switch the client back to the root table and try again.
2074            */
2075           log_debug("not found in key table %s", table->name);
2076           if (!server_client_is_default_key_table(c, table) ||
2077               (c->flags & CLIENT_REPEAT)) {
2078                     log_debug("trying in root table");
2079                     server_client_set_key_table(c, NULL);
2080                     table = c->keytable;
2081                     if (c->flags & CLIENT_REPEAT)
2082                               first = table;
2083                     c->flags &= ~CLIENT_REPEAT;
2084                     server_status_client(c);
2085                     goto table_changed;
2086           }
2087 
2088           /*
2089            * No match in the root table either. If this wasn't the first table
2090            * tried, don't pass the key to the pane.
2091            */
2092           if (first != table && (~flags & CLIENT_REPEAT)) {
2093                     server_client_set_key_table(c, NULL);
2094                     server_status_client(c);
2095                     goto out;
2096           }
2097 
2098 forward_key:
2099           if (c->flags & CLIENT_READONLY)
2100                     goto out;
2101           if (wp != NULL)
2102                     window_pane_key(wp, c, s, wl, key, m);
2103 
2104 out:
2105           if (s != NULL && key != KEYC_FOCUS_OUT)
2106                     server_client_update_latest(c);
2107           free(event);
2108           return (CMD_RETURN_NORMAL);
2109 }
2110 
2111 /* Handle a key event. */
2112 int
server_client_handle_key(struct client * c,struct key_event * event)2113 server_client_handle_key(struct client *c, struct key_event *event)
2114 {
2115           struct session                *s = c->session;
2116           struct cmdq_item    *item;
2117 
2118           /* Check the client is good to accept input. */
2119           if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS))
2120                     return (0);
2121 
2122           /*
2123            * Key presses in overlay mode and the command prompt are a special
2124            * case. The queue might be blocked so they need to be processed
2125            * immediately rather than queued.
2126            */
2127           if (~c->flags & CLIENT_READONLY) {
2128                     if (c->message_string != NULL) {
2129                               if (c->message_ignore_keys)
2130                                         return (0);
2131                               status_message_clear(c);
2132                     }
2133                     if (c->overlay_key != NULL) {
2134                               switch (c->overlay_key(c, c->overlay_data, event)) {
2135                               case 0:
2136                                         return (0);
2137                               case 1:
2138                                         server_client_clear_overlay(c);
2139                                         return (0);
2140                               }
2141                     }
2142                     server_client_clear_overlay(c);
2143                     if (c->prompt_string != NULL) {
2144                               if (status_prompt_key(c, event->key) == 0)
2145                                         return (0);
2146                     }
2147           }
2148 
2149           /*
2150            * Add the key to the queue so it happens after any commands queued by
2151            * previous keys.
2152            */
2153           item = cmdq_get_callback(server_client_key_callback, event);
2154           cmdq_append(c, item);
2155           return (1);
2156 }
2157 
2158 /* Client functions that need to happen every loop. */
2159 void
server_client_loop(void)2160 server_client_loop(void)
2161 {
2162           struct client                 *c;
2163           struct window                 *w;
2164           struct window_pane  *wp;
2165 
2166           /* Check for window resize. This is done before redrawing. */
2167           RB_FOREACH(w, windows, &windows)
2168                     server_client_check_window_resize(w);
2169 
2170           /* Check clients. */
2171           TAILQ_FOREACH(c, &clients, entry) {
2172                     server_client_check_exit(c);
2173                     if (c->session != NULL) {
2174                               server_client_check_modes(c);
2175                               server_client_check_redraw(c);
2176                               server_client_reset_state(c);
2177                     }
2178           }
2179 
2180           /*
2181            * Any windows will have been redrawn as part of clients, so clear
2182            * their flags now.
2183            */
2184           RB_FOREACH(w, windows, &windows) {
2185                     TAILQ_FOREACH(wp, &w->panes, entry) {
2186                               if (wp->fd != -1) {
2187                                         server_client_check_pane_resize(wp);
2188                                         server_client_check_pane_buffer(wp);
2189                               }
2190                               wp->flags &= ~PANE_REDRAW;
2191                     }
2192                     check_window_name(w);
2193           }
2194 }
2195 
2196 /* Check if window needs to be resized. */
2197 static void
server_client_check_window_resize(struct window * w)2198 server_client_check_window_resize(struct window *w)
2199 {
2200           struct winlink      *wl;
2201 
2202           if (~w->flags & WINDOW_RESIZE)
2203                     return;
2204 
2205           TAILQ_FOREACH(wl, &w->winlinks, wentry) {
2206                     if (wl->session->attached != 0 && wl->session->curw == wl)
2207                               break;
2208           }
2209           if (wl == NULL)
2210                     return;
2211 
2212           log_debug("%s: resizing window @%u", __func__, w->id);
2213           resize_window(w, w->new_sx, w->new_sy, w->new_xpixel, w->new_ypixel);
2214 }
2215 
2216 /* Resize timer event. */
2217 static void
server_client_resize_timer(__unused int fd,__unused short events,void * data)2218 server_client_resize_timer(__unused int fd, __unused short events, void *data)
2219 {
2220           struct window_pane  *wp = data;
2221 
2222           log_debug("%s: %%%u resize timer expired", __func__, wp->id);
2223           evtimer_del(&wp->resize_timer);
2224 }
2225 
2226 /* Check if pane should be resized. */
2227 static void
server_client_check_pane_resize(struct window_pane * wp)2228 server_client_check_pane_resize(struct window_pane *wp)
2229 {
2230           struct window_pane_resize     *r;
2231           struct window_pane_resize     *r1;
2232           struct window_pane_resize     *first;
2233           struct window_pane_resize     *last;
2234           struct timeval                           tv = { .tv_usec = 250000 };
2235 
2236           if (TAILQ_EMPTY(&wp->resize_queue))
2237                     return;
2238 
2239           if (!event_initialized(&wp->resize_timer))
2240                     evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
2241           if (evtimer_pending(&wp->resize_timer, NULL))
2242                     return;
2243 
2244           log_debug("%s: %%%u needs to be resized", __func__, wp->id);
2245           TAILQ_FOREACH(r, &wp->resize_queue, entry) {
2246                     log_debug("queued resize: %ux%u -> %ux%u", r->osx, r->osy,
2247                         r->sx, r->sy);
2248           }
2249 
2250           /*
2251            * There are three cases that matter:
2252            *
2253            * - Only one resize. It can just be applied.
2254            *
2255            * - Multiple resizes and the ending size is different from the
2256            *   starting size. We can discard all resizes except the most recent.
2257            *
2258            * - Multiple resizes and the ending size is the same as the starting
2259            *   size. We must resize at least twice to force the application to
2260            *   redraw. So apply the first and leave the last on the queue for
2261            *   next time.
2262            */
2263           first = TAILQ_FIRST(&wp->resize_queue);
2264           last = TAILQ_LAST(&wp->resize_queue, window_pane_resizes);
2265           if (first == last) {
2266                     /* Only one resize. */
2267                     window_pane_send_resize(wp, first->sx, first->sy);
2268                     TAILQ_REMOVE(&wp->resize_queue, first, entry);
2269                     free(first);
2270           } else if (last->sx != first->osx || last->sy != first->osy) {
2271                     /* Multiple resizes ending up with a different size. */
2272                     window_pane_send_resize(wp, last->sx, last->sy);
2273                     TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
2274                               TAILQ_REMOVE(&wp->resize_queue, r, entry);
2275                               free(r);
2276                     }
2277           } else {
2278                     /*
2279                      * Multiple resizes ending up with the same size. There will
2280                      * not be more than one to the same size in succession so we
2281                      * can just use the last-but-one on the list and leave the last
2282                      * for later. We reduce the time until the next check to avoid
2283                      * a long delay between the resizes.
2284                      */
2285                     r = TAILQ_PREV(last, window_pane_resizes, entry);
2286                     window_pane_send_resize(wp, r->sx, r->sy);
2287                     TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
2288                               if (r == last)
2289                                         break;
2290                               TAILQ_REMOVE(&wp->resize_queue, r, entry);
2291                               free(r);
2292                     }
2293                     tv.tv_usec = 10000;
2294           }
2295           evtimer_add(&wp->resize_timer, &tv);
2296 }
2297 
2298 /* Check pane buffer size. */
2299 static void
server_client_check_pane_buffer(struct window_pane * wp)2300 server_client_check_pane_buffer(struct window_pane *wp)
2301 {
2302           struct evbuffer                         *evb = wp->event->input;
2303           size_t                                   minimum;
2304           struct client                           *c;
2305           struct window_pane_offset     *wpo;
2306           int                                      off = 1, flag;
2307           u_int                                    attached_clients = 0;
2308           size_t                                   new_size;
2309 
2310           /*
2311            * Work out the minimum used size. This is the most that can be removed
2312            * from the buffer.
2313            */
2314           minimum = wp->offset.used;
2315           if (wp->pipe_fd != -1 && wp->pipe_offset.used < minimum)
2316                     minimum = wp->pipe_offset.used;
2317           TAILQ_FOREACH(c, &clients, entry) {
2318                     if (c->session == NULL)
2319                               continue;
2320                     attached_clients++;
2321 
2322                     if (~c->flags & CLIENT_CONTROL) {
2323                               off = 0;
2324                               continue;
2325                     }
2326                     wpo = control_pane_offset(c, wp, &flag);
2327                     if (wpo == NULL) {
2328                               if (!flag)
2329                                         off = 0;
2330                               continue;
2331                     }
2332                     if (!flag)
2333                               off = 0;
2334 
2335                     window_pane_get_new_data(wp, wpo, &new_size);
2336                     log_debug("%s: %s has %zu bytes used and %zu left for %%%u",
2337                         __func__, c->name, wpo->used - wp->base_offset, new_size,
2338                         wp->id);
2339                     if (wpo->used < minimum)
2340                               minimum = wpo->used;
2341           }
2342           if (attached_clients == 0)
2343                     off = 0;
2344           minimum -= wp->base_offset;
2345           if (minimum == 0)
2346                     goto out;
2347 
2348           /* Drain the buffer. */
2349           log_debug("%s: %%%u has %zu minimum (of %zu) bytes used", __func__,
2350               wp->id, minimum, EVBUFFER_LENGTH(evb));
2351           evbuffer_drain(evb, minimum);
2352 
2353           /*
2354            * Adjust the base offset. If it would roll over, all the offsets into
2355            * the buffer need to be adjusted.
2356            */
2357           if (wp->base_offset > SIZE_MAX - minimum) {
2358                     log_debug("%s: %%%u base offset has wrapped", __func__, wp->id);
2359                     wp->offset.used -= wp->base_offset;
2360                     if (wp->pipe_fd != -1)
2361                               wp->pipe_offset.used -= wp->base_offset;
2362                     TAILQ_FOREACH(c, &clients, entry) {
2363                               if (c->session == NULL || (~c->flags & CLIENT_CONTROL))
2364                                         continue;
2365                               wpo = control_pane_offset(c, wp, &flag);
2366                               if (wpo != NULL && !flag)
2367                                         wpo->used -= wp->base_offset;
2368                     }
2369                     wp->base_offset = minimum;
2370           } else
2371                     wp->base_offset += minimum;
2372 
2373 out:
2374           /*
2375            * If there is data remaining, and there are no clients able to consume
2376            * it, do not read any more. This is true when there are attached
2377            * clients, all of which are control clients which are not able to
2378            * accept any more data.
2379            */
2380           log_debug("%s: pane %%%u is %s", __func__, wp->id, off ? "off" : "on");
2381           if (off)
2382                     bufferevent_disable(wp->event, EV_READ);
2383           else
2384                     bufferevent_enable(wp->event, EV_READ);
2385 }
2386 
2387 /*
2388  * Update cursor position and mode settings. The scroll region and attributes
2389  * are cleared when idle (waiting for an event) as this is the most likely time
2390  * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
2391  * compromise between excessive resets and likelihood of an interrupt.
2392  *
2393  * tty_region/tty_reset/tty_update_mode already take care of not resetting
2394  * things that are already in their default state.
2395  */
2396 static void
server_client_reset_state(struct client * c)2397 server_client_reset_state(struct client *c)
2398 {
2399           struct tty                    *tty = &c->tty;
2400           struct window                 *w = c->session->curw->window;
2401           struct window_pane  *wp = server_client_get_pane(c), *loop;
2402           struct screen                 *s = NULL;
2403           struct options                *oo = c->session->options;
2404           int                            mode = 0, cursor, flags, n;
2405           u_int                          cx = 0, cy = 0, ox, oy, sx, sy;
2406 
2407           if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
2408                     return;
2409 
2410           /* Disable the block flag. */
2411           flags = (tty->flags & TTY_BLOCK);
2412           tty->flags &= ~TTY_BLOCK;
2413 
2414           /* Get mode from overlay if any, else from screen. */
2415           if (c->overlay_draw != NULL) {
2416                     if (c->overlay_mode != NULL)
2417                               s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
2418           } else
2419                     s = wp->screen;
2420           if (s != NULL)
2421                     mode = s->mode;
2422           if (log_get_level() != 0) {
2423                     log_debug("%s: client %s mode %s", __func__, c->name,
2424                         screen_mode_to_string(mode));
2425           }
2426 
2427           /* Reset region and margin. */
2428           tty_region_off(tty);
2429           tty_margin_off(tty);
2430 
2431           /* Move cursor to pane cursor and offset. */
2432           if (c->prompt_string != NULL) {
2433                     n = options_get_number(c->session->options, "status-position");
2434                     if (n == 0)
2435                               cy = 0;
2436                     else {
2437                               n = status_line_size(c);
2438                               if (n == 0)
2439                                         cy = tty->sy - 1;
2440                               else
2441                                         cy = tty->sy - n;
2442                     }
2443                     cx = c->prompt_cursor;
2444                     mode &= ~MODE_CURSOR;
2445           } else if (c->overlay_draw == NULL) {
2446                     cursor = 0;
2447                     tty_window_offset(tty, &ox, &oy, &sx, &sy);
2448                     if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
2449                         wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) {
2450                               cursor = 1;
2451 
2452                               cx = wp->xoff + s->cx - ox;
2453                               cy = wp->yoff + s->cy - oy;
2454 
2455                               if (status_at_line(c) == 0)
2456                                         cy += status_line_size(c);
2457                     }
2458                     if (!cursor)
2459                               mode &= ~MODE_CURSOR;
2460           }
2461           log_debug("%s: cursor to %u,%u", __func__, cx, cy);
2462           tty_cursor(tty, cx, cy);
2463 
2464           /*
2465            * Set mouse mode if requested. To support dragging, always use button
2466            * mode.
2467            */
2468           if (options_get_number(oo, "mouse")) {
2469                     if (c->overlay_draw == NULL) {
2470                               mode &= ~ALL_MOUSE_MODES;
2471                               TAILQ_FOREACH(loop, &w->panes, entry) {
2472                                         if (loop->screen->mode & MODE_MOUSE_ALL)
2473                                                   mode |= MODE_MOUSE_ALL;
2474                               }
2475                     }
2476                     if (~mode & MODE_MOUSE_ALL)
2477                               mode |= MODE_MOUSE_BUTTON;
2478           }
2479 
2480           /* Clear bracketed paste mode if at the prompt. */
2481           if (c->overlay_draw == NULL && c->prompt_string != NULL)
2482                     mode &= ~MODE_BRACKETPASTE;
2483 
2484           /* Set the terminal mode and reset attributes. */
2485           tty_update_mode(tty, mode, s);
2486           tty_reset(tty);
2487 
2488           /* All writing must be done, send a sync end (if it was started). */
2489           tty_sync_end(tty);
2490           tty->flags |= flags;
2491 }
2492 
2493 /* Repeat time callback. */
2494 static void
server_client_repeat_timer(__unused int fd,__unused short events,void * data)2495 server_client_repeat_timer(__unused int fd, __unused short events, void *data)
2496 {
2497           struct client       *c = data;
2498 
2499           if (c->flags & CLIENT_REPEAT) {
2500                     server_client_set_key_table(c, NULL);
2501                     c->flags &= ~CLIENT_REPEAT;
2502                     server_status_client(c);
2503           }
2504 }
2505 
2506 /* Double-click callback. */
2507 static void
server_client_click_timer(__unused int fd,__unused short events,void * data)2508 server_client_click_timer(__unused int fd, __unused short events, void *data)
2509 {
2510           struct client                 *c = data;
2511           struct key_event    *event;
2512 
2513           log_debug("click timer expired");
2514 
2515           if (c->flags & CLIENT_TRIPLECLICK) {
2516                     /*
2517                      * Waiting for a third click that hasn't happened, so this must
2518                      * have been a double click.
2519                      */
2520                     event = xmalloc(sizeof *event);
2521                     event->key = KEYC_DOUBLECLICK;
2522                     memcpy(&event->m, &c->click_event, sizeof event->m);
2523                     if (!server_client_handle_key(c, event))
2524                               free(event);
2525           }
2526           c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK);
2527 }
2528 
2529 /* Check if client should be exited. */
2530 static void
server_client_check_exit(struct client * c)2531 server_client_check_exit(struct client *c)
2532 {
2533           struct client_file  *cf;
2534           const char                    *name = c->exit_session;
2535           char                          *data;
2536           size_t                         size, msize;
2537 
2538           if (c->flags & (CLIENT_DEAD|CLIENT_EXITED))
2539                     return;
2540           if (~c->flags & CLIENT_EXIT)
2541                     return;
2542 
2543           if (c->flags & CLIENT_CONTROL) {
2544                     control_discard(c);
2545                     if (!control_all_done(c))
2546                               return;
2547           }
2548           RB_FOREACH(cf, client_files, &c->files) {
2549                     if (EVBUFFER_LENGTH(cf->buffer) != 0)
2550                               return;
2551           }
2552           c->flags |= CLIENT_EXITED;
2553 
2554           switch (c->exit_type) {
2555           case CLIENT_EXIT_RETURN:
2556                     if (c->exit_message != NULL)
2557                               msize = strlen(c->exit_message) + 1;
2558                     else
2559                               msize = 0;
2560                     size = (sizeof c->retval) + msize;
2561                     data = xmalloc(size);
2562                     memcpy(data, &c->retval, sizeof c->retval);
2563                     if (c->exit_message != NULL)
2564                               memcpy(data + sizeof c->retval, c->exit_message, msize);
2565                     proc_send(c->peer, MSG_EXIT, -1, data, size);
2566                     free(data);
2567                     break;
2568           case CLIENT_EXIT_SHUTDOWN:
2569                     proc_send(c->peer, MSG_SHUTDOWN, -1, NULL, 0);
2570                     break;
2571           case CLIENT_EXIT_DETACH:
2572                     proc_send(c->peer, c->exit_msgtype, -1, name, strlen(name) + 1);
2573                     break;
2574           }
2575           free(c->exit_session);
2576           free(c->exit_message);
2577 }
2578 
2579 /* Redraw timer callback. */
2580 static void
server_client_redraw_timer(__unused int fd,__unused short events,__unused void * data)2581 server_client_redraw_timer(__unused int fd, __unused short events,
2582     __unused void *data)
2583 {
2584           log_debug("redraw timer fired");
2585 }
2586 
2587 /*
2588  * Check if modes need to be updated. Only modes in the current window are
2589  * updated and it is done when the status line is redrawn.
2590  */
2591 static void
server_client_check_modes(struct client * c)2592 server_client_check_modes(struct client *c)
2593 {
2594           struct window                           *w = c->session->curw->window;
2595           struct window_pane            *wp;
2596           struct window_mode_entry      *wme;
2597 
2598           if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
2599                     return;
2600           if (~c->flags & CLIENT_REDRAWSTATUS)
2601                     return;
2602           TAILQ_FOREACH(wp, &w->panes, entry) {
2603                     wme = TAILQ_FIRST(&wp->modes);
2604                     if (wme != NULL && wme->mode->update != NULL)
2605                               wme->mode->update(wme);
2606           }
2607 }
2608 
2609 /* Check for client redraws. */
2610 static void
server_client_check_redraw(struct client * c)2611 server_client_check_redraw(struct client *c)
2612 {
2613           struct session                *s = c->session;
2614           struct tty                    *tty = &c->tty;
2615           struct window                 *w = c->session->curw->window;
2616           struct window_pane  *wp;
2617           int                            needed, tty_flags, mode = tty->mode;
2618           uint64_t             client_flags = 0;
2619           int                            redraw;
2620           u_int                          bit = 0;
2621           struct timeval                 tv = { .tv_usec = 1000 };
2622           static struct event  ev;
2623           size_t                         left;
2624 
2625           if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
2626                     return;
2627           if (c->flags & CLIENT_ALLREDRAWFLAGS) {
2628                     log_debug("%s: redraw%s%s%s%s%s", c->name,
2629                         (c->flags & CLIENT_REDRAWWINDOW) ? " window" : "",
2630                         (c->flags & CLIENT_REDRAWSTATUS) ? " status" : "",
2631                         (c->flags & CLIENT_REDRAWBORDERS) ? " borders" : "",
2632                         (c->flags & CLIENT_REDRAWOVERLAY) ? " overlay" : "",
2633                         (c->flags & CLIENT_REDRAWPANES) ? " panes" : "");
2634           }
2635 
2636           /*
2637            * If there is outstanding data, defer the redraw until it has been
2638            * consumed. We can just add a timer to get out of the event loop and
2639            * end up back here.
2640            */
2641           needed = 0;
2642           if (c->flags & CLIENT_ALLREDRAWFLAGS)
2643                     needed = 1;
2644           else {
2645                     TAILQ_FOREACH(wp, &w->panes, entry) {
2646                               if (wp->flags & PANE_REDRAW) {
2647                                         needed = 1;
2648                                         break;
2649                               }
2650                     }
2651                     if (needed)
2652                               client_flags |= CLIENT_REDRAWPANES;
2653           }
2654           if (needed && (left = EVBUFFER_LENGTH(tty->out)) != 0) {
2655                     log_debug("%s: redraw deferred (%zu left)", c->name, left);
2656                     if (!evtimer_initialized(&ev))
2657                               evtimer_set(&ev, server_client_redraw_timer, NULL);
2658                     if (!evtimer_pending(&ev, NULL)) {
2659                               log_debug("redraw timer started");
2660                               evtimer_add(&ev, &tv);
2661                     }
2662 
2663                     if (~c->flags & CLIENT_REDRAWWINDOW) {
2664                               TAILQ_FOREACH(wp, &w->panes, entry) {
2665                                         if (wp->flags & PANE_REDRAW) {
2666                                                   log_debug("%s: pane %%%u needs redraw",
2667                                                       c->name, wp->id);
2668                                                   c->redraw_panes |= (1 << bit);
2669                                         }
2670                                         if (++bit == 64) {
2671                                                   /*
2672                                                    * If more that 64 panes, give up and
2673                                                    * just redraw the window.
2674                                                    */
2675                                                   client_flags &= CLIENT_REDRAWPANES;
2676                                                   client_flags |= CLIENT_REDRAWWINDOW;
2677                                                   break;
2678                                         }
2679                               }
2680                               if (c->redraw_panes != 0)
2681                                         c->flags |= CLIENT_REDRAWPANES;
2682                     }
2683                     c->flags |= client_flags;
2684                     return;
2685           } else if (needed)
2686                     log_debug("%s: redraw needed", c->name);
2687 
2688           tty_flags = tty->flags & (TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR);
2689           tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE))|TTY_NOCURSOR;
2690 
2691           if (~c->flags & CLIENT_REDRAWWINDOW) {
2692                     /*
2693                      * If not redrawing the entire window, check whether each pane
2694                      * needs to be redrawn.
2695                      */
2696                     TAILQ_FOREACH(wp, &w->panes, entry) {
2697                               redraw = 0;
2698                               if (wp->flags & PANE_REDRAW)
2699                                         redraw = 1;
2700                               else if (c->flags & CLIENT_REDRAWPANES)
2701                                         redraw = !!(c->redraw_panes & (1 << bit));
2702                               bit++;
2703                               if (!redraw)
2704                                         continue;
2705                               log_debug("%s: redrawing pane %%%u", __func__, wp->id);
2706                               screen_redraw_pane(c, wp);
2707                     }
2708                     c->redraw_panes = 0;
2709                     c->flags &= ~CLIENT_REDRAWPANES;
2710           }
2711 
2712           if (c->flags & CLIENT_ALLREDRAWFLAGS) {
2713                     if (options_get_number(s->options, "set-titles")) {
2714                               server_client_set_title(c);
2715                               server_client_set_path(c);
2716                     }
2717                     screen_redraw_screen(c);
2718           }
2719 
2720           tty->flags = (tty->flags & ~TTY_NOCURSOR)|(tty_flags & TTY_NOCURSOR);
2721           tty_update_mode(tty, mode, NULL);
2722           tty->flags = (tty->flags & ~(TTY_BLOCK|TTY_FREEZE|TTY_NOCURSOR))|
2723               tty_flags;
2724 
2725           c->flags &= ~(CLIENT_ALLREDRAWFLAGS|CLIENT_STATUSFORCE);
2726 
2727           if (needed) {
2728                     /*
2729                      * We would have deferred the redraw unless the output buffer
2730                      * was empty, so we can record how many bytes the redraw
2731                      * generated.
2732                      */
2733                     c->redraw = EVBUFFER_LENGTH(tty->out);
2734                     log_debug("%s: redraw added %zu bytes", c->name, c->redraw);
2735           }
2736 }
2737 
2738 /* Set client title. */
2739 static void
server_client_set_title(struct client * c)2740 server_client_set_title(struct client *c)
2741 {
2742           struct session                *s = c->session;
2743           const char                    *template;
2744           char                          *title;
2745           struct format_tree  *ft;
2746 
2747           template = options_get_string(s->options, "set-titles-string");
2748 
2749           ft = format_create(c, NULL, FORMAT_NONE, 0);
2750           format_defaults(ft, c, NULL, NULL, NULL);
2751 
2752           title = format_expand_time(ft, template);
2753           if (c->title == NULL || strcmp(title, c->title) != 0) {
2754                     free(c->title);
2755                     c->title = xstrdup(title);
2756                     tty_set_title(&c->tty, c->title);
2757           }
2758           free(title);
2759 
2760           format_free(ft);
2761 }
2762 
2763 /* Set client path. */
2764 static void
server_client_set_path(struct client * c)2765 server_client_set_path(struct client *c)
2766 {
2767           struct session      *s = c->session;
2768           const char          *path;
2769 
2770           if (s->curw == NULL)
2771                     return;
2772           if (s->curw->window->active->base.path == NULL)
2773                     path = "";
2774           else
2775                     path = s->curw->window->active->base.path;
2776           if (c->path == NULL || strcmp(path, c->path) != 0) {
2777                     free(c->path);
2778                     c->path = xstrdup(path);
2779                     tty_set_path(&c->tty, c->path);
2780           }
2781 }
2782 
2783 /* Dispatch message from client. */
2784 static void
server_client_dispatch(struct imsg * imsg,void * arg)2785 server_client_dispatch(struct imsg *imsg, void *arg)
2786 {
2787           struct client       *c = arg;
2788           ssize_t              datalen;
2789           struct session      *s;
2790 
2791           if (c->flags & CLIENT_DEAD)
2792                     return;
2793 
2794           if (imsg == NULL) {
2795                     server_client_lost(c);
2796                     return;
2797           }
2798 
2799           datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
2800 
2801           switch (imsg->hdr.type) {
2802           case MSG_IDENTIFY_CLIENTPID:
2803           case MSG_IDENTIFY_CWD:
2804           case MSG_IDENTIFY_ENVIRON:
2805           case MSG_IDENTIFY_FEATURES:
2806           case MSG_IDENTIFY_FLAGS:
2807           case MSG_IDENTIFY_LONGFLAGS:
2808           case MSG_IDENTIFY_STDIN:
2809           case MSG_IDENTIFY_STDOUT:
2810           case MSG_IDENTIFY_TERM:
2811           case MSG_IDENTIFY_TERMINFO:
2812           case MSG_IDENTIFY_TTYNAME:
2813           case MSG_IDENTIFY_DONE:
2814                     server_client_dispatch_identify(c, imsg);
2815                     break;
2816           case MSG_COMMAND:
2817                     server_client_dispatch_command(c, imsg);
2818                     break;
2819           case MSG_RESIZE:
2820                     if (datalen != 0)
2821                               fatalx("bad MSG_RESIZE size");
2822 
2823                     if (c->flags & CLIENT_CONTROL)
2824                               break;
2825                     server_client_update_latest(c);
2826                     tty_resize(&c->tty);
2827                     tty_repeat_requests(&c->tty);
2828                     recalculate_sizes();
2829                     if (c->overlay_resize == NULL)
2830                               server_client_clear_overlay(c);
2831                     else
2832                               c->overlay_resize(c, c->overlay_data);
2833                     server_redraw_client(c);
2834                     if (c->session != NULL)
2835                               notify_client("client-resized", c);
2836                     break;
2837           case MSG_EXITING:
2838                     if (datalen != 0)
2839                               fatalx("bad MSG_EXITING size");
2840                     server_client_set_session(c, NULL);
2841                     recalculate_sizes();
2842                     tty_close(&c->tty);
2843                     proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
2844                     break;
2845           case MSG_WAKEUP:
2846           case MSG_UNLOCK:
2847                     if (datalen != 0)
2848                               fatalx("bad MSG_WAKEUP size");
2849 
2850                     if (!(c->flags & CLIENT_SUSPENDED))
2851                               break;
2852                     c->flags &= ~CLIENT_SUSPENDED;
2853 
2854                     if (c->fd == -1 || c->session == NULL) /* exited already */
2855                               break;
2856                     s = c->session;
2857 
2858                     if (gettimeofday(&c->activity_time, NULL) != 0)
2859                               fatal("gettimeofday failed");
2860 
2861                     tty_start_tty(&c->tty);
2862                     server_redraw_client(c);
2863                     recalculate_sizes();
2864 
2865                     if (s != NULL)
2866                               session_update_activity(s, &c->activity_time);
2867                     break;
2868           case MSG_SHELL:
2869                     if (datalen != 0)
2870                               fatalx("bad MSG_SHELL size");
2871 
2872                     server_client_dispatch_shell(c);
2873                     break;
2874           case MSG_WRITE_READY:
2875                     file_write_ready(&c->files, imsg);
2876                     break;
2877           case MSG_READ:
2878                     file_read_data(&c->files, imsg);
2879                     break;
2880           case MSG_READ_DONE:
2881                     file_read_done(&c->files, imsg);
2882                     break;
2883           }
2884 }
2885 
2886 /* Callback when command is not allowed. */
2887 static enum cmd_retval
server_client_read_only(struct cmdq_item * item,__unused void * data)2888 server_client_read_only(struct cmdq_item *item, __unused void *data)
2889 {
2890           cmdq_error(item, "client is read-only");
2891           return (CMD_RETURN_ERROR);
2892 }
2893 
2894 /* Callback when command is done. */
2895 static enum cmd_retval
server_client_command_done(struct cmdq_item * item,__unused void * data)2896 server_client_command_done(struct cmdq_item *item, __unused void *data)
2897 {
2898           struct client       *c = cmdq_get_client(item);
2899 
2900           if (~c->flags & CLIENT_ATTACHED)
2901                     c->flags |= CLIENT_EXIT;
2902           else if (~c->flags & CLIENT_EXIT) {
2903                     if (c->flags & CLIENT_CONTROL)
2904                               control_ready(c);
2905                     tty_send_requests(&c->tty);
2906           }
2907           return (CMD_RETURN_NORMAL);
2908 }
2909 
2910 /* Handle command message. */
2911 static void
server_client_dispatch_command(struct client * c,struct imsg * imsg)2912 server_client_dispatch_command(struct client *c, struct imsg *imsg)
2913 {
2914           struct msg_command    data;
2915           char                           *buf;
2916           size_t                          len;
2917           int                             argc;
2918           char                          **argv, *cause;
2919           struct cmd_parse_result        *pr;
2920           struct args_value    *values;
2921           struct cmdq_item     *new_item;
2922 
2923           if (c->flags & CLIENT_EXIT)
2924                     return;
2925 
2926           if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data)
2927                     fatalx("bad MSG_COMMAND size");
2928           memcpy(&data, imsg->data, sizeof data);
2929 
2930           buf = (char *)imsg->data + sizeof data;
2931           len = imsg->hdr.len  - IMSG_HEADER_SIZE - sizeof data;
2932           if (len > 0 && buf[len - 1] != '\0')
2933                     fatalx("bad MSG_COMMAND string");
2934 
2935           argc = data.argc;
2936           if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
2937                     cause = xstrdup("command too long");
2938                     goto error;
2939           }
2940 
2941           if (argc == 0) {
2942                     argc = 1;
2943                     argv = xcalloc(1, sizeof *argv);
2944                     *argv = xstrdup("new-session");
2945           }
2946 
2947           values = args_from_vector(argc, argv);
2948           pr = cmd_parse_from_arguments(values, argc, NULL);
2949           switch (pr->status) {
2950           case CMD_PARSE_ERROR:
2951                     cause = pr->error;
2952                     goto error;
2953           case CMD_PARSE_SUCCESS:
2954                     break;
2955           }
2956           args_free_values(values, argc);
2957           free(values);
2958           cmd_free_argv(argc, argv);
2959 
2960           if ((c->flags & CLIENT_READONLY) &&
2961               !cmd_list_all_have(pr->cmdlist, CMD_READONLY))
2962                     new_item = cmdq_get_callback(server_client_read_only, NULL);
2963           else
2964                     new_item = cmdq_get_command(pr->cmdlist, NULL);
2965           cmdq_append(c, new_item);
2966           cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
2967 
2968           cmd_list_free(pr->cmdlist);
2969           return;
2970 
2971 error:
2972           cmd_free_argv(argc, argv);
2973 
2974           cmdq_append(c, cmdq_get_error(cause));
2975           free(cause);
2976 
2977           c->flags |= CLIENT_EXIT;
2978 }
2979 
2980 /* Handle identify message. */
2981 static void
server_client_dispatch_identify(struct client * c,struct imsg * imsg)2982 server_client_dispatch_identify(struct client *c, struct imsg *imsg)
2983 {
2984           const char          *data, *home;
2985           size_t               datalen;
2986           int                  flags, feat;
2987           uint64_t   longflags;
2988           char                *name;
2989 
2990           if (c->flags & CLIENT_IDENTIFIED)
2991                     fatalx("out-of-order identify message");
2992 
2993           data = imsg->data;
2994           datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
2995 
2996           switch (imsg->hdr.type)       {
2997           case MSG_IDENTIFY_FEATURES:
2998                     if (datalen != sizeof feat)
2999                               fatalx("bad MSG_IDENTIFY_FEATURES size");
3000                     memcpy(&feat, data, sizeof feat);
3001                     c->term_features |= feat;
3002                     log_debug("client %p IDENTIFY_FEATURES %s", c,
3003                         tty_get_features(feat));
3004                     break;
3005           case MSG_IDENTIFY_FLAGS:
3006                     if (datalen != sizeof flags)
3007                               fatalx("bad MSG_IDENTIFY_FLAGS size");
3008                     memcpy(&flags, data, sizeof flags);
3009                     c->flags |= flags;
3010                     log_debug("client %p IDENTIFY_FLAGS %#x", c, flags);
3011                     break;
3012           case MSG_IDENTIFY_LONGFLAGS:
3013                     if (datalen != sizeof longflags)
3014                               fatalx("bad MSG_IDENTIFY_LONGFLAGS size");
3015                     memcpy(&longflags, data, sizeof longflags);
3016                     c->flags |= longflags;
3017                     log_debug("client %p IDENTIFY_LONGFLAGS %#llx", c,
3018                         (unsigned long long)longflags);
3019                     break;
3020           case MSG_IDENTIFY_TERM:
3021                     if (datalen == 0 || data[datalen - 1] != '\0')
3022                               fatalx("bad MSG_IDENTIFY_TERM string");
3023                     if (*data == '\0')
3024                               c->term_name = xstrdup("unknown");
3025                     else
3026                               c->term_name = xstrdup(data);
3027                     log_debug("client %p IDENTIFY_TERM %s", c, data);
3028                     break;
3029           case MSG_IDENTIFY_TERMINFO:
3030                     if (datalen == 0 || data[datalen - 1] != '\0')
3031                               fatalx("bad MSG_IDENTIFY_TERMINFO string");
3032                     c->term_caps = xreallocarray(c->term_caps, c->term_ncaps + 1,
3033                         sizeof *c->term_caps);
3034                     c->term_caps[c->term_ncaps++] = xstrdup(data);
3035                     log_debug("client %p IDENTIFY_TERMINFO %s", c, data);
3036                     break;
3037           case MSG_IDENTIFY_TTYNAME:
3038                     if (datalen == 0 || data[datalen - 1] != '\0')
3039                               fatalx("bad MSG_IDENTIFY_TTYNAME string");
3040                     c->ttyname = xstrdup(data);
3041                     log_debug("client %p IDENTIFY_TTYNAME %s", c, data);
3042                     break;
3043           case MSG_IDENTIFY_CWD:
3044                     if (datalen == 0 || data[datalen - 1] != '\0')
3045                               fatalx("bad MSG_IDENTIFY_CWD string");
3046                     if (access(data, X_OK) == 0)
3047                               c->cwd = xstrdup(data);
3048                     else if ((home = find_home()) != NULL)
3049                               c->cwd = xstrdup(home);
3050                     else
3051                               c->cwd = xstrdup("/");
3052                     log_debug("client %p IDENTIFY_CWD %s", c, data);
3053                     break;
3054           case MSG_IDENTIFY_STDIN:
3055                     if (datalen != 0)
3056                               fatalx("bad MSG_IDENTIFY_STDIN size");
3057                     c->fd = imsg_get_fd(imsg);
3058                     log_debug("client %p IDENTIFY_STDIN %d", c, c->fd);
3059                     break;
3060           case MSG_IDENTIFY_STDOUT:
3061                     if (datalen != 0)
3062                               fatalx("bad MSG_IDENTIFY_STDOUT size");
3063                     c->out_fd = imsg_get_fd(imsg);
3064                     log_debug("client %p IDENTIFY_STDOUT %d", c, c->out_fd);
3065                     break;
3066           case MSG_IDENTIFY_ENVIRON:
3067                     if (datalen == 0 || data[datalen - 1] != '\0')
3068                               fatalx("bad MSG_IDENTIFY_ENVIRON string");
3069                     if (strchr(data, '=') != NULL)
3070                               environ_put(c->environ, data, 0);
3071                     log_debug("client %p IDENTIFY_ENVIRON %s", c, data);
3072                     break;
3073           case MSG_IDENTIFY_CLIENTPID:
3074                     if (datalen != sizeof c->pid)
3075                               fatalx("bad MSG_IDENTIFY_CLIENTPID size");
3076                     memcpy(&c->pid, data, sizeof c->pid);
3077                     log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid);
3078                     break;
3079           default:
3080                     break;
3081           }
3082 
3083           if (imsg->hdr.type != MSG_IDENTIFY_DONE)
3084                     return;
3085           c->flags |= CLIENT_IDENTIFIED;
3086 
3087           if (*c->ttyname != '\0')
3088                     name = xstrdup(c->ttyname);
3089           else
3090                     xasprintf(&name, "client-%ld", (long)c->pid);
3091           c->name = name;
3092           log_debug("client %p name is %s", c, c->name);
3093 
3094 #ifdef __CYGWIN__
3095           c->fd = open(c->ttyname, O_RDWR|O_NOCTTY);
3096 #endif
3097 
3098           if (c->flags & CLIENT_CONTROL)
3099                     control_start(c);
3100           else if (c->fd != -1) {
3101                     if (tty_init(&c->tty, c) != 0) {
3102                               close(c->fd);
3103                               c->fd = -1;
3104                     } else {
3105                               tty_resize(&c->tty);
3106                               c->flags |= CLIENT_TERMINAL;
3107                     }
3108                     close(c->out_fd);
3109                     c->out_fd = -1;
3110           }
3111 
3112           /*
3113            * If this is the first client, load configuration files. Any later
3114            * clients are allowed to continue with their command even if the
3115            * config has not been loaded - they might have been run from inside it
3116            */
3117           if ((~c->flags & CLIENT_EXIT) &&
3118                !cfg_finished &&
3119                c == TAILQ_FIRST(&clients))
3120                     start_cfg();
3121 }
3122 
3123 /* Handle shell message. */
3124 static void
server_client_dispatch_shell(struct client * c)3125 server_client_dispatch_shell(struct client *c)
3126 {
3127           const char          *shell;
3128 
3129           shell = options_get_string(global_s_options, "default-shell");
3130           if (!checkshell(shell))
3131                     shell = _PATH_BSHELL;
3132           proc_send(c->peer, MSG_SHELL, -1, shell, strlen(shell) + 1);
3133 
3134           proc_kill_peer(c->peer);
3135 }
3136 
3137 /* Get client working directory. */
3138 const char *
server_client_get_cwd(struct client * c,struct session * s)3139 server_client_get_cwd(struct client *c, struct session *s)
3140 {
3141           const char          *home;
3142 
3143           if (!cfg_finished && cfg_client != NULL)
3144                     return (cfg_client->cwd);
3145           if (c != NULL && c->session == NULL && c->cwd != NULL)
3146                     return (c->cwd);
3147           if (s != NULL && s->cwd != NULL)
3148                     return (s->cwd);
3149           if (c != NULL && (s = c->session) != NULL && s->cwd != NULL)
3150                     return (s->cwd);
3151           if ((home = find_home()) != NULL)
3152                     return (home);
3153           return ("/");
3154 }
3155 
3156 /* Get control client flags. */
3157 static uint64_t
server_client_control_flags(struct client * c,const char * next)3158 server_client_control_flags(struct client *c, const char *next)
3159 {
3160           if (strcmp(next, "pause-after") == 0) {
3161                     c->pause_age = 0;
3162                     return (CLIENT_CONTROL_PAUSEAFTER);
3163           }
3164           if (sscanf(next, "pause-after=%u", &c->pause_age) == 1) {
3165                     c->pause_age *= 1000;
3166                     return (CLIENT_CONTROL_PAUSEAFTER);
3167           }
3168           if (strcmp(next, "no-output") == 0)
3169                     return (CLIENT_CONTROL_NOOUTPUT);
3170           if (strcmp(next, "wait-exit") == 0)
3171                     return (CLIENT_CONTROL_WAITEXIT);
3172           return (0);
3173 }
3174 
3175 /* Set client flags. */
3176 void
server_client_set_flags(struct client * c,const char * flags)3177 server_client_set_flags(struct client *c, const char *flags)
3178 {
3179           char      *s, *copy, *next;
3180           uint64_t flag;
3181           int        not;
3182 
3183           s = copy = xstrdup(flags);
3184           while ((next = strsep(&s, ",")) != NULL) {
3185                     not = (*next == '!');
3186                     if (not)
3187                               next++;
3188 
3189                     if (c->flags & CLIENT_CONTROL)
3190                               flag = server_client_control_flags(c, next);
3191                     else
3192                               flag = 0;
3193                     if (strcmp(next, "read-only") == 0)
3194                               flag = CLIENT_READONLY;
3195                     else if (strcmp(next, "ignore-size") == 0)
3196                               flag = CLIENT_IGNORESIZE;
3197                     else if (strcmp(next, "active-pane") == 0)
3198                               flag = CLIENT_ACTIVEPANE;
3199                     if (flag == 0)
3200                               continue;
3201 
3202                     log_debug("client %s set flag %s", c->name, next);
3203                     if (not) {
3204                               if (c->flags & CLIENT_READONLY)
3205                                         flag &= ~CLIENT_READONLY;
3206                               c->flags &= ~flag;
3207                     } else
3208                               c->flags |= flag;
3209                     if (flag == CLIENT_CONTROL_NOOUTPUT)
3210                               control_reset_offsets(c);
3211           }
3212           free(copy);
3213           proc_send(c->peer, MSG_FLAGS, -1, &c->flags, sizeof c->flags);
3214 }
3215 
3216 /* Get client flags. This is only flags useful to show to users. */
3217 const char *
server_client_get_flags(struct client * c)3218 server_client_get_flags(struct client *c)
3219 {
3220           static char         s[256];
3221           char                tmp[32];
3222 
3223           *s = '\0';
3224           if (c->flags & CLIENT_ATTACHED)
3225                     strlcat(s, "attached,", sizeof s);
3226           if (c->flags & CLIENT_FOCUSED)
3227                     strlcat(s, "focused,", sizeof s);
3228           if (c->flags & CLIENT_CONTROL)
3229                     strlcat(s, "control-mode,", sizeof s);
3230           if (c->flags & CLIENT_IGNORESIZE)
3231                     strlcat(s, "ignore-size,", sizeof s);
3232           if (c->flags & CLIENT_CONTROL_NOOUTPUT)
3233                     strlcat(s, "no-output,", sizeof s);
3234           if (c->flags & CLIENT_CONTROL_WAITEXIT)
3235                     strlcat(s, "wait-exit,", sizeof s);
3236           if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
3237                     xsnprintf(tmp, sizeof tmp, "pause-after=%u,",
3238                         c->pause_age / 1000);
3239                     strlcat(s, tmp, sizeof s);
3240           }
3241           if (c->flags & CLIENT_READONLY)
3242                     strlcat(s, "read-only,", sizeof s);
3243           if (c->flags & CLIENT_ACTIVEPANE)
3244                     strlcat(s, "active-pane,", sizeof s);
3245           if (c->flags & CLIENT_SUSPENDED)
3246                     strlcat(s, "suspended,", sizeof s);
3247           if (c->flags & CLIENT_UTF8)
3248                     strlcat(s, "UTF-8,", sizeof s);
3249           if (*s != '\0')
3250                     s[strlen(s) - 1] = '\0';
3251           return (s);
3252 }
3253 
3254 /* Get client window. */
3255 struct client_window *
server_client_get_client_window(struct client * c,u_int id)3256 server_client_get_client_window(struct client *c, u_int id)
3257 {
3258           struct client_window          cw = { .window = id };
3259 
3260           return (RB_FIND(client_windows, &c->windows, &cw));
3261 }
3262 
3263 /* Add client window. */
3264 struct client_window *
server_client_add_client_window(struct client * c,u_int id)3265 server_client_add_client_window(struct client *c, u_int id)
3266 {
3267           struct client_window          *cw;
3268 
3269           cw = server_client_get_client_window(c, id);
3270           if (cw == NULL) {
3271                     cw = xcalloc(1, sizeof *cw);
3272                     cw->window = id;
3273                     RB_INSERT(client_windows, &c->windows, cw);
3274           }
3275           return (cw);
3276 }
3277 
3278 /* Get client active pane. */
3279 struct window_pane *
server_client_get_pane(struct client * c)3280 server_client_get_pane(struct client *c)
3281 {
3282           struct session                *s = c->session;
3283           struct client_window          *cw;
3284 
3285           if (s == NULL)
3286                     return (NULL);
3287 
3288           if (~c->flags & CLIENT_ACTIVEPANE)
3289                     return (s->curw->window->active);
3290           cw = server_client_get_client_window(c, s->curw->window->id);
3291           if (cw == NULL)
3292                     return (s->curw->window->active);
3293           return (cw->pane);
3294 }
3295 
3296 /* Set client active pane. */
3297 void
server_client_set_pane(struct client * c,struct window_pane * wp)3298 server_client_set_pane(struct client *c, struct window_pane *wp)
3299 {
3300           struct session                *s = c->session;
3301           struct client_window          *cw;
3302 
3303           if (s == NULL)
3304                     return;
3305 
3306           cw = server_client_add_client_window(c, s->curw->window->id);
3307           cw->pane = wp;
3308           log_debug("%s pane now %%%u", c->name, wp->id);
3309 }
3310 
3311 /* Remove pane from client lists. */
3312 void
server_client_remove_pane(struct window_pane * wp)3313 server_client_remove_pane(struct window_pane *wp)
3314 {
3315           struct client                 *c;
3316           struct window                 *w = wp->window;
3317           struct client_window          *cw;
3318 
3319           TAILQ_FOREACH(c, &clients, entry) {
3320                     cw = server_client_get_client_window(c, w->id);
3321                     if (cw != NULL && cw->pane == wp) {
3322                               RB_REMOVE(client_windows, &c->windows, cw);
3323                               free(cw);
3324                     }
3325           }
3326 }
3327 
3328 /* Print to a client. */
3329 void
server_client_print(struct client * c,int parse,struct evbuffer * evb)3330 server_client_print(struct client *c, int parse, struct evbuffer *evb)
3331 {
3332           void                                    *data = EVBUFFER_DATA(evb);
3333           size_t                                   size = EVBUFFER_LENGTH(evb);
3334           struct window_pane            *wp;
3335           struct window_mode_entry      *wme;
3336           char                                    *sanitized, *msg, *line;
3337 
3338           if (!parse) {
3339                     utf8_stravisx(&msg, data, size,
3340                         VIS_OCTAL|VIS_CSTYLE|VIS_NOSLASH);
3341                     log_debug("%s: %s", __func__, msg);
3342           } else {
3343                     msg = (char *)EVBUFFER_DATA(evb);
3344                     if (msg[size - 1] != '\0')
3345                               evbuffer_add(evb, "", 1);
3346           }
3347 
3348           if (c == NULL)
3349                     goto out;
3350 
3351           if (c->session == NULL || (c->flags & CLIENT_CONTROL)) {
3352                     if (~c->flags & CLIENT_UTF8) {
3353                               sanitized = utf8_sanitize(msg);
3354                               if (c->flags & CLIENT_CONTROL)
3355                                         control_write(c, "%s", sanitized);
3356                               else
3357                                         file_print(c, "%s\n", sanitized);
3358                               free(sanitized);
3359                     } else {
3360                               if (c->flags & CLIENT_CONTROL)
3361                                         control_write(c, "%s", msg);
3362                               else
3363                                         file_print(c, "%s\n", msg);
3364                     }
3365                     goto out;
3366           }
3367 
3368           wp = server_client_get_pane(c);
3369           wme = TAILQ_FIRST(&wp->modes);
3370           if (wme == NULL || wme->mode != &window_view_mode)
3371                     window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL);
3372           if (parse) {
3373                     do {
3374                               line = evbuffer_readln(evb, NULL, EVBUFFER_EOL_LF);
3375                               if (line != NULL) {
3376                                         window_copy_add(wp, 1, "%s", line);
3377                                         free(line);
3378                               }
3379                     } while (line != NULL);
3380 
3381                     size = EVBUFFER_LENGTH(evb);
3382                     if (size != 0) {
3383                               line = (char *)EVBUFFER_DATA(evb);
3384                               window_copy_add(wp, 1, "%.*s", (int)size, line);
3385                     }
3386           } else
3387                     window_copy_add(wp, 0, "%s", msg);
3388 
3389 out:
3390           if (!parse)
3391                     free(msg);
3392 }
3393