ztmux 3.7.10

A Rust port of tmux — the full terminal multiplexer, server and client
Documentation
// Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
// OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
use crate::compat::queue::tailq_empty;
use crate::*;
use crate::options_::*;

pub static CMD_RESIZE_PANE_ENTRY: cmd_entry = cmd_entry {
    name: "resize-pane",
    alias: Some("resizep"),

    args: args_parse::new("DLMRTt:Ux:y:Z", 0, 1, None),
    usage: "[-DLMRTUZ] [-x width] [-y height] [-t target-pane] [adjustment]",

    target: cmd_entry_flag::new(b't', cmd_find_type::CMD_FIND_PANE, cmd_find_flags::empty()),

    flags: cmd_flag::CMD_AFTERHOOK,
    exec: cmd_resize_pane_exec,
    source: cmd_entry_flag::zeroed(),
};

/// C `vendor/tmux/cmd-resize-pane.c:55`: `static enum cmd_retval cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)`
unsafe fn cmd_resize_pane_exec(self_: *mut cmd, item: *mut cmdq_item) -> cmd_retval {
    unsafe {
        let args = cmd_get_args(self_);
        let target = cmdq_get_target(item);
        let event = cmdq_get_event(item);
        let wp = (*target).wp;
        let wl = (*target).wl;
        let w = (*wl).window;
        let c = cmdq_get_client(item);
        let mut s = (*target).s;
        let mut cause: *mut u8 = null_mut();
        let mut adjust;
        let x: i32;
        let mut y: i32;
        let gd = (*wp).base.grid;

        if args_has(args, 'T') {
            if !tailq_empty(&raw mut (*wp).modes) {
                return cmd_retval::CMD_RETURN_NORMAL;
            }
            adjust = screen_size_y(&raw mut (*wp).base) - 1 - (*wp).base.cy;
            if adjust > (*gd).hsize {
                adjust = (*gd).hsize;
            }
            grid_remove_history(gd, adjust);
            (*wp).base.cy += adjust;
            (*wp).flags |= window_pane_flags::PANE_REDRAW;
            return cmd_retval::CMD_RETURN_NORMAL;
        }

        if args_has(args, 'M') {
            if !(*event).m.valid || cmd_mouse_window(&raw mut (*event).m, &raw mut s).is_none() {
                return cmd_retval::CMD_RETURN_NORMAL;
            }
            if c.is_null() || (*c).session != s {
                return cmd_retval::CMD_RETURN_NORMAL;
            }
            (*c).tty.mouse_drag_update = Some(cmd_resize_pane_mouse_update);
            cmd_resize_pane_mouse_update(c, &raw mut (*event).m);
            return cmd_retval::CMD_RETURN_NORMAL;
        }

        if args_has(args, 'Z') {
            if (*w).flags.intersects(window_flag::ZOOMED) {
                window_unzoom(w, 1);
            } else {
                window_zoom(wp);
            }
            server_redraw_window(w);
            return cmd_retval::CMD_RETURN_NORMAL;
        }
        server_unzoom_window(w);

        let adjust = if args_count(args) == 0 {
            1
        } else {
            match strtonum(args_string(args, 0), 1, i32::MAX) {
                Ok(n) => n,
                Err(errstr) => {
                    cmdq_error!(item, "adjustment {}", _s(errstr.as_ptr()));
                    return cmd_retval::CMD_RETURN_ERROR;
                }
            }
        };

        if args_has(args, 'x') {
            x = args_percentage(
                args,
                b'x',
                0,
                i32::MAX as i64,
                (*w).sx as i64,
                &raw mut cause,
            ) as i32;
            if !cause.is_null() {
                cmdq_error!(item, "width {}", _s(cause));
                free_(cause);
                return cmd_retval::CMD_RETURN_ERROR;
            }
            layout_resize_pane_to(wp, layout_type::LAYOUT_LEFTRIGHT, x as u32);
        }
        if args_has(args, 'y') {
            y = args_percentage(
                args,
                b'y',
                0,
                i32::MAX as i64,
                (*w).sy as i64,
                &raw mut cause,
            ) as i32;
            if !cause.is_null() {
                cmdq_error!(item, "height {}", _s(cause));
                free_(cause);
                return cmd_retval::CMD_RETURN_ERROR;
            }

            let status: i32 = options_get_number___(&*(*w).options, "pane-border-status");
            match pane_status::try_from(status) {
                Ok(pane_status::PANE_STATUS_TOP) => {
                    if y != i32::MAX && (*wp).yoff == 1 {
                        y += 1;
                    }
                }
                Ok(pane_status::PANE_STATUS_BOTTOM) => {
                    if y != i32::MAX && (*wp).yoff + (*wp).sy == (*w).sy - 1 {
                        y += 1;
                    }
                }
                Ok(pane_status::PANE_STATUS_OFF) | Err(_) => (),
            }
            layout_resize_pane_to(wp, layout_type::LAYOUT_TOPBOTTOM, y as u32);
        }

        if args_has(args, 'L') {
            layout_resize_pane(wp, layout_type::LAYOUT_LEFTRIGHT, -adjust, 1);
        } else if args_has(args, 'R') {
            layout_resize_pane(wp, layout_type::LAYOUT_LEFTRIGHT, adjust, 1);
        } else if args_has(args, 'U') {
            layout_resize_pane(wp, layout_type::LAYOUT_TOPBOTTOM, -adjust, 1);
        } else if args_has(args, 'D') {
            layout_resize_pane(wp, layout_type::LAYOUT_TOPBOTTOM, adjust, 1);
        }
        server_redraw_window((*wl).window);
    }

    cmd_retval::CMD_RETURN_NORMAL
}

/// C `vendor/tmux/cmd-resize-pane.c:192`: `static enum cmd_retval cmd_resize_pane_mouse_update(__unused struct cmd *self, struct cmdq_item *item)`
unsafe fn cmd_resize_pane_mouse_update(c: *mut client, m: *mut mouse_event) {
    unsafe {
        let mut y: u32;
        let mut ly: u32;

        const OFFSETS: [[c_int; 2]; 5] = [[0, 0], [0, 1], [1, 0], [0, -1], [-1, 0]];
        let mut ncells: u32 = 0;
        let mut cells: [*mut layout_cell; OFFSETS.len()] = zeroed();
        let mut resizes: u32 = 0;

        let wl: *mut winlink = transmute_ptr(cmd_mouse_window(m, null_mut()));
        if wl.is_null() {
            (*c).tty.mouse_drag_update = None;
            return;
        }
        let w: *mut window = (*wl).window;

        y = (*m).y + (*m).oy;
        let x: u32 = (*m).x + (*m).ox;
        if (*m).statusat == 0 && y >= (*m).statuslines {
            y -= (*m).statuslines;
        } else if (*m).statusat > 0 && y >= (*m).statusat as u32 {
            y = ((*m).statusat - 1) as u32;
        }
        ly = (*m).ly + (*m).oy;
        let lx: u32 = (*m).lx + (*m).ox;
        if (*m).statusat == 0 && ly >= (*m).statuslines {
            ly -= (*m).statuslines;
        } else if (*m).statusat > 0 && ly >= (*m).statusat as u32 {
            ly = ((*m).statusat - 1) as u32;
        }

        for offset in OFFSETS {
            let mut lc = layout_search_by_border(
                (*w).layout_root,
                (lx as i32 + offset[0]).max(0) as u32,
                (ly as i32 + offset[1]).max(0) as u32,
            );
            if lc.is_null() {
                continue;
            }

            for j in 0..ncells {
                if cells[j as usize] == lc {
                    lc = null_mut();
                    break;
                }
            }
            if lc.is_null() {
                continue;
            }

            cells[ncells as usize] = lc;
            ncells += 1;
        }
        if ncells == 0 {
            return;
        }

        for i in 0..ncells {
            let type_ = (*(*cells[i as usize]).parent).type_;
            if y != ly && type_ == layout_type::LAYOUT_TOPBOTTOM {
                layout_resize_layout(w, cells[i as usize], type_, y as i32 - ly as i32, 0);
                resizes += 1;
            } else if x != lx && type_ == layout_type::LAYOUT_LEFTRIGHT {
                layout_resize_layout(w, cells[i as usize], type_, x as i32 - lx as i32, 0);
                resizes += 1;
            }
        }
        if resizes != 0 {
            server_redraw_window(w);
        }
    }
}