Bug Summary

File:src/usr.bin/tmux/window.c
Warning:line 1119, column 46
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

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