| 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 | } |