15494e770Schristos /* $OpenBSD$ */ 2698d5317Sjmmv 3698d5317Sjmmv /* 4ed4e6cd4Schristos * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> 5698d5317Sjmmv * 6698d5317Sjmmv * Permission to use, copy, modify, and distribute this software for any 7698d5317Sjmmv * purpose with or without fee is hereby granted, provided that the above 8698d5317Sjmmv * copyright notice and this permission notice appear in all copies. 9698d5317Sjmmv * 10698d5317Sjmmv * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11698d5317Sjmmv * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12698d5317Sjmmv * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13698d5317Sjmmv * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14698d5317Sjmmv * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15698d5317Sjmmv * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16698d5317Sjmmv * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17698d5317Sjmmv */ 18698d5317Sjmmv 19698d5317Sjmmv #include <sys/types.h> 20698d5317Sjmmv 21698d5317Sjmmv #include <stdlib.h> 22aa83ff61Schristos #include <string.h> 23698d5317Sjmmv 24698d5317Sjmmv #include "tmux.h" 25698d5317Sjmmv 26698d5317Sjmmv /* 27698d5317Sjmmv * Increase or decrease pane size. 28698d5317Sjmmv */ 29698d5317Sjmmv 304e179ddaSchristos static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *); 31698d5317Sjmmv 324e179ddaSchristos static void cmd_resize_pane_mouse_update(struct client *, 334e179ddaSchristos struct mouse_event *); 345494e770Schristos 35698d5317Sjmmv const struct cmd_entry cmd_resize_pane_entry = { 36ed4e6cd4Schristos .name = "resize-pane", 37ed4e6cd4Schristos .alias = "resizep", 38ed4e6cd4Schristos 396db26757Swiz .args = { "DLMRTt:Ux:y:Z", 0, 1, NULL }, 409fb66d81Schristos .usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " " 415494e770Schristos "[adjustment]", 42ed4e6cd4Schristos 43c9ad075bSchristos .target = { 't', CMD_FIND_PANE, 0 }, 44ed4e6cd4Schristos 454e179ddaSchristos .flags = CMD_AFTERHOOK, 46ed4e6cd4Schristos .exec = cmd_resize_pane_exec 47698d5317Sjmmv }; 48698d5317Sjmmv 494e179ddaSchristos static enum cmd_retval 504e179ddaSchristos cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) 51698d5317Sjmmv { 529fb66d81Schristos struct args *args = cmd_get_args(self); 539fb66d81Schristos struct cmd_find_state *target = cmdq_get_target(item); 549fb66d81Schristos struct key_event *event = cmdq_get_event(item); 559fb66d81Schristos struct window_pane *wp = target->wp; 569fb66d81Schristos struct winlink *wl = target->wl; 57ed4e6cd4Schristos struct window *w = wl->window; 589fb66d81Schristos struct client *c = cmdq_get_client(item); 599fb66d81Schristos struct session *s = target->s; 609fb66d81Schristos const char *errstr; 619fb66d81Schristos char *cause; 62698d5317Sjmmv u_int adjust; 636db26757Swiz int x, y, status; 649fb66d81Schristos struct grid *gd = wp->base.grid; 659fb66d81Schristos 669fb66d81Schristos if (args_has(args, 'T')) { 679fb66d81Schristos if (!TAILQ_EMPTY(&wp->modes)) 689fb66d81Schristos return (CMD_RETURN_NORMAL); 699fb66d81Schristos adjust = screen_size_y(&wp->base) - 1 - wp->base.cy; 709fb66d81Schristos if (adjust > gd->hsize) 719fb66d81Schristos adjust = gd->hsize; 729fb66d81Schristos grid_remove_history(gd, adjust); 739fb66d81Schristos wp->base.cy += adjust; 749fb66d81Schristos wp->flags |= PANE_REDRAW; 759fb66d81Schristos return (CMD_RETURN_NORMAL); 769fb66d81Schristos } 77698d5317Sjmmv 785494e770Schristos if (args_has(args, 'M')) { 799fb66d81Schristos if (!event->m.valid || cmd_mouse_window(&event->m, &s) == NULL) 805494e770Schristos return (CMD_RETURN_NORMAL); 815494e770Schristos if (c == NULL || c->session != s) 825494e770Schristos return (CMD_RETURN_NORMAL); 835494e770Schristos c->tty.mouse_drag_update = cmd_resize_pane_mouse_update; 849fb66d81Schristos cmd_resize_pane_mouse_update(c, &event->m); 855494e770Schristos return (CMD_RETURN_NORMAL); 865494e770Schristos } 875494e770Schristos 88928fc495Schristos if (args_has(args, 'Z')) { 89928fc495Schristos if (w->flags & WINDOW_ZOOMED) 90*f8cf1a91Swiz window_unzoom(w, 1); 91928fc495Schristos else 92928fc495Schristos window_zoom(wp); 93928fc495Schristos server_redraw_window(w); 94928fc495Schristos return (CMD_RETURN_NORMAL); 95928fc495Schristos } 96928fc495Schristos server_unzoom_window(w); 97698d5317Sjmmv 986db26757Swiz if (args_count(args) == 0) 99698d5317Sjmmv adjust = 1; 100698d5317Sjmmv else { 1016db26757Swiz adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr); 102698d5317Sjmmv if (errstr != NULL) { 1034e179ddaSchristos cmdq_error(item, "adjustment %s", errstr); 104928fc495Schristos return (CMD_RETURN_ERROR); 105698d5317Sjmmv } 106698d5317Sjmmv } 107698d5317Sjmmv 1089fb66d81Schristos if (args_has(args, 'x')) { 1099fb66d81Schristos x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause); 110928fc495Schristos if (cause != NULL) { 1114e179ddaSchristos cmdq_error(item, "width %s", cause); 112928fc495Schristos free(cause); 113928fc495Schristos return (CMD_RETURN_ERROR); 114928fc495Schristos } 115928fc495Schristos layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x); 116928fc495Schristos } 1179fb66d81Schristos if (args_has(args, 'y')) { 1189fb66d81Schristos y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause); 119928fc495Schristos if (cause != NULL) { 1204e179ddaSchristos cmdq_error(item, "height %s", cause); 121928fc495Schristos free(cause); 122928fc495Schristos return (CMD_RETURN_ERROR); 123928fc495Schristos } 1246db26757Swiz status = options_get_number(w->options, "pane-border-status"); 1256db26757Swiz switch (status) { 1266db26757Swiz case PANE_STATUS_TOP: 1276db26757Swiz if (y != INT_MAX && wp->yoff == 1) 1286db26757Swiz y++; 1296db26757Swiz break; 1306db26757Swiz case PANE_STATUS_BOTTOM: 1316db26757Swiz if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1) 1326db26757Swiz y++; 1336db26757Swiz break; 1346db26757Swiz } 135928fc495Schristos layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y); 136928fc495Schristos } 137928fc495Schristos 138ef36e747Schristos if (args_has(args, 'L')) 1394e179ddaSchristos layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1); 140ef36e747Schristos else if (args_has(args, 'R')) 1414e179ddaSchristos layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1); 142ef36e747Schristos else if (args_has(args, 'U')) 1434e179ddaSchristos layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1); 144ef36e747Schristos else if (args_has(args, 'D')) 1454e179ddaSchristos layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1); 146698d5317Sjmmv server_redraw_window(wl->window); 147698d5317Sjmmv 148928fc495Schristos return (CMD_RETURN_NORMAL); 149698d5317Sjmmv } 1505494e770Schristos 1514e179ddaSchristos static void 1525494e770Schristos cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m) 1535494e770Schristos { 1545494e770Schristos struct winlink *wl; 1558f3b9483Schristos struct window *w; 1568f3b9483Schristos u_int y, ly, x, lx; 1578f3b9483Schristos static const int offsets[][2] = { 1588f3b9483Schristos { 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }, 1598f3b9483Schristos }; 1608f3b9483Schristos struct layout_cell *cells[nitems(offsets)], *lc; 1618f3b9483Schristos u_int ncells = 0, i, j, resizes = 0; 1628f3b9483Schristos enum layout_type type; 1635494e770Schristos 1645494e770Schristos wl = cmd_mouse_window(m, NULL); 1655494e770Schristos if (wl == NULL) { 1665494e770Schristos c->tty.mouse_drag_update = NULL; 1675494e770Schristos return; 1685494e770Schristos } 1698f3b9483Schristos w = wl->window; 1705494e770Schristos 1716483eba0Schristos y = m->y + m->oy; x = m->x + m->ox; 1726483eba0Schristos if (m->statusat == 0 && y >= m->statuslines) 1736483eba0Schristos y -= m->statuslines; 1745494e770Schristos else if (m->statusat > 0 && y >= (u_int)m->statusat) 1755494e770Schristos y = m->statusat - 1; 1766483eba0Schristos ly = m->ly + m->oy; lx = m->lx + m->ox; 1776483eba0Schristos if (m->statusat == 0 && ly >= m->statuslines) 1786483eba0Schristos ly -= m->statuslines; 1795494e770Schristos else if (m->statusat > 0 && ly >= (u_int)m->statusat) 1805494e770Schristos ly = m->statusat - 1; 1815494e770Schristos 1828f3b9483Schristos for (i = 0; i < nitems(cells); i++) { 1838f3b9483Schristos lc = layout_search_by_border(w->layout_root, lx + offsets[i][0], 1848f3b9483Schristos ly + offsets[i][1]); 1858f3b9483Schristos if (lc == NULL) 1865494e770Schristos continue; 1875494e770Schristos 1888f3b9483Schristos for (j = 0; j < ncells; j++) { 1898f3b9483Schristos if (cells[j] == lc) { 1908f3b9483Schristos lc = NULL; 1918f3b9483Schristos break; 1925494e770Schristos } 1938f3b9483Schristos } 1948f3b9483Schristos if (lc == NULL) 1958f3b9483Schristos continue; 1968f3b9483Schristos 1978f3b9483Schristos cells[ncells] = lc; 1988f3b9483Schristos ncells++; 1998f3b9483Schristos } 2008f3b9483Schristos if (ncells == 0) 201c9ad075bSchristos return; 2028f3b9483Schristos 2038f3b9483Schristos for (i = 0; i < ncells; i++) { 2048f3b9483Schristos type = cells[i]->parent->type; 2058f3b9483Schristos if (y != ly && type == LAYOUT_TOPBOTTOM) { 2068f3b9483Schristos layout_resize_layout(w, cells[i], type, y - ly, 0); 2078f3b9483Schristos resizes++; 2088f3b9483Schristos } else if (x != lx && type == LAYOUT_LEFTRIGHT) { 2098f3b9483Schristos layout_resize_layout(w, cells[i], type, x - lx, 0); 2108f3b9483Schristos resizes++; 211c9ad075bSchristos } 2128f3b9483Schristos } 2138f3b9483Schristos if (resizes != 0) 2148f3b9483Schristos server_redraw_window(w); 2155494e770Schristos } 216