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