tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

window.c
Go to the documentation of this file.
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2007 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 
22 #include <ctype.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <fnmatch.h>
26 #include <regex.h>
27 #include <signal.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 
34 #include "tmux.h"
35 
36 /*
37  * Each window is attached to a number of panes, each of which is a pty. This
38  * file contains code to handle them.
39  *
40  * A pane has two buffers attached, these are filled and emptied by the main
41  * server poll loop. Output data is received from pty's in screen format,
42  * translated and returned as a series of escape sequences and strings via
43  * input_parse (in input.c). Input data is received as key codes and written
44  * directly via input_key.
45  *
46  * Each pane also has a "virtual" screen (screen.c) which contains the current
47  * state and is redisplayed when the window is reattached to a client.
48  *
49  * Windows are stored directly on a global array and wrapped in any number of
50  * winlink structs to be linked onto local session RB trees. A reference count
51  * is maintained and a window removed from the global list and destroyed when
52  * it reaches zero.
53  */
54 
55 /* Global window list. */
56 struct windows windows;
57 
58 /* Global panes tree. */
59 struct window_pane_tree all_window_panes;
60 static u_int next_window_pane_id;
61 static u_int next_window_id;
62 static u_int next_active_point;
63 
65  struct cmdq_item *item;
66  u_int wp;
67 };
68 
69 static struct window_pane *window_pane_create(struct window *, u_int, u_int,
70  u_int);
71 static void window_pane_destroy(struct window_pane *);
72 
74 RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
75 RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
76 
77 int
78 window_cmp(struct window *w1, struct window *w2)
79 {
80  return (w1->id - w2->id);
81 }
82 
83 int
84 winlink_cmp(struct winlink *wl1, struct winlink *wl2)
85 {
86  return (wl1->idx - wl2->idx);
87 }
88 
89 int
90 window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2)
91 {
92  return (wp1->id - wp2->id);
93 }
94 
95 struct winlink *
96 winlink_find_by_window(struct winlinks *wwl, struct window *w)
97 {
98  struct winlink *wl;
99 
100  RB_FOREACH(wl, winlinks, wwl) {
101  if (wl->window == w)
102  return (wl);
103  }
104 
105  return (NULL);
106 }
107 
108 struct winlink *
109 winlink_find_by_index(struct winlinks *wwl, int idx)
110 {
111  struct winlink wl;
112 
113  if (idx < 0)
114  fatalx("bad index");
115 
116  wl.idx = idx;
117  return (RB_FIND(winlinks, wwl, &wl));
118 }
119 
120 struct winlink *
121 winlink_find_by_window_id(struct winlinks *wwl, u_int id)
122 {
123  struct winlink *wl;
124 
125  RB_FOREACH(wl, winlinks, wwl) {
126  if (wl->window->id == id)
127  return (wl);
128  }
129  return (NULL);
130 }
131 
132 static int
133 winlink_next_index(struct winlinks *wwl, int idx)
134 {
135  int i;
136 
137  i = idx;
138  do {
139  if (winlink_find_by_index(wwl, i) == NULL)
140  return (i);
141  if (i == INT_MAX)
142  i = 0;
143  else
144  i++;
145  } while (i != idx);
146  return (-1);
147 }
148 
149 u_int
150 winlink_count(struct winlinks *wwl)
151 {
152  struct winlink *wl;
153  u_int n;
154 
155  n = 0;
156  RB_FOREACH(wl, winlinks, wwl)
157  n++;
158 
159  return (n);
160 }
161 
162 struct winlink *
163 winlink_add(struct winlinks *wwl, int idx)
164 {
165  struct winlink *wl;
166 
167  if (idx < 0) {
168  if ((idx = winlink_next_index(wwl, -idx - 1)) == -1)
169  return (NULL);
170  } else if (winlink_find_by_index(wwl, idx) != NULL)
171  return (NULL);
172 
173  wl = xcalloc(1, sizeof *wl);
174  wl->idx = idx;
175  RB_INSERT(winlinks, wwl, wl);
176 
177  return (wl);
178 }
179 
180 void
181 winlink_set_window(struct winlink *wl, struct window *w)
182 {
183  if (wl->window != NULL) {
184  TAILQ_REMOVE(&wl->window->winlinks, wl, wentry);
185  window_remove_ref(wl->window, __func__);
186  }
187  TAILQ_INSERT_TAIL(&w->winlinks, wl, wentry);
188  wl->window = w;
189  window_add_ref(w, __func__);
190 }
191 
192 void
193 winlink_remove(struct winlinks *wwl, struct winlink *wl)
194 {
195  struct window *w = wl->window;
196 
197  if (w != NULL) {
198  TAILQ_REMOVE(&w->winlinks, wl, wentry);
199  window_remove_ref(w, __func__);
200  }
201 
202  RB_REMOVE(winlinks, wwl, wl);
203  free(wl);
204 }
205 
206 struct winlink *
208 {
209  return (RB_NEXT(winlinks, wwl, wl));
210 }
211 
212 struct winlink *
214 {
215  return (RB_PREV(winlinks, wwl, wl));
216 }
217 
218 struct winlink *
219 winlink_next_by_number(struct winlink *wl, struct session *s, int n)
220 {
221  for (; n > 0; n--) {
222  if ((wl = RB_NEXT(winlinks, wwl, wl)) == NULL)
223  wl = RB_MIN(winlinks, &s->windows);
224  }
225 
226  return (wl);
227 }
228 
229 struct winlink *
230 winlink_previous_by_number(struct winlink *wl, struct session *s, int n)
231 {
232  for (; n > 0; n--) {
233  if ((wl = RB_PREV(winlinks, wwl, wl)) == NULL)
234  wl = RB_MAX(winlinks, &s->windows);
235  }
236 
237  return (wl);
238 }
239 
240 void
241 winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
242 {
243  if (wl == NULL)
244  return;
245 
246  winlink_stack_remove(stack, wl);
247  TAILQ_INSERT_HEAD(stack, wl, sentry);
248 }
249 
250 void
251 winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
252 {
253  struct winlink *wl2;
254 
255  if (wl == NULL)
256  return;
257 
258  TAILQ_FOREACH(wl2, stack, sentry) {
259  if (wl2 == wl) {
260  TAILQ_REMOVE(stack, wl, sentry);
261  return;
262  }
263  }
264 }
265 
266 struct window *
267 window_find_by_id_str(const char *s)
268 {
269  const char *errstr;
270  u_int id;
271 
272  if (*s != '@')
273  return (NULL);
274 
275  id = strtonum(s + 1, 0, UINT_MAX, &errstr);
276  if (errstr != NULL)
277  return (NULL);
278  return (window_find_by_id(id));
279 }
280 
281 struct window *
283 {
284  struct window w;
285 
286  w.id = id;
287  return (RB_FIND(windows, &windows, &w));
288 }
289 
290 void
292 {
293  gettimeofday(&w->activity_time, NULL);
295 }
296 
297 struct window *
298 window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
299 {
300  struct window *w;
301 
302  if (xpixel == 0)
304  if (ypixel == 0)
306 
307  w = xcalloc(1, sizeof *w);
308  w->name = xstrdup("");
309  w->flags = 0;
310 
311  TAILQ_INIT(&w->panes);
312  w->active = NULL;
313 
314  w->lastlayout = -1;
315  w->layout_root = NULL;
316 
317  w->sx = sx;
318  w->sy = sy;
319  w->xpixel = xpixel;
320  w->ypixel = ypixel;
321 
323 
324  w->references = 0;
325  TAILQ_INIT(&w->winlinks);
326 
327  w->id = next_window_id++;
328  RB_INSERT(windows, &windows, w);
329 
331 
332  log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
333  w->xpixel, w->ypixel);
334  return (w);
335 }
336 
337 static void
339 {
340  log_debug("window @%u destroyed (%d references)", w->id, w->references);
341 
342  RB_REMOVE(windows, &windows, w);
343 
344  if (w->layout_root != NULL)
346  if (w->saved_layout_root != NULL)
348  free(w->old_layout);
349 
351 
352  if (event_initialized(&w->name_event))
353  evtimer_del(&w->name_event);
354 
355  if (event_initialized(&w->alerts_timer))
356  evtimer_del(&w->alerts_timer);
357  if (event_initialized(&w->offset_timer))
358  event_del(&w->offset_timer);
359 
360  options_free(w->options);
361 
362  free(w->name);
363  free(w);
364 }
365 
366 int
368 {
369  int n;
370 
371  if (wp->pipe_fd != -1) {
372  if (EVBUFFER_LENGTH(wp->pipe_event->output) != 0)
373  return (0);
374  if (ioctl(wp->fd, FIONREAD, &n) != -1 && n > 0)
375  return (0);
376  }
377 
378  if (~wp->flags & PANE_EXITED)
379  return (0);
380  return (1);
381 }
382 
383 void
384 window_add_ref(struct window *w, const char *from)
385 {
386  w->references++;
387  log_debug("%s: @%u %s, now %d", __func__, w->id, from, w->references);
388 }
389 
390 void
391 window_remove_ref(struct window *w, const char *from)
392 {
393  w->references--;
394  log_debug("%s: @%u %s, now %d", __func__, w->id, from, w->references);
395 
396  if (w->references == 0)
397  window_destroy(w);
398 }
399 
400 void
401 window_set_name(struct window *w, const char *new_name)
402 {
403  free(w->name);
404  utf8_stravis(&w->name, new_name, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
405  notify_window("window-renamed", w);
406 }
407 
408 void
409 window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
410 {
411  if (xpixel == 0)
413  if (ypixel == 0)
415 
416  log_debug("%s: @%u resize %ux%u (%ux%u)", __func__, w->id, sx, sy,
417  xpixel == -1 ? w->xpixel : (u_int)xpixel,
418  ypixel == -1 ? w->ypixel : (u_int)ypixel);
419  w->sx = sx;
420  w->sy = sy;
421  if (xpixel != -1)
422  w->xpixel = xpixel;
423  if (ypixel != -1)
424  w->ypixel = ypixel;
425 }
426 
427 void
428 window_pane_send_resize(struct window_pane *wp, u_int sx, u_int sy)
429 {
430  struct window *w = wp->window;
431  struct winsize ws;
432 
433  if (wp->fd == -1)
434  return;
435 
436  log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, sx, sy);
437 
438  memset(&ws, 0, sizeof ws);
439  ws.ws_col = sx;
440  ws.ws_row = sy;
441  ws.ws_xpixel = w->xpixel * ws.ws_col;
442  ws.ws_ypixel = w->ypixel * ws.ws_row;
443  if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1)
444 #ifdef __sun
445  /*
446  * Some versions of Solaris apparently can return an error when
447  * resizing; don't know why this happens, can't reproduce on
448  * other platforms and ignoring it doesn't seem to cause any
449  * issues.
450  */
451  if (errno != EINVAL && errno != ENXIO)
452 #endif
453  fatal("ioctl failed");
454 }
455 
456 int
457 window_has_pane(struct window *w, struct window_pane *wp)
458 {
459  struct window_pane *wp1;
460 
461  TAILQ_FOREACH(wp1, &w->panes, entry) {
462  if (wp1 == wp)
463  return (1);
464  }
465  return (0);
466 }
467 
468 int
469 window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
470 {
471  log_debug("%s: pane %%%u", __func__, wp->id);
472 
473  if (wp == w->active)
474  return (0);
475  w->last = w->active;
476 
477  w->active = wp;
479  w->active->flags |= PANE_CHANGED;
480 
482 
483  if (notify)
484  notify_window("window-pane-changed", w);
485  return (1);
486 }
487 
488 void
490 {
491  struct grid_cell *gc1, *gc2;
492  int c1, c2;
493 
494  if (wp == w->active)
495  return;
496 
497  for (;;) {
498  /*
499  * If the active and inactive styles or palettes are different,
500  * need to redraw the panes.
501  */
502  gc1 = &wp->cached_gc;
503  gc2 = &wp->cached_active_gc;
504  if (!grid_cells_look_equal(gc1, gc2))
505  wp->flags |= PANE_REDRAW;
506  else {
507  c1 = window_pane_get_palette(wp, gc1->fg);
508  c2 = window_pane_get_palette(wp, gc2->fg);
509  if (c1 != c2)
510  wp->flags |= PANE_REDRAW;
511  else {
512  c1 = window_pane_get_palette(wp, gc1->bg);
513  c2 = window_pane_get_palette(wp, gc2->bg);
514  if (c1 != c2)
515  wp->flags |= PANE_REDRAW;
516  }
517  }
518  if (wp == w->active)
519  break;
520  wp = w->active;
521  }
522 }
523 
524 struct window_pane *
525 window_get_active_at(struct window *w, u_int x, u_int y)
526 {
527  struct window_pane *wp;
528 
529  TAILQ_FOREACH(wp, &w->panes, entry) {
530  if (!window_pane_visible(wp))
531  continue;
532  if (x < wp->xoff || x > wp->xoff + wp->sx)
533  continue;
534  if (y < wp->yoff || y > wp->yoff + wp->sy)
535  continue;
536  return (wp);
537  }
538  return (NULL);
539 }
540 
541 struct window_pane *
542 window_find_string(struct window *w, const char *s)
543 {
544  u_int x, y, top = 0, bottom = w->sy - 1;
545  int status;
546 
547  x = w->sx / 2;
548  y = w->sy / 2;
549 
550  status = options_get_number(w->options, "pane-border-status");
551  if (status == PANE_STATUS_TOP)
552  top++;
553  else if (status == PANE_STATUS_BOTTOM)
554  bottom--;
555 
556  if (strcasecmp(s, "top") == 0)
557  y = top;
558  else if (strcasecmp(s, "bottom") == 0)
559  y = bottom;
560  else if (strcasecmp(s, "left") == 0)
561  x = 0;
562  else if (strcasecmp(s, "right") == 0)
563  x = w->sx - 1;
564  else if (strcasecmp(s, "top-left") == 0) {
565  x = 0;
566  y = top;
567  } else if (strcasecmp(s, "top-right") == 0) {
568  x = w->sx - 1;
569  y = top;
570  } else if (strcasecmp(s, "bottom-left") == 0) {
571  x = 0;
572  y = bottom;
573  } else if (strcasecmp(s, "bottom-right") == 0) {
574  x = w->sx - 1;
575  y = bottom;
576  } else
577  return (NULL);
578 
579  return (window_get_active_at(w, x, y));
580 }
581 
582 int
584 {
585  struct window *w = wp->window;
586  struct window_pane *wp1;
587 
588  if (w->flags & WINDOW_ZOOMED)
589  return (-1);
590 
591  if (window_count_panes(w) == 1)
592  return (-1);
593 
594  if (w->active != wp)
595  window_set_active_pane(w, wp, 1);
596 
597  TAILQ_FOREACH(wp1, &w->panes, entry) {
598  wp1->saved_layout_cell = wp1->layout_cell;
599  wp1->layout_cell = NULL;
600  }
601 
603  layout_init(w, wp);
604  w->flags |= WINDOW_ZOOMED;
605  notify_window("window-layout-changed", w);
606 
607  return (0);
608 }
609 
610 int
612 {
613  struct window_pane *wp;
614 
615  if (!(w->flags & WINDOW_ZOOMED))
616  return (-1);
617 
618  w->flags &= ~~WINDOW_ZOOMED;
619  layout_free(w);
621  w->saved_layout_root = NULL;
622 
623  TAILQ_FOREACH(wp, &w->panes, entry) {
624  wp->layout_cell = wp->saved_layout_cell;
625  wp->saved_layout_cell = NULL;
626  }
627  layout_fix_panes(w, NULL);
628  notify_window("window-layout-changed", w);
629 
630  return (0);
631 }
632 
633 int
634 window_push_zoom(struct window *w, int always, int flag)
635 {
636  log_debug("%s: @%u %d", __func__, w->id,
637  flag && (w->flags & WINDOW_ZOOMED));
638  if (flag && (always || (w->flags & WINDOW_ZOOMED)))
639  w->flags |= WINDOW_WASZOOMED;
640  else
641  w->flags &= ~~WINDOW_WASZOOMED;
642  return (window_unzoom(w) == 0);
643 }
644 
645 int
647 {
648  log_debug("%s: @%u %d", __func__, w->id,
649  !!(w->flags & WINDOW_WASZOOMED));
650  if (w->flags & WINDOW_WASZOOMED)
651  return (window_zoom(w->active) == 0);
652  return (0);
653 }
654 
655 struct window_pane *
656 window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
657  int flags)
658 {
659  struct window_pane *wp;
660 
661  if (other == NULL)
662  other = w->active;
663 
664  wp = window_pane_create(w, w->sx, w->sy, hlimit);
665  if (TAILQ_EMPTY(&w->panes)) {
666  log_debug("%s: @%u at start", __func__, w->id);
667  TAILQ_INSERT_HEAD(&w->panes, wp, entry);
668  } else if (flags & SPAWN_BEFORE) {
669  log_debug("%s: @%u before %%%u", __func__, w->id, wp->id);
670  if (flags & SPAWN_FULLSIZE)
671  TAILQ_INSERT_HEAD(&w->panes, wp, entry);
672  else
673  TAILQ_INSERT_BEFORE(other, wp, entry);
674  } else {
675  log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
676  if (flags & SPAWN_FULLSIZE)
677  TAILQ_INSERT_TAIL(&w->panes, wp, entry);
678  else
679  TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
680  }
681  return (wp);
682 }
683 
684 void
685 window_lost_pane(struct window *w, struct window_pane *wp)
686 {
687  log_debug("%s: @%u pane %%%u", __func__, w->id, wp->id);
688 
689  if (wp == marked_pane.wp)
691 
692  if (wp == w->active) {
693  w->active = w->last;
694  w->last = NULL;
695  if (w->active == NULL) {
696  w->active = TAILQ_PREV(wp, window_panes, entry);
697  if (w->active == NULL)
698  w->active = TAILQ_NEXT(wp, entry);
699  }
700  if (w->active != NULL) {
701  w->active->flags |= PANE_CHANGED;
702  notify_window("window-pane-changed", w);
703  }
704  } else if (wp == w->last)
705  w->last = NULL;
706 }
707 
708 void
709 window_remove_pane(struct window *w, struct window_pane *wp)
710 {
711  window_lost_pane(w, wp);
712 
713  TAILQ_REMOVE(&w->panes, wp, entry);
715 }
716 
717 struct window_pane *
718 window_pane_at_index(struct window *w, u_int idx)
719 {
720  struct window_pane *wp;
721  u_int n;
722 
723  n = options_get_number(w->options, "pane-base-index");
724  TAILQ_FOREACH(wp, &w->panes, entry) {
725  if (n == idx)
726  return (wp);
727  n++;
728  }
729  return (NULL);
730 }
731 
732 struct window_pane *
733 window_pane_next_by_number(struct window *w, struct window_pane *wp, u_int n)
734 {
735  for (; n > 0; n--) {
736  if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
737  wp = TAILQ_FIRST(&w->panes);
738  }
739 
740  return (wp);
741 }
742 
743 struct window_pane *
745  u_int n)
746 {
747  for (; n > 0; n--) {
748  if ((wp = TAILQ_PREV(wp, window_panes, entry)) == NULL)
749  wp = TAILQ_LAST(&w->panes, window_panes);
750  }
751 
752  return (wp);
753 }
754 
755 int
756 window_pane_index(struct window_pane *wp, u_int *i)
757 {
758  struct window_pane *wq;
759  struct window *w = wp->window;
760 
761  *i = options_get_number(w->options, "pane-base-index");
762  TAILQ_FOREACH(wq, &w->panes, entry) {
763  if (wp == wq) {
764  return (0);
765  }
766  (*i)++;
767  }
768 
769  return (-1);
770 }
771 
772 u_int
774 {
775  struct window_pane *wp;
776  u_int n;
777 
778  n = 0;
779  TAILQ_FOREACH(wp, &w->panes, entry)
780  n++;
781  return (n);
782 }
783 
784 void
786 {
787  struct window_pane *wp;
788 
789  while (!TAILQ_EMPTY(&w->panes)) {
790  wp = TAILQ_FIRST(&w->panes);
791  TAILQ_REMOVE(&w->panes, wp, entry);
793  }
794 }
795 
796 const char *
797 window_printable_flags(struct winlink *wl, int escape)
798 {
799  struct session *s = wl->session;
800  static char flags[32];
801  int pos;
802 
803  pos = 0;
804  if (wl->flags & WINLINK_ACTIVITY) {
805  flags[pos++] = '#';
806  if (escape)
807  flags[pos++] = '#';
808  }
809  if (wl->flags & WINLINK_BELL)
810  flags[pos++] = '!';
811  if (wl->flags & WINLINK_SILENCE)
812  flags[pos++] = '~';
813  if (wl == s->curw)
814  flags[pos++] = '*';
815  if (wl == TAILQ_FIRST(&s->lastw))
816  flags[pos++] = '-';
817  if (server_check_marked() && wl == marked_pane.wl)
818  flags[pos++] = 'M';
819  if (wl->window->flags & WINDOW_ZOOMED)
820  flags[pos++] = 'Z';
821  flags[pos] = '\0';
822  return (flags);
823 }
824 
825 struct window_pane *
827 {
828  const char *errstr;
829  u_int id;
830 
831  if (*s != '%')
832  return (NULL);
833 
834  id = strtonum(s + 1, 0, UINT_MAX, &errstr);
835  if (errstr != NULL)
836  return (NULL);
837  return (window_pane_find_by_id(id));
838 }
839 
840 struct window_pane *
842 {
843  struct window_pane wp;
844 
845  wp.id = id;
846  return (RB_FIND(window_pane_tree, &all_window_panes, &wp));
847 }
848 
849 static struct window_pane *
850 window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
851 {
852  struct window_pane *wp;
853  char host[HOST_NAME_MAX + 1];
854 
855  wp = xcalloc(1, sizeof *wp);
856  wp->window = w;
857  wp->options = options_create(w->options);
858  wp->flags = PANE_STYLECHANGED;
859 
860  wp->id = next_window_pane_id++;
861  RB_INSERT(window_pane_tree, &all_window_panes, wp);
862 
863  wp->fd = -1;
864 
865  wp->fg = 8;
866  wp->bg = 8;
867 
868  TAILQ_INIT(&wp->modes);
869 
870  TAILQ_INIT (&wp->resize_queue);
871 
872  wp->sx = sx;
873  wp->sy = sy;
874 
875  wp->pipe_fd = -1;
876 
877  screen_init(&wp->base, sx, sy, hlimit);
878  wp->screen = &wp->base;
879 
880  screen_init(&wp->status_screen, 1, 1, 0);
881 
882  if (gethostname(host, sizeof host) == 0)
883  screen_set_title(&wp->base, host);
884 
885  return (wp);
886 }
887 
888 static void
890 {
891  struct window_pane_resize *r;
892  struct window_pane_resize *r1;
893 
895  free(wp->searchstr);
896 
897  if (wp->fd != -1) {
898 #ifdef HAVE_UTEMPTER
899  utempter_remove_record(wp->fd);
900 #endif
901  bufferevent_free(wp->event);
902  close(wp->fd);
903  }
904  if (wp->ictx != NULL)
905  input_free(wp->ictx);
906 
908 
909  screen_free(&wp->base);
910 
911  if (wp->pipe_fd != -1) {
912  bufferevent_free(wp->pipe_event);
913  close(wp->pipe_fd);
914  }
915 
916  if (event_initialized(&wp->resize_timer))
917  event_del(&wp->resize_timer);
918  TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
919  TAILQ_REMOVE(&wp->resize_queue, r, entry);
920  free(r);
921  }
922 
923  RB_REMOVE(window_pane_tree, &all_window_panes, wp);
924 
925  options_free(wp->options);
926  free((void *)wp->cwd);
927  free(wp->shell);
928  cmd_free_argv(wp->argc, wp->argv);
929  free(wp->palette);
930  free(wp);
931 }
932 
933 static void
934 window_pane_read_callback(__unused struct bufferevent *bufev, void *data)
935 {
936  struct window_pane *wp = data;
937  struct evbuffer *evb = wp->event->input;
938  struct window_pane_offset *wpo = &wp->pipe_offset;
939  size_t size = EVBUFFER_LENGTH(evb);
940  char *new_data;
941  size_t new_size;
942  struct client *c;
943 
944  if (wp->pipe_fd != -1) {
945  new_data = window_pane_get_new_data(wp, wpo, &new_size);
946  if (new_size > 0) {
947  bufferevent_write(wp->pipe_event, new_data, new_size);
948  window_pane_update_used_data(wp, wpo, new_size);
949  }
950  }
951 
952  log_debug("%%%u has %zu bytes", wp->id, size);
953  TAILQ_FOREACH(c, &clients, entry) {
954  if (c->session != NULL && (c->flags & CLIENT_CONTROL))
955  control_write_output(c, wp);
956  }
957  input_parse_pane(wp);
958  bufferevent_disable(wp->event, EV_READ);
959 }
960 
961 static void
962 window_pane_error_callback(__unused struct bufferevent *bufev,
963  __unused short what, void *data)
964 {
965  struct window_pane *wp = data;
966 
967  log_debug("%%%u error", wp->id);
968  wp->flags |= PANE_EXITED;
969 
971  server_destroy_pane(wp, 1);
972 }
973 
974 void
976 {
977  setblocking(wp->fd, 0);
978 
979  wp->event = bufferevent_new(wp->fd, window_pane_read_callback,
980  NULL, window_pane_error_callback, wp);
981  wp->ictx = input_init(wp, wp->event);
982 
983  bufferevent_enable(wp->event, EV_READ|EV_WRITE);
984 }
985 
986 void
987 window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
988 {
989  struct window_mode_entry *wme;
990  struct window_pane_resize *r;
991 
992  if (sx == wp->sx && sy == wp->sy)
993  return;
994 
995  r = xmalloc (sizeof *r);
996  r->sx = sx;
997  r->sy = sy;
998  r->osx = wp->sx;
999  r->osy = wp->sy;
1000  TAILQ_INSERT_TAIL (&wp->resize_queue, r, entry);
1001 
1002  wp->sx = sx;
1003  wp->sy = sy;
1004 
1005  log_debug("%s: %%%u resize %ux%u", __func__, wp->id, sx, sy);
1006  screen_resize(&wp->base, sx, sy, wp->base.saved_grid == NULL);
1007 
1008  wme = TAILQ_FIRST(&wp->modes);
1009  if (wme != NULL && wme->mode->resize != NULL)
1010  wme->mode->resize(wme, sx, sy);
1011 }
1012 
1013 void
1014 window_pane_set_palette(struct window_pane *wp, u_int n, int colour)
1015 {
1016  if (n > 0xff)
1017  return;
1018 
1019  if (wp->palette == NULL)
1020  wp->palette = xcalloc(0x100, sizeof *wp->palette);
1021 
1022  wp->palette[n] = colour;
1023  wp->flags |= PANE_REDRAW;
1024 }
1025 
1026 void
1028 {
1029  if (n > 0xff || wp->palette == NULL)
1030  return;
1031 
1032  wp->palette[n] = 0;
1033  wp->flags |= PANE_REDRAW;
1034 }
1035 
1036 void
1038 {
1039  if (wp->palette == NULL)
1040  return;
1041 
1042  free(wp->palette);
1043  wp->palette = NULL;
1044  wp->flags |= PANE_REDRAW;
1045 }
1046 
1047 int
1049 {
1050  int new;
1051 
1052  if (wp == NULL || wp->palette == NULL)
1053  return (-1);
1054 
1055  new = -1;
1056  if (c < 8)
1057  new = wp->palette[c];
1058  else if (c >= 90 && c <= 97)
1059  new = wp->palette[8 + c - 90];
1060  else if (c & COLOUR_FLAG_256)
1061  new = wp->palette[c & ~~COLOUR_FLAG_256];
1062  if (new == 0)
1063  return (-1);
1064  return (new);
1065 }
1066 
1067 int
1069  const struct window_mode *mode, struct cmd_find_state *fs,
1070  struct args *args)
1071 {
1072  struct window_mode_entry *wme;
1073 
1074  if (!TAILQ_EMPTY(&wp->modes) && TAILQ_FIRST(&wp->modes)->mode == mode)
1075  return (1);
1076 
1077  TAILQ_FOREACH(wme, &wp->modes, entry) {
1078  if (wme->mode == mode)
1079  break;
1080  }
1081  if (wme != NULL) {
1082  TAILQ_REMOVE(&wp->modes, wme, entry);
1083  TAILQ_INSERT_HEAD(&wp->modes, wme, entry);
1084  } else {
1085  wme = xcalloc(1, sizeof *wme);
1086  wme->wp = wp;
1087  wme->swp = swp;
1088  wme->mode = mode;
1089  wme->prefix = 1;
1090  TAILQ_INSERT_HEAD(&wp->modes, wme, entry);
1091  wme->screen = wme->mode->init(wme, fs, args);
1092  }
1093 
1094  wp->screen = wme->screen;
1096 
1099  notify_pane("pane-mode-changed", wp);
1100 
1101  return (0);
1102 }
1103 
1104 void
1106 {
1107  struct window_mode_entry *wme, *next;
1108 
1109  if (TAILQ_EMPTY(&wp->modes))
1110  return;
1111 
1112  wme = TAILQ_FIRST(&wp->modes);
1113  TAILQ_REMOVE(&wp->modes, wme, entry);
1114  wme->mode->free(wme);
1115  free(wme);
1116 
1117  next = TAILQ_FIRST(&wp->modes);
1118  if (next == NULL) {
1119  log_debug("%s: no next mode", __func__);
1120  wp->screen = &wp->base;
1121  } else {
1122  log_debug("%s: next mode is %s", __func__, next->mode->name);
1123  wp->screen = next->screen;
1124  if (next->mode->resize != NULL)
1125  next->mode->resize(next, wp->sx, wp->sy);
1126  }
1128 
1131  notify_pane("pane-mode-changed", wp);
1132 }
1133 
1134 void
1136 {
1137  while (!TAILQ_EMPTY(&wp->modes))
1139 }
1140 
1141 static void
1143 {
1144  struct window_pane *loop;
1145 
1146  TAILQ_FOREACH(loop, &wp->window->panes, entry) {
1147  if (loop != wp &&
1148  TAILQ_EMPTY(&loop->modes) &&
1149  loop->fd != -1 &&
1150  (~loop->flags & PANE_INPUTOFF) &&
1151  window_pane_visible(loop) &&
1152  options_get_number(loop->options, "synchronize-panes"))
1153  input_key_pane(loop, key, NULL);
1154  }
1155 }
1156 
1157 int
1158 window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
1159  struct winlink *wl, key_code key, struct mouse_event *m)
1160 {
1161  struct window_mode_entry *wme;
1162 
1163  if (KEYC_IS_MOUSE(key) && m == NULL)
1164  return (-1);
1165 
1166  wme = TAILQ_FIRST(&wp->modes);
1167  if (wme != NULL) {
1168  if (wme->mode->key != NULL && c != NULL) {
1169  key &= ~~KEYC_MASK_FLAGS;
1170  wme->mode->key(wme, c, s, wl, key, m);
1171  }
1172  return (0);
1173  }
1174 
1175  if (wp->fd == -1 || wp->flags & PANE_INPUTOFF)
1176  return (0);
1177 
1178  if (input_key_pane(wp, key, m) != 0)
1179  return (-1);
1180 
1181  if (KEYC_IS_MOUSE(key))
1182  return (0);
1183  if (options_get_number(wp->options, "synchronize-panes"))
1185  return (0);
1186 }
1187 
1188 int
1190 {
1191  if (~wp->window->flags & WINDOW_ZOOMED)
1192  return (1);
1193  return (wp == wp->window->active);
1194 }
1195 
1196 u_int
1197 window_pane_search(struct window_pane *wp, const char *term, int regex,
1198  int ignore)
1199 {
1200  struct screen *s = &wp->base;
1201  regex_t r;
1202  char *new = NULL, *line;
1203  u_int i;
1204  int flags = 0, found;
1205  size_t n;
1206 
1207  if (!regex) {
1208  if (ignore)
1209  flags |= FNM_CASEFOLD;
1210  xasprintf(&new, "*%s*", term);
1211  } else {
1212  if (ignore)
1213  flags |= REG_ICASE;
1214  if (regcomp(&r, term, flags|REG_EXTENDED) != 0)
1215  return (0);
1216  }
1217 
1218  for (i = 0; i < screen_size_y(s); i++) {
1219  line = grid_view_string_cells(s->grid, 0, i, screen_size_x(s));
1220  for (n = strlen(line); n > 0; n--) {
1221  if (!isspace((u_char)line[n - 1]))
1222  break;
1223  line[n - 1] = '\0';
1224  }
1225  log_debug("%s: %s", __func__, line);
1226  if (!regex)
1227  found = (fnmatch(new, line, flags) == 0);
1228  else
1229  found = (regexec(&r, line, 0, NULL, 0) == 0);
1230  free(line);
1231  if (found)
1232  break;
1233  }
1234  if (!regex)
1235  free(new);
1236  else
1237  regfree(&r);
1238 
1239  if (i == screen_size_y(s))
1240  return (0);
1241  return (i + 1);
1242 }
1243 
1244 /* Get MRU pane from a list. */
1245 static struct window_pane *
1246 window_pane_choose_best(struct window_pane **list, u_int size)
1247 {
1248  struct window_pane *next, *best;
1249  u_int i;
1250 
1251  if (size == 0)
1252  return (NULL);
1253 
1254  best = list[0];
1255  for (i = 1; i < size; i++) {
1256  next = list[i];
1257  if (next->active_point > best->active_point)
1258  best = next;
1259  }
1260  return (best);
1261 }
1262 
1263 /*
1264  * Find the pane directly above another. We build a list of those adjacent to
1265  * top edge and then choose the best.
1266  */
1267 struct window_pane *
1269 {
1270  struct window *w;
1271  struct window_pane *next, *best, **list;
1272  u_int edge, left, right, end, size;
1273  int status, found;
1274 
1275  if (wp == NULL)
1276  return (NULL);
1277  w = wp->window;
1278  status = options_get_number(w->options, "pane-border-status");
1279 
1280  list = NULL;
1281  size = 0;
1282 
1283  edge = wp->yoff;
1284  if (status == PANE_STATUS_TOP) {
1285  if (edge == 1)
1286  edge = w->sy + 1;
1287  } else if (status == PANE_STATUS_BOTTOM) {
1288  if (edge == 0)
1289  edge = w->sy;
1290  } else {
1291  if (edge == 0)
1292  edge = w->sy + 1;
1293  }
1294 
1295  left = wp->xoff;
1296  right = wp->xoff + wp->sx;
1297 
1298  TAILQ_FOREACH(next, &w->panes, entry) {
1299  if (next == wp)
1300  continue;
1301  if (next->yoff + next->sy + 1 != edge)
1302  continue;
1303  end = next->xoff + next->sx - 1;
1304 
1305  found = 0;
1306  if (next->xoff < left && end > right)
1307  found = 1;
1308  else if (next->xoff >= left && next->xoff <= right)
1309  found = 1;
1310  else if (end >= left && end <= right)
1311  found = 1;
1312  if (!found)
1313  continue;
1314  list = xreallocarray(list, size + 1, sizeof *list);
1315  list[size++] = next;
1316  }
1317 
1318  best = window_pane_choose_best(list, size);
1319  free(list);
1320  return (best);
1321 }
1322 
1323 /* Find the pane directly below another. */
1324 struct window_pane *
1326 {
1327  struct window *w;
1328  struct window_pane *next, *best, **list;
1329  u_int edge, left, right, end, size;
1330  int status, found;
1331 
1332  if (wp == NULL)
1333  return (NULL);
1334  w = wp->window;
1335  status = options_get_number(w->options, "pane-border-status");
1336 
1337  list = NULL;
1338  size = 0;
1339 
1340  edge = wp->yoff + wp->sy + 1;
1341  if (status == PANE_STATUS_TOP) {
1342  if (edge >= w->sy)
1343  edge = 1;
1344  } else if (status == PANE_STATUS_BOTTOM) {
1345  if (edge >= w->sy - 1)
1346  edge = 0;
1347  } else {
1348  if (edge >= w->sy)
1349  edge = 0;
1350  }
1351 
1352  left = wp->xoff;
1353  right = wp->xoff + wp->sx;
1354 
1355  TAILQ_FOREACH(next, &w->panes, entry) {
1356  if (next == wp)
1357  continue;
1358  if (next->yoff != edge)
1359  continue;
1360  end = next->xoff + next->sx - 1;
1361 
1362  found = 0;
1363  if (next->xoff < left && end > right)
1364  found = 1;
1365  else if (next->xoff >= left && next->xoff <= right)
1366  found = 1;
1367  else if (end >= left && end <= right)
1368  found = 1;
1369  if (!found)
1370  continue;
1371  list = xreallocarray(list, size + 1, sizeof *list);
1372  list[size++] = next;
1373  }
1374 
1375  best = window_pane_choose_best(list, size);
1376  free(list);
1377  return (best);
1378 }
1379 
1380 /* Find the pane directly to the left of another. */
1381 struct window_pane *
1383 {
1384  struct window *w;
1385  struct window_pane *next, *best, **list;
1386  u_int edge, top, bottom, end, size;
1387  int found;
1388 
1389  if (wp == NULL)
1390  return (NULL);
1391  w = wp->window;
1392 
1393  list = NULL;
1394  size = 0;
1395 
1396  edge = wp->xoff;
1397  if (edge == 0)
1398  edge = w->sx + 1;
1399 
1400  top = wp->yoff;
1401  bottom = wp->yoff + wp->sy;
1402 
1403  TAILQ_FOREACH(next, &w->panes, entry) {
1404  if (next == wp)
1405  continue;
1406  if (next->xoff + next->sx + 1 != edge)
1407  continue;
1408  end = next->yoff + next->sy - 1;
1409 
1410  found = 0;
1411  if (next->yoff < top && end > bottom)
1412  found = 1;
1413  else if (next->yoff >= top && next->yoff <= bottom)
1414  found = 1;
1415  else if (end >= top && end <= bottom)
1416  found = 1;
1417  if (!found)
1418  continue;
1419  list = xreallocarray(list, size + 1, sizeof *list);
1420  list[size++] = next;
1421  }
1422 
1423  best = window_pane_choose_best(list, size);
1424  free(list);
1425  return (best);
1426 }
1427 
1428 /* Find the pane directly to the right of another. */
1429 struct window_pane *
1431 {
1432  struct window *w;
1433  struct window_pane *next, *best, **list;
1434  u_int edge, top, bottom, end, size;
1435  int found;
1436 
1437  if (wp == NULL)
1438  return (NULL);
1439  w = wp->window;
1440 
1441  list = NULL;
1442  size = 0;
1443 
1444  edge = wp->xoff + wp->sx + 1;
1445  if (edge >= w->sx)
1446  edge = 0;
1447 
1448  top = wp->yoff;
1449  bottom = wp->yoff + wp->sy;
1450 
1451  TAILQ_FOREACH(next, &w->panes, entry) {
1452  if (next == wp)
1453  continue;
1454  if (next->xoff != edge)
1455  continue;
1456  end = next->yoff + next->sy - 1;
1457 
1458  found = 0;
1459  if (next->yoff < top && end > bottom)
1460  found = 1;
1461  else if (next->yoff >= top && next->yoff <= bottom)
1462  found = 1;
1463  else if (end >= top && end <= bottom)
1464  found = 1;
1465  if (!found)
1466  continue;
1467  list = xreallocarray(list, size + 1, sizeof *list);
1468  list[size++] = next;
1469  }
1470 
1471  best = window_pane_choose_best(list, size);
1472  free(list);
1473  return (best);
1474 }
1475 
1476 /* Clear alert flags for a winlink */
1477 void
1479 {
1480  struct winlink *loop;
1481 
1482  wl->window->flags &= ~~WINDOW_ALERTFLAGS;
1483  TAILQ_FOREACH(loop, &wl->window->winlinks, wentry) {
1484  if ((loop->flags & WINLINK_ALERTFLAGS) != 0) {
1485  loop->flags &= ~~WINLINK_ALERTFLAGS;
1487  }
1488  }
1489 }
1490 
1491 /* Shuffle window indexes up. */
1492 int
1493 winlink_shuffle_up(struct session *s, struct winlink *wl, int before)
1494 {
1495  int idx, last;
1496 
1497  if (wl == NULL)
1498  return (-1);
1499  if (before)
1500  idx = wl->idx;
1501  else
1502  idx = wl->idx + 1;
1503 
1504  /* Find the next free index. */
1505  for (last = idx; last < INT_MAX; last++) {
1506  if (winlink_find_by_index(&s->windows, last) == NULL)
1507  break;
1508  }
1509  if (last == INT_MAX)
1510  return (-1);
1511 
1512  /* Move everything from last - 1 to idx up a bit. */
1513  for (; last > idx; last--) {
1514  wl = winlink_find_by_index(&s->windows, last - 1);
1515  RB_REMOVE(winlinks, &s->windows, wl);
1516  wl->idx++;
1517  RB_INSERT(winlinks, &s->windows, wl);
1518  }
1519 
1520  return (idx);
1521 }
1522 
1523 static void
1524 window_pane_input_callback(struct client *c, __unused const char *path,
1525  int error, int closed, struct evbuffer *buffer, void *data)
1526 {
1527  struct window_pane_input_data *cdata = data;
1528  struct window_pane *wp;
1529  u_char *buf = EVBUFFER_DATA(buffer);
1530  size_t len = EVBUFFER_LENGTH(buffer);
1531 
1532  wp = window_pane_find_by_id(cdata->wp);
1533  if (wp == NULL || closed || error != 0 || c->flags & CLIENT_DEAD) {
1534  if (wp == NULL)
1535  c->flags |= CLIENT_EXIT;
1536 
1537  evbuffer_drain(buffer, len);
1538  cmdq_continue(cdata->item);
1539 
1541  free(cdata);
1542  return;
1543  }
1544  input_parse_buffer(wp, buf, len);
1545  evbuffer_drain(buffer, len);
1546 }
1547 
1548 int
1550  char **cause)
1551 {
1552  struct client *c = cmdq_get_client(item);
1553  struct window_pane_input_data *cdata;
1554 
1555  if (~wp->flags & PANE_EMPTY) {
1556  *cause = xstrdup("pane is not empty");
1557  return (-1);
1558  }
1559 
1560  cdata = xmalloc(sizeof *cdata);
1561  cdata->item = item;
1562  cdata->wp = wp->id;
1563 
1564  c->references++;
1565  file_read(c, "-", window_pane_input_callback, cdata);
1566 
1567  return (0);
1568 }
1569 
1570 void *
1572  struct window_pane_offset *wpo, size_t *size)
1573 {
1574  size_t used = wpo->used - wp->base_offset;
1575 
1576  *size = EVBUFFER_LENGTH(wp->event->input) - used;
1577  return (EVBUFFER_DATA(wp->event->input) + used);
1578 }
1579 
1580 void
1582  struct window_pane_offset *wpo, size_t size)
1583 {
1584  size_t used = wpo->used - wp->base_offset;
1585 
1586  if (size > EVBUFFER_LENGTH(wp->event->input) - used)
1587  size = EVBUFFER_LENGTH(wp->event->input) - used;
1588  wpo->used += size;
1589 }
void alerts_queue(struct window *w, int flags)
Definition: alerts.c:158
struct client * cmdq_get_client(struct cmdq_item *item)
Definition: cmd-queue.c:150
void cmdq_continue(struct cmdq_item *item)
Definition: cmd-queue.c:434
void cmd_free_argv(int argc, char **argv)
Definition: cmd.c:344
#define __unused
Definition: compat.h:60
long long strtonum(const char *, long long, long long, const char **)
#define HOST_NAME_MAX
Definition: compat.h:265
#define FNM_CASEFOLD
Definition: compat.h:213
void control_write_output(struct client *c, struct window_pane *wp)
Definition: control.c:468
void file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
Definition: file.c:356
char * grid_view_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
Definition: grid-view.c:229
int grid_cells_look_equal(const struct grid_cell *gc1, const struct grid_cell *gc2)
Definition: grid.c:228
int input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m)
Definition: input-keys.c:392
void input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
Definition: input.c:957
struct input_ctx * input_init(struct window_pane *wp, struct bufferevent *bev)
Definition: input.c:800
void input_free(struct input_ctx *ictx)
Definition: input.c:823
void input_parse_pane(struct window_pane *wp)
Definition: input.c:945
key_code key
Definition: key-string.c:32
void layout_init(struct window *w, struct window_pane *wp)
Definition: layout.c:478
void layout_free_cell(struct layout_cell *lc)
Definition: layout.c:73
void layout_free(struct window *w)
Definition: layout.c:489
void layout_fix_panes(struct window *w, struct window_pane *skip)
Definition: layout.c:289
void fatal(const char *msg,...)
Definition: log.c:144
void fatalx(const char *msg,...)
Definition: log.c:159
void log_debug(const char *msg,...)
Definition: log.c:130
void notify_pane(const char *name, struct window_pane *wp)
Definition: notify.c:262
void notify_window(const char *name, struct window *w)
Definition: notify.c:253
void options_free(struct options *oo)
Definition: options.c:182
long long options_get_number(struct options *oo, const char *name)
Definition: options.c:699
struct options * options_create(struct options *parent)
Definition: options.c:171
int screen_set_title(struct screen *s, const char *title)
Definition: screen.c:174
void screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
Definition: screen.c:276
void screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
Definition: screen.c:74
void screen_free(struct screen *s)
Definition: screen.c:122
void server_client_unref(struct client *c)
void server_redraw_window_borders(struct window *w)
Definition: server-fn.c:105
void server_destroy_pane(struct window_pane *wp, int notify)
Definition: server-fn.c:308
void server_status_window(struct window *w)
Definition: server-fn.c:116
void server_status_session(struct session *s)
Definition: server-fn.c:70
int server_check_marked(void)
Definition: server.c:97
void server_clear_marked(void)
Definition: server.c:77
struct cmd_find_state marked_pane
Definition: server.c:51
struct clients clients
Definition: server.c:42
Definition: tmux.h:1435
Definition: tmux.h:1608
int references
Definition: tmux.h:1746
struct session * session
Definition: tmux.h:1743
uint64_t flags
Definition: tmux.h:1703
struct window_pane * wp
Definition: tmux.h:1454
struct winlink * wl
Definition: tmux.h:1452
int bg
Definition: tmux.h:693
int fg
Definition: tmux.h:692
Definition: tmux.h:816
struct grid * saved_grid
Definition: tmux.h:836
struct grid * grid
Definition: tmux.h:821
Definition: tmux.h:1179
struct winlinks windows
Definition: tmux.h:1194
struct winlink_stack lastw
Definition: tmux.h:1193
struct winlink * curw
Definition: tmux.h:1192
int flags
Definition: tmux.h:1203
Definition: tmux.h:927
struct window_pane * swp
Definition: tmux.h:929
const struct window_mode * mode
Definition: tmux.h:931
struct screen * screen
Definition: tmux.h:934
struct window_pane * wp
Definition: tmux.h:928
u_int prefix
Definition: tmux.h:935
void(* resize)(struct window_mode_entry *, u_int, u_int)
Definition: tmux.h:912
void(* free)(struct window_mode_entry *)
Definition: tmux.h:911
struct screen *(* init)(struct window_mode_entry *, struct cmd_find_state *, struct args *)
Definition: tmux.h:909
const char * name
Definition: tmux.h:906
void(* key)(struct window_mode_entry *, struct client *, struct session *, struct winlink *, key_code, struct mouse_event *)
Definition: tmux.h:914
struct cmdq_item * item
Definition: window.c:65
size_t used
Definition: tmux.h:942
char * shell
Definition: tmux.h:994
struct screen * screen
Definition: tmux.h:1020
int * palette
Definition: tmux.h:1014
int argc
Definition: tmux.h:992
struct event resize_timer
Definition: tmux.h:1008
char * searchstr
Definition: tmux.h:1028
u_int xoff
Definition: tmux.h:971
struct window_pane_offset pipe_offset
Definition: tmux.h:1018
u_int active_point
Definition: tmux.h:960
struct layout_cell * saved_layout_cell
Definition: tmux.h:966
struct layout_cell * layout_cell
Definition: tmux.h:965
int fd
Definition: tmux.h:1001
struct window_pane_resizes resize_queue
Definition: tmux.h:1007
int fg
Definition: tmux.h:974
int bg
Definition: tmux.h:975
u_int yoff
Definition: tmux.h:972
char ** argv
Definition: tmux.h:993
int status
Definition: tmux.h:999
int flags
Definition: tmux.h:977
struct grid_cell cached_active_gc
Definition: tmux.h:1013
int pipe_fd
Definition: tmux.h:1016
char * cwd
Definition: tmux.h:995
struct input_ctx * ictx
Definition: tmux.h:1010
struct screen base
Definition: tmux.h:1021
u_int sy
Definition: tmux.h:969
struct bufferevent * event
Definition: tmux.h:1002
struct window * window
Definition: tmux.h:962
struct options * options
Definition: tmux.h:963
u_int sx
Definition: tmux.h:968
struct grid_cell cached_gc
Definition: tmux.h:1012
struct bufferevent * pipe_event
Definition: tmux.h:1017
struct screen status_screen
Definition: tmux.h:1023
u_int id
Definition: tmux.h:959
Definition: tmux.h:1041
struct event alerts_timer
Definition: tmux.h:1049
struct event offset_timer
Definition: tmux.h:1050
u_int ypixel
Definition: tmux.h:1066
u_int id
Definition: tmux.h:1042
int lastlayout
Definition: tmux.h:1058
struct timeval activity_time
Definition: tmux.h:1052
struct layout_cell * layout_root
Definition: tmux.h:1059
struct layout_cell * saved_layout_root
Definition: tmux.h:1060
char * old_layout
Definition: tmux.h:1061
char * name
Definition: tmux.h:1045
int flags
Definition: tmux.h:1073
u_int references
Definition: tmux.h:1087
struct options * options
Definition: tmux.h:1085
u_int sx
Definition: tmux.h:1063
struct event name_event
Definition: tmux.h:1046
struct window_panes panes
Definition: tmux.h:1056
u_int xpixel
Definition: tmux.h:1065
struct window_pane * active
Definition: tmux.h:1054
u_int sy
Definition: tmux.h:1064
struct window_pane * last
Definition: tmux.h:1055
struct options * global_w_options
Definition: tmux.c:38
void setblocking(int fd, int state)
Definition: tmux.c:233
#define PANE_CHANGED
Definition: tmux.h:985
#define WINDOW_WASZOOMED
Definition: tmux.h:1078
#define KEYC_IS_MOUSE(key)
Definition: tmux.h:144
#define WINDOW_ZOOMED
Definition: tmux.h:1077
#define WINLINK_SILENCE
Definition: tmux.h:1103
#define WINLINK_BELL
Definition: tmux.h:1101
#define PANE_STATUS_BOTTOM
Definition: tmux.h:1122
#define PANE_STATUS_TOP
Definition: tmux.h:1121
unsigned long long key_code
Definition: tmux.h:177
#define PANE_STYLECHANGED
Definition: tmux.h:990
#define PANE_EMPTY
Definition: tmux.h:989
#define WINLINK_ACTIVITY
Definition: tmux.h:1102
#define PANE_INPUTOFF
Definition: tmux.h:984
#define DEFAULT_YPIXEL
Definition: tmux.h:91
#define CLIENT_CONTROL
Definition: tmux.h:1667
#define PANE_EXITED
Definition: tmux.h:986
#define screen_size_y(s)
Definition: tmux.h:882
#define PANE_REDRAW
Definition: tmux.h:978
int utf8_stravis(char **, const char *, int)
Definition: utf8.c:352
#define screen_size_x(s)
Definition: tmux.h:881
#define WINLINK_ALERTFLAGS
Definition: tmux.h:1104
#define SPAWN_BEFORE
Definition: tmux.h:1891
#define DEFAULT_XPIXEL
Definition: tmux.h:90
void tty_update_window_offset(struct window *)
Definition: tty.c:856
#define CLIENT_DEAD
Definition: tmux.h:1663
#define SPAWN_FULLSIZE
Definition: tmux.h:1893
#define CLIENT_EXIT
Definition: tmux.h:1656
#define COLOUR_FLAG_256
Definition: tmux.h:643
#define WINDOW_ACTIVITY
Definition: tmux.h:1075
int winlink_cmp(struct winlink *wl1, struct winlink *wl2)
Definition: window.c:84
static void window_destroy(struct window *w)
Definition: window.c:338
void window_destroy_panes(struct window *w)
Definition: window.c:785
struct window_pane * window_pane_next_by_number(struct window *w, struct window_pane *wp, u_int n)
Definition: window.c:733
int window_pane_get_palette(struct window_pane *wp, int c)
Definition: window.c:1048
int window_pane_start_input(struct window_pane *wp, struct cmdq_item *item, char **cause)
Definition: window.c:1549
struct winlink * winlink_find_by_index(struct winlinks *wwl, int idx)
Definition: window.c:109
int window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
Definition: window.c:469
static void window_pane_error_callback(struct bufferevent *bufev, short what, void *data)
Definition: window.c:962
struct window_pane * window_pane_find_right(struct window_pane *wp)
Definition: window.c:1430
static struct window_pane * window_pane_choose_best(struct window_pane **list, u_int size)
Definition: window.c:1246
struct window * window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
Definition: window.c:298
struct window_pane * window_pane_find_left(struct window_pane *wp)
Definition: window.c:1382
void winlink_remove(struct winlinks *wwl, struct winlink *wl)
Definition: window.c:193
struct window_pane * window_pane_at_index(struct window *w, u_int idx)
Definition: window.c:718
struct window * window_find_by_id_str(const char *s)
Definition: window.c:267
void winlink_stack_push(struct winlink_stack *stack, struct winlink *wl)
Definition: window.c:241
void winlink_clear_flags(struct winlink *wl)
Definition: window.c:1478
u_int window_count_panes(struct window *w)
Definition: window.c:773
RB_GENERATE(windows, window, entry, window_cmp)
struct window_pane * window_find_string(struct window *w, const char *s)
Definition: window.c:542
void window_remove_ref(struct window *w, const char *from)
Definition: window.c:391
struct winlink * winlink_next_by_number(struct winlink *wl, struct session *s, int n)
Definition: window.c:219
struct window_pane * window_add_pane(struct window *w, struct window_pane *other, u_int hlimit, int flags)
Definition: window.c:656
static int winlink_next_index(struct winlinks *wwl, int idx)
Definition: window.c:133
void window_redraw_active_switch(struct window *w, struct window_pane *wp)
Definition: window.c:489
void window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
Definition: window.c:987
int window_pane_index(struct window_pane *wp, u_int *i)
Definition: window.c:756
struct winlink * winlink_next(struct winlink *wl)
Definition: window.c:207
void window_pane_reset_palette(struct window_pane *wp)
Definition: window.c:1037
int window_unzoom(struct window *w)
Definition: window.c:611
void window_remove_pane(struct window *w, struct window_pane *wp)
Definition: window.c:709
void window_pane_reset_mode_all(struct window_pane *wp)
Definition: window.c:1135
int window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2)
Definition: window.c:90
const char * window_printable_flags(struct winlink *wl, int escape)
Definition: window.c:797
void window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
Definition: window.c:409
struct window_pane * window_pane_find_by_id(u_int id)
Definition: window.c:841
int window_push_zoom(struct window *w, int always, int flag)
Definition: window.c:634
struct window_pane * window_pane_find_by_id_str(const char *s)
Definition: window.c:826
int window_zoom(struct window_pane *wp)
Definition: window.c:583
static void window_pane_input_callback(struct client *c, const char *path, int error, int closed, struct evbuffer *buffer, void *data)
Definition: window.c:1524
struct winlink * winlink_previous_by_number(struct winlink *wl, struct session *s, int n)
Definition: window.c:230
static u_int next_window_pane_id
Definition: window.c:60
int window_pop_zoom(struct window *w)
Definition: window.c:646
void * window_pane_get_new_data(struct window_pane *wp, struct window_pane_offset *wpo, size_t *size)
Definition: window.c:1571
u_int window_pane_search(struct window_pane *wp, const char *term, int regex, int ignore)
Definition: window.c:1197
int winlink_shuffle_up(struct session *s, struct winlink *wl, int before)
Definition: window.c:1493
static void window_pane_read_callback(struct bufferevent *bufev, void *data)
Definition: window.c:934
void winlink_set_window(struct winlink *wl, struct window *w)
Definition: window.c:181
void window_pane_reset_mode(struct window_pane *wp)
Definition: window.c:1105
void window_pane_update_used_data(struct window_pane *wp, struct window_pane_offset *wpo, size_t size)
Definition: window.c:1581
int window_has_pane(struct window *w, struct window_pane *wp)
Definition: window.c:457
static struct window_pane * window_pane_create(struct window *, u_int, u_int, u_int)
Definition: window.c:850
void window_pane_set_palette(struct window_pane *wp, u_int n, int colour)
Definition: window.c:1014
struct window_pane * window_pane_find_down(struct window_pane *wp)
Definition: window.c:1325
struct window_pane * window_get_active_at(struct window *w, u_int x, u_int y)
Definition: window.c:525
void window_update_activity(struct window *w)
Definition: window.c:291
void window_lost_pane(struct window *w, struct window_pane *wp)
Definition: window.c:685
static u_int next_window_id
Definition: window.c:61
void winlink_stack_remove(struct winlink_stack *stack, struct winlink *wl)
Definition: window.c:251
struct windows windows
Definition: window.c:56
int window_pane_visible(struct window_pane *wp)
Definition: window.c:1189
static void window_pane_destroy(struct window_pane *)
Definition: window.c:889
int window_cmp(struct window *w1, struct window *w2)
Definition: window.c:78
struct winlink * winlink_add(struct winlinks *wwl, int idx)
Definition: window.c:163
void window_pane_send_resize(struct window_pane *wp, u_int sx, u_int sy)
Definition: window.c:428
struct winlink * winlink_find_by_window_id(struct winlinks *wwl, u_int id)
Definition: window.c:121
u_int winlink_count(struct winlinks *wwl)
Definition: window.c:150
void window_add_ref(struct window *w, const char *from)
Definition: window.c:384
struct winlink * winlink_find_by_window(struct winlinks *wwl, struct window *w)
Definition: window.c:96
static void window_pane_copy_key(struct window_pane *wp, key_code key)
Definition: window.c:1142
void window_set_name(struct window *w, const char *new_name)
Definition: window.c:401
struct winlink * winlink_previous(struct winlink *wl)
Definition: window.c:213
static u_int next_active_point
Definition: window.c:62
struct window_pane * window_pane_find_up(struct window_pane *wp)
Definition: window.c:1268
void window_pane_unset_palette(struct window_pane *wp, u_int n)
Definition: window.c:1027
int window_pane_set_mode(struct window_pane *wp, struct window_pane *swp, const struct window_mode *mode, struct cmd_find_state *fs, struct args *args)
Definition: window.c:1068
struct window_pane_tree all_window_panes
Definition: window.c:59
int window_pane_key(struct window_pane *wp, struct client *c, struct session *s, struct winlink *wl, key_code key, struct mouse_event *m)
Definition: window.c:1158
struct window_pane * window_pane_previous_by_number(struct window *w, struct window_pane *wp, u_int n)
Definition: window.c:744
void window_pane_set_event(struct window_pane *wp)
Definition: window.c:975
int window_pane_destroy_ready(struct window_pane *wp)
Definition: window.c:367
struct window * window_find_by_id(u_int id)
Definition: window.c:282
void * xmalloc(size_t size)
Definition: xmalloc.c:27
void * xreallocarray(void *ptr, size_t nmemb, size_t size)
Definition: xmalloc.c:61
int xasprintf(char **ret, const char *fmt,...)
Definition: xmalloc.c:109
void * xcalloc(size_t nmemb, size_t size)
Definition: xmalloc.c:41
char * xstrdup(const char *str)
Definition: xmalloc.c:89