Coverage Report

Created: 2025-07-11 06:20

/src/tmux/cmd-swap-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
23
#include "tmux.h"
24
25
/*
26
 * Swap two panes.
27
 */
28
29
static enum cmd_retval  cmd_swap_pane_exec(struct cmd *, struct cmdq_item *);
30
31
const struct cmd_entry cmd_swap_pane_entry = {
32
  .name = "swap-pane",
33
  .alias = "swapp",
34
35
  .args = { "dDs:t:UZ", 0, 0, NULL },
36
  .usage = "[-dDUZ] " CMD_SRCDST_PANE_USAGE,
37
38
  .source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED },
39
  .target = { 't', CMD_FIND_PANE, 0 },
40
41
  .flags = 0,
42
  .exec = cmd_swap_pane_exec
43
};
44
45
static enum cmd_retval
46
cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
47
0
{
48
0
  struct args   *args = cmd_get_args(self);
49
0
  struct cmd_find_state *source = cmdq_get_source(item);
50
0
  struct cmd_find_state *target = cmdq_get_target(item);
51
0
  struct window   *src_w, *dst_w;
52
0
  struct window_pane  *tmp_wp, *src_wp, *dst_wp;
53
0
  struct layout_cell  *src_lc, *dst_lc;
54
0
  u_int      sx, sy, xoff, yoff;
55
56
0
  dst_w = target->wl->window;
57
0
  dst_wp = target->wp;
58
0
  src_w = source->wl->window;
59
0
  src_wp = source->wp;
60
61
0
  if (window_push_zoom(dst_w, 0, args_has(args, 'Z')))
62
0
    server_redraw_window(dst_w);
63
64
0
  if (args_has(args, 'D')) {
65
0
    src_w = dst_w;
66
0
    src_wp = TAILQ_NEXT(dst_wp, entry);
67
0
    if (src_wp == NULL)
68
0
      src_wp = TAILQ_FIRST(&dst_w->panes);
69
0
  } else if (args_has(args, 'U')) {
70
0
    src_w = dst_w;
71
0
    src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
72
0
    if (src_wp == NULL)
73
0
      src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
74
0
  }
75
76
0
  if (src_w != dst_w && window_push_zoom(src_w, 0, args_has(args, 'Z')))
77
0
    server_redraw_window(src_w);
78
79
0
  if (src_wp == dst_wp)
80
0
    goto out;
81
82
0
  server_client_remove_pane(src_wp);
83
0
  server_client_remove_pane(dst_wp);
84
85
0
  tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
86
0
  TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
87
0
  TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
88
0
  if (tmp_wp == src_wp)
89
0
    tmp_wp = dst_wp;
90
0
  if (tmp_wp == NULL)
91
0
    TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
92
0
  else
93
0
    TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);
94
95
0
  src_lc = src_wp->layout_cell;
96
0
  dst_lc = dst_wp->layout_cell;
97
0
  src_lc->wp = dst_wp;
98
0
  dst_wp->layout_cell = src_lc;
99
0
  dst_lc->wp = src_wp;
100
0
  src_wp->layout_cell = dst_lc;
101
102
0
  src_wp->window = dst_w;
103
0
  options_set_parent(src_wp->options, dst_w->options);
104
0
  src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
105
0
  dst_wp->window = src_w;
106
0
  options_set_parent(dst_wp->options, src_w->options);
107
0
  dst_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
108
109
0
  sx = src_wp->sx; sy = src_wp->sy;
110
0
  xoff = src_wp->xoff; yoff = src_wp->yoff;
111
0
  src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff;
112
0
  window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy);
113
0
  dst_wp->xoff = xoff; dst_wp->yoff = yoff;
114
0
  window_pane_resize(dst_wp, sx, sy);
115
116
0
  if (!args_has(args, 'd')) {
117
0
    if (src_w != dst_w) {
118
0
      window_set_active_pane(src_w, dst_wp, 1);
119
0
      window_set_active_pane(dst_w, src_wp, 1);
120
0
    } else {
121
0
      tmp_wp = dst_wp;
122
0
      window_set_active_pane(src_w, tmp_wp, 1);
123
0
    }
124
0
  } else {
125
0
    if (src_w->active == src_wp)
126
0
      window_set_active_pane(src_w, dst_wp, 1);
127
0
    if (dst_w->active == dst_wp)
128
0
      window_set_active_pane(dst_w, src_wp, 1);
129
0
  }
130
0
  if (src_w != dst_w) {
131
0
    window_pane_stack_remove(&src_w->last_panes, src_wp);
132
0
    window_pane_stack_remove(&dst_w->last_panes, dst_wp);
133
0
    colour_palette_from_option(&src_wp->palette, src_wp->options);
134
0
    colour_palette_from_option(&dst_wp->palette, dst_wp->options);
135
0
    layout_fix_panes(src_w, NULL);
136
0
    server_redraw_window(src_w);
137
0
  }
138
0
  layout_fix_panes(dst_w, NULL);
139
0
  server_redraw_window(dst_w);
140
141
0
  notify_window("window-layout-changed", src_w);
142
0
  if (src_w != dst_w)
143
0
    notify_window("window-layout-changed", dst_w);
144
145
0
out:
146
0
  if (window_pop_zoom(src_w))
147
0
    server_redraw_window(src_w);
148
0
  if (src_w != dst_w && window_pop_zoom(dst_w))
149
0
    server_redraw_window(dst_w);
150
0
  return (CMD_RETURN_NORMAL);
151
0
}