Coverage Report

Created: 2023-06-07 06:04

/src/tmux/cmd-resize-pane.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD$ */
2
3
/*
4
 * Copyright (c) 2009 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
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include "tmux.h"
25
26
/*
27
 * Increase or decrease pane size.
28
 */
29
30
static enum cmd_retval  cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
31
32
static void cmd_resize_pane_mouse_update(struct client *,
33
        struct mouse_event *);
34
35
const struct cmd_entry cmd_resize_pane_entry = {
36
  .name = "resize-pane",
37
  .alias = "resizep",
38
39
  .args = { "DLMRTt:Ux:y:Z", 0, 1, NULL },
40
  .usage = "[-DLMRTUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " "
41
     "[adjustment]",
42
43
  .target = { 't', CMD_FIND_PANE, 0 },
44
45
  .flags = CMD_AFTERHOOK,
46
  .exec = cmd_resize_pane_exec
47
};
48
49
static enum cmd_retval
50
cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
51
0
{
52
0
  struct args   *args = cmd_get_args(self);
53
0
  struct cmd_find_state *target = cmdq_get_target(item);
54
0
  struct key_event  *event = cmdq_get_event(item);
55
0
  struct window_pane  *wp = target->wp;
56
0
  struct winlink    *wl = target->wl;
57
0
  struct window   *w = wl->window;
58
0
  struct client   *c = cmdq_get_client(item);
59
0
  struct session    *s = target->s;
60
0
  const char          *errstr;
61
0
  char      *cause;
62
0
  u_int      adjust;
63
0
  int      x, y, status;
64
0
  struct grid   *gd = wp->base.grid;
65
66
0
  if (args_has(args, 'T')) {
67
0
    if (!TAILQ_EMPTY(&wp->modes))
68
0
      return (CMD_RETURN_NORMAL);
69
0
    adjust = screen_size_y(&wp->base) - 1 - wp->base.cy;
70
0
    if (adjust > gd->hsize)
71
0
      adjust = gd->hsize;
72
0
    grid_remove_history(gd, adjust);
73
0
    wp->base.cy += adjust;
74
0
    wp->flags |= PANE_REDRAW;
75
0
    return (CMD_RETURN_NORMAL);
76
0
  }
77
78
0
  if (args_has(args, 'M')) {
79
0
    if (!event->m.valid || cmd_mouse_window(&event->m, &s) == NULL)
80
0
      return (CMD_RETURN_NORMAL);
81
0
    if (c == NULL || c->session != s)
82
0
      return (CMD_RETURN_NORMAL);
83
0
    c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
84
0
    cmd_resize_pane_mouse_update(c, &event->m);
85
0
    return (CMD_RETURN_NORMAL);
86
0
  }
87
88
0
  if (args_has(args, 'Z')) {
89
0
    if (w->flags & WINDOW_ZOOMED)
90
0
      window_unzoom(w);
91
0
    else
92
0
      window_zoom(wp);
93
0
    server_redraw_window(w);
94
0
    return (CMD_RETURN_NORMAL);
95
0
  }
96
0
  server_unzoom_window(w);
97
98
0
  if (args_count(args) == 0)
99
0
    adjust = 1;
100
0
  else {
101
0
    adjust = strtonum(args_string(args, 0), 1, INT_MAX, &errstr);
102
0
    if (errstr != NULL) {
103
0
      cmdq_error(item, "adjustment %s", errstr);
104
0
      return (CMD_RETURN_ERROR);
105
0
    }
106
0
  }
107
108
0
  if (args_has(args, 'x')) {
109
0
    x = args_percentage(args, 'x', 0, INT_MAX, w->sx, &cause);
110
0
    if (cause != NULL) {
111
0
      cmdq_error(item, "width %s", cause);
112
0
      free(cause);
113
0
      return (CMD_RETURN_ERROR);
114
0
    }
115
0
    layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x);
116
0
  }
117
0
  if (args_has(args, 'y')) {
118
0
    y = args_percentage(args, 'y', 0, INT_MAX, w->sy, &cause);
119
0
    if (cause != NULL) {
120
0
      cmdq_error(item, "height %s", cause);
121
0
      free(cause);
122
0
      return (CMD_RETURN_ERROR);
123
0
    }
124
0
    status = options_get_number(w->options, "pane-border-status");
125
0
    switch (status) {
126
0
    case PANE_STATUS_TOP:
127
0
      if (y != INT_MAX && wp->yoff == 1)
128
0
        y++;
129
0
      break;
130
0
    case PANE_STATUS_BOTTOM:
131
0
      if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1)
132
0
        y++;
133
0
      break;
134
0
    }
135
0
    layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
136
0
  }
137
138
0
  if (args_has(args, 'L'))
139
0
    layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1);
140
0
  else if (args_has(args, 'R'))
141
0
    layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1);
142
0
  else if (args_has(args, 'U'))
143
0
    layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1);
144
0
  else if (args_has(args, 'D'))
145
0
    layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1);
146
0
  server_redraw_window(wl->window);
147
148
0
  return (CMD_RETURN_NORMAL);
149
0
}
150
151
static void
152
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
153
0
{
154
0
  struct winlink    *wl;
155
0
  struct window   *w;
156
0
  u_int      y, ly, x, lx;
157
0
  static const int         offsets[][2] = {
158
0
      { 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
159
0
  };
160
0
  struct layout_cell  *cells[nitems(offsets)], *lc;
161
0
  u_int      ncells = 0, i, j, resizes = 0;
162
0
  enum layout_type   type;
163
164
0
  wl = cmd_mouse_window(m, NULL);
165
0
  if (wl == NULL) {
166
0
    c->tty.mouse_drag_update = NULL;
167
0
    return;
168
0
  }
169
0
  w = wl->window;
170
171
0
  y = m->y + m->oy; x = m->x + m->ox;
172
0
  if (m->statusat == 0 && y >= m->statuslines)
173
0
    y -= m->statuslines;
174
0
  else if (m->statusat > 0 && y >= (u_int)m->statusat)
175
0
    y = m->statusat - 1;
176
0
  ly = m->ly + m->oy; lx = m->lx + m->ox;
177
0
  if (m->statusat == 0 && ly >= m->statuslines)
178
0
    ly -= m->statuslines;
179
0
  else if (m->statusat > 0 && ly >= (u_int)m->statusat)
180
0
    ly = m->statusat - 1;
181
182
0
  for (i = 0; i < nitems(cells); i++) {
183
0
    lc = layout_search_by_border(w->layout_root, lx + offsets[i][0],
184
0
        ly + offsets[i][1]);
185
0
    if (lc == NULL)
186
0
      continue;
187
188
0
    for (j = 0; j < ncells; j++) {
189
0
      if (cells[j] == lc) {
190
0
        lc = NULL;
191
0
        break;
192
0
      }
193
0
    }
194
0
    if (lc == NULL)
195
0
      continue;
196
197
0
    cells[ncells] = lc;
198
0
    ncells++;
199
0
  }
200
0
  if (ncells == 0)
201
0
    return;
202
203
0
  for (i = 0; i < ncells; i++) {
204
0
    type = cells[i]->parent->type;
205
0
    if (y != ly && type == LAYOUT_TOPBOTTOM) {
206
0
      layout_resize_layout(w, cells[i], type, y - ly, 0);
207
0
      resizes++;
208
0
    } else if (x != lx && type == LAYOUT_LEFTRIGHT) {
209
0
      layout_resize_layout(w, cells[i], type, x - lx, 0);
210
0
      resizes++;
211
0
    }
212
0
  }
213
0
  if (resizes != 0)
214
0
    server_redraw_window(w);
215
0
}