Compare commits

..

8 Commits

Author SHA1 Message Date
Nicholas Marriott
1a9ac07961 Add test images. 2026-03-13 16:48:39 +00:00
Thomas Adam
274ebb2613 Feedback from nicm 2026-03-12 08:20:05 +00:00
Thomas Adam
9c3ec2b8eb Refactor kitty images to use unified image cache API
The original kitty implementation used a passthrough approach where images
were forwarded directly to the outer terminal without being stored in tmux's
image cache.

This refactors kitty images to work like sixel images.
2026-03-05 17:21:40 +00:00
Thomas Adam
aefdb34846 rename: ENABLE_SIXEL to ENABLE_SIXEL_IMAGES 2026-03-05 17:21:18 +00:00
Thomas Adam
5a233e26ec rename ENABLE_KITTY to ENABLE_KITTY_IMAGES 2026-03-05 17:21:18 +00:00
Thomas Adam
1634db8589 configure: deprecate enable-sixel
This moves --enable-sixel to --enable-sixel-images
2026-03-05 17:21:18 +00:00
Thomas Adam
3b7e9fb175 format: add image_support
This adds a new image_support format which returns:

   "sixel" -- if sixel is compiled in
   "kitty" -- if kitty is compiled in
   "kitty,sixel" -- if compiled with both kitty and sixel
2026-03-05 17:21:18 +00:00
Thomas Adam
cf6cbe430c Add support for the kitty graphics protocol
Kitty-capable terminals (kitty, ghostty, and others) can display
inline images via APC escape sequences.

Kitty's image support uses a passthrough model: APC sequences from
programs running inside panes are relayed verbatim to the outer
terminal with cursor positioning adjusted for the pane offset.

The outer terminal handles all image rendering and therefore itself must
be kitty-aware.
2026-03-05 17:21:18 +00:00
134 changed files with 5595 additions and 8550 deletions

View File

@@ -1,11 +0,0 @@
For pull request code reviews in this repository, do not leave any review comments under any circumstances.
If asked to review a pull request, produce no comments.
Do not comment on pull requests in this repository.
For pull request code reviews in this repository, do not leave a pull request overview.
Do not leave inline review comments.
If asked to review a pull request, provide no summary, no overview, and no code comments.

View File

@@ -17,7 +17,7 @@ jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v6
- uses: dessant/lock-threads@v5
with:
github-token: ${{ github.token }}
issue-inactive-days: '30'

344
CHANGES
View File

@@ -1,347 +1,3 @@
CHANGES FROM 3.7 to 3.7a
* Fix crash in break-pane when no name is provided.
* Scrollbar options are now cached rather than being looked up for every redraw
(issue 5298).
* Only forbid #( in names, allow #[, empty names, : and .
CHANGES FROM 3.6b TO 3.7
* Add floating panes. These are panes which sit above the layout ("tiled
panes") like popups but unlike popups are not modal and behave like panes (so
the same escape sequence support). Floating panes are created with the
new-pane command, bound to * by default.
This is an early release of this feature and they are relatively limited.
Currently floating panes can only be moved and resized using the mouse. The
default second status line (if status-format is set to 2) has changed to show
a list of panes. Many obvious features are not yet available for floating
panes (notably the ability to swap floating panes, resize them using
resize-pane, change them between floating and tiles, and restore custom
layouts with floating panes).
Mostly written by Michael Grant with help from Dane Jensen; testing and fixes
from others.
* Allow run-shell arguments after a shell command to be expanded as #{1}, #{2}
and so on (from Rasmus Thystrup Karstensen in issue 5121).
* Add -g to kill-session to kill all sessions in a session group (issue 5157
from github at jiku dot jp).
* Tighten up read-only checks on attach-session, detach-client and
switch-client so that a user should be able to only detach their own client
(reported by John Walker).
* Increase escape delay if the buffer contains a partial paste end, fixes
issues with at least Windows Terminal (from jing dot empty at gmail.com issue
5088).
* When mode-keys is set to vi, do not allow the cursor to go into the invisible
extra cell to the right of the visible text; this is closer to what vi(1)
does (from Max Vim in issue 5070).
* Add a five second limit on pasting for terminals which mysteriously lose the
end sequence if the paste is too big (that is, Terminal.app) (reported by
Garri Djavadyan in issue 4527).
* Show file open errors more sensibly (reported by Meriel Luna Mittelbach in
issue 5081).
* Update supported features list for Foot terminal (from Meriel Luna Mittelbach
in issue 5079).
* Turn off the "is this a paste" guessing if the terminal supports bracket
pasting instead (issue 5031).
* Check FIONREAD for all panes not just piped panes.
* Add emacs-style recentre-top-bottom command to copy mode (issue 5053 from
sinyax75 at gmail dot com).
* Allow the indicator in tree mode to be customized by two new options:
tree-mode-preview-format and tree-mode-preview-style.
* Fix control client hang on exit after toggling no-output (issue 5049 from
Aaron Campbell). Also various other control mode fixes.
* Add support for line numbers in copy mode. There is a new
copy-mode-line-numbers option which may be set to off, default (tmux's normal
line numbering where 0 is the top visible line), absolute (first line in
history is 1), relative (relative to the cursor) and hybrid (current line is
absolute, others relative). Also adds copy-mode-line-number-style and
copy-mode-current-line-number-style to set the style of the line numbers.
When copy mode is entered with the mouse, line numbers stay off. From Leo
Henon in issue 5025.
* Make C-[ have the same bindings as Escape for terminals with extended
keys where they are different (issue 5035 from Eric Nicolas).
* Sanitize paste buffer names in paste_set and paste_rename (issue 5032 from
Barrett Ruth).
* Do not hang in run-shell when job_run fails (from Barrett Ruth in issue
5037).
* Add ability to forward progress bar to outside terminal (issue 4972
from Eric Dorland).
* Translate keypad keys to text in prompt input (from Barrett Ruth in issue
4996).
* Sanitize pane titles and window and session names more consistently and
strictly, prevents C0 characters and other invisible characters causing
problems (reported by Chris Monardo in issue 4999).
* Make clock visible on terminals without colours (from Manuel Einfalt in issue
5001).
* Add detach to default session menu (suggested by Przemyslaw Sztoch).
* Include window format variables for pane notifications (issue 5007 from Saul
Nogueras).
* Limit precision to 100 for formats to stop silly formats from running out of
memory, reported by z1281552865 at gmail dot com. Also various other similar
changes, mostly found by OSS-Fuzz.
* Add WAYLAND_DISPLAY to default update-environment (issue 4965). Also some
additional XDG_* variables (issue 5169).
* Add -C flag to command-prompt to match display-message -C (do not freeze
panes) (from Barrett Ruth in issue 4978).
* Cache user from getpwuid because it can be very expensive on some
platforms (from Ben Maurer in issue 4973).
* Add remain-on-exit key to keep pane around until a key is pressed (from
Michael Grant).
* Add some new mouse ranges called "control0" to "control9" and use to add some
mouse controls to the pane state line (from Dane Jensen with some bits from
Michael Grant).
* Handle OSC 9;4 progress bar sequence and store in format variables (from Eric
Dorland in issue 4954).
* Correctly size buffer used for parsing clipboard sequences (from Michal
Majchrowicz).
* Limit MSG_COMMAND argument to between 0 and 1000 to prevent a misbehaving
client from crashing the server (from Michal Majchrowicz).
* Reorganize host keys are represented internally so they can be built more
easily (from Dane Jensen in issue 4953).
* Add new fuzzers for command parsing, formats and styles (from David
Korczynski in issue 4957). Also fix various issues shown from these.
* Add bracket_paste_flag format flag (from George Nachman in issue 4951).
* Use \- for hyphens in tmux.1 to cause newer groff versions to render them
correctly (from Keith Thompson in issue 4948).
* Various minor code improvements and fixes from Pavel Lavrukhin (issue 4936
and others).
* Use window options for cursor-style to avoid crash when no pane (from Arden
Packeer in issue 4942).
* Fix issue where popup window gets overwritten by background updates (from
Conor Taylor in issue 4920).
* Protect against overflow when scrollbar is off screen (from san65384 at gmail
dot com in issue 4933).
* Copy hyperlinks when redrawing popup so they do not vanish (from Antoine
Gaudreau Simard in issue 4925).
* Work around systemd killing panes early during system shutdown by creating
dependencies from the panes to the service which started tmux (issue 4926
from Dmitry Torokhov).
* Allow codepoint-widths to accept ranges (from san65384 at gmail dot com in
issue 4930).
* Add a short builtin help text for each mode accessible with C-h (based on
code from Patrick Motard in issue 4751).
* Draw message as one format, allowing prompts and messages to occupy only a
portion of the status bar, overlaying the normal status content rather than
replacing the entire line. A new message-format option now controls the
entire message (like status-format). The message-style option now need to
include "fill" in order to cover the whole width (the default has
"fill=yellow"). From Conor Taylor in issue 4861.
* Add next/previous variables for windows in W: loop (from Conor Taylor in
issue 4856).
* Various bug and memory leak fixes from Renaud Allard (issue 4916).
* Add pane_pipe_pid with pipe file descriptor.
* Make -c work with new-session -A (from Jody Frankowski in issue 4906).
* Allow copy mode to work for readonly clients, except for copy commands (from
Dane Jensen).
* Pass paste buffer through vis(3) when pasting to prevent buffers containing
for example the bracket end sequence causing issues, a new -S flag disables
(reported by Mason Davis).
* Add sorting (-O flag) and a custom format (-F) to list-keys (from Dane Jensen
in issue 4845).
* Add scroll-exit-on, scroll-exit-off, scroll-exit-toggle commands to copy mode
(from xcdnlgd at hotmail dot com in issue 4884).
* Respond to DECRQM 2026 (from David Turnbull in issue 4887) and various others
(from Ayman Bagabas in issue 5118).
* Fix various memory leaks reported by Huihui Huang (issue 4872).
* Pass which clipboard is set through to the terminal (from Axel Lindskog in
issue 4858).
* Reuse extended entry when clearing RGB cell, to prevent memory growth when
cells are repeatedly cleared (from Michael K Darling in issue 4862).
* Do not write before buffer when parsing empty clipboard or palette replies,
or try to allocate zero bytes with an empty clipboard sequence (reported by
DongHan Kim).
* Various bug fixes and code improvements from Conor Taylor (issue 4848).
* Clear search counts when clearing marks in case of repeated search (reported
by Daniel Pereira in issue 4817).
* Make OSC 52 work in popups (from gogongxt at 163 dot com in issue 4797).
* Refresh copy mode when style changes (from Josh Cooper in issue 4830).
* Make sorting code common and add -O for sorting to the list commands (from
Dane Jensen in issue 4813).
* Do not treat cells as empty unless the background colour stays the same,
fixes invisible clock in clock mode (reported by Theo Buehler).
* When history-limit is changed, apply to existing panes, not just new
ones (issue 4705).
* Reevaluate menu and popup styles on each draw to allow them to change when
options change (from Josh Cooper in issues 4828 and 4829).
* Handle theme keys earlier so they are processed even if a popup is open (from
Josh Cooper in issue 4827).
* Fix window-size=latest not resizing on switch-client in session groups (from
Ilya Grigoriev in issue 4818).
* Add -e flag to command-prompt to close if empty (from Dane Jensen in issue
4812).
* Correctly draw indicators when pane-border-indicators is set to both
(reported by Ilya Grigoriev in issue 4780).
* Remember last pane or type of location for double and triple clicks and
correctly handle it changes between first and second or second and third
(issue 4795 from Shaobo Song).
* Add paste to the default pane menu (issue 4763).
* Reduce request timeout to 500 milliseconds to match the extended escape-time,
and discard palette requests if receiving a reply for a different index.
* Extend escape timeout if there are active forwarded requests not just
tmux's own requests (issue 4793).
* Correct redrawing of wide characters when overwritten (reported by Jake
Stewart in issue 4737).
* If cannot find a terminator for palette responses, treat as a partial key not
complete (issue 4749).
* Do not send theme unless it has changed, and do not send immediately when
updates are enabled (issue 5787).
* Do not use ;;s in list-keys output as it is confusing and cannot be
parsed on input (from Patrick Motard in issue 4750).
* Redraw pane borders when entering or leaving alternate screen (from Mike
Jonkmans in issue 4788).
* Add focus-follows-mouse option (from Barry Wasdell in issue 4771).
* Add selection_mode format variable for copy mode (from Mike Jonkmans in issue
4773).
* Add prompt-command-cursor-style (from Joshua Cooper in issue 4765).
* With status-keys vi, move the cursor left by one when pressing Escape to
enter command mode, like vi (issue 4767 from Joshua Cooper).
* Add {current}/{active} for -t for current window or active pane (from Manuel
Einfalt, issue 4766).
* Add support for applications to use synchronized output mode (DECSET 2026) to
prevent screen tearing during rapid updates (from Chris Lloyd in issue 4744).
* Do not set a default prompt cursor colour because some terminals (urxvt, st)
do not support the reset sequence (issue 4759).
* Add a scroll-to-mouse command for copy mode to scroll to the mouse position
and bind to the scrollbar, brings the scrollbar keys into line with the other
mouse keys (from Michael Grant in issue 4731).
* Bump the maximum number of SIXEL images to 20.
* Fix key code for M-BSpace (issue 4717).
* Fix calculation of scaled SIXEL size (from nincsnevem662 at gmail dot com in
issue 4739). Also various other fixes and improvements for SIXEL.
* Fix a race between fork and pane_current_path, most noticeable on systems
where starting processes is slow (issue 4719).
* Fix mouse position calculation on scrollbar with pane status line at the top
(issue 4738 from Michael Grant).
* Do not read outside buffer if format is a single #, and do not loop forever
if UTF-8 is unfinished in a format (reported by Giorgi Kobakhia in issue
4735).
* Add a missing skin tone character (from Jake Stewart in issue 4736).
* Allow UTF-8 characters to be combined in either order (reported by Jake
Stewart in issue 4726).
* Do not show scrollbar when entering copy mode from a pane in the alternate
screen (issue 4728 from Michael Grant).
* Fix the size calculation for left-right windows used to spread out cells
horizontally evenly (from Michael Grant in issue 4724).
* Add a get-clipboard option which when enabled (the default is off) and a
clipboard is requested from a pane, requests it from the terminal and
forwards to the requesting pane; also remove the now-redundant
forward-to-pane ability from "refresh-client -l" (issue 4275).
* Fix the noattr attribute in styles, used by the default mode-style (issue
4713).
* Do not remove TERM for commands run from config file (regression reported by
Dennis Eriksen).
* Add seconds options for clock mode (from augustus7613 dot mail at pm dot me,
issue 4697; later improved by Joao Pedro in issue 4760).
CHANGES FROM 3.6a TO 3.6b
* Remove images from the correct list when they are removed while in the
alternate screen (reported by xlabai at tencent dot com).
CHANGES FROM 3.6 TO 3.6a
* Fix a buffer overread and an infinite loop in format processing (reported by

View File

@@ -1,4 +1,9 @@
Copyright (c) Various Authors
THIS IS FOR INFORMATION ONLY, CODE IS UNDER THE LICENCE AT THE TOP OF ITS FILE.
The README, CHANGES, FAQ and TODO files are licensed under the ISC license. All
other files have a license and copyright notice at their start, typically:
Copyright (c) <author>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View File

@@ -27,7 +27,7 @@ else
AM_CFLAGS += -O0
endif
if IS_DEBUG
AM_CFLAGS += -g3 -ggdb
AM_CFLAGS += -g
AM_CFLAGS += -Wno-long-long -Wall -W -Wformat=2 -Wno-use-after-free
AM_CFLAGS += -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
AM_CFLAGS += -Wwrite-strings -Wshadow -Wpointer-arith -Wsign-compare
@@ -41,10 +41,6 @@ endif
AM_CPPFLAGS += -DDEBUG
endif
AM_CPPFLAGS += -iquote.
if IS_ASAN
AM_CFLAGS += -fsanitize=address
AM_LDFLAGS += -fsanitize=address
endif
endif
# Set flags for Solaris.
@@ -236,25 +232,24 @@ nodist_tmux_SOURCES += compat/utf8proc.c
endif
# Enable sixel support.
if ENABLE_SIXEL
if ENABLE_SIXEL_IMAGES
dist_tmux_SOURCES += image.c image-sixel.c
else
# If not sixel, still need image.c for kitty.
if ENABLE_KITTY_IMAGES
dist_tmux_SOURCES += image.c
endif
endif
# Enable kitty graphics protocol support.
if ENABLE_KITTY_IMAGES
dist_tmux_SOURCES += image-kitty.c
endif
# Add bits for fuzzing if enabled.
if NEED_FUZZING
check_PROGRAMS = \
fuzz/input-fuzzer \
fuzz/cmd-parse-fuzzer \
fuzz/format-fuzzer \
fuzz/style-fuzzer
check_PROGRAMS = fuzz/input-fuzzer
fuzz_input_fuzzer_LDFLAGS = $(FUZZING_LIBS)
fuzz_input_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
fuzz_cmd_parse_fuzzer_LDFLAGS = $(FUZZING_LIBS)
fuzz_cmd_parse_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
fuzz_format_fuzzer_LDFLAGS = $(FUZZING_LIBS)
fuzz_format_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
fuzz_style_fuzzer_LDFLAGS = $(FUZZING_LIBS)
fuzz_style_fuzzer_LDADD = $(LDADD) $(tmux_OBJECTS)
endif
# Install tmux.1 in the right format.
@@ -269,7 +264,3 @@ install-exec-hook:
$(mkdir_p) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/tmux.1.@MANFORMAT@ \
$(DESTDIR)$(mandir)/man1/tmux.1
# And uninstall it.
uninstall-hook:
rm -f $(DESTDIR)$(mandir)/man1/tmux.1

View File

@@ -61,7 +61,6 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
struct window_pane *wp;
char *cwd, *cause;
enum msgtype msgtype;
uid_t uid;
if (RB_EMPTY(&sessions)) {
cmdq_error(item, "no sessions");
@@ -107,16 +106,8 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
}
if (fflag)
server_client_set_flags(c, fflag);
if (rflag) {
if (c->flags & CLIENT_READONLY) {
uid = proc_get_peer_uid(c->peer);
if (uid != getuid()) {
cmdq_error(item, "client is read-only");
return (CMD_RETURN_ERROR);
}
}
if (rflag)
c->flags |= (CLIENT_READONLY|CLIENT_IGNORESIZE);
}
c->last_session = c->session;
if (c->session != NULL) {

View File

@@ -58,14 +58,9 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
struct session *dst_s = target->s;
struct window_pane *wp = source->wp;
struct window *w = wl->window;
char *newname, *cause, *cp;
char *name, *cause, *cp;
int idx = target->idx, before;
const char *template, *name = args_get(args, 'n');
if (name != NULL && !check_name(name)) {
cmdq_error(item, "invalid window name: %s", name);
return (CMD_RETURN_ERROR);
}
const char *template;
before = args_has(args, 'b');
if (args_has(args, 'a') || before) {
@@ -78,15 +73,15 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
}
server_unzoom_window(w);
if (window_count_panes(w, 1) == 1) {
if (window_count_panes(w) == 1) {
if (server_link_window(src_s, wl, dst_s, idx, 0,
!args_has(args, 'd'), &cause) != 0) {
cmdq_error(item, "%s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
if (name != NULL) {
window_set_name(w, name, 0);
if (args_has(args, 'n')) {
window_set_name(w, args_get(args, 'n'));
options_set_number(w->options, "automatic-rename", 0);
}
server_unlink_window(src_s, wl);
@@ -101,7 +96,6 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
}
TAILQ_REMOVE(&w->panes, wp, entry);
TAILQ_REMOVE(&w->z_index, wp, zentry);
server_client_remove_pane(wp);
window_lost_pane(w, wp);
layout_close_pane(wp);
@@ -110,16 +104,15 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
options_set_parent(wp->options, w->options);
wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
w->active = wp;
w->latest = tc;
if (name == NULL) {
newname = default_window_name(w);
window_set_name(w, newname, 0);
free(newname);
if (!args_has(args, 'n')) {
name = default_window_name(w);
window_set_name(w, name);
free(name);
} else {
window_set_name(w, name, 0);
window_set_name(w, args_get(args, 'n'));
options_set_number(w->options, "automatic-rename", 0);
}

View File

@@ -29,21 +29,18 @@
static enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
static char *cmd_capture_pane_append(char *, size_t *, const char *,
size_t);
static char *cmd_capture_pane_append(char *, size_t *, char *, size_t);
static char *cmd_capture_pane_pending(struct args *, struct window_pane *,
size_t *);
static char *cmd_capture_pane_history(struct args *, struct cmdq_item *,
struct window_pane *, size_t *);
static char *cmd_capture_pane_hyperlinks(struct grid *, struct screen *,
u_int, u_int *, u_int *, size_t *);
const struct cmd_entry cmd_capture_pane_entry = {
.name = "capture-pane",
.alias = "capturep",
.args = { "ab:CeE:FHJLMNpPqS:Tt:", 0, 0, NULL },
.usage = "[-aCeFHJLMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
.args = { "ab:CeE:JMNpPqS:Tt:", 0, 0, NULL },
.usage = "[-aCeJMNpPqT] " CMD_BUFFER_USAGE " [-E end-line] "
"[-S start-line] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@@ -66,8 +63,7 @@ const struct cmd_entry cmd_clear_history_entry = {
};
static char *
cmd_capture_pane_append(char *buf, size_t *len, const char *line,
size_t linelen)
cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
{
buf = xrealloc(buf, *len + linelen + 1);
memcpy(buf + *len, line, linelen);
@@ -107,46 +103,6 @@ cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
return (buf);
}
static char *
cmd_capture_pane_hyperlinks(struct grid *gd, struct screen *s, u_int py,
u_int *links, u_int *nlinks, size_t *len)
{
const struct grid_line *gl = grid_peek_line(gd, py);
struct grid_cell gc;
const char *uri;
char *line = xstrdup("");
u_int i, j;
*len = 0;
if (s->hyperlinks == NULL || (~gl->flags & GRID_LINE_HYPERLINK))
return (line);
for (i = 0; i < gl->cellused; i++) {
grid_get_cell(gd, i, py, &gc);
if (gc.link == 0)
continue;
for (j = 0; j < *nlinks; j++) {
if (links[j] == gc.link)
break;
}
if (j != *nlinks)
continue;
if (!hyperlinks_get(s->hyperlinks, gc.link, &uri, NULL, NULL))
continue;
if (*nlinks == gd->sx)
break;
links[(*nlinks)++] = gc.link;
if (*len != 0)
line = cmd_capture_pane_append(line, len, " ", 1);
line = cmd_capture_pane_append(line, len, uri, strlen(uri));
}
return (line);
}
static char *
cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
struct window_pane *wp, size_t *len)
@@ -156,11 +112,9 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
struct screen *s;
struct grid_cell *gc = NULL;
struct window_mode_entry *wme;
int n, join_lines, number_lines, flags = 0;
int show_flags, hyperlinks;
u_int *links = NULL, nlinks = 0;
int n, join_lines, flags = 0;
u_int i, sx, top, bottom, tmp;
char *cause, *buf = NULL, *line, b[64], *cp;
char *cause, *buf, *line;
const char *Sflag, *Eflag;
size_t linelen;
@@ -198,7 +152,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
if (cause != NULL) {
top = gd->hsize;
free(cause);
} else if (n < 0 && (u_int)-n > gd->hsize)
} else if (n < 0 && (u_int) -n > gd->hsize)
top = 0;
else
top = gd->hsize + n;
@@ -215,7 +169,7 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
if (cause != NULL) {
bottom = gd->hsize + gd->sy - 1;
free(cause);
} else if (n < 0 && (u_int)-n > gd->hsize)
} else if (n < 0 && (u_int) -n > gd->hsize)
bottom = 0;
else
bottom = gd->hsize + n;
@@ -238,57 +192,12 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
flags |= GRID_STRING_EMPTY_CELLS;
if (!join_lines && !args_has(args, 'N'))
flags |= GRID_STRING_TRIM_SPACES;
number_lines = args_has(args, 'L');
show_flags = args_has(args, 'F');
hyperlinks = args_has(args, 'H');
if (hyperlinks)
links = xreallocarray(NULL, gd->sx, sizeof *links);
buf = NULL;
for (i = top; i <= bottom; i++) {
if (hyperlinks) {
line = cmd_capture_pane_hyperlinks(gd, s, i, links,
&nlinks, &linelen);
} else {
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
linelen = strlen(line);
}
if (hyperlinks && linelen == 0) {
free(line);
continue;
}
line = grid_string_cells(gd, 0, i, sx, &gc, flags, s);
linelen = strlen(line);
if (number_lines) {
if (i >= gd->hsize)
n = i - gd->hsize;
else
n = (int)i - (int)gd->hsize;
n = snprintf(b, sizeof b, "%d ", n);
if (n >= 0)
buf = cmd_capture_pane_append(buf, len, b, n);
}
if (show_flags) {
cp = b;
*cp = '\0';
gl = grid_peek_line(gd, i);
if (gl->flags & GRID_LINE_DEAD)
*cp++ = 'D';
if (gl->flags & GRID_LINE_HYPERLINK)
*cp++ = 'H';
if (gl->flags & GRID_LINE_START_OUTPUT)
*cp++ = 'O';
if (gl->flags & GRID_LINE_START_PROMPT)
*cp++ = 'P';
if (gl->flags & GRID_LINE_WRAPPED)
*cp++ = 'W';
if (gl->flags & GRID_LINE_EXTENDED)
*cp++ = 'X';
if (b == cp)
*cp++ = '-';
*cp++ = ' ';
*cp = '\0';
buf = cmd_capture_pane_append(buf, len, b, strlen (b));
}
buf = cmd_capture_pane_append(buf, len, line, linelen);
gl = grid_peek_line(gd, i);
@@ -297,9 +206,6 @@ cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
free(line);
}
free(links);
if (buf == NULL)
buf = xstrdup("");
return (buf);
}
@@ -322,7 +228,7 @@ cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
}
len = 0;
if (args_has(args, 'P') && !args_has(args, 'H'))
if (args_has(args, 'P'))
buf = cmd_capture_pane_pending(args, wp, &len);
else
buf = cmd_capture_pane_history(args, item, wp, &len);

View File

@@ -42,8 +42,8 @@ const struct cmd_entry cmd_command_prompt_entry = {
.name = "command-prompt",
.alias = NULL,
.args = { "1CbeFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
.usage = "[-1CbeFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
.args = { "1beFiklI:Np:t:T:", 0, 1, cmd_command_prompt_args_parse },
.usage = "[-1beFiklN] [-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE
" [-T prompt-type] [template]",
.flags = CMD_CLIENT_TFLAG,
@@ -165,8 +165,6 @@ cmd_command_prompt_exec(struct cmd *self, struct cmdq_item *item)
cdata->flags |= PROMPT_KEY;
else if (args_has(args, 'e'))
cdata->flags |= PROMPT_BSPACE_EXIT;
if (args_has(args, 'C'))
cdata->flags |= PROMPT_NOFREEZE;
status_prompt_set(tc, target, cdata->prompts[0].prompt,
cdata->prompts[0].input, cmd_command_prompt_callback,
cmd_command_prompt_free, cdata, cdata->flags, cdata->prompt_type);

View File

@@ -63,8 +63,6 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
struct client *c = cmdq_get_client(item);
struct session *s;
struct window_pane *wp = target->wp, *swp;
u_int tty_ox, tty_oy, tty_sx, tty_sy;
int line_numbers;
if (args_has(args, 'q')) {
window_pane_reset_mode_all(wp);
@@ -87,23 +85,17 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
swp = source->wp;
else
swp = wp;
line_numbers = 1;
if (event != NULL && KEYC_IS_MOUSE(event->key))
line_numbers = 0;
if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) {
window_copy_set_line_numbers(wp, line_numbers);
if (args_has(args, 'M'))
window_copy_start_drag(c, &event->m);
} else
window_copy_set_line_numbers(wp, line_numbers);
}
if (args_has(args, 'u'))
window_copy_pageup(wp, 0);
if (args_has(args, 'd'))
window_copy_pagedown(wp, 0, args_has(args, 'e'));
if (args_has(args, 'S')) {
tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
tty_oy, args_has(args, 'e'));
args_has(args, 'e'));
return (CMD_RETURN_NORMAL);
}

View File

@@ -59,7 +59,6 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *source = cmdq_get_source(item);
struct client *c = cmdq_get_client(item);
struct client *tc = cmdq_get_target_client(item), *loop;
struct session *s;
enum msgtype msgtype;
@@ -70,13 +69,6 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (c->flags & CLIENT_READONLY) {
if (args_has(args, 's') || args_has(args, 'a') || c != tc) {
cmdq_error(item, "client is read-only");
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'P'))
msgtype = MSG_DETACHKILL;
else

View File

@@ -370,7 +370,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
flags |= MENU_NOMOUSE;
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
style, selected_style, border_style, target, NULL, NULL) != 0)
goto out;
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
out:

View File

@@ -55,27 +55,6 @@ cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx,
return (ARGS_PARSE_COMMANDS_OR_STRING);
}
static void
cmd_display_panes_put(struct screen_redraw_ctx *ctx,
struct window_pane *wp, u_int cx, u_int cy, const char *buf, size_t len)
{
struct client *c = ctx->c;
struct tty *tty = &c->tty;
struct visible_ranges *r;
struct visible_range *ri;
u_int i, j;
r = screen_redraw_get_visible_ranges(wp, ctx->ox + cx, ctx->oy + cy,
len, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
for (j = ri->px; j < ri->px + ri->nx; j++) {
tty_cursor(tty, j - ctx->ox, cy);
tty_putn(tty, &buf[j - ri->px], 1, 1);
}
}
}
static void
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window_pane *wp)
@@ -87,15 +66,14 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window *w = wp->window;
struct grid_cell fgc, bgc;
u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy;
u_int cx, cy;
int colour, active_colour;
char buf[16], lbuf[16], rbuf[16], *ptr;
size_t len, llen, rlen;
if (wp->xoff + (int)wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + (int)ctx->sx ||
wp->yoff + (int)wp->sy <= ctx->oy ||
wp->yoff >= ctx->oy + (int)ctx->sy)
if (wp->xoff + wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + ctx->sx ||
wp->yoff + wp->sy <= ctx->oy ||
wp->yoff >= ctx->oy + ctx->sy)
return;
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
@@ -169,17 +147,13 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
if (sx >= len + llen + 1) {
len += llen + 1;
cx = xoff + px - len / 2;
cy = yoff + py;
cmd_display_panes_put(ctx, wp, cx, cy, buf, len);
cx += len;
cmd_display_panes_put(ctx, wp, cx, cy, " ", 1);
cx++;
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
tty_cursor(tty, xoff + px - len / 2, yoff + py);
tty_putn(tty, buf, len, len);
tty_putn(tty, " ", 1, 1);
tty_putn(tty, lbuf, llen, llen);
} else {
cx = xoff + px - len / 2;
cy = yoff + py;
cmd_display_panes_put(ctx, wp, cx, cy, buf, len);
tty_cursor(tty, xoff + px - len / 2, yoff + py);
tty_putn(tty, buf, len, len);
}
goto out;
}
@@ -195,11 +169,9 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
for (j = 0; j < 5; j++) {
for (i = px; i < px + 5; i++) {
if (!window_clock_table[idx][j][i - px])
continue;
cx = xoff + i;
cy = yoff + py + j;
cmd_display_panes_put(ctx, wp, cx, cy, " ", 1);
tty_cursor(tty, xoff + i, yoff + py + j);
if (window_clock_table[idx][j][i - px])
tty_putc(tty, ' ');
}
}
px += 6;
@@ -209,14 +181,13 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
goto out;
tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL);
if (rlen != 0 && sx >= rlen) {
cx = xoff + sx - rlen;
cy = yoff;
cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen);
tty_cursor(tty, xoff + sx - rlen, yoff);
tty_putn(tty, rbuf, rlen, rlen);
}
if (llen != 0) {
cx = xoff + sx / 2 + len * 3 - llen - 1;
cy = yoff + py + 5;
cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen);
tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1,
yoff + py + 5);
tty_putn(tty, lbuf, llen, llen);
}
out:

View File

@@ -71,8 +71,11 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
struct window *src_w, *dst_w;
struct window_pane *src_wp, *dst_wp;
char *cause = NULL;
int flags = 0, dst_idx;
int size, dst_idx;
int flags;
enum layout_type type;
struct layout_cell *lc;
u_int curval = 0;
dst_s = target->s;
dst_wl = target->wl;
@@ -91,30 +94,66 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
lc = layout_get_tiled_cell(item, args, dst_w, dst_wp, flags, &cause);
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = dst_w->sy;
else
curval = dst_w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = dst_wp->sy;
else
curval = dst_wp->sx;
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'l', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
}
if (cause != NULL) {
cmdq_error(item, "size or position %s", cause);
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
flags = 0;
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
lc = layout_split_pane(dst_wp, type, size, flags);
if (lc == NULL) {
cmdq_error(item, "create pane failed: pane too small");
return (CMD_RETURN_ERROR);
}
layout_close_pane(src_wp);
server_client_remove_pane(src_wp);
window_lost_pane(src_w, src_wp);
TAILQ_REMOVE(&src_w->panes, src_wp, entry);
TAILQ_REMOVE(&src_w->z_index, src_wp, zentry);
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
if (flags & SPAWN_BEFORE) {
if (flags & SPAWN_BEFORE)
TAILQ_INSERT_BEFORE(dst_wp, src_wp, entry);
TAILQ_INSERT_BEFORE(dst_wp, src_wp, zentry);
} else {
else
TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry);
TAILQ_INSERT_AFTER(&dst_w->z_index, dst_wp, src_wp, zentry);
}
layout_assign_pane(lc, src_wp, 0);
colour_palette_from_option(&src_wp->palette, src_wp->options);
@@ -131,7 +170,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
} else
server_status_session(dst_s);
if (window_count_panes(src_w, 1) == 0)
if (window_count_panes(src_w) == 0)
server_kill_window(src_w, 1);
else
notify_window("window-layout-changed", src_w);

View File

@@ -62,10 +62,6 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (wp == NULL) {
cmdq_error(item, "no active pane to kill");
return (CMD_RETURN_ERROR);
}
server_kill_pane(wp);
return (CMD_RETURN_NORMAL);
}

View File

@@ -33,8 +33,8 @@ const struct cmd_entry cmd_kill_session_entry = {
.name = "kill-session",
.alias = NULL,
.args = { "aCgt:", 0, 0, NULL },
.usage = "[-aCg] " CMD_TARGET_SESSION_USAGE,
.args = { "aCt:", 0, 0, NULL },
.usage = "[-aC] " CMD_TARGET_SESSION_USAGE,
.target = { 't', CMD_FIND_SESSION, 0 },
@@ -48,7 +48,6 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct session *s = target->s, *sloop, *stmp;
struct session_group *sg;
struct winlink *wl;
if (args_has(args, 'C')) {
@@ -64,12 +63,6 @@ cmd_kill_session_exec(struct cmd *self, struct cmdq_item *item)
session_destroy(sloop, 1, __func__);
}
}
} else if (args_has(args, 'g') &&
(sg = session_group_contains(s)) != NULL) {
TAILQ_FOREACH_SAFE(sloop, &sg->sessions, gentry, stmp) {
server_destroy_session(sloop);
session_destroy(sloop, 1, __func__);
}
} else {
server_destroy_session(s);
session_destroy(s, 1, __func__);

View File

@@ -35,7 +35,7 @@
"," \
"bind-key #{?key_has_repeat,#{?key_repeat,-r, },} " \
"-T #{p|#{key_table_width}:key_table} " \
"#{p|#{key_string_width}:#{q|a:key_string}} " \
"#{p|#{key_string_width}:key_string} " \
"#{key_command}}"
static enum cmd_retval cmd_list_keys_exec(struct cmd *, struct cmdq_item *);
@@ -93,7 +93,7 @@ cmd_list_keys_get_table_width(struct key_binding **l, u_int n)
}
static struct key_binding **
cmd_list_keys_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
cmd_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
{
const char *tables[] = { "prefix", "root" };
struct key_table *t;
@@ -119,7 +119,7 @@ cmd_list_keys_get_root_and_prefix(u_int *n, struct sort_criteria *sort_crit)
}
static void
cmd_list_keys_filter_key_list(int filter_notes, int filter_key, key_code only,
cmd_filter_key_list(int filter_notes, int filter_key, key_code only,
struct key_binding **l, u_int *n)
{
key_code key;
@@ -137,10 +137,10 @@ cmd_list_keys_filter_key_list(int filter_notes, int filter_key, key_code only,
}
static void
cmd_list_keys_format_add_key_binding(struct format_tree *ft,
cmd_format_add_key_binding(struct format_tree *ft,
const struct key_binding *bd, const char *prefix)
{
char *s;
const char *s;
if (bd->flags & KEY_BINDING_REPEAT)
format_add(ft, "key_repeat", "1");
@@ -155,12 +155,12 @@ cmd_list_keys_format_add_key_binding(struct format_tree *ft,
format_add(ft, "key_prefix", "%s", prefix);
format_add(ft, "key_table", "%s", bd->tablename);
format_add(ft, "key_string", "%s", key_string_lookup_key(bd->key, 0));
s = key_string_lookup_key(bd->key, 0);
format_add(ft, "key_string", "%s", s);
s = cmd_list_print(bd->cmdlist, CMD_LIST_PRINT_ESCAPED|
CMD_LIST_PRINT_NO_GROUPS);
s = cmd_list_print(bd->cmdlist,
CMD_LIST_PRINT_ESCAPED|CMD_LIST_PRINT_NO_GROUPS);
format_add(ft, "key_command", "%s", s);
free(s);
}
static enum cmd_retval
@@ -195,6 +195,10 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
}
sort_crit.reversed = args_has(args, 'r');
prefix = cmd_list_keys_get_prefix(args);
single = args_has(args, '1');
notes_only = args_has(args, 'N');
if ((tablename = args_get(args, 'T')) != NULL) {
table = key_bindings_get_table(tablename, 0);
if (table == NULL) {
@@ -203,26 +207,20 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
}
}
prefix = cmd_list_keys_get_prefix(args);
single = args_has(args, '1');
notes_only = args_has(args, 'N');
if ((template = args_get(args, 'F')) == NULL)
template = LIST_KEYS_TEMPLATE;
if (table)
l = sort_get_key_bindings_table(table, &n, &sort_crit);
else if (notes_only)
l = cmd_list_keys_get_root_and_prefix(&n, &sort_crit);
l = cmd_get_root_and_prefix(&n, &sort_crit);
else
l = sort_get_key_bindings(&n, &sort_crit);
filter_notes = notes_only && !args_has(args, 'a');
filter_key = only != KEYC_UNKNOWN;
if (filter_notes || filter_key) {
cmd_list_keys_filter_key_list(filter_notes, filter_key, only, l,
&n);
}
if (filter_notes || filter_key)
cmd_filter_key_list(filter_notes, filter_key, only, l, &n);
if (single)
n = 1;
@@ -234,7 +232,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
format_add(ft, "key_table_width", "%u",
cmd_list_keys_get_table_width(l, n));
for (i = 0; i < n; i++) {
cmd_list_keys_format_add_key_binding(ft, l[i], prefix);
cmd_format_add_key_binding(ft, l[i], prefix);
line = format_expand(ft, template);
if ((single && tc != NULL) || n == 1)

View File

@@ -110,28 +110,22 @@ cmd_list_panes_window(struct cmd *self, struct session *s, struct winlink *wl,
switch (type) {
case 0:
template = "#{pane_index}: "
"[#{pane_width}x#{pane_height}"
"#{?pane_floating_flag, "
"#{pane_x}#,#{pane_y}#,#{pane_z}}] [history "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 1:
template = "#{window_index}.#{pane_index}: "
"[#{pane_width}x#{pane_height}"
"#{?pane_floating_flag, "
"#{pane_x}#,#{pane_y}#,#{pane_z}}] [history "
"[#{pane_width}x#{pane_height}] [history "
"#{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;
case 2:
template = "#{session_name}:#{window_index}."
"#{pane_index}: [#{pane_width}x#{pane_height}"
"#{?pane_floating_flag, "
"#{pane_x}#,#{pane_y}#,#{pane_z}}] [history "
"#{history_size}/#{history_limit}, "
"#{pane_index}: [#{pane_width}x#{pane_height}] "
"[history #{history_size}/#{history_limit}, "
"#{history_bytes} bytes] #{pane_id}"
"#{?pane_active, (active),}#{?pane_dead, (dead),}";
break;

View File

@@ -77,8 +77,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
struct termios tio, *tiop;
struct session_group *sg = NULL;
const char *errstr, *template, *group, *tmp;
char *cause, *cwd = NULL, *cp, *ename;
char *wname = NULL, *sname = NULL, *prefix = NULL;
char *cause, *cwd = NULL, *cp, *newname = NULL;
char *name, *prefix = NULL;
int detached, already_attached, is_control = 0;
u_int sx, sy, dsx, dsy, count = args_count(args);
struct spawn_context sc = { 0 };
@@ -99,29 +99,20 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_ERROR);
}
if ((tmp = args_get(args, 'n')) != NULL) {
ename = format_single(item, tmp, c, NULL, NULL, NULL);
if (!check_name(ename)) {
cmdq_error(item, "invalid window name: %s", ename);
free(ename);
tmp = args_get(args, 's');
if (tmp != NULL) {
name = format_single(item, tmp, c, NULL, NULL, NULL);
newname = session_check_name(name);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", name);
free(name);
return (CMD_RETURN_ERROR);
}
wname = clean_name(ename, 0);
free(ename);
}
if ((tmp = args_get(args, 's')) != NULL) {
ename = format_single(item, tmp, c, NULL, NULL, NULL);
if (!check_name(ename)) {
cmdq_error(item, "invalid session name: %s", ename);
free(ename);
goto fail;
}
sname = clean_name(ename, 0);
free(ename);
free(name);
}
if (args_has(args, 'A')) {
if (sname != NULL)
as = session_find(sname);
if (newname != NULL)
as = session_find(newname);
else
as = target->s;
if (as != NULL) {
@@ -129,13 +120,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
args_has(args, 'D'), args_has(args, 'X'), 0,
args_get(args, 'c'), args_has(args, 'E'),
args_get(args, 'f'));
free(wname);
free(sname);
free(newname);
return (retval);
}
}
if (sname != NULL && session_find(sname) != NULL) {
cmdq_error(item, "duplicate session: %s", sname);
if (newname != NULL && session_find(newname) != NULL) {
cmdq_error(item, "duplicate session: %s", newname);
goto fail;
}
@@ -152,12 +142,12 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
else if (groupwith != NULL)
prefix = xstrdup(groupwith->name);
else {
if (!check_name(group)) {
cmdq_error(item,
"invalid session group name: %s", group);
prefix = session_check_name(group);
if (prefix == NULL) {
cmdq_error(item, "invalid session group: %s",
group);
goto fail;
}
prefix = clean_name(group, 0);
}
}
@@ -286,7 +276,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
environ_put(env, av->string, 0);
av = args_next_value(av);
}
s = session_create(prefix, sname, cwd, env, oo, tiop);
s = session_create(prefix, newname, cwd, env, oo, tiop);
/* Spawn the initial window. */
sc.item = item;
@@ -294,7 +284,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
if (!detached)
sc.tc = c;
sc.name = wname;
sc.name = args_get(args, 'n');
args_to_vector(args, &sc.argc, &sc.argv);
sc.idx = -1;
@@ -367,8 +357,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(wname);
free(sname);
free(newname);
free(prefix);
return (CMD_RETURN_NORMAL);
@@ -376,8 +365,7 @@ fail:
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
free(cwd);
free(wname);
free(sname);
free(newname);
free(prefix);
return (CMD_RETURN_ERROR);
}

View File

@@ -61,7 +61,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
struct winlink *wl = target->wl, *new_wl = NULL;
int idx = target->idx, before;
char *cause = NULL, *cp, *expanded, *wname = NULL;
char *cause = NULL, *cp, *expanded;
const char *template, *name;
struct cmd_find_state fs;
struct args_value *av;
@@ -71,18 +71,8 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
* name already exists, select it.
*/
name = args_get(args, 'n');
if (name != NULL) {
if (args_has(args, 'S') && name != NULL && target->idx == -1) {
expanded = format_single(item, name, c, s, NULL, NULL);
if (!check_name(expanded)) {
cmdq_error(item, "invalid window name: %s", expanded);
free(expanded);
return (CMD_RETURN_ERROR);
}
wname = clean_name(expanded, 0);
free(expanded);
}
if (args_has(args, 'S') && wname != NULL && target->idx == -1) {
expanded = format_single(item, wname, c, s, NULL, NULL);
RB_FOREACH(wl, winlinks, &s->windows) {
if (strcmp(wl->window->name, expanded) != 0)
continue;
@@ -90,14 +80,12 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
new_wl = wl;
continue;
}
cmdq_error(item, "multiple windows named %s", wname);
free(wname);
cmdq_error(item, "multiple windows named %s", name);
free(expanded);
return (CMD_RETURN_ERROR);
}
free(expanded);
if (new_wl != NULL) {
free(wname);
if (args_has(args, 'd'))
return (CMD_RETURN_NORMAL);
if (session_set_current(s, new_wl) == 0)
@@ -120,7 +108,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
sc.s = s;
sc.tc = tc;
sc.name = wname;
sc.name = args_get(args, 'n');
args_to_vector(args, &sc.argc, &sc.argv);
sc.environ = environ_create();
@@ -142,7 +130,10 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
if ((new_wl = spawn_window(&sc, &cause)) == NULL) {
cmdq_error(item, "create window failed: %s", cause);
free(cause);
goto fail;
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
if (!args_has(args, 'd') || new_wl == s->curw) {
cmd_find_from_winlink(current, new_wl, 0);
@@ -165,13 +156,5 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
free(wname);
return (CMD_RETURN_NORMAL);
fail:
if (sc.argv != NULL)
cmd_free_argv(sc.argc, sc.argv);
environ_free(sc.environ);
free(wname);
return (CMD_RETURN_ERROR);
}

View File

@@ -37,8 +37,6 @@ static void printflike(1,2) yyerror(const char *, ...);
static char *yylex_token(int);
static char *yylex_format(void);
#define CMD_PARSE_MAX_ENVIRON_LEN 16384
struct cmd_parse_scope {
int flag;
TAILQ_ENTRY (cmd_parse_scope) entry;
@@ -234,10 +232,6 @@ assignment : EQUALS
flag = flag && scope->flag;
}
if (strlen($1) > CMD_PARSE_MAX_ENVIRON_LEN) {
yyerror("environment variable is too long");
YYABORT;
}
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
environ_put(global_environ, $1, 0);
free($1);
@@ -256,10 +250,6 @@ hidden_assignment : HIDDEN EQUALS
flag = flag && scope->flag;
}
if (strlen($2) > CMD_PARSE_MAX_ENVIRON_LEN) {
yyerror("environment variable is too long");
YYABORT;
}
if ((~flags & CMD_PARSE_PARSEONLY) && flag)
environ_put(global_environ, $2, ENVIRON_HIDDEN);
free($2);
@@ -1614,9 +1604,7 @@ yylex_token_tilde(char **buf, size_t *len)
if (*name == '\0') {
envent = environ_find(global_environ, "HOME");
if (envent != NULL &&
envent->value != NULL &&
*envent->value != '\0')
if (envent != NULL && *envent->value != '\0')
home = envent->value;
else if ((pw = getpwuid(getuid())) != NULL)
home = pw->pw_dir;

View File

@@ -128,8 +128,6 @@ cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item)
sigprocmask(SIG_SETMASK, &oldset, NULL);
cmdq_error(item, "fork error: %s", strerror(errno));
close(pipe_fd[0]);
close(pipe_fd[1]);
free(cmd);
return (CMD_RETURN_ERROR);
case 0:

View File

@@ -52,12 +52,12 @@ cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
char *newname, *tmp;
tmp = format_single_from_target(item, args_string(args, 0));
if (!check_name(tmp)) {
cmdq_error(item, "invalid session name: %s", tmp);
newname = session_check_name(tmp);
if (newname == NULL) {
cmdq_error(item, "invalid session: %s", tmp);
free(tmp);
return (CMD_RETURN_ERROR);
}
newname = clean_name(tmp, 0);
free(tmp);
if (strcmp(newname, s->name) == 0) {
free(newname);

View File

@@ -48,21 +48,15 @@ cmd_rename_window_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl;
char *name;
char *newname;
name = format_single_from_target(item, args_string(args, 0));
if (!check_name(name)) {
cmdq_error(item, "invalid window name: %s", name);
free(name);
return (CMD_RETURN_ERROR);
}
window_set_name(wl->window, name, 0);
newname = format_single_from_target(item, args_string(args, 0));
window_set_name(wl->window, newname);
options_set_number(wl->window->options, "automatic-rename", 0);
free(name);
server_redraw_window_borders(wl->window);
server_status_window(wl->window);
free(newname);
return (CMD_RETURN_NORMAL);
}

View File

@@ -29,12 +29,8 @@
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
static enum cmd_retval cmd_resize_pane_mouse_update(struct cmd *,
struct cmdq_item *);
static void cmd_resize_pane_mouse_update_floating(struct client *,
struct mouse_event *);
static void cmd_resize_pane_mouse_update_tiled(struct client *,
struct mouse_event *);
static void cmd_resize_pane_mouse_update(struct client *,
struct mouse_event *);
const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane",
@@ -55,10 +51,13 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct window_pane *wp = target->wp;
struct winlink *wl = target->wl;
struct window *w = wl->window;
const char *errstr;
struct client *c = cmdq_get_client(item);
struct session *s = target->s;
const char *errstr;
char *cause;
u_int adjust;
int x, y, status;
@@ -76,8 +75,15 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'M'))
return (cmd_resize_pane_mouse_update(self, item));
if (args_has(args, 'M')) {
if (!event->m.valid || cmd_mouse_window(&event->m, &s) == NULL)
return (CMD_RETURN_NORMAL);
if (c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
cmd_resize_pane_mouse_update(c, &event->m);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'Z')) {
if (w->flags & WINDOW_ZOOMED)
@@ -142,168 +148,13 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
static enum cmd_retval
cmd_resize_pane_mouse_update(__unused struct cmd *self, struct cmdq_item *item)
{
struct cmd_find_state *target = cmdq_get_target(item);
struct key_event *event = cmdq_get_event(item);
struct window_pane *wp = target->wp;
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct client *c = cmdq_get_client(item);
struct session *s = target->s;
if (!event->m.valid)
return (CMD_RETURN_NORMAL);
wp = cmd_mouse_pane(&event->m, &s, NULL);
if (wp == NULL || c == NULL || c->session != s)
return (CMD_RETURN_NORMAL);
if (!window_pane_is_floating(wp)) {
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
cmd_resize_pane_mouse_update_tiled(c, &event->m);
return (CMD_RETURN_NORMAL);
}
window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1);
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
cmd_resize_pane_mouse_update_floating(c, &event->m);
return (CMD_RETURN_NORMAL);
}
static void
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
struct window *w;
struct window_pane *wp;
struct layout_cell *lc;
int y, ly, x, lx, sx, sy, new_sx, new_sy;
int left, right;
int new_xoff, new_yoff, resizes = 0;
wp = cmd_mouse_pane(m, NULL, &wl);
if (wp == NULL) {
c->tty.mouse_drag_update = NULL;
return;
}
w = wl->window;
lc = wp->layout_cell;
sx = wp->sx;
sy = wp->sy;
left = wp->xoff - 1;
right = wp->xoff + sx;
if (window_pane_show_scrollbar(wp) &&
w->sb_pos == PANE_SCROLLBARS_LEFT) {
left -= wp->scrollbar_style.width + wp->scrollbar_style.pad;
} else if (window_pane_show_scrollbar(wp) &&
w->sb_pos == PANE_SCROLLBARS_RIGHT) {
right += wp->scrollbar_style.width + wp->scrollbar_style.pad;
}
y = m->y + m->oy; x = m->x + m->ox;
if (m->statusat == 0 && y >= (int)m->statuslines)
y -= m->statuslines;
else if (m->statusat > 0 && y >= m->statusat)
y = m->statusat - 1;
ly = m->ly + m->oy; lx = m->lx + m->ox;
if (m->statusat == 0 && ly >= (int)m->statuslines)
ly -= m->statuslines;
else if (m->statusat > 0 && ly >= m->statusat)
ly = m->statusat - 1;
if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) {
/* Top left corner. */
new_sx = lc->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = lc->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
new_xoff = x + 1; /* because mouse is on border at xoff - 1 */
new_yoff = y + 1;
layout_set_size(lc, new_sx, new_sy, new_xoff, new_yoff);
resizes++;
} else if ((lx == right + 1 || lx == right) &&
ly == wp->yoff - 1) {
/* Top right corner. */
new_sx = x - lc->xoff;
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = lc->sy + (ly - y);
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
new_yoff = y + 1;
layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff);
resizes++;
} else if ((lx == left || lx == left + 1) &&
ly == wp->yoff + sy) {
/* Bottom left corner. */
new_sx = lc->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM)
return;
new_xoff = x + 1;
layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff);
resizes++;
} else if ((lx == right + 1 || lx == right) &&
ly == wp->yoff + sy) {
/* Bottom right corner. */
new_sx = x - lc->xoff;
if (new_sx < PANE_MINIMUM)
new_sx = PANE_MINIMUM;
new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM)
new_sy = PANE_MINIMUM;
layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff);
resizes++;
} else if (lx == right) {
/* Right border. */
new_sx = x - lc->xoff;
if (new_sx < PANE_MINIMUM)
return;
layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff);
resizes++;
} else if (lx == left) {
/* Left border. */
new_sx = lc->sx + (lx - x);
if (new_sx < PANE_MINIMUM)
return;
new_xoff = x + 1;
layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff);
resizes++;
} else if (ly == wp->yoff + sy) {
/* Bottom border. */
new_sy = y - lc->yoff;
if (new_sy < PANE_MINIMUM)
return;
layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff);
resizes++;
} else if (ly == wp->yoff - 1) {
/* Top border (move instead of resize). */
new_xoff = lc->xoff + (x - lx);
new_yoff = y + 1;
layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff);
resizes++;
}
if (resizes != 0) {
layout_fix_panes(w, NULL);
server_redraw_window(w);
server_redraw_window_borders(w);
}
}
static void
cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
{
struct winlink *wl;
struct window *w;
u_int y, ly, x, lx;
static const int offsets[][2] = {
static const int offsets[][2] = {
{ 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
};
struct layout_cell *cells[nitems(offsets)], *lc;

View File

@@ -44,9 +44,9 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell",
.alias = "run",
.args = { "bd:Ct:Es:c:", 0, -1, cmd_run_shell_args_parse },
.args = { "bd:Ct:Es:c:", 0, 1, cmd_run_shell_args_parse },
.usage = "[-bCE] [-c start-directory] [-d delay] " CMD_TARGET_PANE_USAGE
" [shell-command [argument ...]]",
" [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@@ -115,11 +115,9 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = target->s;
struct window_pane *wp = target->wp;
const char *delay, *cmd;
struct format_tree *ft;
double d;
struct timeval tv;
char *end, key[16];
u_int i;
char *end;
int wait = !args_has(args, 'b');
if ((delay = args_get(args, 'd')) != NULL) {
@@ -134,15 +132,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
cdata = xcalloc(1, sizeof *cdata);
if (!args_has(args, 'C')) {
cmd = args_string(args, 0);
if (cmd != NULL) {
ft = format_create_from_target(item);
for (i = 1; i < args_count(args); i++) {
xsnprintf(key, sizeof key, "%u", i);
format_add(ft, key, "%s", args_string(args, i));
}
cdata->cmd = format_expand(ft, cmd);
format_free(ft);
}
if (cmd != NULL)
cdata->cmd = format_single_from_target(item, cmd);
} else {
cdata->state = args_make_commands_prepare(self, item, 0, NULL,
wait, 1);
@@ -207,17 +198,8 @@ cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
}
if (job_run(cmd, 0, NULL, NULL, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
cdata->flags, -1, -1) == NULL) {
if (cdata->item == NULL)
status_message_set(c, -1, 1, 0, 0,
"failed to run command: %s", cmd);
else {
cmdq_error(cdata->item,
"failed to run command: %s", cmd);
cmdq_continue(cdata->item);
}
cdata->flags, -1, -1) == NULL)
cmd_run_shell_free(cdata);
}
return;
}

View File

@@ -90,7 +90,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
previous = 1;
oldlayout = w->old_layout;
w->old_layout = layout_dump(w, w->layout_root);
w->old_layout = layout_dump(w->layout_root);
if (next || previous) {
if (next)

View File

@@ -103,7 +103,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
* spawned without being visited (for example split-window -d).
*/
lastwp = TAILQ_FIRST(&w->last_panes);
if (lastwp == NULL && window_count_panes(w, 1) == 2) {
if (lastwp == NULL && window_count_panes(w) == 2) {
lastwp = TAILQ_PREV(w->active, window_panes, entry);
if (lastwp == NULL)
lastwp = TAILQ_NEXT(w->active, entry);
@@ -160,10 +160,6 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
server_redraw_window_borders(markedwp->window);
server_status_window(markedwp->window);
}
if (window_pane_is_floating(wp)) {
window_redraw_active_switch(w, wp);
window_set_active_pane(w, wp, 1);
}
return (CMD_RETURN_NORMAL);
}
@@ -217,7 +213,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'T')) {
title = format_single_from_target(item, args_get(args, 'T'));
if (screen_set_title(&wp->base, title, 0)) {
if (screen_set_title(&wp->base, title)) {
notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);

View File

@@ -27,41 +27,22 @@
#include "tmux.h"
/*
* Create a new pane.
* Split a window (add a new pane).
*/
#define SPLIT_WINDOW_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
static enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmdq_item *);
const struct cmd_entry cmd_new_pane_entry = {
.name = "new-pane",
.alias = "newp",
.args = { "bc:de:EfF:hIkl:Lm:p:PR:s:S:t:vx:X:y:Y:Z", 0, -1, NULL },
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] [-m message] [-p percentage] "
"[-s style] [-S active-border-style] "
"[-R inactive-border-style] [-x width] [-y height] "
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
"[shell-command [argument ...]]",
.target = { 't', CMD_FIND_PANE, 0 },
.flags = 0,
.exec = cmd_split_window_exec
};
static enum cmd_retval cmd_split_window_exec(struct cmd *,
struct cmdq_item *);
const struct cmd_entry cmd_split_window_entry = {
.name = "split-window",
.alias = "splitw",
.args = { "bc:de:EfF:hIkl:m:p:PR:s:S:t:vZ", 0, -1, NULL },
.usage = "[-bdefhIklPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] [-m message] [-p percentage] "
"[-s style] [-S active-border-style] "
"[-R inactive-border-style] " CMD_TARGET_PANE_USAGE " "
"[shell-command [argument ...]]",
.args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL },
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE
" [shell-command [argument ...]]",
.target = { 't', CMD_FIND_PANE, 0 },
@@ -81,46 +62,64 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct window_pane *wp = target->wp, *new_wp;
struct layout_cell *lc = NULL;
enum layout_type type;
struct layout_cell *lc;
struct cmd_find_state fs;
int input, empty, is_floating, flags = 0;
const char *template, *style;
int size, flags, input;
const char *template;
char *cause = NULL, *cp;
struct args_value *av;
u_int count = args_count(args);
u_int count = args_count(args), curval = 0;
if (cmd_get_entry(self) == &cmd_new_pane_entry)
is_floating = !args_has(args, 'L');
else
is_floating = 0;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
flags = is_floating ? SPAWN_FLOATING : 0;
/* If the 'p' flag is dropped then this bit can be moved into 'l'. */
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
size = -1;
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, &cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
&cause);
if (cause == NULL)
size = curval * size / 100;
}
if (cause != NULL) {
cmdq_error(item, "size %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
input = (args_has(args, 'I') && count == 0);
flags = 0;
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
input = args_has(args, 'I');
if (input)
empty = 1;
else
empty = args_has(args, 'E');
if (empty &&
count != 0 &&
(count != 1 || *args_string(args, 0) != '\0')) {
cmdq_error(item, "command cannot be given for empty pane");
return (CMD_RETURN_ERROR);
}
if (empty)
if (input || (count == 1 && *args_string(args, 0) == '\0'))
flags |= SPAWN_EMPTY;
if (is_floating)
lc = layout_get_floating_cell(item, args, w, wp, &cause);
else
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
if (cause != NULL) {
cmdq_error(item, "size or position %s", cause);
free(cause);
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL) {
cmdq_error(item, "no space for new pane");
return (CMD_RETURN_ERROR);
}
@@ -157,51 +156,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
environ_free(sc.environ);
return (CMD_RETURN_ERROR);
}
style = args_get(args, 's');
if (style != NULL) {
if (options_set_string(new_wp->options, "window-style", 0,
"%s", style) == NULL) {
cmdq_error(item, "bad style: %s", style);
return (CMD_RETURN_ERROR);
}
options_set_string(new_wp->options, "window-active-style", 0,
"%s", style);
new_wp->flags |= (PANE_REDRAW|PANE_STYLECHANGED|
PANE_THEMECHANGED);
}
style = args_get(args, 'S');
if (style != NULL) {
if (options_set_string(new_wp->options,
"pane-active-border-style", 0, "%s", style) == NULL) {
cmdq_error(item, "bad active border style: %s", style);
return (CMD_RETURN_ERROR);
}
}
style = args_get(args, 'R');
if (style != NULL) {
if (options_set_string(new_wp->options, "pane-border-style", 0,
"%s", style) == NULL) {
cmdq_error(item, "bad inactive border style: %s",
style);
return (CMD_RETURN_ERROR);
}
}
if (args_has(args, 'k') || args_has(args, 'm')) {
options_set_number(new_wp->options, "remain-on-exit", 3);
if (args_has(args, 'm')) {
options_set_string(new_wp->options,
"remain-on-exit-format", 0, "%s",
args_get(args, 'm'));
}
}
if (input) {
switch (window_pane_start_input(new_wp, item, &cause)) {
case -1:
server_client_remove_pane(new_wp);
if (!is_floating)
layout_close_pane(new_wp);
layout_close_pane(new_wp);
window_remove_pane(wp->window, new_wp);
cmdq_error(item, "%s", cause);
free(cause);
@@ -216,12 +175,9 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
}
if (!args_has(args, 'd'))
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
if (!is_floating) {
window_pop_zoom(wp->window);
server_redraw_window(wp->window);
}
server_redraw_session(s);
window_pop_zoom(wp->window);
server_redraw_window(wp->window);
server_status_session(s);
if (args_has(args, 'P')) {
if ((template = args_get(args, 'F')) == NULL)

View File

@@ -79,12 +79,6 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
if (src_wp == dst_wp)
goto out;
if (window_pane_is_floating(src_wp) ||
window_pane_is_floating(dst_wp)) {
cmdq_error(item, "cannot swap floating panes");
return (CMD_RETURN_ERROR);
}
server_client_remove_pane(src_wp);
server_client_remove_pane(dst_wp);
@@ -98,26 +92,12 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
else
TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, zentry);
TAILQ_REMOVE(&dst_w->z_index, dst_wp, zentry);
TAILQ_REPLACE(&src_w->z_index, src_wp, dst_wp, zentry);
if (tmp_wp == src_wp)
tmp_wp = dst_wp;
if (tmp_wp == NULL)
TAILQ_INSERT_HEAD(&dst_w->z_index, src_wp, zentry);
else
TAILQ_INSERT_AFTER(&dst_w->z_index, tmp_wp, src_wp, zentry);
src_lc = src_wp->layout_cell;
dst_lc = dst_wp->layout_cell;
src_lc->wp = dst_wp;
dst_wp->layout_cell = src_lc;
dst_lc->wp = src_wp;
src_wp->layout_cell = dst_lc;
if (window_pane_is_floating(src_wp) != window_pane_is_floating(dst_wp)) {
src_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
dst_wp->layout_cell->flags ^= LAYOUT_CELL_FLOATING;
}
src_wp->window = dst_w;
options_set_parent(src_wp->options, dst_w->options);

View File

@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tmux.h"
@@ -54,7 +53,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
const char *tflag = args_get(args, 't');
enum cmd_find_type type;
int flags;
struct client *c = cmdq_get_client(item);
struct client *tc = cmdq_get_target_client(item);
struct session *s;
struct winlink *wl;
@@ -63,7 +61,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
const char *tablename;
struct key_table *table;
struct sort_criteria sort_crit;
uid_t uid;
if (tflag != NULL &&
(tflag[strcspn(tflag, ":.%")] != '\0' || strcmp(tflag, "=") == 0)) {
@@ -80,13 +77,6 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
wp = target.wp;
if (args_has(args, 'r')) {
if (tc->flags & CLIENT_READONLY) {
uid = proc_get_peer_uid(c->peer);
if (uid != getuid()) {
cmdq_error(item, "client is read-only");
return (CMD_RETURN_ERROR);
}
}
if (tc->flags & CLIENT_READONLY)
tc->flags &= ~(CLIENT_READONLY|CLIENT_IGNORESIZE);
else

8
cmd.c
View File

@@ -71,7 +71,6 @@ extern const struct cmd_entry cmd_lock_server_entry;
extern const struct cmd_entry cmd_lock_session_entry;
extern const struct cmd_entry cmd_move_pane_entry;
extern const struct cmd_entry cmd_move_window_entry;
extern const struct cmd_entry cmd_new_pane_entry;
extern const struct cmd_entry cmd_new_session_entry;
extern const struct cmd_entry cmd_new_window_entry;
extern const struct cmd_entry cmd_next_layout_entry;
@@ -164,7 +163,6 @@ const struct cmd_entry *cmd_table[] = {
&cmd_lock_session_entry,
&cmd_move_pane_entry,
&cmd_move_window_entry,
&cmd_new_pane_entry,
&cmd_new_session_entry,
&cmd_new_window_entry,
&cmd_next_layout_entry,
@@ -305,8 +303,6 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
if (argc == 0)
return (0);
if (argc < 0 || argc > 1000)
return (-1);
*argv = xcalloc(argc, sizeof **argv);
buf[len - 1] = '\0';
@@ -776,9 +772,9 @@ cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
if (m->statusat == 0 && y >= m->statuslines)
y -= m->statuslines;
if ((int)x < wp->xoff || (int)x >= wp->xoff + (int)wp->sx)
if (x < wp->xoff || x >= wp->xoff + wp->sx)
return (-1);
if ((int)y < wp->yoff || (int)y >= wp->yoff + (int)wp->sy)
if (y < wp->yoff || y >= wp->yoff + wp->sy)
return (-1);
if (xp != NULL)

View File

@@ -463,9 +463,6 @@ int utf8proc_wctomb(char *, wchar_t);
#ifdef NEED_FUZZING
/* tmux.c */
#define main __weak main
#define regcomp(preg, pattern, cflags) (0)
#define regexec(preg, string, nmatch, pmatch, eflags) (REG_NOMATCH)
#define regfree(preg) ((void)0)
#endif
/* getopt.c */

View File

@@ -81,8 +81,7 @@ struct systemd_job_watch {
};
static int
job_removed_handler(sd_bus_message *m, void *userdata,
__unused sd_bus_error *ret_error)
job_removed_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
struct systemd_job_watch *watch = userdata;
const char *path = NULL;
@@ -110,7 +109,7 @@ systemd_move_to_new_cgroup(char **cause)
sd_bus_message *m = NULL, *reply = NULL;
sd_bus *bus = NULL;
sd_bus_slot *slot = NULL;
char *name, *desc, *slice, *unit;
char *name, *desc, *slice;
sd_id128_t uuid;
int r;
uint64_t elapsed_usec;
@@ -242,26 +241,6 @@ systemd_move_to_new_cgroup(char **cause)
goto finish;
}
/*
* Try locating systemd unit that started the server, and mark pane units
* as dependent on it. Use "Before" to make sure systemd will not try to
* kill them first.
*/
if (sd_pid_get_user_unit(parent_pid, &unit) == 0 ||
sd_pid_get_unit(parent_pid, &unit) == 0) {
r = sd_bus_message_append(m, "(sv)", "Before", "as", 1, unit);
if (r >= 0) {
r = sd_bus_message_append(m, "(sv)", "PartOf", "as", 1,
unit);
}
free(unit);
if (r < 0) {
xasprintf(cause, "failed to append to properties: %s",
strerror(-r));
goto finish;
}
}
/* End properties array. */
r = sd_bus_message_close_container(m);
if (r < 0) {

View File

@@ -1,6 +1,6 @@
# configure.ac
AC_INIT([tmux], 3.7a)
AC_INIT([tmux], next-3.7)
AC_PREREQ([2.60])
AC_CONFIG_AUX_DIR(etc)
@@ -73,15 +73,6 @@ AC_ARG_ENABLE(
)
AM_CONDITIONAL(IS_OPTIMIZED, test "x$enable_optimizations" = xyes)
# Is this --enable-asan?
AC_ARG_ENABLE(
asan,
AS_HELP_STRING(--enable-asan, enable ASAN build flags),
,
enable_asan=no
)
AM_CONDITIONAL(IS_ASAN, test "x$enable_asan" = xyes)
# Is this a static build?
AC_ARG_ENABLE(
static,
@@ -297,24 +288,24 @@ fi
# Look for ncurses or curses. Try pkg-config first then directly for the
# library.
PKG_CHECK_MODULES(
LIBTINFOW,
tinfow,
LIBTINFO,
tinfo,
[
AM_CPPFLAGS="$LIBTINFOW_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBTINFOW_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBTINFOW_LIBS $LIBS"
AM_CPPFLAGS="$LIBTINFO_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBTINFO_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBTINFO_LIBS $LIBS"
found_ncurses=yes
],
found_ncurses=no
)
if test "x$found_ncurses" = xno; then
PKG_CHECK_MODULES(
LIBTINFO,
tinfo,
LIBNCURSES,
ncurses,
[
AM_CPPFLAGS="$LIBTINFO_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBTINFO_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBTINFO_LIBS $LIBS"
AM_CPPFLAGS="$LIBNCURSES_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBNCURSES_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBNCURSES_LIBS $LIBS"
found_ncurses=yes
],
found_ncurses=no
@@ -333,23 +324,10 @@ if test "x$found_ncurses" = xno; then
found_ncurses=no
)
fi
if test "x$found_ncurses" = xno; then
PKG_CHECK_MODULES(
LIBNCURSES,
ncurses,
[
AM_CPPFLAGS="$LIBNCURSES_CFLAGS $AM_CPPFLAGS"
CPPFLAGS="$LIBNCURSES_CFLAGS $SAVED_CPPFLAGS"
LIBS="$LIBNCURSES_LIBS $LIBS"
found_ncurses=yes
],
found_ncurses=no
)
fi
if test "x$found_ncurses" = xno; then
AC_SEARCH_LIBS(
setupterm,
[tinfow tinfo terminfo ncursesw ncurses],
[tinfo terminfo ncurses ncursesw],
found_ncurses=yes,
found_ncurses=no
)
@@ -485,13 +463,32 @@ fi
# Enable sixel support.
AC_ARG_ENABLE(
sixel,
AS_HELP_STRING(--enable-sixel, enable sixel images)
sixel-images,
AS_HELP_STRING(--enable-sixel-images, enable sixel images)
)
if test "x$enable_sixel" = xyes; then
AC_DEFINE(ENABLE_SIXEL)
AC_ARG_ENABLE(
sixel,
AS_HELP_STRING(--enable-sixel support),
[
enable_sixel_images="$enableval"
]
)
if test "x$enable_sixel_images" = xyes; then
AC_DEFINE(ENABLE_SIXEL_IMAGES)
fi
AM_CONDITIONAL(ENABLE_SIXEL, [test "x$enable_sixel" = xyes])
AM_CONDITIONAL(ENABLE_SIXEL_IMAGES, [test "x$enable_sixel_images" = xyes])
# Enable kitty graphics protocol support.
AC_ARG_ENABLE(
kitty-images,
AS_HELP_STRING(--enable-kitty-images, enable kitty terminal graphics)
)
if test "x$enable_kitty_images" = xyes; then
AC_DEFINE(ENABLE_KITTY_IMAGES)
fi
AM_CONDITIONAL(ENABLE_KITTY_IMAGES, [test "x$enable_kitty_images" = xyes])
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
AC_MSG_CHECKING(for b64_ntop)

View File

@@ -24,8 +24,7 @@
#include "tmux.h"
#define CONTROL_SHOULD_NOTIFY_CLIENT(c) \
((c) != NULL && ((c)->flags & CLIENT_CONTROL) && \
(c)->control_state != NULL)
((c) != NULL && ((c)->flags & CLIENT_CONTROL))
void
control_notify_pane_mode_changed(int pane)
@@ -77,8 +76,6 @@ control_notify_window_pane_changed(struct window *w)
{
struct client *c;
if (w->active == NULL)
return;
TAILQ_FOREACH(c, &clients, entry) {
if (!CONTROL_SHOULD_NOTIFY_CLIENT(c))
continue;

View File

@@ -207,12 +207,10 @@ control_free_sub(struct control_state *cs, struct control_sub *csub)
RB_FOREACH_SAFE(csp, control_sub_panes, &csub->panes, csp1) {
RB_REMOVE(control_sub_panes, &csub->panes, csp);
free(csp->last);
free(csp);
}
RB_FOREACH_SAFE(csw, control_sub_windows, &csub->windows, csw1) {
RB_REMOVE(control_sub_windows, &csub->windows, csw);
free(csw->last);
free(csw);
}
free(csub->last);
@@ -300,7 +298,6 @@ control_reset_offsets(struct client *c)
struct control_pane *cp, *cp1;
RB_FOREACH_SAFE(cp, control_panes, &cs->panes, cp1) {
control_discard_pane(c, cp);
RB_REMOVE(control_panes, &cs->panes, cp);
free(cp);
}
@@ -355,9 +352,6 @@ control_set_pane_off(struct client *c, struct window_pane *wp)
struct control_pane *cp;
cp = control_add_pane(c, wp);
control_discard_pane(c, cp);
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
cp->flags |= CONTROL_PANE_OFF;
}
@@ -834,9 +828,6 @@ control_stop(struct client *c)
struct control_block *cb, *cb1;
struct control_sub *csub, *csub1;
if (cs == NULL)
return;
if (~c->flags & CLIENT_CONTROLCONTROL)
bufferevent_free(cs->write_event);
bufferevent_free(cs->read_event);
@@ -846,11 +837,10 @@ control_stop(struct client *c)
if (evtimer_initialized(&cs->subs_timer))
evtimer_del(&cs->subs_timer);
control_reset_offsets(c);
TAILQ_FOREACH_SAFE(cb, &cs->all_blocks, all_entry, cb1)
control_free_block(cs, cb);
control_reset_offsets(c);
c->control_state = NULL;
free(cs);
}
@@ -1055,9 +1045,6 @@ control_check_subs_timer(__unused int fd, __unused short events, void *data)
log_debug("%s: timer fired", __func__);
evtimer_add(&cs->subs_timer, &tv);
if (s == NULL)
return;
/* Find which subscription types are present. */
RB_FOREACH(csub, control_subs, &cs->subs) {
switch (csub->type) {

29
file.c
View File

@@ -399,10 +399,6 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
}
for (;;) {
size = fread(buffer, 1, sizeof buffer, f);
if (ferror(f)) {
cf->error = errno;
goto done;
}
if (evbuffer_add(cf->buffer, buffer, size) != 0) {
cf->error = ENOMEM;
goto done;
@@ -675,7 +671,7 @@ file_write_close(struct client_files *files, struct imsg *imsg)
/* Client file read error callback. */
static void
file_read_error_callback(__unused struct bufferevent *bev, short what,
file_read_error_callback(__unused struct bufferevent *bev, __unused short what,
void *arg)
{
struct client_file *cf = arg;
@@ -684,7 +680,7 @@ file_read_error_callback(__unused struct bufferevent *bev, short what,
log_debug("read error file %d", cf->stream);
msg.stream = cf->stream;
msg.error = (what & EVBUFFER_ERROR) ? EIO : 0;
msg.error = 0;
proc_send(cf->peer, MSG_READ_DONE, -1, &msg, sizeof msg);
bufferevent_free(cf->event);
@@ -808,7 +804,7 @@ file_read_cancel(struct client_files *files, struct imsg *imsg)
}
/* Handle a write ready message (server). */
int
void
file_write_ready(struct client_files *files, struct imsg *imsg)
{
struct msg_write_ready *msg = imsg->data;
@@ -816,20 +812,19 @@ file_write_ready(struct client_files *files, struct imsg *imsg)
struct client_file find, *cf;
if (msglen != sizeof *msg)
return (-1);
fatalx("bad MSG_WRITE_READY size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
return (0);
return;
if (msg->error != 0) {
cf->error = msg->error;
file_fire_done(cf);
} else
file_push(cf);
return (0);
}
/* Handle read data message (server). */
int
void
file_read_data(struct client_files *files, struct imsg *imsg)
{
struct msg_read_data *msg = imsg->data;
@@ -839,10 +834,10 @@ file_read_data(struct client_files *files, struct imsg *imsg)
size_t bsize = msglen - sizeof *msg;
if (msglen < sizeof *msg)
return (-1);
fatalx("bad MSG_READ_DATA size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
return (0);
return;
log_debug("file %d read %zu bytes", cf->stream, bsize);
if (cf->error == 0 && !cf->closed) {
@@ -852,11 +847,10 @@ file_read_data(struct client_files *files, struct imsg *imsg)
} else
file_fire_read(cf);
}
return (0);
}
/* Handle a read done message (server). */
int
void
file_read_done(struct client_files *files, struct imsg *imsg)
{
struct msg_read_done *msg = imsg->data;
@@ -864,13 +858,12 @@ file_read_done(struct client_files *files, struct imsg *imsg)
struct client_file find, *cf;
if (msglen != sizeof *msg)
return (-1);
fatalx("bad MSG_READ_DONE size");
find.stream = msg->stream;
if ((cf = RB_FIND(client_files, files, &find)) == NULL)
return (0);
return;
log_debug("file %d read done", cf->stream);
cf->error = msg->error;
file_fire_done(cf);
return (0);
}

View File

@@ -49,7 +49,6 @@ format_is_type(struct format_range *fr, struct style *sy)
case STYLE_RANGE_NONE:
case STYLE_RANGE_LEFT:
case STYLE_RANGE_RIGHT:
case STYLE_RANGE_CONTROL:
return (1);
case STYLE_RANGE_PANE:
case STYLE_RANGE_WINDOW:
@@ -1066,10 +1065,6 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
log_debug("%s: range user|%u at %u-%u", __func__,
sr->argument, sr->start, sr->end);
break;
case STYLE_RANGE_CONTROL:
log_debug("%s: range control|%u at %u-%u", __func__,
sr->argument, sr->start, sr->end);
break;
}
format_free_range(&frs, fr);
}
@@ -1121,7 +1116,7 @@ format_width(const char *expanded)
/*
* Trim on the left, taking #[] into account. Note, we copy the whole set of
* unescaped #s, but only add their escaped size to width. This is because the
* format_draw function will actually do the escaping.
* format_draw function will actually do the escaping when it runs
*/
char *
format_trim_left(const char *expanded, u_int limit)

365
format.c
View File

@@ -84,15 +84,6 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
return (strcmp(fj1->cmd, fj2->cmd));
}
/* Maimum pad and trim width. */
#define FORMAT_MAX_WIDTH 10000
/* Maimum repeat size. */
#define FORMAT_MAX_REPEAT 10000
/* Maimum precision. */
#define FORMAT_MAX_PRECISION 100
/* Format modifiers. */
#define FORMAT_TIMESTRING 0x1
#define FORMAT_BASENAME 0x2
@@ -116,14 +107,10 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
#define FORMAT_NOT 0x80000
#define FORMAT_NOT_NOT 0x100000
#define FORMAT_REPEAT 0x200000
#define FORMAT_QUOTE_ARGUMENTS 0x400000
/* Limit on recursion. */
#define FORMAT_LOOP_LIMIT 100
/* Limit on time taken (milliseconds). */
#define FORMAT_TIME_LIMIT 100
/* Format expand flags. */
#define FORMAT_EXPAND_TIME 0x1
#define FORMAT_EXPAND_NOJOBS 0x2
@@ -173,11 +160,9 @@ RB_GENERATE_STATIC(format_entry_tree, format_entry, entry, format_entry_cmp);
struct format_expand_state {
struct format_tree *ft;
u_int loop;
uint64_t start_time;
int flags;
time_t time;
struct tm tm;
int flags;
};
/* Format modifier. */
@@ -298,7 +283,6 @@ format_copy_state(struct format_expand_state *to,
to->time = from->time;
memcpy(&to->tm, &from->tm, sizeof to->tm);
to->flags = from->flags|flags;
to->start_time = from->start_time;
}
/* Format job update callback. */
@@ -841,8 +825,8 @@ format_cb_window_layout(struct format_tree *ft)
return (NULL);
if (w->saved_layout_root != NULL)
return (layout_dump(w, w->saved_layout_root));
return (layout_dump(w, w->layout_root));
return (layout_dump(w->saved_layout_root));
return (layout_dump(w->layout_root));
}
/* Callback for window_visible_layout. */
@@ -854,7 +838,7 @@ format_cb_window_visible_layout(struct format_tree *ft)
if (w == NULL)
return (NULL);
return (layout_dump(w, w->layout_root));
return (layout_dump(w->layout_root));
}
/* Callback for pane_start_command. */
@@ -1020,29 +1004,6 @@ format_cb_pane_fg(struct format_tree *ft)
return (xstrdup(colour_tostring(gc.fg)));
}
/* Callback for pane_flags. */
static void *
format_cb_pane_flags(struct format_tree *ft)
{
if (ft->wp != NULL)
return (xstrdup(window_pane_printable_flags(ft->wp)));
return (NULL);
}
/* Callback for pane_floating_flag. */
static void *
format_cb_pane_floating_flag(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp != NULL) {
if (window_pane_is_floating(wp))
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for pane_bg. */
static void *
format_cb_pane_bg(struct format_tree *ft)
@@ -1185,9 +1146,9 @@ format_cb_pane_at_bottom(struct format_tree *ft)
status = options_get_number(w->options, "pane-border-status");
if (status == PANE_STATUS_BOTTOM)
flag = (wp->yoff + (int)wp->sy == (int)w->sy - 1);
flag = (wp->yoff + wp->sy == w->sy - 1);
else
flag = (wp->yoff + (int)wp->sy == (int)w->sy);
flag = (wp->yoff + wp->sy == w->sy);
xasprintf(&value, "%d", flag);
return (value);
}
@@ -1360,8 +1321,6 @@ format_cb_mouse_status_range(struct format_tree *ft)
return (xstrdup("session"));
case STYLE_RANGE_USER:
return (xstrdup(sr->string));
case STYLE_RANGE_CONTROL:
return (xstrdup("control"));
}
return (NULL);
}
@@ -1396,18 +1355,6 @@ format_cb_alternate_saved_y(struct format_tree *ft)
return (NULL);
}
/* Callback for bracket_paste_flag. */
static void *
format_cb_bracket_paste_flag(struct format_tree *ft)
{
if (ft->wp != NULL && ft->wp->screen != NULL) {
if (ft->wp->screen->mode & MODE_BRACKETPASTE)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for buffer_name. */
static void *
format_cb_buffer_name(struct format_tree *ft)
@@ -1646,13 +1593,9 @@ format_cb_client_user(struct format_tree *ft)
struct passwd *pw;
if (ft->c != NULL) {
if (ft->c->user != NULL)
return (xstrdup(ft->c->user));
uid = proc_get_peer_uid(ft->c->peer);
if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL) {
ft->c->user = xstrdup(pw->pw_name);
return (xstrdup(ft->c->user));
}
if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL)
return (xstrdup(pw->pw_name));
}
return (NULL);
}
@@ -2049,7 +1992,7 @@ static void *
format_cb_pane_at_right(struct format_tree *ft)
{
if (ft->wp != NULL) {
if (ft->wp->xoff + (int)ft->wp->sx == (int)ft->wp->window->sx)
if (ft->wp->xoff + ft->wp->sx == ft->wp->window->sx)
return (xstrdup("1"));
return (xstrdup("0"));
}
@@ -2060,10 +2003,8 @@ format_cb_pane_at_right(struct format_tree *ft)
static void *
format_cb_pane_bottom(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp != NULL)
return (format_printf("%d", wp->yoff + (int)wp->sy - 1));
if (ft->wp != NULL)
return (format_printf("%u", ft->wp->yoff + ft->wp->sy - 1));
return (NULL);
}
@@ -2222,7 +2163,7 @@ static void *
format_cb_pane_left(struct format_tree *ft)
{
if (ft->wp != NULL)
return (format_printf("%d", ft->wp->xoff));
return (format_printf("%u", ft->wp->xoff));
return (NULL);
}
@@ -2309,46 +2250,12 @@ format_cb_pane_pipe_pid(struct format_tree *ft)
return (value);
}
/* Callback for pane_pb_progress. */
static void *
format_cb_pane_pb_progress(struct format_tree *ft)
{
char *value = NULL;
if (ft->wp != NULL)
xasprintf(&value, "%d", ft->wp->base.progress_bar.progress);
return (value);
}
/* Callback for pane_pb_state. */
static void *
format_cb_pane_pb_state(struct format_tree *ft)
{
if (ft->wp != NULL) {
switch (ft->wp->base.progress_bar.state) {
case PROGRESS_BAR_HIDDEN:
return xstrdup("hidden");
case PROGRESS_BAR_NORMAL:
return xstrdup("normal");
case PROGRESS_BAR_ERROR:
return xstrdup("error");
case PROGRESS_BAR_INDETERMINATE:
return xstrdup("indeterminate");
case PROGRESS_BAR_PAUSED:
return xstrdup("paused");
}
}
return (NULL);
}
/* Callback for pane_right. */
static void *
format_cb_pane_right(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp != NULL)
return (format_printf("%d", wp->xoff + (int)wp->sx - 1));
if (ft->wp != NULL)
return (format_printf("%u", ft->wp->xoff + ft->wp->sx - 1));
return (NULL);
}
@@ -2390,7 +2297,7 @@ static void *
format_cb_pane_top(struct format_tree *ft)
{
if (ft->wp != NULL)
return (format_printf("%d", ft->wp->yoff));
return (format_printf("%u", ft->wp->yoff));
return (NULL);
}
@@ -2412,49 +2319,6 @@ format_cb_pane_width(struct format_tree *ft)
return (NULL);
}
/* Callback for pane_x. */
static void *
format_cb_pane_x(struct format_tree *ft)
{
if (ft->wp != NULL)
return (format_printf("%d", ft->wp->xoff));
return (NULL);
}
/* Callback for pane_y. */
static void *
format_cb_pane_y(struct format_tree *ft)
{
if (ft->wp != NULL)
return (format_printf("%d", ft->wp->yoff));
return (NULL);
}
/* Callback for pane_z. */
static void *
format_cb_pane_z(struct format_tree *ft)
{
u_int idx;
if (ft->wp != NULL && window_pane_zindex(ft->wp, &idx) == 0)
return (format_printf("%u", idx));
return (NULL);
}
/* Callback for pane_zoomed_flag. */
static void *
format_cb_pane_zoomed_flag(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp != NULL) {
if (wp->flags & PANE_ZOOMED)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for scroll_region_lower. */
static void *
format_cb_scroll_region_lower(struct format_tree *ft)
@@ -2698,12 +2562,16 @@ format_cb_version(__unused struct format_tree *ft)
/* Callback for sixel_support. */
static void *
format_cb_sixel_support(__unused struct format_tree *ft)
format_cb_image_support(__unused struct format_tree *ft)
{
#ifdef ENABLE_SIXEL
return (xstrdup("1"));
#if defined(ENABLE_SIXEL_IMAGES) && defined(ENABLE_KITTY_IMAGES)
return (xstrdup("kitty,sixel"));
#elif defined(ENABLE_SIXEL_IMAGES)
return (xstrdup("sixel"));
#elif defined(ENABLE_KITTY_IMAGES)
return (xstrdup("kitty"));
#else
return (xstrdup("0"));
return (NULL);
#endif
}
@@ -2970,7 +2838,7 @@ static void *
format_cb_window_panes(struct format_tree *ft)
{
if (ft->w != NULL)
return (format_printf("%u", window_count_panes(ft->w, 1)));
return (format_printf("%u", window_count_panes(ft->w)));
return (NULL);
}
@@ -3147,13 +3015,10 @@ format_cb_uid(__unused struct format_tree *ft)
static void *
format_cb_user(__unused struct format_tree *ft)
{
static char *cached;
struct passwd *pw;
if (cached == NULL && (pw = getpwuid(getuid())) != NULL)
cached = xstrdup(pw->pw_name);
if (cached != NULL)
return (xstrdup(cached));
if ((pw = getpwuid(getuid())) != NULL)
return (xstrdup(pw->pw_name));
return (NULL);
}
@@ -3188,9 +3053,6 @@ static const struct format_table_entry format_table[] = {
{ "alternate_saved_y", FORMAT_TABLE_STRING,
format_cb_alternate_saved_y
},
{ "bracket_paste_flag", FORMAT_TABLE_STRING,
format_cb_bracket_paste_flag
},
{ "buffer_created", FORMAT_TABLE_TIME,
format_cb_buffer_created
},
@@ -3332,6 +3194,9 @@ static const struct format_table_entry format_table[] = {
{ "host_short", FORMAT_TABLE_STRING,
format_cb_host_short
},
{ "image_support", FORMAT_TABLE_STRING,
format_cb_image_support
},
{ "insert_flag", FORMAT_TABLE_STRING,
format_cb_insert_flag
},
@@ -3437,12 +3302,6 @@ static const struct format_table_entry format_table[] = {
{ "pane_fg", FORMAT_TABLE_STRING,
format_cb_pane_fg
},
{ "pane_flags", FORMAT_TABLE_STRING,
format_cb_pane_flags
},
{ "pane_floating_flag", FORMAT_TABLE_STRING,
format_cb_pane_floating_flag
},
{ "pane_format", FORMAT_TABLE_STRING,
format_cb_pane_format
},
@@ -3482,12 +3341,6 @@ static const struct format_table_entry format_table[] = {
{ "pane_path", FORMAT_TABLE_STRING,
format_cb_pane_path
},
{ "pane_pb_progress", FORMAT_TABLE_STRING,
format_cb_pane_pb_progress
},
{ "pane_pb_state", FORMAT_TABLE_STRING,
format_cb_pane_pb_state
},
{ "pane_pid", FORMAT_TABLE_STRING,
format_cb_pane_pid
},
@@ -3530,18 +3383,6 @@ static const struct format_table_entry format_table[] = {
{ "pane_width", FORMAT_TABLE_STRING,
format_cb_pane_width
},
{ "pane_x", FORMAT_TABLE_STRING,
format_cb_pane_x
},
{ "pane_y", FORMAT_TABLE_STRING,
format_cb_pane_y
},
{ "pane_z", FORMAT_TABLE_STRING,
format_cb_pane_z
},
{ "pane_zoomed_flag", FORMAT_TABLE_STRING,
format_cb_pane_zoomed_flag
},
{ "pid", FORMAT_TABLE_STRING,
format_cb_pid
},
@@ -3632,9 +3473,6 @@ static const struct format_table_entry format_table[] = {
{ "session_windows", FORMAT_TABLE_STRING,
format_cb_session_windows
},
{ "sixel_support", FORMAT_TABLE_STRING,
format_cb_sixel_support
},
{ "socket_path", FORMAT_TABLE_STRING,
format_cb_socket_path
},
@@ -4183,41 +4021,18 @@ found:
found = format_quote_style(saved);
free(saved);
}
if (modifiers & FORMAT_QUOTE_ARGUMENTS) {
saved = found;
found = args_escape(saved);
free(saved);
}
return (found);
}
/* Check if format has not taken too long. */
static int
format_check_time(struct format_expand_state *es)
{
uint64_t t = get_timer();
if (t - es->start_time < FORMAT_TIME_LIMIT)
return (1);
t -= es->start_time;
format_log(es, "reached time limit (%llu)", (unsigned long long)t);
return (0);
}
/* Unescape escaped characters. */
static char *
format_unescape(struct format_expand_state *es, const char *s)
format_unescape(const char *s)
{
char *out, *cp;
int brackets = 0;
cp = out = xmalloc(strlen(s) + 1);
for (; *s != '\0'; s++) {
if (!format_check_time(es)){
free(out);
return (xstrdup(""));
}
if (*s == '#' && s[1] == '{')
brackets++;
if (brackets == 0 &&
@@ -4236,17 +4051,13 @@ format_unescape(struct format_expand_state *es, const char *s)
/* Remove escaped characters. */
static char *
format_strip(struct format_expand_state *es, const char *s)
format_strip(const char *s)
{
char *out, *cp;
int brackets = 0;
cp = out = xmalloc(strlen(s) + 1);
for (; *s != '\0'; s++) {
if (!format_check_time(es)){
free(out);
return (xstrdup(""));
}
if (*s == '#' && s[1] == '{')
brackets++;
if (*s == '#' && strchr(",#{}:", s[1]) != NULL) {
@@ -4263,14 +4074,12 @@ format_strip(struct format_expand_state *es, const char *s)
}
/* Skip until end. */
static const char *
format_skip1(struct format_expand_state *es, const char *s, const char *end)
const char *
format_skip(const char *s, const char *end)
{
int brackets = 0;
for (; *s != '\0'; s++) {
if (es != NULL && !format_check_time(es))
return (NULL);
if (*s == '#' && s[1] == '{')
brackets++;
if (*s == '#' &&
@@ -4289,13 +4098,6 @@ format_skip1(struct format_expand_state *es, const char *s, const char *end)
return (s);
}
/* Skip until end. */
const char *
format_skip(const char *s, const char *end)
{
return (format_skip1(NULL, s, end));
}
/* Return left and right alternatives separated by commas. */
static int
format_choose(struct format_expand_state *es, const char *s, char **left,
@@ -4304,7 +4106,7 @@ format_choose(struct format_expand_state *es, const char *s, char **left,
const char *cp;
char *left0, *right0;
cp = format_skip1(es, s, ",");
cp = format_skip(s, ",");
if (cp == NULL)
return (-1);
left0 = xstrndup(s, cp - s);
@@ -4394,8 +4196,6 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
/* Skip any separator character. */
if (*cp == ';')
cp++;
if (*cp == '\0')
break;
/* Check single character modifiers with no arguments. */
if (strchr("labcdnwETSWPL!<>", cp[0]) != NULL &&
@@ -4435,7 +4235,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
/* Single argument with no wrapper character. */
if (!ispunct((u_char)cp[1]) || cp[1] == '-') {
end = format_skip1(es, cp + 1, ":;");
end = format_skip(cp + 1, ":;");
if (end == NULL)
break;
@@ -4458,7 +4258,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s,
cp++;
break;
}
end = format_skip1(es, cp + 1, last);
end = format_skip(cp + 1, last);
if (end == NULL)
break;
cp++;
@@ -4572,7 +4372,7 @@ format_bool_op_n(struct format_expand_state *es, const char *fmt, int and)
cp1 = fmt;
while (and ? result : !result) {
cp2 = format_skip1(es, cp1, ",");
cp2 = format_skip(cp1, ",");
if (cp2 == NULL)
raw = xstrdup(cp1);
@@ -4695,37 +4495,6 @@ format_window_name(struct format_expand_state *es, const char *fmt)
return (xstrdup("0"));
}
/* Add neighbor window variables to the format tree. */
static void
format_add_window_neighbor(struct format_tree *nft, struct winlink *wl,
struct session *s, const char *prefix)
{
struct options_entry *o;
const char *oname;
char *key, *prefixed, *oval;
xasprintf(&key, "%s_window_index", prefix);
format_add(nft, key, "%u", wl->idx);
free(key);
xasprintf(&key, "%s_window_active", prefix);
format_add(nft, key, "%d", wl == s->curw);
free(key);
o = options_first(wl->window->options);
while (o != NULL) {
oname = options_name(o);
if (*oname == '@') {
xasprintf(&prefixed, "%s_%s", prefix, oname);
oval = options_to_string(o, -1, 1);
format_add(nft, prefixed, "%s", oval);
free(oval);
free(prefixed);
}
o = options_next(o);
}
}
/* Loop over windows. */
static char *
format_loop_windows(struct format_expand_state *es, const char *fmt)
@@ -4769,17 +4538,6 @@ format_loop_windows(struct format_expand_state *es, const char *fmt)
nft = format_create(c, item, FORMAT_WINDOW|w->id,
ft->flags|last);
format_defaults(nft, ft->c, ft->s, wl, NULL);
/* Add neighbor window data to the format tree. */
format_add(nft, "window_after_active", "%d",
i > 0 && l[i - 1] == ft->s->curw);
format_add(nft, "window_before_active", "%d",
i + 1 < n && l[i + 1] == ft->s->curw);
if (i + 1 < n)
format_add_window_neighbor(nft, l[i + 1], ft->s, "next");
if (i > 0)
format_add_window_neighbor(nft, l[i - 1], ft->s, "prev");
format_copy_state(&next, es, 0);
next.ft = nft;
expanded = format_expand1(&next, use);
@@ -4956,8 +4714,7 @@ format_replace_expression(struct format_modifier *mexp,
/* The third argument may be precision. */
if (argc >= 3) {
prec = strtonum(mexp->argv[2], -FORMAT_MAX_PRECISION,
FORMAT_MAX_PRECISION, &errstr);
prec = strtonum(mexp->argv[2], INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) {
format_log(es, "expression precision %s: %s", errstr,
mexp->argv[2]);
@@ -5102,8 +4859,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
case '=':
if (fm->argc < 1)
break;
limit = strtonum(fm->argv[0], -FORMAT_MAX_WIDTH,
FORMAT_MAX_WIDTH, &errstr);
limit = strtonum(fm->argv[0], INT_MIN, INT_MAX,
&errstr);
if (errstr != NULL)
limit = 0;
if (fm->argc >= 2 && fm->argv[1] != NULL)
@@ -5112,8 +4869,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
case 'p':
if (fm->argc < 1)
break;
width = strtonum(fm->argv[0], -FORMAT_MAX_WIDTH,
FORMAT_MAX_WIDTH, &errstr);
width = strtonum(fm->argv[0], INT_MIN, INT_MAX,
&errstr);
if (errstr != NULL)
width = 0;
break;
@@ -5150,10 +4907,8 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
if (strchr(fm->argv[0], 'p') != NULL)
modifiers |= FORMAT_PRETTY;
else if (fm->argc >= 2 &&
strchr(fm->argv[0], 'f') != NULL) {
free(time_format);
time_format = format_strip(es, fm->argv[1]);
}
strchr(fm->argv[0], 'f') != NULL)
time_format = format_strip(fm->argv[1]);
break;
case 'q':
if (fm->argc < 1)
@@ -5161,8 +4916,6 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
else if (strchr(fm->argv[0], 'e') != NULL ||
strchr(fm->argv[0], 'h') != NULL)
modifiers |= FORMAT_QUOTE_STYLE;
else if (strchr(fm->argv[0], 'a') != NULL)
modifiers |= FORMAT_QUOTE_ARGUMENTS;
break;
case 'E':
modifiers |= FORMAT_EXPAND;
@@ -5270,7 +5023,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
/* Is this a literal string? */
if (modifiers & FORMAT_LITERAL) {
format_log(es, "literal string is '%s'", copy);
value = format_unescape(es, copy);
value = format_unescape(copy);
goto done;
}
@@ -5334,24 +5087,18 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
value = format_search(search, wp, new);
}
free(new);
} else if (modifiers & FORMAT_REPEAT) {
} else if (modifiers & FORMAT_REPEAT) {
/* Repeat multiple times. */
if (format_choose(es, copy, &left, &right, 1) != 0) {
format_log(es, "repeat syntax error: %s", copy);
goto fail;
}
nrep = strtonum(right, 1, FORMAT_MAX_REPEAT, &errstr);
nrep = strtonum(right, 1, 10000, &errstr);
if (errstr != NULL)
value = xstrdup("");
else {
value = xstrdup("");
for (i = 0; i < nrep; i++) {
if (!format_check_time(es)) {
free(right);
free(left);
free(value);
goto fail;
}
xasprintf(&new, "%s%s", value, left);
free(value);
value = new;
@@ -5359,7 +5106,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
}
free(right);
free(left);
} else if (modifiers & FORMAT_NOT) {
} else if (modifiers & FORMAT_NOT) {
value = format_bool_op_1(es, copy, 1);
} else if (modifiers & FORMAT_NOT_NOT) {
value = format_bool_op_1(es, copy, 0);
@@ -5423,7 +5170,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
*/
cp = copy + 1;
while (1) {
cp2 = format_skip1(es, cp, ",");
cp2 = format_skip(cp, ",");
if (cp2 == NULL) {
format_log(es,
"no condition matched in '%s'; using last "
@@ -5458,7 +5205,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
}
cp = cp2 + 1;
cp2 = format_skip1(es, cp, ",");
cp2 = format_skip(cp, ",");
if (format_true(found)) {
format_log(es, "condition '%s' is true",
condition);
@@ -5541,7 +5288,6 @@ done:
if (marker != NULL && strcmp(new, value) != 0) {
free(value);
xasprintf(&value, "%s%s", new, marker);
free(new);
} else {
free(value);
value = new;
@@ -5552,7 +5298,6 @@ done:
if (marker != NULL && strcmp(new, value) != 0) {
free(value);
xasprintf(&value, "%s%s", marker, new);
free(new);
} else {
free(value);
value = new;
@@ -5626,7 +5371,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
int ch, brackets;
char expanded[8192];
if (fmt == NULL || *fmt == '\0' || !format_check_time(es))
if (fmt == NULL || *fmt == '\0')
return (xstrdup(""));
if (es->loop == FORMAT_LOOP_LIMIT) {
@@ -5665,7 +5410,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
buf[off++] = *fmt++;
continue;
}
if (*++fmt == '\0')
if (*fmt++ == '\0')
break;
ch = (u_char)*fmt++;
@@ -5708,7 +5453,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
fmt += n + 1;
continue;
case '{':
ptr = format_skip1(es, (char *)fmt - 2, "}");
ptr = format_skip((char *)fmt - 2, "}");
if (ptr == NULL)
break;
n = ptr - fmt;
@@ -5731,7 +5476,7 @@ format_expand1(struct format_expand_state *es, const char *fmt)
n++;
}
if (*ptr == '[') {
style_end = format_skip1(es, fmt - 2, "]");
style_end = format_skip(fmt - 2, "]");
format_log(es, "found #*%zu[", n);
while (len - off < n + 2) {
buf = xreallocarray(buf, 2, len);
@@ -5795,7 +5540,6 @@ format_expand_time(struct format_tree *ft, const char *fmt)
memset(&es, 0, sizeof es);
es.ft = ft;
es.flags = FORMAT_EXPAND_TIME;
es.start_time = get_timer();
return (format_expand1(&es, fmt));
}
@@ -5808,7 +5552,6 @@ format_expand(struct format_tree *ft, const char *fmt)
memset(&es, 0, sizeof es);
es.ft = ft;
es.flags = 0;
es.start_time = get_timer();
return (format_expand1(&es, fmt));
}

View File

@@ -1,83 +0,0 @@
/*
* Copyright (c) 2026 David Korczynski <david@adalogics.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.
*/
/*
* Fuzz the tmux command parser (cmd_parse_from_buffer).
*
* This exercises:
* - cmd-parse.y (yacc grammar, lexer, command building)
* - cmd.c (command lookup and validation)
* - arguments.c (argument parsing and flag handling)
* - cmd-find.c (target resolution)
* - options.c (option name lookups during parsing)
*/
#include <stddef.h>
#include <string.h>
#include "tmux.h"
struct event_base *libevent;
int
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
{
struct cmd_parse_input pi;
struct cmd_parse_result *pr;
if (size > 2048 || size == 0)
return 0;
memset(&pi, 0, sizeof pi);
pi.flags = CMD_PARSE_QUIET;
pr = cmd_parse_from_buffer(data, size, &pi);
switch (pr->status) {
case CMD_PARSE_SUCCESS:
cmd_list_free(pr->cmdlist);
break;
case CMD_PARSE_ERROR:
free(pr->error);
break;
default:
break;
}
return 0;
}
int
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
{
const struct options_table_entry *oe;
global_environ = environ_create();
global_options = options_create(NULL);
global_s_options = options_create(NULL);
global_w_options = options_create(NULL);
for (oe = options_table; oe->name != NULL; oe++) {
if (oe->scope & OPTIONS_TABLE_SERVER)
options_default(global_options, oe);
if (oe->scope & OPTIONS_TABLE_SESSION)
options_default(global_s_options, oe);
if (oe->scope & OPTIONS_TABLE_WINDOW)
options_default(global_w_options, oe);
}
libevent = osdep_event_init();
socket_path = xstrdup("dummy");
return 0;
}

View File

@@ -1,133 +0,0 @@
# tmux command names
"set-option"
"bind-key"
"unbind-key"
"send-keys"
"new-session"
"new-window"
"split-window"
"select-window"
"select-pane"
"kill-pane"
"kill-window"
"kill-session"
"kill-server"
"list-sessions"
"list-windows"
"list-panes"
"list-keys"
"list-buffers"
"list-clients"
"list-commands"
"attach-session"
"detach-client"
"switch-client"
"rename-session"
"rename-window"
"resize-pane"
"resize-window"
"display-message"
"display-menu"
"display-popup"
"display-panes"
"copy-mode"
"paste-buffer"
"capture-pane"
"save-buffer"
"load-buffer"
"set-buffer"
"delete-buffer"
"show-buffer"
"choose-buffer"
"choose-tree"
"choose-client"
"if-shell"
"run-shell"
"source-file"
"command-prompt"
"confirm-before"
"pipe-pane"
"wait-for"
"set-environment"
"show-environment"
"set-hook"
"show-hooks"
"show-messages"
"show-options"
"set-window-option"
"show-window-options"
"clear-history"
"clock-mode"
"find-window"
"join-pane"
"move-pane"
"break-pane"
"swap-pane"
"swap-window"
"move-window"
"link-window"
"unlink-window"
"rotate-window"
"next-window"
"previous-window"
"last-window"
"last-pane"
"next-layout"
"previous-layout"
"select-layout"
"customize-mode"
"refresh-client"
"suspend-client"
"lock-client"
"lock-server"
"lock-session"
"respawn-pane"
"respawn-window"
"start-server"
"server-access"
"send-prefix"
"clear-prompt-history"
"show-prompt-history"
# Common flags and syntax
"-t"
"-s"
"-g"
"-w"
"-p"
"-a"
"-o"
"-q"
"-u"
"-F"
"-f"
"-b"
"-d"
"-e"
"-n"
"-r"
# Targets and option names
"status"
"default"
"mouse"
"on"
"off"
"vi"
"emacs"
"set -g"
"set -s"
"setw"
"bind"
"unbind"
# Syntax elements
"{"
"}"
";"
"#{"
"%if"
"%elif"
"%else"
"%endif"
"%hidden"

View File

@@ -1,2 +0,0 @@
[libfuzzer]
max_len = 2048

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) 2026 David Korczynski <david@adalogics.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.
*/
/*
* Fuzz the tmux format string expander (format_expand).
*
* This exercises:
* - format.c (format parsing, modifier chains, conditionals, math, regex)
* - colour.c (colour name and RGB parsing within formats)
* - utf8.c (UTF-8 width calculations in format padding)
*/
#include <stddef.h>
#include <string.h>
#include "tmux.h"
struct event_base *libevent;
int
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
{
struct format_tree *ft;
char *buf, *expanded;
if (size > 2048 || size == 0)
return 0;
/* Null-terminate the input for format_expand. */
buf = malloc(size + 1);
if (buf == NULL)
return 0;
memcpy(buf, data, size);
buf[size] = '\0';
ft = format_create(NULL, NULL, 0, FORMAT_NOJOBS);
format_add(ft, "session_name", "%s", "fuzz-session");
format_add(ft, "window_index", "%d", 0);
format_add(ft, "window_name", "%s", "fuzz-window");
format_add(ft, "pane_index", "%d", 0);
format_add(ft, "pane_id", "%s", "%%0");
format_add(ft, "host", "%s", "fuzzhost");
format_add(ft, "pane_width", "%d", 80);
format_add(ft, "pane_height", "%d", 25);
expanded = format_expand(ft, buf);
free(expanded);
format_free(ft);
free(buf);
return 0;
}
int
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
{
const struct options_table_entry *oe;
global_environ = environ_create();
global_options = options_create(NULL);
global_s_options = options_create(NULL);
global_w_options = options_create(NULL);
for (oe = options_table; oe->name != NULL; oe++) {
if (oe->scope & OPTIONS_TABLE_SERVER)
options_default(global_options, oe);
if (oe->scope & OPTIONS_TABLE_SESSION)
options_default(global_s_options, oe);
if (oe->scope & OPTIONS_TABLE_WINDOW)
options_default(global_w_options, oe);
}
libevent = osdep_event_init();
socket_path = xstrdup("dummy");
return 0;
}

View File

@@ -1,71 +0,0 @@
# Format expansion syntax
"#{"
"}"
"#{?"
"#{=="
"#{!="
"#{<"
"#{>"
"#{m:"
"#{C:"
"#{s/"
"#{t:"
"#{T:"
"#{E:"
"#{S:"
"#{W:"
"#{P:"
"##"
# Common format modifiers
"b:"
"d:"
"q:"
"l:"
"e:"
"t:"
"p:"
"w:"
"n:"
"a:"
"=:"
"||"
"&&"
","
"#{e|"
"#{p-1:"
"#{=/10/...:"
# Format variables
"session_name"
"window_index"
"window_name"
"pane_index"
"pane_id"
"host"
"pane_width"
"pane_height"
"pane_current_command"
"pane_pid"
"session_id"
"window_id"
"client_name"
"version"
"line"
# Conditionals
"#{?pane_active,"
",}"
"#{?#{==:"
# Math and comparison
"#{e|+:"
"#{e|-:"
"#{e|*:"
"#{e|/:"
"#{e|%:"
# Nested
"#{="
"#{"
"#{l:"

View File

@@ -1,2 +0,0 @@
[libfuzzer]
max_len = 2048

View File

@@ -1,79 +0,0 @@
/*
* Copyright (c) 2026 David Korczynski <david@adalogics.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.
*/
/*
* Fuzz the tmux style parser (style_parse).
*
* This exercises:
* - style.c (style string parsing, alignment, ranges)
* - colour.c (colour name, RGB, and indexed colour parsing)
*/
#include <stddef.h>
#include <string.h>
#include "tmux.h"
struct event_base *libevent;
int
LLVMFuzzerTestOneInput(const u_char *data, size_t size)
{
struct style sy;
struct grid_cell gc;
char *buf;
if (size > 512 || size == 0)
return 0;
/* Null-terminate the input for style_parse. */
buf = malloc(size + 1);
if (buf == NULL)
return 0;
memcpy(buf, data, size);
buf[size] = '\0';
memset(&gc, 0, sizeof gc);
style_set(&sy, &gc);
style_parse(&sy, &gc, buf);
free(buf);
return 0;
}
int
LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
{
const struct options_table_entry *oe;
global_environ = environ_create();
global_options = options_create(NULL);
global_s_options = options_create(NULL);
global_w_options = options_create(NULL);
for (oe = options_table; oe->name != NULL; oe++) {
if (oe->scope & OPTIONS_TABLE_SERVER)
options_default(global_options, oe);
if (oe->scope & OPTIONS_TABLE_SESSION)
options_default(global_s_options, oe);
if (oe->scope & OPTIONS_TABLE_WINDOW)
options_default(global_w_options, oe);
}
libevent = osdep_event_init();
socket_path = xstrdup("dummy");
return 0;
}

View File

@@ -1,73 +0,0 @@
# Style attributes
"default"
"ignore"
"nodefaults"
"bright"
"bold"
"dim"
"underscore"
"blink"
"reverse"
"hidden"
"italics"
"overline"
"strikethrough"
"double-underscore"
"curly-underscore"
"dotted-underscore"
"dashed-underscore"
"nobright"
"nobold"
"nodim"
"nounderscore"
"noblink"
"noreverse"
"nohidden"
"noitalics"
"nooverline"
"nostrikethrough"
# Colours
"fg="
"bg="
"us="
"fill="
"colour0"
"colour255"
"red"
"green"
"blue"
"yellow"
"cyan"
"magenta"
"white"
"black"
# RGB and hex
"#ff0000"
"#00ff00"
"#0000ff"
# Alignment and ranges
"align=left"
"align=centre"
"align=right"
"align=absolute-centre"
"list=on"
"list=focus"
"list=left-marker"
"list=right-marker"
"range=left"
"range=right"
"range=pane"
"range=window"
"range=session"
"range=user"
# Width and padding
"width="
"pad="
# Delimiters
","
" "

View File

@@ -1,2 +0,0 @@
[libfuzzer]
max_len = 512

View File

@@ -45,20 +45,15 @@ grid_reader_line_length(struct grid_reader *gr)
/* Move cursor forward one position. */
void
grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all, int onemore)
grid_reader_cursor_right(struct grid_reader *gr, int wrap, int all)
{
u_int px;
struct grid_cell gc;
if (all)
px = gr->gd->sx;
else if (onemore)
else
px = grid_reader_line_length(gr);
else {
px = grid_reader_line_length(gr);
if (px != 0)
px--;
}
if (wrap && gr->cx >= px && gr->cy < gr->gd->hsize + gr->gd->sy - 1) {
grid_reader_cursor_start_of_line(gr, 0);

36
grid.c
View File

@@ -125,8 +125,6 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
else if (gce->offset >= gl->extdsize)
fatalx("offset too big");
gl->flags |= GRID_LINE_EXTENDED;
if (gc->link != 0)
gl->flags |= GRID_LINE_HYPERLINK;
if (gc->flags & GRID_FLAG_TAB)
uc = gc->data.width;
@@ -202,7 +200,7 @@ grid_adjust_lines(struct grid *gd, u_int lines)
/* Copy default into a cell. */
static void
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg, int moved)
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
{
struct grid_line *gl = &gd->linedata[py];
struct grid_cell_entry *gce = &gl->celldata[px];
@@ -211,7 +209,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg, int moved)
int had_extd = (gce->flags & GRID_FLAG_EXTENDED);
memcpy(gce, &grid_cleared_entry, sizeof *gce);
if (!moved && had_extd && old_offset < gl->extdsize) {
if (had_extd && old_offset < gl->extdsize) {
gce->flags |= GRID_FLAG_EXTENDED;
gce->offset = old_offset;
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
@@ -287,8 +285,9 @@ static void
grid_free_line(struct grid *gd, u_int py)
{
free(gd->linedata[py].celldata);
gd->linedata[py].celldata = NULL;
free(gd->linedata[py].extddata);
memset(&gd->linedata[py], 0, sizeof gd->linedata[py]);
gd->linedata[py].extddata = NULL;
}
/* Free several lines. */
@@ -333,7 +332,9 @@ void
grid_destroy(struct grid *gd)
{
grid_free_lines(gd, 0, gd->hsize + gd->sy);
free(gd->linedata);
free(gd);
}
@@ -413,14 +414,12 @@ grid_collect_history(struct grid *gd, int all)
void
grid_remove_history(struct grid *gd, u_int ny)
{
u_int yy, start;
u_int yy;
if (ny > gd->hsize)
return;
start = gd->hsize + gd->sy - ny;
for (yy = 0; yy < ny; yy++)
grid_free_line(gd, start + yy);
memset(&gd->linedata[start], 0, ny * sizeof *gd->linedata);
grid_free_line(gd, gd->hsize + gd->sy - 1 - yy);
gd->hsize -= ny;
}
@@ -496,7 +495,7 @@ static void
grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
{
struct grid_line *gl;
u_int xx;
u_int xx, old_cellsize;
gl = &gd->linedata[py];
if (sx <= gl->cellsize)
@@ -509,14 +508,11 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
else if (gd->sx > sx)
sx = gd->sx;
gl->celldata = xreallocarray(gl->celldata, sx,
old_cellsize = gl->cellsize;
gl->celldata = xrecallocarray(gl->celldata, old_cellsize, sx,
sizeof *gl->celldata);
if (gl->cellsize < sx) {
memset(gl->celldata + gl->cellsize, 0,
(sx - gl->cellsize) * sizeof *gl->celldata);
}
for (xx = gl->cellsize; xx < sx; xx++)
grid_clear_cell(gd, xx, py, bg, 0);
for (xx = old_cellsize; xx < sx; xx++)
grid_clear_cell(gd, xx, py, bg);
gl->cellsize = sx;
}
@@ -684,7 +680,7 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
grid_expand_line(gd, yy, px + ox, 8); /* default bg first */
for (xx = px; xx < px + ox; xx++)
grid_clear_cell(gd, xx, yy, bg, 0);
grid_clear_cell(gd, xx, yy, bg);
}
}
@@ -778,7 +774,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx,
for (xx = px; xx < px + nx; xx++) {
if (xx >= dx && xx < dx + nx)
continue;
grid_clear_cell(gd, xx, py, bg, 1);
grid_clear_cell(gd, xx, py, bg);
}
}
@@ -1118,7 +1114,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
if (gc.flags & GRID_FLAG_PADDING)
continue;
if (lastgc != NULL && (flags & GRID_STRING_WITH_SEQUENCES)) {
if (flags & GRID_STRING_WITH_SEQUENCES) {
grid_string_cells_code(*lastgc, &gc, code, sizeof code,
flags, s, &has_link);
codelen = strlen(code);

325
image-kitty.c Normal file
View File

@@ -0,0 +1,325 @@
/* $OpenBSD$ */
/*
* Copyright (c) 2026 Thomas Adam <thomas@xteddy.org>
*
* 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.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "tmux.h"
/*
* kitty_image stores the raw decoded pixel data and metadata from a kitty
* graphics protocol APC sequence. It is used to re-emit the sequence to the
* outer terminal on redraw.
*/
struct kitty_image {
/* Control-data fields parsed from the APC sequence. */
char action; /* a=: 'T'=transmit+display, 't', 'p', 'd' */
u_int format; /* f=: 32=RGBA, 24=RGB, 100=PNG */
char medium; /* t=: 'd'=direct, 'f'=file, 't'=tmp, 's'=shm */
u_int pixel_w; /* s=: source image pixel width */
u_int pixel_h; /* v=: source image pixel height */
u_int cols; /* c=: display columns (0=auto) */
u_int rows; /* r=: display rows (0=auto) */
u_int image_id; /* i=: image id (0=unassigned) */
u_int image_num; /* I=: image number */
u_int placement_id; /* p=: placement id */
u_int more; /* m=: 1=more chunks coming, 0=last */
u_int quiet; /* q=: suppress responses */
int z_index; /* z=: z-index */
char compression; /* o=: 'z'=zlib, 0=none */
char delete_what; /* d=: delete target (used with a=d) */
/* Cell size at the time of parsing (from the owning window). */
u_int xpixel;
u_int ypixel;
/* Original base64-encoded payload (concatenated across all chunks). */
char *encoded;
size_t encodedlen;
char *ctrl;
size_t ctrllen;
};
/*
* Parse control-data key=value pairs from a kitty APC sequence.
* Format: key=value,key=value,...
*/
static int
kitty_parse_control(const char *ctrl, size_t ctrllen, struct kitty_image *ki)
{
const char *p = ctrl, *end = ctrl + ctrllen, *errstr;
char key[4], val[32];
size_t klen, vlen;
while (p < end) {
klen = 0;
while (p < end && *p != '=' && klen < sizeof(key) - 1)
key[klen++] = *p++;
key[klen] = '\0';
if (p >= end || *p != '=')
return (-1);
p++;
vlen = 0;
while (p < end && *p != ',' && vlen < sizeof(val) - 1)
val[vlen++] = *p++;
val[vlen] = '\0';
if (p < end && *p == ',')
p++;
if (klen != 1)
continue;
switch (key[0]) {
case 'a':
ki->action = val[0];
break;
case 'f':
ki->format = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 't':
ki->medium = val[0];
break;
case 's':
ki->pixel_w = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'v':
ki->pixel_h = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'c':
ki->cols = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'r':
ki->rows = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'i':
ki->image_id = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'I':
ki->image_num = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'p':
ki->placement_id = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'm':
ki->more = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'q':
ki->quiet = strtonum(val, 0, UINT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'z':
ki->z_index = strtonum(val, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL)
return (-1);
break;
case 'o':
ki->compression = val[0];
break;
case 'd':
ki->delete_what = val[0];
break;
}
}
return (0);
}
/*
* Parse a kitty APC body (after the leading 'G').
* Stores the original control string and base64 payload verbatim for
* pass-through re-emission to the outer terminal.
*/
struct kitty_image *
kitty_parse(const u_char *buf, size_t len, u_int xpixel, u_int ypixel)
{
struct kitty_image *ki;
const u_char *semi;
const char *ctrl;
size_t ctrllen, paylen;
if (len == 0)
return (NULL);
semi = memchr(buf, ';', len);
if (semi != NULL) {
ctrl = (const char *)buf;
ctrllen = semi - buf;
paylen = len - ctrllen - 1;
} else {
ctrl = (const char *)buf;
ctrllen = len;
paylen = 0;
}
ki = xcalloc(1, sizeof *ki);
ki->xpixel = xpixel;
ki->ypixel = ypixel;
ki->action = 'T';
ki->format = 32;
ki->medium = 'd';
if (kitty_parse_control(ctrl, ctrllen, ki) != 0) {
free(ki);
return (NULL);
}
if (paylen > 0) {
ki->encoded = xmalloc(paylen + 1);
memcpy(ki->encoded, semi + 1, paylen);
ki->encoded[paylen] = '\0';
ki->encodedlen = paylen;
}
ki->ctrl = xmalloc(ctrllen + 1);
memcpy(ki->ctrl, ctrl, ctrllen);
ki->ctrl[ctrllen] = '\0';
ki->ctrllen = ctrllen;
return (ki);
}
void
kitty_free(struct kitty_image *ki)
{
if (ki == NULL)
return;
free(ki->encoded);
free(ki->ctrl);
free(ki);
}
/*
* Get the size in cells of a kitty image. If cols/rows are 0 (auto),
* calculate from pixel dimensions. Returns size via sx/sy pointers.
*/
void
kitty_size_in_cells(struct kitty_image *ki, u_int *sx, u_int *sy)
{
*sx = ki->cols;
*sy = ki->rows;
/*
* If cols/rows are 0, they mean "auto" - calculate from
* pixel dimensions.
*/
if (*sx == 0 && ki->pixel_w > 0 && ki->xpixel > 0) {
*sx = (ki->pixel_w + ki->xpixel - 1) / ki->xpixel;
}
if (*sy == 0 && ki->pixel_h > 0 && ki->ypixel > 0) {
*sy = (ki->pixel_h + ki->ypixel - 1) / ki->ypixel;
}
/* If still 0, use a reasonable default */
if (*sx == 0)
*sx = 10;
if (*sy == 0)
*sy = 10;
}
char
kitty_get_action(struct kitty_image *ki)
{
return (ki->action);
}
u_int
kitty_get_image_id(struct kitty_image *ki)
{
return (ki->image_id);
}
u_int
kitty_get_rows(struct kitty_image *ki)
{
return (ki->rows);
}
/*
* Serialize a kitty_image back into an APC escape sequence for transmission
* to the terminal. This recreates the original command that was parsed.
*/
char *
kitty_print(struct kitty_image *ki, size_t *outlen)
{
char *out;
size_t total, pos;
if (ki == NULL || ki->ctrl == NULL)
return (NULL);
/* Calculate total length: ESC _ G + ctrl + ; + encoded + ESC \ */
total = 3 + ki->ctrllen; /* \033_G + ctrl */
if (ki->encoded != NULL && ki->encodedlen > 0) {
total += 1 + ki->encodedlen; /* ; + encoded */
}
total += 2; /* \033\\ */
out = xmalloc(total + 1);
*outlen = total;
/* Build the sequence */
pos = 0;
memcpy(out + pos, "\033_G", 3);
pos += 3;
memcpy(out + pos, ki->ctrl, ki->ctrllen);
pos += ki->ctrllen;
if (ki->encoded != NULL && ki->encodedlen > 0) {
out[pos++] = ';';
memcpy(out + pos, ki->encoded, ki->encodedlen);
pos += ki->encodedlen;
}
memcpy(out + pos, "\033\\", 2);
pos += 2;
out[pos] = '\0';
return (out);
}
char *
kitty_delete_all(size_t *outlen)
{
char *out;
out = xstrdup("\033_Ga=d,d=a\033\\");
*outlen = strlen(out);
return (out);
}

View File

@@ -122,13 +122,19 @@ sixel_set_pixel(struct sixel_image *si, u_int x, u_int y, u_int c)
static int
sixel_parse_write(struct sixel_image *si, u_int ch)
{
struct sixel_line *sl;
u_int i;
if (sixel_parse_expand_lines(si, si->dy + 6) != 0)
return (1);
sl = &si->lines[si->dy];
for (i = 0; i < 6; i++) {
if (ch & (1 << i)) {
if (sixel_set_pixel(si, si->dx, si->dy + i, si->dc))
return (1);
}
if (sixel_parse_expand_line(si, sl, si->dx + 1) != 0)
return (1);
if (ch & (1 << i))
sl->data[si->dx] = si->dc;
sl++;
}
return (0);
}
@@ -351,7 +357,7 @@ sixel_parse(const char *buf, size_t len, u_int p2, u_int xpixel, u_int ypixel)
return (si);
bad:
sixel_free(si);
free(si);
return (NULL);
}
@@ -481,9 +487,9 @@ static void
sixel_print_add(char **buf, size_t *len, size_t *used, const char *s,
size_t slen)
{
while (*used + slen >= *len + 1) {
*buf = xreallocarray(*buf, 2, *len);
if (*used + slen >= *len + 1) {
(*len) *= 2;
*buf = xrealloc(*buf, *len);
}
memcpy(*buf + *used, s, slen);
(*used) += slen;

119
image.c
View File

@@ -53,13 +53,30 @@ image_log(struct image *im, const char* from, const char* fmt, ...)
static void
image_free(struct image *im)
{
struct screen *s = im->s;
image_log(im, __func__, NULL);
TAILQ_REMOVE(&all_images, im, all_entry);
all_images_count--;
TAILQ_REMOVE(im->list, im, entry);
sixel_free(im->data);
TAILQ_REMOVE(&s->images, im, entry);
switch (im->type) {
#ifdef ENABLE_SIXEL_IMAGES
case IMAGE_SIXEL:
sixel_free(im->data.sixel);
break;
#endif
#ifdef ENABLE_KITTY_IMAGES
case IMAGE_KITTY:
kitty_free(im->data.kitty);
break;
#endif
default:
break;
}
free(im->fallback);
free(im);
}
@@ -79,13 +96,30 @@ image_free_all(struct screen *s)
/* Create text placeholder for an image. */
static void
image_fallback(char **ret, u_int sx, u_int sy)
image_fallback(char **ret, enum image_type type, u_int sx, u_int sy)
{
char *buf, *label;
u_int py, size, lsize;
const char *type_name;
switch (type) {
#ifdef ENABLE_SIXEL_IMAGES
case IMAGE_SIXEL:
type_name = "SIXEL";
break;
#endif
#ifdef ENABLE_KITTY_IMAGES
case IMAGE_KITTY:
type_name = "KITTY";
break;
#endif
default:
type_name = "UNKNOWN";
break;
}
/* Allocate first line. */
lsize = xasprintf(&label, "SIXEL IMAGE (%ux%u)\r\n", sx, sy) + 1;
lsize = xasprintf(&label, "%s IMAGE (%ux%u)\r\n", type_name, sx, sy) + 1;
if (sx < lsize - 3)
size = lsize - 1;
else
@@ -120,23 +154,39 @@ image_fallback(char **ret, u_int sx, u_int sy)
}
struct image*
image_store(struct screen *s, struct sixel_image *si)
image_store(struct screen *s, enum image_type type, void *data)
{
struct image *im;
im = xcalloc(1, sizeof *im);
im->type = type;
im->s = s;
im->data = si;
im->px = s->cx;
im->py = s->cy;
sixel_size_in_cells(si, &im->sx, &im->sy);
image_fallback(&im->fallback, im->sx, im->sy);
switch (type) {
#ifdef ENABLE_SIXEL_IMAGES
case IMAGE_SIXEL:
im->data.sixel = data;
sixel_size_in_cells(im->data.sixel, &im->sx, &im->sy);
break;
#endif
#ifdef ENABLE_KITTY_IMAGES
case IMAGE_KITTY:
im->data.kitty = data;
kitty_size_in_cells(im->data.kitty, &im->sx, &im->sy);
break;
#endif
default:
break;
}
image_fallback(&im->fallback, type, im->sx, im->sy);
image_log(im, __func__, NULL);
im->list = &s->images;
TAILQ_INSERT_TAIL(im->list, im, entry);
TAILQ_INSERT_TAIL(&s->images, im, entry);
TAILQ_INSERT_TAIL(&all_images, im, all_entry);
if (++all_images_count == MAX_IMAGE_COUNT)
@@ -187,8 +237,10 @@ image_scroll_up(struct screen *s, u_int lines)
{
struct image *im, *im1;
int redraw = 0;
u_int sx, sy;
#ifdef ENABLE_SIXEL_IMAGES
struct sixel_image *new;
u_int sx, sy;
#endif
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
if (im->py >= lines) {
@@ -203,20 +255,43 @@ image_scroll_up(struct screen *s, u_int lines)
redraw = 1;
continue;
}
sx = im->sx;
sy = (im->py + im->sy) - lines;
image_log(im, __func__, "3, lines=%u, sy=%u", lines, sy);
new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1);
sixel_free(im->data);
im->data = new;
/* Image is partially scrolled off - need to crop it */
switch (im->type) {
#ifdef ENABLE_SIXEL_IMAGES
case IMAGE_SIXEL:
sx = im->sx;
sy = (im->py + im->sy) - lines;
image_log(im, __func__, "sixel, lines=%u, sy=%u",
lines, sy);
im->py = 0;
sixel_size_in_cells(im->data, &im->sx, &im->sy);
new = sixel_scale(im->data.sixel, 0, 0, 0, im->sy - sy,
sx, sy, 1);
sixel_free(im->data.sixel);
im->data.sixel = new;
free(im->fallback);
image_fallback(&im->fallback, im->sx, im->sy);
redraw = 1;
im->py = 0;
sixel_size_in_cells(im->data.sixel, &im->sx, &im->sy);
free(im->fallback);
image_fallback(&im->fallback, im->type, im->sx, im->sy);
redraw = 1;
break;
#endif
#ifdef ENABLE_KITTY_IMAGES
case IMAGE_KITTY:
/*
* For kitty images, we can't rescale - the terminal
* owns the placement. Just adjust position and let
* the terminal handle clipping.
*/
im->py = 0;
redraw = 1;
break;
#endif
default:
break;
}
}
return (redraw);
}

View File

@@ -673,7 +673,8 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
}
/* Ignore internal function key codes. */
if (KEYC_IS_USER(key) || KEYC_IS_SPECIAL(key) || KEYC_IS_MOUSE(key)) {
if ((key >= KEYC_BASE && key < KEYC_BASE_END) ||
(key >= KEYC_USER && key < KEYC_USER_END)) {
log_debug("%s: ignoring key 0x%llx", __func__, key);
return (0);
}

284
input.c
View File

@@ -64,7 +64,7 @@ struct input_request {
enum input_request_type type;
uint64_t t;
enum input_end_type end;
enum input_end_type end;
int idx;
void *data;
@@ -145,11 +145,12 @@ struct input_ctx {
*/
struct evbuffer *since_ground;
struct event ground_timer;
};
/* Helper functions. */
struct input_transition;
static void input_request_timer_callback(int, short, void *);
static void input_request_timer_callback(int, short, void *);
static void input_start_request_timer(struct input_ctx *);
static struct input_request *input_make_request(struct input_ctx *,
enum input_request_type);
@@ -164,7 +165,6 @@ static void input_reset_cell(struct input_ctx *);
static void input_report_current_theme(struct input_ctx *);
static void input_osc_4(struct input_ctx *, const char *);
static void input_osc_8(struct input_ctx *, const char *);
static void input_osc_9(struct input_ctx *, const char *);
static void input_osc_10(struct input_ctx *, const char *);
static void input_osc_11(struct input_ctx *, const char *);
static void input_osc_12(struct input_ctx *, const char *);
@@ -181,6 +181,7 @@ static void input_ground(struct input_ctx *);
static void input_enter_dcs(struct input_ctx *);
static void input_enter_osc(struct input_ctx *);
static void input_exit_osc(struct input_ctx *);
static int input_da1_has_sixel(struct input_ctx *);
static void input_enter_apc(struct input_ctx *);
static void input_exit_apc(struct input_ctx *);
static void input_enter_rename(struct input_ctx *);
@@ -281,7 +282,6 @@ enum input_csi_type {
INPUT_CSI_IL,
INPUT_CSI_MODOFF,
INPUT_CSI_MODSET,
INPUT_CSI_QUERY,
INPUT_CSI_QUERY_PRIVATE,
INPUT_CSI_RCP,
INPUT_CSI_REP,
@@ -337,7 +337,6 @@ static const struct input_table_entry input_csi_table[] = {
{ 'n', "", INPUT_CSI_DSR },
{ 'n', ">", INPUT_CSI_MODOFF },
{ 'n', "?", INPUT_CSI_DSR_PRIVATE },
{ 'p', "$", INPUT_CSI_QUERY },
{ 'p', "?$", INPUT_CSI_QUERY_PRIVATE },
{ 'q', " ", INPUT_CSI_DECSCUSR },
{ 'q', ">", INPUT_CSI_XDA },
@@ -952,7 +951,7 @@ input_set_state(struct input_ctx *ictx, const struct input_transition *itr)
/* Parse data. */
static void
input_parse(struct input_ctx *ictx, const u_char *buf, size_t len)
input_parse(struct input_ctx *ictx, u_char *buf, size_t len)
{
struct screen_write_ctx *sctx = &ictx->ctx;
const struct input_state *state = NULL;
@@ -1023,7 +1022,7 @@ input_parse_pane(struct window_pane *wp)
/* Parse given input. */
void
input_parse_buffer(struct window_pane *wp, const u_char *buf, size_t len)
input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len)
{
struct input_ctx *ictx = wp->ictx;
struct screen_write_ctx *sctx = &ictx->ctx;
@@ -1054,7 +1053,7 @@ input_parse_buffer(struct window_pane *wp, const u_char *buf, size_t len)
/* Parse given input for screen. */
void
input_parse_screen(struct input_ctx *ictx, struct screen *s,
screen_write_init_ctx_cb cb, void *arg, const u_char *buf, size_t len)
screen_write_init_ctx_cb cb, void *arg, u_char *buf, size_t len)
{
struct screen_write_ctx *sctx = &ictx->ctx;
@@ -1384,6 +1383,10 @@ input_esc_dispatch(struct input_ctx *ictx)
input_reset_cell(ictx);
screen_write_reset(sctx);
screen_write_fullredraw(sctx);
#ifdef ENABLE_KITTY_IMAGES
if (ictx->wp != NULL)
tty_kitty_delete_all_pane(ictx->wp);
#endif
break;
case INPUT_ESC_IND:
screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
@@ -1559,11 +1562,10 @@ input_csi_dispatch(struct input_ctx *ictx)
case -1:
break;
case 0:
#ifdef ENABLE_SIXEL
input_reply(ictx, 1, "\033[?1;2;4c");
#else
input_reply(ictx, 1, "\033[?1;2c");
#endif
if (input_da1_has_sixel(ictx))
input_reply(ictx, 1, "\033[?1;2;4c");
else
input_reply(ictx, 1, "\033[?1;2c");
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
@@ -1610,34 +1612,8 @@ input_csi_dispatch(struct input_ctx *ictx)
break;
}
break;
case INPUT_CSI_QUERY:
m = input_get(ictx, 0, 0, 0);
switch (m) {
case 4: /* IRM */
n = (s->mode & MODE_INSERT) ? 1 : 2;
break;
default:
n = 0;
break;
}
if (m > 0)
input_reply(ictx, 1, "\033[%d;%d$y", m, n);
break;
case INPUT_CSI_QUERY_PRIVATE:
m = input_get(ictx, 0, 0, 0);
switch (m) {
case 1: /* DECCKM */
n = (s->mode & MODE_KCURSOR) ? 1 : 2;
break;
case 3: /* DECCOLM: always reset */
n = 4;
break;
case 6: /* DECOM */
n = (s->mode & MODE_ORIGIN) ? 1 : 2;
break;
case 7: /* DECAWM */
n = (s->mode & MODE_WRAP) ? 1 : 2;
break;
switch (input_get(ictx, 0, 0, 0)) {
case 12: /* cursor blink: 1 = blink, 2 = steady */
if (s->cstyle != SCREEN_CURSOR_DEFAULT ||
s->mode & MODE_CURSOR_BLINKING_SET)
@@ -1646,54 +1622,34 @@ input_csi_dispatch(struct input_ctx *ictx)
if (ictx->wp != NULL)
oo = ictx->wp->options;
else
oo = global_w_options;
oo = global_options;
p = options_get_number(oo, "cursor-style");
/* blink for 1,3,5; steady for 0,2,4,6 */
n = (p == 1 || p == 3 || p == 5) ? 1 : 2;
n = (p == 1 || p == 3 || p == 5) ? 1 : 2;
}
input_reply(ictx, 1, "\033[?12;%d$y", n);
break;
case 25: /* DECTCEM */
n = (s->mode & MODE_CURSOR) ? 1 : 2;
break;
case 47:
case 1047:
case 1049: /* alternate screen */
n = SCREEN_IS_ALTERNATE(s) ? 1 : 2;
break;
case 1000: /* mouse: normal tracking */
n = (s->mode & MODE_MOUSE_STANDARD) ? 1 : 2;
break;
case 1002: /* mouse: button-event tracking */
n = (s->mode & MODE_MOUSE_BUTTON) ? 1 : 2;
break;
case 1003: /* mouse: any-event tracking */
n = (s->mode & MODE_MOUSE_ALL) ? 1 : 2;
break;
case 1004: /* focus reporting */
case 1004: /* focus reporting */
n = (s->mode & MODE_FOCUSON) ? 1 : 2;
input_reply(ictx, 1, "\033[?1004;%d$y", n);
break;
case 1005: /* mouse: UTF-8 */
n = (s->mode & MODE_MOUSE_UTF8) ? 1 : 2;
break;
case 1006: /* mouse: SGR */
case 1006: /* SGR mouse */
n = (s->mode & MODE_MOUSE_SGR) ? 1 : 2;
input_reply(ictx, 1, "\033[?1006;%d$y", n);
break;
case 2004: /* bracketed paste */
case 2004: /* bracketed paste */
n = (s->mode & MODE_BRACKETPASTE) ? 1 : 2;
input_reply(ictx, 1, "\033[?2004;%d$y", n);
break;
case 2026: /* synchronized output */
case 2026: /* synchronized output */
n = (s->mode & MODE_SYNC) ? 1 : 2;
input_reply(ictx, 1, "\033[?2026;%d$y", n);
break;
case 2031: /* theme update notifications */
n = (s->mode & MODE_THEME_UPDATES) ? 1 : 2;
break;
default:
n = 0;
case 2031:
input_reply(ictx, 1, "\033[?2031;2$y");
break;
}
if (m > 0)
input_reply(ictx, 1, "\033[?%d;%d$y", m, n);
break;
case INPUT_CSI_DSR:
switch (input_get(ictx, 0, 0, 0)) {
@@ -1953,14 +1909,16 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
case 2004:
screen_write_mode_clear(sctx, MODE_BRACKETPASTE);
break;
case 2026:
screen_write_stop_sync(ictx->wp);
break;
case 2031:
screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
if (ictx->wp != NULL)
ictx->wp->flags &= ~PANE_THEMECHANGED;
break;
case 2026: /* synchronized output */
screen_write_stop_sync(ictx->wp);
if (ictx->wp != NULL)
ictx->wp->flags |= PANE_REDRAW;
break;
default:
log_debug("%s: unknown '%c'", __func__, ictx->ch);
break;
@@ -2063,7 +2021,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
ictx->wp->flags &= ~PANE_THEMECHANGED;
}
break;
case 2026:
case 2026: /* synchronized output */
screen_write_start_sync(ictx->wp);
break;
default:
@@ -2077,7 +2035,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
static void
input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx)
{
#ifdef ENABLE_SIXEL
#ifdef ENABLE_SIXEL_IMAGES
int n, m, o;
if (ictx->param_list_len > 3)
@@ -2569,7 +2527,7 @@ input_handle_decrqss(struct input_ctx *ictx)
if (wp != NULL)
oo = wp->options;
else
oo = global_w_options;
oo = global_options;
opt_ps = options_get_number(oo, "cursor-style");
/* Sanity clamp: valid Ps are 0..6 per DECSCUSR. */
@@ -2602,25 +2560,24 @@ input_dcs_dispatch(struct input_ctx *ictx)
const char prefix[] = "tmux;";
const u_int prefixlen = (sizeof prefix) - 1;
long long allow_passthrough = 0;
#ifdef ENABLE_SIXEL
#ifdef ENABLE_SIXEL_IMAGES
struct window *w;
struct sixel_image *si;
int p2;
#endif
if (wp == NULL)
oo = global_w_options;
else
oo = wp->options;
return (0);
oo = wp->options;
if (ictx->flags & INPUT_DISCARD) {
log_debug("%s: %zu bytes (discard)", __func__, len);
return (0);
}
#ifdef ENABLE_SIXEL
if (wp != NULL && buf[0] == 'q' && ictx->interm_len == 0) {
w = wp->window;
#ifdef ENABLE_SIXEL_IMAGES
w = wp->window;
if (buf[0] == 'q' && ictx->interm_len == 0) {
if (input_split(ictx) != 0)
return (0);
p2 = input_get(ictx, 1, 0, 0);
@@ -2699,7 +2656,7 @@ input_exit_osc(struct input_ctx *ictx)
case 2:
if (wp != NULL &&
options_get_number(wp->options, "allow-set-title") &&
screen_set_title(sctx->s, p, 1)) {
screen_set_title(sctx->s, p)) {
notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
@@ -2709,17 +2666,17 @@ input_exit_osc(struct input_ctx *ictx)
input_osc_4(ictx, p);
break;
case 7:
if (wp != NULL && screen_set_path(sctx->s, p, 1)) {
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
if (utf8_isvalid(p)) {
screen_set_path(sctx->s, p);
if (wp != NULL) {
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
}
}
break;
case 8:
input_osc_8(ictx, p);
break;
case 9:
input_osc_9(ictx, p);
break;
case 10:
input_osc_10(ictx, p);
break;
@@ -2764,6 +2721,79 @@ input_enter_apc(struct input_ctx *ictx)
ictx->flags &= ~INPUT_LAST;
}
/*
* Check if any client viewing this pane has an outer terminal that supports
* sixel, so we can report it in the DA1 response.
*/
static int
input_da1_has_sixel(__unused struct input_ctx *ictx)
{
#ifdef ENABLE_SIXEL_IMAGES
struct window_pane *wp = ictx->wp;
struct client *c;
if (wp == NULL)
return (0);
TAILQ_FOREACH(c, &clients, entry) {
if (c->session == NULL)
continue;
if (c->session->curw->window != wp->window)
continue;
if (c->tty.term->flags & TERM_SIXEL)
return (1);
}
#endif
return (0);
}
#ifdef ENABLE_KITTY_IMAGES
/* Handle a kitty graphics APC sequence. */
static void
input_apc_kitty_image(struct input_ctx *ictx)
{
struct screen_write_ctx *sctx = &ictx->ctx;
struct window_pane *wp = ictx->wp;
struct window *w;
struct kitty_image *ki;
if (wp == NULL)
return;
w = wp->window;
ki = kitty_parse(ictx->input_buf + 1, ictx->input_len - 1,
w->xpixel, w->ypixel);
if (ki == NULL)
return;
/* Handle query commands. */
if (kitty_get_action(ki) == 'q') {
if (kitty_get_image_id(ki) != 0)
input_reply(ictx, 0, "\033_Gi=%u;OK\033\\",
kitty_get_image_id(ki));
else
input_reply(ictx, 0, "\033_Ga=q;OK\033\\");
kitty_free(ki);
return;
}
/* Store image placements and trigger a redraw. */
if (kitty_get_action(ki) == 'T' || kitty_get_action(ki) == 't' ||
kitty_get_action(ki) == 'p') {
screen_write_kittyimage(sctx, ki);
} else {
/* For other actions (delete, etc.), pass through. */
char *apc;
size_t apclen;
apclen = xasprintf(&apc, "\033_%s\033\\", ictx->input_buf);
tty_kitty_passthrough(wp, apc, apclen, sctx->s->cx,
sctx->s->cy);
free(apc);
kitty_free(ki);
}
}
#endif
/* APC terminator (ST) received. */
static void
input_exit_apc(struct input_ctx *ictx)
@@ -2775,9 +2805,16 @@ input_exit_apc(struct input_ctx *ictx)
return;
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
#ifdef ENABLE_KITTY_IMAGES
if (ictx->input_len >= 1 && ictx->input_buf[0] == 'G') {
input_apc_kitty_image(ictx);
return;
}
#endif
if (wp != NULL &&
options_get_number(wp->options, "allow-set-title") &&
screen_set_title(sctx->s, ictx->input_buf, 1)) {
screen_set_title(sctx->s, ictx->input_buf)) {
notify_pane("pane-title-changed", wp);
server_redraw_window_borders(wp->window);
server_status_window(wp->window);
@@ -2820,10 +2857,10 @@ input_exit_rename(struct input_ctx *ictx)
if (o != NULL)
options_remove_or_default(o, -1, NULL);
if (!options_get_number(w->options, "automatic-rename"))
window_set_name(w, "", 1);
window_set_name(w, "");
} else {
options_set_number(w->options, "automatic-rename", 0);
window_set_name(w, ictx->input_buf, 1);
window_set_name(w, ictx->input_buf);
}
server_redraw_window_borders(w);
server_status_window(w);
@@ -2988,57 +3025,6 @@ bad:
free(id);
}
/* Helper to handle setting the progress bar and redrawing. */
static void
input_set_progress_bar(struct input_ctx *ictx, enum progress_bar_state state,
int p)
{
screen_set_progress_bar(ictx->ctx.s, state, p);
if (ictx->wp != NULL) {
server_redraw_window_borders(ictx->wp->window);
server_status_window(ictx->wp->window);
}
}
/* Handle the OSC 9;4 sequence for progress bars. */
static void
input_osc_9(struct input_ctx *ictx, const char *p)
{
const char *pb = p;
enum progress_bar_state state;
int progress = 0;
if (*pb++ != '4')
return;
if (*pb == '\0' || (*pb == ';' && pb[1] == '\0'))
return;
if (*pb++ != ';')
return;
if (*pb < '0' || *pb > '4')
goto bad;
state = *pb++ - '0';
if (*pb == '\0' || (*pb == ';' && pb[1] == '\0')) {
input_set_progress_bar(ictx, state, -1);
return;
}
if (*pb++ != ';')
goto bad;
while (*pb >= '0' && *pb <= '9') {
if (progress > 100)
goto bad;
progress = progress * 10 + *pb++ - '0';
}
if (*pb != '\0' || progress < 0 || progress > 100)
goto bad;
input_set_progress_bar(ictx, state, progress);
return;
bad:
log_debug("bad OSC 9;4 %s", p);
}
/* Handle the OSC 10 sequence for setting and querying foreground colour. */
static void
@@ -3249,7 +3235,7 @@ input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out,
return (0);
}
len = ((strlen(end) + 3) / 4) * 3;
len = (strlen(end) / 4) * 3;
if (len == 0)
return (0);
@@ -3268,7 +3254,7 @@ static void
input_osc_52(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
struct screen_write_ctx ctx;
struct screen_write_ctx ctx;
u_char *out;
int outlen;
char clip[sizeof "cpqs01234567"] = "";

View File

@@ -29,8 +29,7 @@
" 'Previous' 'p' {switch-client -p}" \
" ''" \
" 'Renumber' 'N' {move-window -r}" \
" 'Rename' 'r' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
" 'Detach' 'd' {detach-client}" \
" 'Rename' 'n' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
" ''" \
" 'New Session' 's' {new-session}" \
" 'New Window' 'w' {new-window}"
@@ -60,11 +59,11 @@
" '#{?mouse_hyperlink,Type #[underscore]#{=/9/...:mouse_hyperlink},}' 'C-h' {copy-mode -q; send-keys -l -- \"#{q:mouse_hyperlink}\"}" \
" '#{?mouse_hyperlink,Copy #[underscore]#{=/9/...:mouse_hyperlink},}' 'h' {copy-mode -q; set-buffer -- \"#{q:mouse_hyperlink}\"}" \
" ''" \
" '#{?#{!:#{pane_floating_flag}},Horizontal Split,}' 'h' {split-window -h}" \
" '#{?#{!:#{pane_floating_flag}},Vertical Split,}' 'v' {split-window -v}" \
" 'Horizontal Split' 'h' {split-window -h}" \
" 'Vertical Split' 'v' {split-window -v}" \
" ''" \
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Up,}' 'u' {swap-pane -U}" \
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Down,}' 'd' {swap-pane -D}" \
" '#{?#{>:#{window_panes},1},,-}Swap Up' 'u' {swap-pane -U}" \
" '#{?#{>:#{window_panes},1},,-}Swap Down' 'd' {swap-pane -D}" \
" '#{?pane_marked_set,,-}Swap Marked' 's' {swap-pane}" \
" ''" \
" 'Kill' 'X' {kill-pane}" \
@@ -362,7 +361,6 @@ key_bindings_init(void)
"bind -N 'Split window horizontally' % { split-window -h }",
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
"bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
"bind -N 'New floating pane' * { new-pane }",
"bind -N 'Switch to previous client' ( { switch-client -p }",
"bind -N 'Switch to next client' ) { switch-client -n }",
"bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
@@ -461,9 +459,6 @@ key_bindings_init(void)
/* Mouse button 1 triple click on pane. */
"bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }",
/* Mouse button 1 on border. */
"bind -n MouseDown1Border { select-pane -M }",
/* Mouse button 1 drag on border. */
"bind -n MouseDrag1Border { resize-pane -M }",
@@ -471,10 +466,6 @@ key_bindings_init(void)
"bind -n MouseDown1Status { switch-client -t= }",
"bind -n C-MouseDown1Status { swap-window -t@ }",
/* Mouse button 1 down on default pane-border-format */
"bind -n MouseDown1Control9 { display-menu -t= -xM -yM -O -T 'Kill pane #{pane_index}?' 'Yes' 'y' { kill-pane -t= } 'No' 'n' {}}",
"bind -n MouseDown1Control8 { resize-pane -Z }",
/* Mouse wheel down on status line. */
"bind -n WheelDownStatus { next-window }",
@@ -507,7 +498,7 @@ key_bindings_init(void)
"bind -Tcopy-mode C-b { send -X cursor-left }",
"bind -Tcopy-mode C-g { send -X clear-selection }",
"bind -Tcopy-mode C-k { send -X copy-pipe-end-of-line-and-cancel }",
"bind -Tcopy-mode C-l { send -X recentre-top-bottom }",
"bind -Tcopy-mode C-l { send -X cursor-centre-vertical }",
"bind -Tcopy-mode M-l { send -X cursor-centre-horizontal }",
"bind -Tcopy-mode C-n { send -X cursor-down }",
"bind -Tcopy-mode C-p { send -X cursor-up }",
@@ -516,7 +507,6 @@ key_bindings_init(void)
"bind -Tcopy-mode C-v { send -X page-down }",
"bind -Tcopy-mode C-w { send -X copy-pipe-and-cancel }",
"bind -Tcopy-mode Escape { send -X cancel }",
"bind -Tcopy-mode C-[ { send -X cancel }",
"bind -Tcopy-mode Space { send -X page-down }",
"bind -Tcopy-mode , { send -X jump-reverse }",
"bind -Tcopy-mode \\; { send -X jump-again }",
@@ -590,7 +580,6 @@ key_bindings_init(void)
"bind -Tcopy-mode-vi C-v { send -X rectangle-toggle }",
"bind -Tcopy-mode-vi C-y { send -X scroll-up }",
"bind -Tcopy-mode-vi Escape { send -X clear-selection }",
"bind -Tcopy-mode-vi C-[ { send -X clear-selection }",
"bind -Tcopy-mode-vi Space { send -X begin-selection }",
"bind -Tcopy-mode-vi '$' { send -X end-of-line }",
"bind -Tcopy-mode-vi , { send -X jump-reverse }",

View File

@@ -202,7 +202,7 @@ key_string_search_table(const char *string)
return (key_string_table[i].key);
}
if (sscanf(string, "User%u", &user) == 1 && user <= KEYC_NUSER)
if (sscanf(string, "User%u", &user) == 1 && user < KEYC_NUSER)
return (KEYC_USER + user);
return (KEYC_UNKNOWN);
@@ -418,7 +418,7 @@ key_string_lookup_key(key_code key, int with_flags)
s = "MouseMoveBorder";
goto append;
}
if (KEYC_IS_USER(key)) {
if (key >= KEYC_USER && key < KEYC_USER_END) {
snprintf(tmp, sizeof tmp, "User%u", (u_int)(key - KEYC_USER));
strlcat(out, tmp, sizeof out);
goto out;

View File

@@ -27,10 +27,10 @@ static struct layout_cell *layout_find_bottomright(struct layout_cell *);
static u_short layout_checksum(const char *);
static int layout_append(struct layout_cell *, char *,
size_t);
static int layout_construct(struct layout_cell *,
const char **, struct layout_cell **);
static struct layout_cell *layout_construct(struct layout_cell *,
const char **);
static void layout_assign(struct window_pane **,
struct layout_cell *, int);
struct layout_cell *);
/* Find the bottom-right cell. */
static struct layout_cell *
@@ -58,30 +58,14 @@ layout_checksum(const char *layout)
/* Dump layout as a string. */
char *
layout_dump(struct window *w, struct layout_cell *root)
layout_dump(struct layout_cell *root)
{
char layout[8192], *out;
int bracket = 0;
struct window_pane *wp;
char layout[8192], *out;
*layout = '\0';
if (layout_append(root, layout, sizeof layout) != 0)
return (NULL);
TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (!window_pane_is_floating(wp))
break;
if (!bracket) {
strlcat(layout, "<", sizeof layout);
bracket = 1;
}
if (layout_append(wp->layout_cell, layout, sizeof layout) != 0)
return (NULL);
strlcat(layout, ",", sizeof layout);
}
if (bracket)
layout[strlen(layout) - 1] = '>';
xasprintf(&out, "%04hx,%s", layout_checksum(layout), layout);
return (out);
}
@@ -97,13 +81,12 @@ layout_append(struct layout_cell *lc, char *buf, size_t len)
if (len == 0)
return (-1);
if (lc == NULL)
return (0);
if (lc->wp != NULL) {
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%d,%d,%u",
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%u,%u,%u",
lc->sx, lc->sy, lc->xoff, lc->yoff, lc->wp->id);
} else {
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%d,%d",
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%u,%u",
lc->sx, lc->sy, lc->xoff, lc->yoff);
}
if (tmplen > (sizeof tmp) - 1)
@@ -173,43 +156,37 @@ layout_check(struct layout_cell *lc)
int
layout_parse(struct window *w, const char *layout, char **cause)
{
struct layout_cell *lcchild, *tiled_lc = NULL;
struct layout_cell *lc, *lcchild;
struct window_pane *wp;
u_int npanes, ncells, sx = 0, sy = 0;
u_short csum;
int n;
/* Check validity. */
if (sscanf(layout, "%hx,%n", &csum, &n) != 1 || n != 5) {
if (sscanf(layout, "%hx,", &csum) != 1) {
*cause = xstrdup("invalid layout");
return (-1);
}
layout += n;
layout += 5;
if (csum != layout_checksum(layout)) {
*cause = xstrdup("invalid layout");
return (-1);
}
/* Build the layout. */
if (layout_construct(NULL, &layout, &tiled_lc) != 0) {
lc = layout_construct(NULL, &layout);
if (lc == NULL) {
*cause = xstrdup("invalid layout");
return (-1);
}
if (tiled_lc == NULL) {
/* A stub layout cell for an empty window. */
tiled_lc = layout_create_cell(NULL);
tiled_lc->type = LAYOUT_LEFTRIGHT;
layout_set_size(tiled_lc, w->sx, w->sy, 0, 0);
}
if (*layout != '\0') {
*cause = xstrdup("invalid layout");
goto fail;
}
/* Check this window will fit into the layout. */
npanes = window_count_panes(w, 1);
for (;;) {
ncells = layout_count_cells(tiled_lc);
npanes = window_count_panes(w);
ncells = layout_count_cells(lc);
if (npanes > ncells) {
xasprintf(cause, "have %u panes but need %u", npanes,
ncells);
@@ -218,12 +195,9 @@ layout_parse(struct window *w, const char *layout, char **cause)
if (npanes == ncells)
break;
/*
* Fewer panes than cells, close the bottom right until none
* remain.
*/
lcchild = layout_find_bottomright(tiled_lc);
layout_destroy_cell(w, lcchild, &tiled_lc);
/* Fewer panes than cells - close the bottom right. */
lcchild = layout_find_bottomright(lc);
layout_destroy_cell(w, lcchild, &lc);
}
/*
@@ -231,104 +205,91 @@ layout_parse(struct window *w, const char *layout, char **cause)
* an incorrect top cell size - if it is larger than the top child then
* correct that (if this is still wrong the check code will catch it).
*/
switch (tiled_lc->type) {
switch (lc->type) {
case LAYOUT_WINDOWPANE:
break;
case LAYOUT_LEFTRIGHT:
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
sy = lcchild->sy + 1;
sx += lcchild->sx + 1;
}
break;
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
sx = lcchild->sx + 1;
sy += lcchild->sy + 1;
}
break;
}
if (tiled_lc->type != LAYOUT_WINDOWPANE &&
(tiled_lc->sx != sx || tiled_lc->sy != sy)) {
layout_print_cell(tiled_lc, __func__, 0);
tiled_lc->sx = sx - 1; tiled_lc->sy = sy - 1;
if (lc->type != LAYOUT_WINDOWPANE && (lc->sx != sx || lc->sy != sy)) {
log_debug("fix layout %u,%u to %u,%u", lc->sx, lc->sy, sx,sy);
layout_print_cell(lc, __func__, 0);
lc->sx = sx - 1; lc->sy = sy - 1;
}
/* Check the new layout. */
if (!layout_check(tiled_lc)) {
if (!layout_check(lc)) {
*cause = xstrdup("size mismatch after applying layout");
goto fail;
}
/* Resize window to the layout size. */
if (sx != 0 && sy != 0)
window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1);
/* Resize to the layout size. */
window_resize(w, lc->sx, lc->sy, -1, -1);
/* Destroy the old layout and swap to the new. */
layout_free_cell(w->layout_root);
w->layout_root = tiled_lc;
w->layout_root = lc;
/* Assign the panes into the cells. */
wp = TAILQ_FIRST(&w->panes);
if (tiled_lc != NULL)
layout_assign(&wp, tiled_lc, 0);
/* Fix pane z-indexes. */
while (!TAILQ_EMPTY(&w->z_index)) {
wp = TAILQ_FIRST(&w->z_index);
TAILQ_REMOVE(&w->z_index, wp, zentry);
}
layout_fix_zindexes(w, tiled_lc);
layout_assign(&wp, lc);
/* Update pane offsets and sizes. */
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
recalculate_sizes();
layout_print_cell(tiled_lc, __func__, 0);
layout_print_cell(lc, __func__, 0);
notify_window("window-layout-changed", w);
return (0);
fail:
layout_free_cell(tiled_lc);
layout_free_cell(lc);
return (-1);
}
/* Assign panes into cells. */
static void
layout_assign(struct window_pane **wp, struct layout_cell *lc, int flags)
layout_assign(struct window_pane **wp, struct layout_cell *lc)
{
struct layout_cell *lcchild;
if (lc == NULL)
return;
switch (lc->type) {
case LAYOUT_WINDOWPANE:
layout_make_leaf(lc, *wp);
lc->flags |= flags;
*wp = TAILQ_NEXT(*wp, entry);
return;
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_assign(wp, lcchild, flags);
layout_assign(wp, lcchild);
return;
}
}
/* Construct a cell from all or part of a layout tree. */
static struct layout_cell *
layout_construct_cell(struct layout_cell *lcparent, const char **layout)
layout_construct(struct layout_cell *lcparent, const char **layout)
{
struct layout_cell *lc;
u_int sx, sy;
int xoff, yoff;
struct layout_cell *lc, *lcchild;
u_int sx, sy, xoff, yoff;
const char *saved;
if (!isdigit((u_char) **layout))
return (NULL);
if (sscanf(*layout, "%ux%u,%d,%d", &sx, &sy, &xoff, &yoff) != 4)
if (sscanf(*layout, "%ux%u,%u,%u", &sx, &sy, &xoff, &yoff) != 4)
return (NULL);
while (isdigit((u_char) **layout))
@@ -363,35 +324,17 @@ layout_construct_cell(struct layout_cell *lcparent, const char **layout)
lc->xoff = xoff;
lc->yoff = yoff;
return (lc);
}
/*
* Given a character string layout, recursively construct cells.
* Possible return values:
* lc LAYOUT_WINDOWPANE, no children
* lc LAYOUT_LEFTRIGHT or LAYOUT_TOPBOTTOM, with children
*/
static int
layout_construct(struct layout_cell *lcparent, const char **layout,
struct layout_cell **lc)
{
struct layout_cell *lcchild;
*lc = layout_construct_cell(lcparent, layout);
switch (**layout) {
case ',':
case '}':
case ']':
case '>':
case '\0':
return (0);
return (lc);
case '{':
(*lc)->type = LAYOUT_LEFTRIGHT;
lc->type = LAYOUT_LEFTRIGHT;
break;
case '[':
(*lc)->type = LAYOUT_TOPBOTTOM;
lc->type = LAYOUT_TOPBOTTOM;
break;
default:
goto fail;
@@ -399,12 +342,13 @@ layout_construct(struct layout_cell *lcparent, const char **layout,
do {
(*layout)++;
if (layout_construct(*lc, layout, &lcchild) != 0)
lcchild = layout_construct(lc, layout);
if (lcchild == NULL)
goto fail;
TAILQ_INSERT_TAIL(&(*lc)->cells, lcchild, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
} while (**layout == ',');
switch ((*lc)->type) {
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
if (**layout != '}')
goto fail;
@@ -418,9 +362,9 @@ layout_construct(struct layout_cell *lcparent, const char **layout,
}
(*layout)++;
return (0);
return (lc);
fail:
layout_free_cell(*lc);
return (-1);
layout_free_cell(lc);
return (NULL);
}

View File

@@ -123,18 +123,6 @@ layout_set_previous(struct window *w)
return (layout);
}
static struct window_pane *
layout_first_tiled(struct window *w)
{
struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_is_floating(wp))
return (wp);
}
return (NULL);
}
static void
layout_set_even(struct window *w, enum layout_type type)
{
@@ -145,7 +133,7 @@ layout_set_even(struct window *w, enum layout_type type)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
@@ -168,8 +156,6 @@ layout_set_even(struct window *w, enum layout_type type)
/* Build new leaf cells. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp))
continue;
lcnew = layout_create_cell(lc);
layout_make_leaf(lcnew, wp);
lcnew->sx = w->sx;
@@ -215,7 +201,7 @@ layout_set_main_h(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
n--; /* take off main pane */
@@ -264,16 +250,14 @@ layout_set_main_h(struct window *w)
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, sx, mainh, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
} else {
@@ -282,9 +266,7 @@ layout_set_main_h(struct window *w)
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp))
continue;
if (wp == layout_first_tiled(w))
if (wp == TAILQ_FIRST(&w->panes))
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0);
@@ -317,7 +299,7 @@ layout_set_main_h_mirrored(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
n--; /* take off main pane */
@@ -367,9 +349,7 @@ layout_set_main_h_mirrored(struct window *w)
lcother = layout_create_cell(lc);
layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
} else {
@@ -378,9 +358,7 @@ layout_set_main_h_mirrored(struct window *w)
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp))
continue;
if (wp == layout_first_tiled(w))
if (wp == TAILQ_FIRST(&w->panes))
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0);
@@ -393,7 +371,7 @@ layout_set_main_h_mirrored(struct window *w)
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, sx, mainh, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Fix cell offsets. */
@@ -419,7 +397,7 @@ layout_set_main_v(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
n--; /* take off main pane */
@@ -468,16 +446,14 @@ layout_set_main_v(struct window *w)
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, mainw, sy, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
} else {
@@ -486,9 +462,7 @@ layout_set_main_v(struct window *w)
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp))
continue;
if (wp == layout_first_tiled(w))
if (wp == TAILQ_FIRST(&w->panes))
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0);
@@ -521,7 +495,7 @@ layout_set_main_v_mirrored(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
n--; /* take off main pane */
@@ -571,9 +545,7 @@ layout_set_main_v_mirrored(struct window *w)
lcother = layout_create_cell(lc);
layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry);
layout_make_leaf(lcother, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry);
} else {
@@ -582,9 +554,7 @@ layout_set_main_v_mirrored(struct window *w)
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp))
continue;
if (wp == layout_first_tiled(w))
if (wp == TAILQ_FIRST(&w->panes))
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0);
@@ -597,7 +567,7 @@ layout_set_main_v_mirrored(struct window *w)
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, mainw, sy, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Fix cell offsets. */
@@ -623,7 +593,7 @@ layout_set_tiled(struct window *w)
layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0);
n = window_count_panes(w);
if (n <= 1)
return;
@@ -659,10 +629,8 @@ layout_set_tiled(struct window *w)
layout_set_size(lc, sx, sy, 0, 0);
layout_make_node(lc, LAYOUT_TOPBOTTOM);
/* Create a grid of the cells, skipping any floating panes. */
/* Create a grid of the cells. */
wp = TAILQ_FIRST(&w->panes);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
for (j = 0; j < rows; j++) {
/* If this is the last cell, all done. */
if (wp == NULL)
@@ -677,8 +645,6 @@ layout_set_tiled(struct window *w)
if (n - (j * columns) == 1 || columns == 1) {
layout_make_leaf(lcrow, wp);
wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
continue;
}
@@ -691,11 +657,8 @@ layout_set_tiled(struct window *w)
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
/* Move to the next non-floating cell. */
wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
if (wp == NULL)
/* Move to the next cell. */
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
break;
}

354
layout.c
View File

@@ -47,7 +47,6 @@ static int layout_set_size_check(struct window *, struct layout_cell *,
static void layout_resize_child_cells(struct window *,
struct layout_cell *);
/* Create a new layout cell. */
struct layout_cell *
layout_create_cell(struct layout_cell *lcparent)
{
@@ -55,7 +54,6 @@ layout_create_cell(struct layout_cell *lcparent)
lc = xmalloc(sizeof *lc);
lc->type = LAYOUT_WINDOWPANE;
lc->flags = 0;
lc->parent = lcparent;
TAILQ_INIT(&lc->cells);
@@ -63,23 +61,19 @@ layout_create_cell(struct layout_cell *lcparent)
lc->sx = UINT_MAX;
lc->sy = UINT_MAX;
lc->xoff = INT_MAX;
lc->yoff = INT_MAX;
lc->xoff = UINT_MAX;
lc->yoff = UINT_MAX;
lc->wp = NULL;
return (lc);
}
/* Free a layout cell. */
void
layout_free_cell(struct layout_cell *lc)
{
struct layout_cell *lcchild;
if (lc == NULL)
return;
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
@@ -90,26 +84,20 @@ layout_free_cell(struct layout_cell *lc)
}
break;
case LAYOUT_WINDOWPANE:
if (lc->wp != NULL) {
lc->wp->layout_cell->parent = NULL;
if (lc->wp != NULL)
lc->wp->layout_cell = NULL;
}
break;
}
free(lc);
}
/* Log a cell. */
void
layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
{
struct layout_cell *lcchild;
const char *type;
if (lc == NULL)
return;
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
type = "LEFTRIGHT";
@@ -124,31 +112,28 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
type = "UNKNOWN";
break;
}
log_debug("%s:%*s%p type %s [parent %p] wp=%p [%d,%d %ux%u]", hdr, n,
log_debug("%s:%*s%p type %s [parent %p] wp=%p [%u,%u %ux%u]", hdr, n,
" ", lc, type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx,
lc->sy);
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_print_cell(lcchild, hdr, n + 1);
layout_print_cell(lcchild, hdr, n + 1);
break;
case LAYOUT_WINDOWPANE:
break;
}
}
/* Search for a cell by the border position. */
struct layout_cell *
layout_search_by_border(struct layout_cell *lc, u_int x, u_int y)
{
struct layout_cell *lcchild, *last = NULL;
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if ((int)x >= lcchild->xoff &&
(int)x < lcchild->xoff + (int)lcchild->sx &&
(int)y >= lcchild->yoff &&
(int)y < lcchild->yoff + (int)lcchild->sy) {
if (x >= lcchild->xoff && x < lcchild->xoff + lcchild->sx &&
y >= lcchild->yoff && y < lcchild->yoff + lcchild->sy) {
/* Inside the cell - recurse. */
return (layout_search_by_border(lcchild, x, y));
}
@@ -160,13 +145,11 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y)
switch (lc->type) {
case LAYOUT_LEFTRIGHT:
if ((int)x < lcchild->xoff &&
(int)x >= last->xoff + (int)last->sx)
if (x < lcchild->xoff && x >= last->xoff + last->sx)
return (last);
break;
case LAYOUT_TOPBOTTOM:
if ((int)y < lcchild->yoff &&
(int)y >= last->yoff + (int)last->sy)
if (y < lcchild->yoff && y >= last->yoff + last->sy)
return (last);
break;
case LAYOUT_WINDOWPANE:
@@ -179,9 +162,9 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y)
return (NULL);
}
/* Set cell size. */
void
layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, int xoff, int yoff)
layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, u_int xoff,
u_int yoff)
{
lc->sx = sx;
lc->sy = sy;
@@ -190,7 +173,6 @@ layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, int xoff, int yoff)
lc->yoff = yoff;
}
/* Make a cell a leaf cell. */
void
layout_make_leaf(struct layout_cell *lc, struct window_pane *wp)
{
@@ -202,7 +184,6 @@ layout_make_leaf(struct layout_cell *lc, struct window_pane *wp)
lc->wp = wp;
}
/* Make a cell a node cell. */
void
layout_make_node(struct layout_cell *lc, enum layout_type type)
{
@@ -217,41 +198,16 @@ layout_make_node(struct layout_cell *lc, enum layout_type type)
lc->wp = NULL;
}
/* Fix z-indexes. */
void
layout_fix_zindexes(struct window *w, struct layout_cell *lc)
{
struct layout_cell *lcchild;
if (lc == NULL)
return;
switch (lc->type) {
case LAYOUT_WINDOWPANE:
TAILQ_INSERT_TAIL(&w->z_index, lc->wp, zentry);
break;
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_fix_zindexes(w, lcchild);
return;
default:
fatalx("bad layout type");
}
}
/* Fix cell offsets for a child cell. */
static void
layout_fix_offsets1(struct layout_cell *lc)
{
struct layout_cell *lcchild;
int xoff, yoff;
u_int xoff, yoff;
if (lc->type == LAYOUT_LEFTRIGHT) {
xoff = lc->xoff;
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
lcchild->xoff = xoff;
lcchild->yoff = lc->yoff;
if (lcchild->type != LAYOUT_WINDOWPANE)
@@ -261,8 +217,6 @@ layout_fix_offsets1(struct layout_cell *lc)
} else {
yoff = lc->yoff;
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
lcchild->xoff = lc->xoff;
lcchild->yoff = yoff;
if (lcchild->type != LAYOUT_WINDOWPANE)
@@ -276,11 +230,7 @@ layout_fix_offsets1(struct layout_cell *lc)
void
layout_fix_offsets(struct window *w)
{
struct layout_cell *lc = w->layout_root;
/* Root consists of a single floating cell */
if (lc->flags & LAYOUT_CELL_FLOATING)
return;
struct layout_cell *lc = w->layout_root;
lc->xoff = 0;
lc->yoff = 0;
@@ -292,22 +242,13 @@ layout_fix_offsets(struct window *w)
static int
layout_cell_is_top(struct window *w, struct layout_cell *lc)
{
struct layout_cell *next, *edge;
struct layout_cell *next;
while (lc != w->layout_root) {
next = lc->parent;
if (next == NULL)
if (next->type == LAYOUT_TOPBOTTOM &&
lc != TAILQ_FIRST(&next->cells))
return (0);
if (next->type == LAYOUT_TOPBOTTOM) {
edge = TAILQ_FIRST(&next->cells);
while (edge != NULL) {
if (~edge->flags & LAYOUT_CELL_FLOATING)
break;
edge = TAILQ_NEXT(edge, entry);
}
if (lc != edge)
return (0);
}
lc = next;
}
return (1);
@@ -317,22 +258,13 @@ layout_cell_is_top(struct window *w, struct layout_cell *lc)
static int
layout_cell_is_bottom(struct window *w, struct layout_cell *lc)
{
struct layout_cell *next, *edge;
struct layout_cell *next;
while (lc != w->layout_root) {
next = lc->parent;
if (next == NULL)
if (next->type == LAYOUT_TOPBOTTOM &&
lc != TAILQ_LAST(&next->cells, layout_cells))
return (0);
if (next->type == LAYOUT_TOPBOTTOM) {
edge = TAILQ_LAST(&next->cells, layout_cells);
while (edge != NULL) {
if (~edge->flags & LAYOUT_CELL_FLOATING)
break;
edge = TAILQ_PREV(edge, layout_cells, entry);
}
if (lc != edge)
return (0);
}
lc = next;
}
return (1);
@@ -359,10 +291,12 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
{
struct window_pane *wp;
struct layout_cell *lc;
int status, sb_w, sb_pad;
int status, scrollbars, sb_pos, sb_w, sb_pad;
u_int sx, sy;
status = options_get_number(w->options, "pane-border-status");
scrollbars = options_get_number(w->options, "pane-scrollbars");
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((lc = wp->layout_cell) == NULL || wp == skip)
@@ -373,21 +307,20 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
sx = lc->sx;
sy = lc->sy;
if (!window_pane_is_floating(wp) &&
layout_add_horizontal_border(w, lc, status)) {
if (layout_add_horizontal_border(w, lc, status)) {
if (status == PANE_STATUS_TOP)
wp->yoff++;
sy--;
}
if (window_pane_show_scrollbar(wp)) {
if (window_pane_show_scrollbar(wp, scrollbars)) {
sb_w = wp->scrollbar_style.width;
sb_pad = wp->scrollbar_style.pad;
if (sb_w < 1)
sb_w = 1;
if (sb_pad < 0)
sb_pad = 0;
if (w->sb_pos == PANE_SCROLLBARS_LEFT) {
if (sb_pos == PANE_SCROLLBARS_LEFT) {
if ((int)sx - sb_w < PANE_MINIMUM) {
wp->xoff = wp->xoff +
(int)sx - PANE_MINIMUM;
@@ -396,7 +329,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
sx = sx - sb_w - sb_pad;
wp->xoff = wp->xoff + sb_w + sb_pad;
}
} else /* w->sb_pos == PANE_SCROLLBARS_RIGHT */
} else /* sb_pos == PANE_SCROLLBARS_RIGHT */
if ((int)sx - sb_w - sb_pad < PANE_MINIMUM)
sx = PANE_MINIMUM;
else
@@ -413,13 +346,14 @@ u_int
layout_count_cells(struct layout_cell *lc)
{
struct layout_cell *lcchild;
u_int count = 0;
u_int count;
switch (lc->type) {
case LAYOUT_WINDOWPANE:
return (1);
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
count = 0;
TAILQ_FOREACH(lcchild, &lc->cells, entry)
count += layout_count_cells(lcchild);
return (count);
@@ -436,15 +370,16 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
struct layout_cell *lcchild;
struct style *sb_style = &w->active->scrollbar_style;
u_int available, minimum;
int status;
int status, scrollbars;
status = options_get_number(w->options, "pane-border-status");
scrollbars = options_get_number(w->options, "pane-scrollbars");
if (lc->type == LAYOUT_WINDOWPANE) {
/* Space available in this cell only. */
if (type == LAYOUT_LEFTRIGHT) {
available = lc->sx;
if (w->sb != PANE_SCROLLBARS_OFF)
if (scrollbars)
minimum = PANE_MINIMUM + sb_style->width +
sb_style->pad;
else
@@ -501,11 +436,8 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
/* Child cell runs in a different direction. */
if (lc->type != type) {
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_resize_adjust(w, lcchild, type, change);
}
return;
}
@@ -517,8 +449,6 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (change == 0)
break;
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
if (change > 0) {
layout_resize_adjust(w, lcchild, type, 1);
change--;
@@ -537,33 +467,28 @@ void
layout_destroy_cell(struct window *w, struct layout_cell *lc,
struct layout_cell **lcroot)
{
struct layout_cell *lcother = NULL, *lcparent;
struct layout_cell *lcother, *lcparent;
/* If no parent, this is the last pane in a window. */
/*
* If no parent, this is the last pane so window close is imminent and
* there is no need to resize anything.
*/
lcparent = lc->parent;
if (lcparent == NULL) {
if (lc->wp != NULL)
*lcroot = NULL;
layout_free_cell(lc);
*lcroot = NULL;
return;
}
if (~lc->flags & LAYOUT_CELL_FLOATING) {
/* Merge the space into the previous or next cell. */
if (lc == TAILQ_FIRST(&lcparent->cells))
lcother = TAILQ_NEXT(lc, entry);
else
lcother = TAILQ_PREV(lc, layout_cells, entry);
}
if (lcother != NULL && (~lcother->flags & LAYOUT_CELL_FLOATING)) {
if (lcparent->type == LAYOUT_LEFTRIGHT) {
layout_resize_adjust(w, lcother, lcparent->type,
lc->sx + 1);
} else {
layout_resize_adjust(w, lcother, lcparent->type,
lc->sy + 1);
}
}
/* Merge the space into the previous or next cell. */
if (lc == TAILQ_FIRST(&lcparent->cells))
lcother = TAILQ_NEXT(lc, entry);
else
lcother = TAILQ_PREV(lc, layout_cells, entry);
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1);
else if (lcother != NULL)
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
/* Remove this from the parent's list. */
TAILQ_REMOVE(&lcparent->cells, lc, entry);
@@ -574,15 +499,12 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
* replace it by that cell.
*/
lc = TAILQ_FIRST(&lcparent->cells);
if (lc != NULL && TAILQ_NEXT(lc, entry) == NULL) {
if (TAILQ_NEXT(lc, entry) == NULL) {
TAILQ_REMOVE(&lcparent->cells, lc, entry);
lc->parent = lcparent->parent;
if (lc->parent == NULL) {
if (~lc->flags & LAYOUT_CELL_FLOATING) {
lc->xoff = 0;
lc->yoff = 0;
}
lc->xoff = 0; lc->yoff = 0;
*lcroot = lc;
} else
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
@@ -591,7 +513,6 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
}
}
/* Initialize layout for pane. */
void
layout_init(struct window *w, struct window_pane *wp)
{
@@ -603,7 +524,6 @@ layout_init(struct window *w, struct window_pane *wp)
layout_fix_panes(w, NULL);
}
/* Free layout for pane. */
void
layout_free(struct window *w)
{
@@ -630,8 +550,6 @@ layout_resize(struct window *w, u_int sx, u_int sy)
* out proportionately - this should leave the layout fitting the new
* window size.
*/
if (lc->type == LAYOUT_WINDOWPANE && (lc->flags & LAYOUT_CELL_FLOATING))
return;
xchange = sx - lc->sx;
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT);
if (xchange < 0 && xchange < -xlimit)
@@ -823,7 +741,7 @@ layout_resize_pane_shrink(struct window *w, struct layout_cell *lc,
return (size);
}
/* Assign window pane to new cell. */
/* Assign window pane to newly split cell. */
void
layout_assign_pane(struct layout_cell *lc, struct window_pane *wp,
int do_not_resize)
@@ -944,8 +862,6 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
count = 0;
previous = 0;
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
count++;
if (lc->type == LAYOUT_LEFTRIGHT)
previous += lcchild->sx;
@@ -964,8 +880,6 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
/* Resize children into the new size. */
idx = 0;
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
if (lcchild->flags & LAYOUT_CELL_FLOATING)
continue;
if (lc->type == LAYOUT_TOPBOTTOM) {
lcchild->sx = lc->sx;
lcchild->xoff = lc->xoff;
@@ -974,10 +888,9 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
lc->type, lc->sx, count - idx, available);
available -= (lcchild->sx + 1);
}
if (lc->type == LAYOUT_LEFTRIGHT) {
if (lc->type == LAYOUT_LEFTRIGHT)
lcchild->sy = lc->sy;
lcchild->yoff = lc->yoff;
} else {
else {
lcchild->sy = layout_new_pane_size(w, previous, lcchild,
lc->type, lc->sy, count - idx, available);
available -= (lcchild->sy + 1);
@@ -1000,6 +913,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
u_int sx, sy, xoff, yoff, size1, size2, minimum;
u_int new_size, saved_size, resize_first = 0;
int full_size = (flags & SPAWN_FULLSIZE), status;
int scrollbars;
/*
* If full_size is specified, add a new cell at the top of the window
@@ -1010,6 +924,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
else
lc = wp->layout_cell;
status = options_get_number(wp->window->options, "pane-border-status");
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
/* Copy the old cell size. */
sx = lc->sx;
@@ -1020,7 +935,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
/* Check there is enough space for the two new panes. */
switch (type) {
case LAYOUT_LEFTRIGHT:
if (wp->window->sb != PANE_SCROLLBARS_OFF) {
if (scrollbars) {
minimum = PANE_MINIMUM * 2 + sb_style->width +
sb_style->pad;
} else
@@ -1164,51 +1079,14 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
return (lcnew);
}
/*
* Creates a cell for a new floating pane. This must be followed by
* layout_assign_pane before much else happens!
*/
struct layout_cell *
layout_floating_pane(struct window *w, u_int sx, u_int sy, int ox, int oy)
{
struct layout_cell *lc = w->layout_root, *lcnew, *lcparent;
if (lc->type == LAYOUT_WINDOWPANE) {
/*
* Adding a pane to a root that doesn't have a container. Must
* create and insert a new root.
*/
lcparent = layout_create_cell(NULL);
layout_make_node(lcparent, LAYOUT_TOPBOTTOM);
layout_set_size(lcparent, w->sx, w->sy, 0, 0);
w->layout_root = lcparent;
/* Insert the old cell. */
lc->parent = lcparent;
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
} else
lcparent = w->layout_root;
lcnew = layout_create_cell(lcparent);
TAILQ_INSERT_TAIL(&lcparent->cells, lcnew, entry);
lcnew->flags |= LAYOUT_CELL_FLOATING;
layout_set_size(lcnew, sx, sy, ox, oy);
return (lcnew);
}
/* Destroy the cell associated with a pane. */
void
layout_close_pane(struct window_pane *wp)
{
struct window *w = wp->window;
if (wp->layout_cell == NULL)
return;
/* Remove the cell. */
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
wp->layout_cell = NULL;
/* Fix pane offsets and sizes. */
if (w->layout_root != NULL) {
@@ -1218,7 +1096,6 @@ layout_close_pane(struct window_pane *wp)
notify_window("window-layout-changed", w);
}
/* Spread out cells inside a parent cell. */
int
layout_spread_cell(struct window *w, struct layout_cell *parent)
{
@@ -1247,7 +1124,6 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
each = (size - (number - 1)) / number;
if (each == 0)
return (0);
/*
* Remaining space after assigning that which can be evenly
* distributed.
@@ -1282,7 +1158,6 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
return (changed);
}
/* Spread out cells evenly. */
void
layout_spread_out(struct window_pane *wp)
{
@@ -1301,122 +1176,3 @@ layout_spread_out(struct window_pane *wp)
}
} while ((parent = parent->parent) != NULL);
}
/* Get a new tiled cell. */
struct layout_cell *
layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp, int flags, char **cause)
{
struct layout_cell *lc;
enum layout_type type;
u_int curval;
int size = -1;
if (window_pane_is_floating(wp)) {
*cause = xstrdup("can't split a floating pane");
return (NULL);
}
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
cause);
if (*cause == NULL)
size = curval * size / 100;
}
if (*cause != NULL) {
*cause = xstrdup("invalid tiled geometry");
return (NULL);
}
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL)
*cause = xstrdup("no space for a new pane");
return (lc);
}
/* Get a new floating cell. */
struct layout_cell *
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
struct window *w, __unused struct window_pane *wp, char **cause)
{
struct layout_cell *lcnew;
int sx = w->sx / 2, sy = w->sy / 4;
int ox = INT_MAX, oy = INT_MAX;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, w->sx - 1, w->sx,
item, cause);
if (*cause != NULL)
return (NULL);
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, w->sy - 1, w->sy,
item, cause);
if (*cause != NULL)
return (NULL);
}
if (args_has(args, 'X')) {
ox = args_percentage_and_expand(args, 'X', -sx, w->sx,
w->sx, item, cause);
if (*cause != NULL)
return (NULL);
}
if (args_has(args, 'Y')) {
oy = args_percentage_and_expand(args, 'Y', -sy, w->sy,
w->sy, item, cause);
if (*cause != NULL)
return (NULL);
}
if (ox == INT_MAX) {
if (w->last_new_pane_x == 0)
ox = 4;
else {
ox = w->last_new_pane_x + 4;
if (w->last_new_pane_x > w->sx)
ox = 4;
}
w->last_new_pane_x = ox;
}
if (oy == INT_MAX) {
if (w->last_new_pane_y == 0)
oy = 2;
else {
oy = w->last_new_pane_y + 2;
if (w->last_new_pane_y > w->sy)
oy = 2;
}
w->last_new_pane_y = oy;
}
lcnew = layout_floating_pane(w, sx, sy, ox, oy);
return (lcnew);
}

7
menu.c
View File

@@ -363,7 +363,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
name = menu->items[i].name;
if (name == NULL || *name == '-')
continue;
if ((event->key & ~KEYC_MASK_FLAGS) == menu->items[i].key) {
if (event->key == menu->items[i].key) {
md->choice = i;
goto chosen;
}
@@ -471,7 +471,6 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
case '\r':
goto chosen;
case '\033': /* Escape */
case '['|KEYC_CTRL:
case 'c'|KEYC_CTRL:
case 'g'|KEYC_CTRL:
case 'q':
@@ -638,7 +637,7 @@ menu_display(struct menu *menu, int flags, int starting_choice,
style, selected_style, border_style, fs, cb, data);
if (md == NULL)
return (-1);
server_client_set_overlay(c, 0, menu_check_cb, menu_mode_cb,
menu_draw_cb, menu_key_cb, menu_free_cb, menu_resize_cb, md);
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
menu_key_cb, menu_free_cb, menu_resize_cb, md);
return (0);
}

View File

@@ -58,7 +58,6 @@ struct mode_tree_data {
mode_tree_key_cb keycb;
mode_tree_swap_cb swapcb;
mode_tree_sort_cb sortcb;
mode_tree_help_cb helpcb;
struct mode_tree_list children;
struct mode_tree_list saved;
@@ -133,35 +132,6 @@ static const struct menu_item mode_tree_menu_items[] = {
{ NULL, KEYC_NONE, NULL }
};
static const char* mode_tree_help_start[] = {
"\r\033[1m Up, k \033[0m\016x\017 \033[0mMove cursor up\n",
"\r\033[1m Down, j \033[0m\016x\017 \033[0mMove cursor down\n",
"\r\033[1m g \033[0m\016x\017 \033[0mGo to top\n",
"\r\033[1m G \033[0m\016x\017 \033[0mGo to bottom\n",
"\r\033[1m PPage, C-b \033[0m\016x\017 \033[0mPage up\n",
"\r\033[1m NPage, C-f \033[0m\016x\017 \033[0mPage down\n",
"\r\033[1m Left, h \033[0m\016x\017 \033[0mCollapse %1\n",
"\r\033[1m Right, l \033[0m\016x\017 \033[0mExpand %1\n",
"\r\033[1m M-- \033[0m\016x\017 \033[0mCollapse all %1s\n",
"\r\033[1m M-+ \033[0m\016x\017 \033[0mExpand all %1s\n",
"\r\033[1m t \033[0m\016x\017 \033[0mToggle %1 tag\n",
"\r\033[1m T \033[0m\016x\017 \033[0mUntag all %1s\n",
"\r\033[1m C-t \033[0m\016x\017 \033[0mTag all %1s\n",
"\r\033[1m C-s \033[0m\016x\017 \033[0mSearch forward\n",
"\r\033[1m n \033[0m\016x\017 \033[0mRepeat search forward\n",
"\r\033[1m N \033[0m\016x\017 \033[0mRepeat search backward\n",
"\r\033[1m f \033[0m\016x\017 \033[0mFilter %1s\n",
"\r\033[1m O \033[0m\016x\017 \033[0mChange sort order\n",
"\r\033[1m r \033[0m\016x\017 \033[0mReverse sort order\n",
"\r\033[1m v \033[0m\016x\017 \033[0mToggle preview\n",
NULL
};
static const char* mode_tree_help_end[] = {
"\r\033[1m q, Escape \033[0m\016x\017 \033[0mExit mode\033[H",
NULL
};
#define MODE_TREE_HELP_DEFAULT_WIDTH 39
static int
mode_tree_is_lowercase(const char *ptr)
{
@@ -300,8 +270,6 @@ mode_tree_clear_tagged(struct mode_tree_list *mtl)
void
mode_tree_up(struct mode_tree_data *mtd, int wrap)
{
if (mtd->line_size == 0)
return;
if (mtd->current == 0) {
if (wrap) {
mtd->current = mtd->line_size - 1;
@@ -318,8 +286,6 @@ mode_tree_up(struct mode_tree_data *mtd, int wrap)
int
mode_tree_down(struct mode_tree_data *mtd, int wrap)
{
if (mtd->line_size == 0)
return (0);
if (mtd->current == mtd->line_size - 1) {
if (wrap) {
mtd->current = 0;
@@ -366,8 +332,6 @@ mode_tree_swap(struct mode_tree_data *mtd, int direction)
void *
mode_tree_get_current(struct mode_tree_data *mtd)
{
if (mtd->line_size == 0)
return (NULL);
return (mtd->line_list[mtd->current].item->itemdata);
}
@@ -438,8 +402,6 @@ mode_tree_set_current(struct mode_tree_data *mtd, uint64_t tag)
return (1);
}
if (mtd->current >= mtd->line_size) {
if (mtd->line_size == 0)
return (0);
mtd->current = mtd->line_size - 1;
if (mtd->current > mtd->height - 1)
mtd->offset = mtd->current - mtd->height + 1;
@@ -491,9 +453,8 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb,
mode_tree_help_cb helpcb, void *modedata, const struct menu_item *menu,
struct screen **s)
mode_tree_swap_cb swapcb, mode_tree_sort_cb sortcb, void *modedata,
const struct menu_item *menu, struct screen **s)
{
struct mode_tree_data *mtd;
@@ -527,7 +488,6 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mtd->keycb = keycb;
mtd->swapcb = swapcb;
mtd->sortcb = sortcb;
mtd->helpcb = helpcb;
TAILQ_INIT(&mtd->children);
@@ -1163,57 +1123,6 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
}
}
static void
mode_tree_display_help(__unused struct mode_tree_data *mtd, struct client *c)
{
struct session *s = c->session;
u_int px, py, w, h = 0;
const char **line, **lines = NULL, *item = "item";
char *new_line;
if (mtd->helpcb == NULL)
w = MODE_TREE_HELP_DEFAULT_WIDTH;
else {
lines = mtd->helpcb(&w, &item);
if (w < MODE_TREE_HELP_DEFAULT_WIDTH)
w = MODE_TREE_HELP_DEFAULT_WIDTH;
}
for (line = mode_tree_help_start; *line != NULL; line++)
h++;
for (line = lines; line != NULL && *line != NULL; line++)
h++;
for (line = mode_tree_help_end; *line != NULL; line++)
h++;
if (c->tty.sx < w || c->tty.sy < h)
return;
px = (c->tty.sx - w) / 2;
py = (c->tty.sy - h) / 2;
if (popup_display(POPUP_CLOSEANYKEY|POPUP_NOJOB, BOX_LINES_DEFAULT,
NULL, px, py, w, h, NULL, NULL, 0, NULL, NULL, NULL, c, s, NULL,
NULL, NULL, NULL) != 0)
return;
popup_write(c, "\033[H\033[?25l\033[?7l\033)0", 17);
for (line = mode_tree_help_start; *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
for (line = lines; line != NULL && *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
for (line = mode_tree_help_end; *line != NULL; line++) {
new_line = cmd_template_replace(*line, item, 1);
popup_write(c, new_line, strlen(new_line));
free(new_line);
}
popup_write(c, "\033[H", 3);
}
int
mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
struct mouse_event *m, u_int *xp, u_int *yp)
@@ -1221,12 +1130,7 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
struct mode_tree_line *line;
struct mode_tree_item *current, *parent, *mti;
u_int i, x, y;
int choice, preview;
if (mtd->line_size == 0) {
*key = KEYC_NONE;
return (1);
}
int choice;
if (KEYC_IS_MOUSE(*key) && m != NULL) {
if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) {
@@ -1238,10 +1142,9 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
if (yp != NULL)
*yp = y;
if (x > mtd->width || y > mtd->height) {
preview = mtd->preview;
if (*key == KEYC_MOUSEDOWN3_PANE)
mode_tree_display_menu(mtd, c, x, y, 1);
if (preview == MODE_TREE_PREVIEW_OFF)
if (mtd->preview == MODE_TREE_PREVIEW_OFF)
*key = KEYC_NONE;
return (0);
}
@@ -1288,13 +1191,8 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
switch (*key) {
case 'q':
case '\033': /* Escape */
case '['|KEYC_CTRL:
case 'g'|KEYC_CTRL:
return (1);
case KEYC_F1:
case 'h'|KEYC_CTRL:
mode_tree_display_help(mtd, c);
break;
case KEYC_UP:
case 'k':
case KEYC_WHEELUP_PANE:

View File

@@ -95,7 +95,7 @@ check_window_name(struct window *w)
name = format_window_name(w);
if (strcmp(name, w->name) != 0) {
log_debug("@%u new name %s (was %s)", w->id, name, w->name);
window_set_name(w, name, 1);
window_set_name(w, name);
server_redraw_window_borders(w);
server_status_window(w);
} else
@@ -166,9 +166,7 @@ parse_window_name(const char *in)
if (*name == '/')
name = basename(name);
name = clean_name(name, 0);
name = xstrdup(name);
free(copy);
if (name == NULL)
return (xstrdup(""));
return (name);
}

View File

@@ -208,12 +208,8 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
format_add(ne->formats, "hook_window", "@%u", w->id);
format_add(ne->formats, "hook_window_name", "%s", w->name);
}
if (wp != NULL) {
if (wp != NULL)
format_add(ne->formats, "hook_pane", "%%%d", wp->id);
format_add(ne->formats, "hook_window", "@%u", wp->window->id);
format_add(ne->formats, "hook_window_name", "%s",
wp->window->name);
}
format_log_debug(ne->formats, __func__);
if (c != NULL)

View File

@@ -91,7 +91,7 @@ static const char *options_table_window_size_list[] = {
"largest", "smallest", "manual", "latest", NULL
};
static const char *options_table_remain_on_exit_list[] = {
"off", "on", "failed", "key", NULL
"off", "on", "failed", NULL
};
static const char *options_table_destroy_unattached_list[] = {
"off", "on", "keep-last", "keep-group", NULL
@@ -108,9 +108,6 @@ static const char *options_table_extended_keys_format_list[] = {
static const char *options_table_allow_passthrough_list[] = {
"off", "on", "all", NULL
};
static const char *options_table_copy_mode_line_numbers_list[] = {
"off", "default", "absolute", "relative", "hybrid", NULL
};
/* Status line format. */
#define OPTIONS_TABLE_STATUS_FORMAT1 \
@@ -144,7 +141,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
"#{T:window-status-format}" \
"#[pop-default]" \
"#[norange default]" \
"#{?loop_last_flag,,#{E:window-status-separator}}" \
"#{?loop_last_flag,,#{window-status-separator}}" \
"," \
"#[range=window|#{window_index} list=focus " \
"#{?#{!=:#{E:window-status-current-style},default}," \
@@ -171,7 +168,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
"#{T:window-status-current-format}" \
"#[pop-default]" \
"#[norange list=on default]" \
"#{?loop_last_flag,,#{E:window-status-separator}}" \
"#{?loop_last_flag,,#{window-status-separator}}" \
"}" \
"#[nolist align=right range=right #{E:status-right-style}]" \
"#[push-default]" \
@@ -188,7 +185,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
"#{E:pane-status-style}" \
"]" \
"#[push-default]" \
"#{T:window-pane-status-format}" \
"#P[#{pane_width}x#{pane_height}]" \
"#[pop-default]" \
"#[norange list=on default] " \
"," \
@@ -199,7 +196,7 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
"}" \
"]" \
"#[push-default]" \
"#{T:window-pane-current-status-format}" \
"#P[#{pane_width}x#{pane_height}]*" \
"#[pop-default]" \
"#[norange list=on default] " \
"}"
@@ -417,10 +414,10 @@ const struct options_table_entry options_table[] = {
.choices = options_table_get_clipboard_list,
.default_num = 1,
.text = "When an application requests the clipboard, whether to "
"ignore the request ('off'); respond with the newest buffer "
"('buffer'); request the clipboard from the most recently "
"used terminal ('request'); or to request the clipboard, "
"create a buffer, and send it to the application ('both')."
"ignore the request ('off'); respond with the newest buffer "
"('buffer'); request the clipboard from the most recently "
"used terminal ('request'); or to request the clipboard, "
"create a buffer, and send it to the application ('both')."
},
{ .name = "history-file",
@@ -726,24 +723,13 @@ const struct options_table_entry options_table[] = {
{ .name = "message-command-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SESSION,
.default_str = "bg=black,fg=yellow,fill=black",
.default_str = "bg=black,fg=yellow",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of the command prompt when in command mode, if "
"'mode-keys' is set to 'vi'."
},
{ .name = "message-format",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SESSION,
.default_str = "#[#{?#{command_prompt},"
"#{E:message-command-style},"
"#{E:message-style}}]"
"#{message}",
.text = "Format string for the prompt and message area. "
"The '#{message}' placeholder is replaced with the content."
},
{ .name = "message-line",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SESSION,
@@ -755,13 +741,10 @@ const struct options_table_entry options_table[] = {
{ .name = "message-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SESSION,
.default_str = "bg=yellow,fg=black,fill=yellow",
.default_str = "bg=yellow,fg=black",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of messages and the command prompt. "
"A 'fill' attribute controls background clearing and "
"a 'width' attribute (fixed or percentage) constrains "
"the prompt area width."
.text = "Style of messages and the command prompt."
},
{ .name = "mouse",
@@ -1027,9 +1010,7 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_SESSION,
.flags = OPTIONS_TABLE_IS_ARRAY,
.default_str = "DISPLAY KRB5CCNAME MSYSTEM SSH_ASKPASS SSH_AUTH_SOCK "
"SSH_AGENT_PID SSH_CONNECTION WAYLAND_DISPLAY "
"WINDOWID XAUTHORITY XDG_CURRENT_DESKTOP "
"XDG_SESSION_DESKTOP XDG_SESSION_TYPE",
"SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY",
.text = "List of environment variables to update in the session "
"environment when a client is attached."
},
@@ -1180,7 +1161,7 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "#[align=right]"
"#{t/p:top_line_time}#{?#{e|>:#{top_line_time},0}, ,}"
"[#{copy_position}/#{copy_position_limit}]"
"[#{scroll_position}/#{history_size}]"
"#{?search_timed_out, (timed out),"
"#{?search_count, (#{search_count}"
"#{?search_count_partial,+,} results),}}",
@@ -1205,32 +1186,6 @@ const struct options_table_entry options_table[] = {
.text = "Style of selection in copy mode."
},
{ .name = "copy-mode-current-line-number-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "fg=yellow",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of current line number in copy mode."
},
{ .name = "copy-mode-line-number-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "fg=white,dim",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of line numbers in copy mode."
},
{ .name = "copy-mode-line-numbers",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,
.choices = options_table_copy_mode_line_numbers_list,
.default_num = 0,
.text = "Line number mode in copy mode."
},
{ .name = "fill-character",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
@@ -1314,7 +1269,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-active-border-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "#{?pane_in_mode,fg=yellow,#{?synchronize-panes,fg=red,fg=green}}",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
@@ -1334,14 +1289,7 @@ const struct options_table_entry options_table[] = {
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "#{?pane_active,#[reverse],}#{pane_index}#[default] "
"\"#{pane_title}\""
"#{?#{mouse},"
"#[align=right]"
"#[range=control|8]["
"#{?#{window_zoomed_flag},u,z}"
"]#[norange]"
"#[range=control|9][x]#[norange]"
",}",
"\"#{pane_title}\"",
.text = "Format of text in the pane status lines."
},
@@ -1373,7 +1321,7 @@ const struct options_table_entry options_table[] = {
{ .name = "pane-border-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "default",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
@@ -1445,9 +1393,8 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.choices = options_table_remain_on_exit_list,
.default_num = 0,
.text = "Whether panes should remain ('on'), remain until a key is "
"pressed ('key') or be automatically killed ('off' or "
"'failed') when the program inside exits."
.text = "Whether panes should remain ('on') or be automatically "
"killed ('off' or 'failed') when the program inside exits."
},
{ .name = "remain-on-exit-format",
@@ -1488,28 +1435,6 @@ const struct options_table_entry options_table[] = {
"A value of 0 means no limit."
},
{ .name = "tree-mode-preview-format",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "#{?pane_format,"
"#{pane_index}:#{pane_title},"
"#{window_index}:#{window_name}}",
.text = "Format of the preview indicator in tree mode."
},
{ .name = "tree-mode-preview-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "fg=#{?#{||:"
"#{&&:#{pane_format},#{pane_active}},"
"#{&&:#{window_format},#{window_active}}},"
"#{display-panes-active-colour},"
"#{display-panes-colour}}",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of preview indicator in tree mode."
},
{ .name = "window-active-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
@@ -1519,21 +1444,6 @@ const struct options_table_entry options_table[] = {
.text = "Default style of the active pane."
},
{ .name = "window-pane-current-status-format",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "#P:[#T]#{?pane_flags,#{pane_flags}, }",
.text = "Format of the current window pane in the status line."
},
{ .name = "window-pane-status-format",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
.default_str = "#P:[#T]#{?pane_flags,#{pane_flags}, }",
.text = "Format of window panes in the status line, except the "
"current pane."
},
{ .name = "window-size",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_WINDOW,

View File

@@ -1237,13 +1237,8 @@ options_push_changes(const char *name)
if (strcmp(name, "pane-border-status") == 0 ||
strcmp(name, "pane-scrollbars") == 0 ||
strcmp(name, "pane-scrollbars-position") == 0) {
RB_FOREACH(w, windows, &windows) {
w->sb = options_get_number(w->options,
"pane-scrollbars");
w->sb_pos = options_get_number(w->options,
"pane-scrollbars-position");
RB_FOREACH(w, windows, &windows)
layout_fix_panes(w, NULL);
}
}
if (strcmp(name, "pane-scrollbars-style") == 0) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {

35
paste.c
View File

@@ -176,6 +176,7 @@ paste_add(const char *prefix, char *data, size_t size)
}
pb = xmalloc(sizeof *pb);
pb->name = NULL;
do {
free(pb->name);
@@ -203,7 +204,6 @@ int
paste_rename(const char *oldname, const char *newname, char **cause)
{
struct paste_buffer *pb, *pb_new;
char *name;
if (cause != NULL)
*cause = NULL;
@@ -219,33 +219,23 @@ paste_rename(const char *oldname, const char *newname, char **cause)
return (-1);
}
name = clean_name(newname, 0);
if (name == NULL) {
if (cause != NULL)
xasprintf(cause, "invalid buffer name: %s", newname);
return (-1);
}
pb = paste_get_name(oldname);
if (pb == NULL) {
if (cause != NULL)
xasprintf(cause, "no buffer %s", oldname);
free(name);
return (-1);
}
pb_new = paste_get_name(name);
if (pb_new == pb) {
free(name);
pb_new = paste_get_name(newname);
if (pb_new == pb)
return (0);
}
if (pb_new != NULL)
paste_free(pb_new);
RB_REMOVE(paste_name_tree, &paste_by_name, pb);
free(pb->name);
pb->name = name;
pb->name = xstrdup(newname);
if (pb->automatic)
paste_num_automatic--;
@@ -254,7 +244,7 @@ paste_rename(const char *oldname, const char *newname, char **cause)
RB_INSERT(paste_name_tree, &paste_by_name, pb);
notify_paste_buffer(oldname, 1);
notify_paste_buffer(pb->name, 0);
notify_paste_buffer(newname, 0);
return (0);
}
@@ -267,7 +257,6 @@ int
paste_set(char *data, size_t size, const char *name, char **cause)
{
struct paste_buffer *pb, *old;
char *newname;
if (cause != NULL)
*cause = NULL;
@@ -287,15 +276,9 @@ paste_set(char *data, size_t size, const char *name, char **cause)
return (-1);
}
newname = clean_name(name, 0);
if (newname == NULL) {
if (cause != NULL)
xasprintf(cause, "invalid buffer name: %s", name);
return (-1);
}
pb = xmalloc(sizeof *pb);
pb->name = newname;
pb->name = xstrdup(name);
pb->data = data;
pb->size = size;
@@ -305,13 +288,13 @@ paste_set(char *data, size_t size, const char *name, char **cause)
pb->created = time(NULL);
if ((old = paste_get_name(pb->name)) != NULL)
if ((old = paste_get_name(name)) != NULL)
paste_free(old);
RB_INSERT(paste_name_tree, &paste_by_name, pb);
RB_INSERT(paste_time_tree, &paste_by_time, pb);
notify_paste_buffer(pb->name, 0);
notify_paste_buffer(name, 0);
return (0);
}

76
popup.c
View File

@@ -103,27 +103,6 @@ static const struct menu_item popup_internal_menu_items[] = {
{ NULL, KEYC_NONE, NULL }
};
static void
popup_free(struct popup_data *pd)
{
server_client_unref(pd->c);
if (pd->job != NULL)
job_free(pd->job);
input_free(pd->ictx);
free(pd->or[0].ranges);
free(pd->or[1].ranges);
free(pd->r.ranges);
screen_free(&pd->s);
colour_palette_free(&pd->palette);
free(pd->title);
free(pd->style);
free(pd->border_style);
free(pd);
}
static void
popup_reapply_styles(struct popup_data *pd)
{
@@ -185,6 +164,7 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
if (pd->c->flags & CLIENT_REDRAWOVERLAY)
return (0);
ttyctx->bigger = 0;
ttyctx->wox = 0;
ttyctx->woy = 0;
ttyctx->wsx = c->tty.sx;
@@ -207,7 +187,6 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx)
struct popup_data *pd = ctx->arg;
memcpy(&ttyctx->defaults, &pd->defaults, sizeof ttyctx->defaults);
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
ttyctx->palette = &pd->palette;
ttyctx->redraw_cb = popup_redraw_cb;
ttyctx->set_client_cb = popup_set_client_cb;
@@ -300,10 +279,6 @@ popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx)
popup_reapply_styles(pd);
screen_init(&s, pd->sx, pd->sy, 0);
if (pd->s.hyperlinks != NULL) {
hyperlinks_free(s.hyperlinks);
s.hyperlinks = hyperlinks_copy(pd->s.hyperlinks);
}
screen_write_start(&ctx, &s);
screen_write_clearscreen(&ctx, 8);
@@ -364,8 +339,22 @@ popup_free_cb(struct client *c, void *data)
cmdq_get_client(item)->retval = pd->status;
cmdq_continue(item);
}
server_client_unref(pd->c);
popup_free(pd);
if (pd->job != NULL)
job_free(pd->job);
input_free(pd->ictx);
free(pd->or[0].ranges);
free(pd->or[1].ranges);
free(pd->r.ranges);
screen_free(&pd->s);
colour_palette_free(&pd->palette);
free(pd->title);
free(pd->style);
free(pd->border_style);
free(pd);
}
static void
@@ -435,7 +424,7 @@ popup_make_pane(struct popup_data *pd, enum layout_type type)
pd->job = NULL;
}
screen_set_title(&pd->s, new_wp->base.title, 0);
screen_set_title(&pd->s, new_wp->base.title);
screen_free(&new_wp->base);
memcpy(&new_wp->base, &pd->s, sizeof wp->base);
screen_resize(&new_wp->base, new_wp->sx, new_wp->sy, 1);
@@ -858,39 +847,16 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
pd->psx = sx;
pd->psy = sy;
if (flags & POPUP_NOJOB)
pd->ictx = input_init(NULL, NULL, &pd->palette, NULL);
else {
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
if (pd->job == NULL) {
popup_free(pd);
return (-1);
}
pd->ictx = input_init(NULL, job_get_event(pd->job),
&pd->palette, c);
}
pd->job = job_run(shellcmd, argc, argv, env, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy);
pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette, c);
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
return (0);
}
void
popup_write(struct client *c, const char *data, size_t size)
{
struct popup_data *pd = c->overlay_data;
if (!popup_present(c))
return;
c->overlay_check = NULL;
c->overlay_data = NULL;
input_parse_screen(pd->ictx, &pd->s, popup_init_ctx_cb, pd, data, size);
c->overlay_check = popup_check_cb;
c->overlay_data = pd;
}
static void
popup_editor_free(struct popup_editor *pe)
{

View File

@@ -4,9 +4,9 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMUX2="$TEST_TMUX -Ltest2 -f/dev/null"
TMUX2="$TEST_TMUX -Ltest2"
$TMUX2 kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -11,9 +11,9 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMUX_OUTER="$TEST_TMUX -Ltest2 -f/dev/null"
TMUX_OUTER="$TEST_TMUX -Ltest2"
$TMUX_OUTER kill-server 2>/dev/null
trap "$TMUX kill-server 2>/dev/null; $TMUX_OUTER kill-server 2>/dev/null" 0 1 15

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
TMP=$(mktemp)
TMP2=$(mktemp)
trap "rm -f $TMP $TMP2" 0 1 15

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
for i in conf/*.conf; do

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -8,7 +8,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -f/dev/null -Ltest"
$TMUX kill-server 2>/dev/null
$TMUX new -d -x40 -y10 \

View File

@@ -34,17 +34,14 @@ $TMUX send-keys -X previous-word
$TMUX send-keys -X copy-selection
[ "$($TMUX show-buffer)" = "line" ] || exit 1
# Test that `next-word-end` stops at the end of the line.
# Test that `next-word-end` wraps around indented line breaks.
$TMUX send-keys -X next-word
$TMUX send-keys -X next-word
$TMUX send-keys -X begin-selection
$TMUX send-keys -X next-word-end
$TMUX send-keys -X next-word-end
$TMUX send-keys -X copy-selection
[ "$($TMUX show-buffer)" = "words" ] || exit 1
# Move to the next word for the following tests.
$TMUX send-keys -X next-word
[ "$($TMUX show-buffer)" = "$(printf "words\n\tIndented")" ] || exit 1
# Test that `next-word` wraps around un-indented line breaks.
$TMUX send-keys -X next-word

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -f/dev/null -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -9,12 +9,13 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
sleep 1
TMP=$(mktemp)
trap "rm -f $TMP; $TMUX kill-server 2>/dev/null" 0 1 15
TMP2=$(mktemp)
trap "rm -f $TMP $TMP2; $TMUX kill-server 2>/dev/null" 0 1 15
$TMUX -f/dev/null new -d -x80 -y24 || exit 1
sleep 1
@@ -24,21 +25,19 @@ $TMUX set -g remain-on-exit on
exit_status=0
# query_decrpm <outfile> <mode> [setup_seq]
# query_decrpm <outfile> [setup_seq]
# Spawn a pane that optionally sends setup_seq, then sends DECRQM for
# mode 2026 and captures the response into outfile in cat -v form.
query_decrpm() {
query_decrpm () {
_outfile=$1
_mode=$2
_setup=$3
_n=$4
_setup=$2
$TMUX respawnw -k -t:0 -- sh -c "
exec 2>/dev/null
stty raw -echo
${_setup:+printf '$_setup'; sleep 0.2}
printf '\033[%s\$p' "$_mode"
dd bs=1 count=$_n 2>/dev/null | cat -v > $_outfile
printf '\033[?2026\$p'
dd bs=1 count=11 2>/dev/null | cat -v > $_outfile
sleep 0.2
" || exit 1
sleep 2
@@ -47,7 +46,7 @@ query_decrpm() {
# ------------------------------------------------------------------
# Test 1: mode 2026 should be reset by default (Ps=2)
# ------------------------------------------------------------------
query_decrpm "$TMP" "?2026" '' 11
query_decrpm "$TMP"
actual=$(cat "$TMP")
expected='^[[?2026;2$y'
@@ -64,9 +63,9 @@ fi
# ------------------------------------------------------------------
# Test 2: set mode 2026 (SM ?2026), then query (expect Ps=1)
# ------------------------------------------------------------------
query_decrpm "$TMP" "?2026" '\033[?2026h' 11
query_decrpm "$TMP2" '\033[?2026h'
actual=$(cat "$TMP")
actual=$(cat "$TMP2")
expected='^[[?2026;1$y'
if [ "$actual" = "$expected" ]; then
@@ -78,61 +77,6 @@ else
exit_status=1
fi
# ------------------------------------------------------------------
# Test 3: mode 25 should return current value
# ------------------------------------------------------------------
query_decrpm "$TMP" "?25" '\033[?25l' 9
actual=$(cat "$TMP")
expected='^[[?25;2$y'
if [ "$actual" = "$expected" ]; then
if [ -n "$VERBOSE" ]; then
echo "[PASS] DECTCEM 25 (reset) -> $actual"
fi
else
echo "[FAIL] DECTCEM 25 (reset): expected '$expected', got '$actual'"
exit_status=1
fi
# ------------------------------------------------------------------
# Test 4: mode ?9999 should return not recognized
# ------------------------------------------------------------------
query_decrpm "$TMP" "?9999" '\033[?9999h' 11
actual=$(cat "$TMP")
expected='^[[?9999;0$y'
if [ "$actual" = "$expected" ]; then
if [ -n "$VERBOSE" ]; then
echo "[PASS] DECSM 9999 (not recognized) -> $actual"
fi
else
echo "[FAIL] DECSM 9999 (not recognized): expected '$expected', got '$actual'"
exit_status=1
fi
$TMUX kill-server 2>/dev/null
exit $exit_status
# ------------------------------------------------------------------
# Test 5: mode 4 is reset by default
# ------------------------------------------------------------------
query_decrpm "$TMP" "4" '\033[4h' 11
actual=$(cat "$TMP")
expected='^[[4;1$y'
if [ "$actual" = "$expected" ]; then
if [ -n "$VERBOSE" ]; then
echo "[PASS] SM 4 (is set) -> $actual"
fi
else
echo "[FAIL] SM 4 (is set): expected '$expected', got '$actual'"
exit_status=1
fi
$TMUX kill-server 2>/dev/null
exit $exit_status
exit $exit_status

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
# test_format $format $expected_result
test_format()

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
$TMUX -f/dev/null has -tfoo </dev/null 2>/dev/null && exit 1

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,13 +4,12 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
sleep 1
$TMUX -f/dev/null new -x20 -y2 -d \; set -g escape-time 0 || exit 1
sleep 1
W=$($TMUX new-window -P -- sh -c 'stty raw -echo && cat -tv')
$TMUX -f/dev/null new -x20 -y2 -d || exit 1
sleep 1
$TMUX set -g escape-time 0
exit_status=0
@@ -18,13 +17,14 @@ assert_key () {
key=$1
expected_code=$2
$TMUX send-keys -t$W -R \; \
clear-history -t$W \; \
send-keys -t$W "$key" 'EOL' || exit 1
W=$($TMUX new-window -P -- sh -c 'stty raw -echo && cat -tv')
$TMUX send-keys -t$W "$key" 'EOL' || exit 1
sleep 0.2
actual_code=$($TMUX capturep -pt$W | \
head -1 | \
sed -e 's/EOL.*$//')
$TMUX kill-window -t$W || exit 1
if [ "$actual_code" = "$expected_code" ]; then
if [ -n "$VERBOSE" ]; then

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
sleep 1

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -5,14 +5,14 @@
PATH=/bin:/usr/bin
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TERM=$($TMUX start \; show -gv default-terminal)
TMP=$(mktemp)
OUT=$(mktemp)
SCRIPT=$(mktemp)
trap "rm -f $TMP $OUT $SCRIPT" 0 1 15
#trap "rm -f $TMP $OUT $SCRIPT" 0 1 15
cat <<EOF >$SCRIPT
(

View File

@@ -8,7 +8,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -6,7 +6,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

View File

@@ -4,7 +4,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
$TMUX new -d

View File

@@ -7,7 +7,7 @@ PATH=/bin:/usr/bin
TERM=screen
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -Ltest -f/dev/null"
TMUX="$TEST_TMUX -Ltest"
$TMUX kill-server 2>/dev/null
TMP=$(mktemp)

Some files were not shown because too many files have changed in this diff Show More