File: | src/usr.bin/tmux/window.c |
Warning: | line 1119, column 46 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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. */ | |||
58 | struct windows windows; | |||
59 | ||||
60 | /* Global panes tree. */ | |||
61 | struct window_pane_tree all_window_panes; | |||
62 | static u_int next_window_pane_id; | |||
63 | static u_int next_window_id; | |||
64 | static u_int next_active_point; | |||
65 | ||||
66 | struct window_pane_input_data { | |||
67 | struct cmdq_item *item; | |||
68 | u_int wp; | |||
69 | }; | |||
70 | ||||
71 | static struct window_pane *window_pane_create(struct window *, u_int, u_int, | |||
72 | u_int); | |||
73 | static void window_pane_destroy(struct window_pane *); | |||
74 | ||||
75 | RB_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); }; | |||
76 | RB_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); }; | |||
77 | RB_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 | ||||
79 | int | |||
80 | window_cmp(struct window *w1, struct window *w2) | |||
81 | { | |||
82 | return (w1->id - w2->id); | |||
83 | } | |||
84 | ||||
85 | int | |||
86 | winlink_cmp(struct winlink *wl1, struct winlink *wl2) | |||
87 | { | |||
88 | return (wl1->idx - wl2->idx); | |||
89 | } | |||
90 | ||||
91 | int | |||
92 | window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2) | |||
93 | { | |||
94 | return (wp1->id - wp2->id); | |||
95 | } | |||
96 | ||||
97 | struct winlink * | |||
98 | winlink_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 | ||||
110 | struct winlink * | |||
111 | winlink_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 | ||||
122 | struct winlink * | |||
123 | winlink_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 | ||||
134 | static int | |||
135 | winlink_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 | ||||
151 | u_int | |||
152 | winlink_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 | ||||
164 | struct winlink * | |||
165 | winlink_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 | ||||
182 | void | |||
183 | winlink_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 | ||||
194 | void | |||
195 | winlink_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 | ||||
208 | struct winlink * | |||
209 | winlink_next(struct winlink *wl) | |||
210 | { | |||
211 | return (RB_NEXT(winlinks, wwl, wl)winlinks_RB_NEXT(wl)); | |||
212 | } | |||
213 | ||||
214 | struct winlink * | |||
215 | winlink_previous(struct winlink *wl) | |||
216 | { | |||
217 | return (RB_PREV(winlinks, wwl, wl)winlinks_RB_PREV(wl)); | |||
218 | } | |||
219 | ||||
220 | struct winlink * | |||
221 | winlink_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 | ||||
231 | struct winlink * | |||
232 | winlink_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 | ||||
242 | void | |||
243 | winlink_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 | ||||
252 | void | |||
253 | winlink_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 | ||||
268 | struct window * | |||
269 | window_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 | ||||
283 | struct window * | |||
284 | window_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 | ||||
292 | void | |||
293 | window_update_activity(struct window *w) | |||
294 | { | |||
295 | gettimeofday(&w->activity_time, NULL((void *)0)); | |||
296 | alerts_queue(w, WINDOW_ACTIVITY0x2); | |||
297 | } | |||
298 | ||||
299 | struct window * | |||
300 | window_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 | ||||
341 | static void | |||
342 | window_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 | ||||
370 | int | |||
371 | window_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 | ||||
387 | void | |||
388 | window_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 | ||||
394 | void | |||
395 | window_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 | ||||
404 | void | |||
405 | window_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 | ||||
412 | void | |||
413 | window_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 | ||||
431 | void | |||
432 | window_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 | ||||
451 | int | |||
452 | window_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 | ||||
463 | void | |||
464 | window_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 | ||||
472 | void | |||
473 | window_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 | ||||
509 | int | |||
510 | window_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 | ||||
534 | static int | |||
535 | window_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 | ||||
542 | void | |||
543 | window_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 | ||||
578 | struct window_pane * | |||
579 | window_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 | ||||
595 | struct window_pane * | |||
596 | window_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 | ||||
636 | int | |||
637 | window_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 | ||||
664 | int | |||
665 | window_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 | ||||
687 | int | |||
688 | window_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 | ||||
699 | int | |||
700 | window_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 | ||||
709 | struct window_pane * | |||
710 | window_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 | ||||
738 | void | |||
739 | window_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 | ||||
762 | void | |||
763 | window_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); | |||
| ||||
768 | window_pane_destroy(wp); | |||
769 | } | |||
770 | ||||
771 | struct window_pane * | |||
772 | window_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 | ||||
786 | struct window_pane * | |||
787 | window_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 | ||||
797 | struct window_pane * | |||
798 | window_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 | ||||
809 | int | |||
810 | window_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 | ||||
826 | u_int | |||
827 | window_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 | ||||
838 | void | |||
839 | window_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 | ||||
850 | const char * | |||
851 | window_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 | ||||
879 | struct window_pane * | |||
880 | window_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 | ||||
894 | struct window_pane * | |||
895 | window_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 | ||||
903 | static struct window_pane * | |||
904 | window_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 | ||||
942 | static void | |||
943 | window_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); | |||
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 | ||||
984 | static void | |||
985 | window_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 | ||||
1012 | static void | |||
1013 | window_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 | ||||
1025 | void | |||
1026 | window_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 | ||||
1037 | void | |||
1038 | window_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 | ||||
1064 | int | |||
1065 | window_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 | ||||
1101 | void | |||
1102 | window_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))) | |||
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); | |||
1111 | wme->mode->free(wme); | |||
1112 | free(wme); | |||
1113 | ||||
1114 | next = TAILQ_FIRST(&wp->modes)((&wp->modes)->tqh_first); | |||
1115 | if (next
| |||
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); | |||
| ||||
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 | ||||
1131 | void | |||
1132 | window_pane_reset_mode_all(struct window_pane *wp) | |||
1133 | { | |||
1134 | while (!TAILQ_EMPTY(&wp->modes)(((&wp->modes)->tqh_first) == ((void *)0))) | |||
1135 | window_pane_reset_mode(wp); | |||
1136 | } | |||
1137 | ||||
1138 | static void | |||
1139 | window_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 | ||||
1154 | int | |||
1155 | window_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 | ||||
1185 | int | |||
1186 | window_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 | ||||
1193 | u_int | |||
1194 | window_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. */ | |||
1242 | static struct window_pane * | |||
1243 | window_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 | */ | |||
1264 | struct window_pane * | |||
1265 | window_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. */ | |||
1321 | struct window_pane * | |||
1322 | window_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. */ | |||
1378 | struct window_pane * | |||
1379 | window_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. */ | |||
1426 | struct window_pane * | |||
1427 | window_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 */ | |||
1474 | void | |||
1475 | winlink_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. */ | |||
1489 | int | |||
1490 | winlink_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 | ||||
1520 | static void | |||
1521 | window_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 | ||||
1545 | int | |||
1546 | window_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 | ||||
1571 | void * | |||
1572 | window_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 | ||||
1581 | void | |||
1582 | window_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 | } |