mirror of
https://github.com/tmux/tmux.git
synced 2026-03-11 11:05:46 +00:00
Compare commits
140 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01918cb017 | ||
|
|
aa6e6fa0f2 | ||
|
|
9bdbe171b7 | ||
|
|
98a3c98c28 | ||
|
|
de2ddddd60 | ||
|
|
a9ffb56b65 | ||
|
|
14b97fc889 | ||
|
|
d0a600ccaa | ||
|
|
a368548645 | ||
|
|
13fe06a459 | ||
|
|
87e87030fe | ||
|
|
a5ef1f2ed6 | ||
|
|
f5d7a80272 | ||
|
|
33f9b316a3 | ||
|
|
d6ff630498 | ||
|
|
eceaa9a493 | ||
|
|
2e19a5ecb9 | ||
|
|
fb1f0fee5a | ||
|
|
6048b0f483 | ||
|
|
f12b857415 | ||
|
|
79bdca4638 | ||
|
|
21f8ac2766 | ||
|
|
89b56c3451 | ||
|
|
fe7486d43b | ||
|
|
400b807d75 | ||
|
|
5f07da6227 | ||
|
|
7eb3ef66e5 | ||
|
|
82776c456e | ||
|
|
80bdd89856 | ||
|
|
ed6327c87b | ||
|
|
b21a710de7 | ||
|
|
aa32457772 | ||
|
|
5c78b48cdf | ||
|
|
5fc2d4a4fc | ||
|
|
969af935f3 | ||
|
|
4f04b2094c | ||
|
|
0d88f8a78b | ||
|
|
6de991d855 | ||
|
|
ff67ef945d | ||
|
|
711b8164bb | ||
|
|
35985c0add | ||
|
|
cfc81692e6 | ||
|
|
a4a7c3c68d | ||
|
|
e7d53020b4 | ||
|
|
03519021b9 | ||
|
|
6f2698004e | ||
|
|
28a5bc8fae | ||
|
|
20154f391e | ||
|
|
98c4291df2 | ||
|
|
5c0ce192ed | ||
|
|
cc743dc296 | ||
|
|
d254293a6d | ||
|
|
850c26dd46 | ||
|
|
db07f33886 | ||
|
|
2fae6a5761 | ||
|
|
2ee0962c96 | ||
|
|
42935bde71 | ||
|
|
ffebf00585 | ||
|
|
ead6d652ff | ||
|
|
a14aa788d4 | ||
|
|
d8721b35a0 | ||
|
|
97738921cd | ||
|
|
486ce9b098 | ||
|
|
8fb6666f17 | ||
|
|
cb77c2aa78 | ||
|
|
0c94c3fbee | ||
|
|
94712a8b0d | ||
|
|
dec6ec9e29 | ||
|
|
9da78d72de | ||
|
|
d0c992306d | ||
|
|
54c2d48d7d | ||
|
|
e6cbeb4f38 | ||
|
|
4581240ced | ||
|
|
f6bad7efd7 | ||
|
|
713e0ddef3 | ||
|
|
ff45b2d343 | ||
|
|
91280f1fca | ||
|
|
7de25d86e1 | ||
|
|
ba31d3a88c | ||
|
|
54cd292f09 | ||
|
|
d1f5142dab | ||
|
|
058d2b94dc | ||
|
|
c177a627d2 | ||
|
|
8f8e0975f1 | ||
|
|
b602c1fb9a | ||
|
|
7448b38327 | ||
|
|
85d5a377c5 | ||
|
|
b9a6162d2f | ||
|
|
8f5903d7c3 | ||
|
|
f0ac0d6793 | ||
|
|
2a04665626 | ||
|
|
07c0970f54 | ||
|
|
546123f950 | ||
|
|
f2f9605c63 | ||
|
|
e4e060f2be | ||
|
|
e3b034fac7 | ||
|
|
82c0eed36d | ||
|
|
80994a8de1 | ||
|
|
9e1093b7d7 | ||
|
|
f2029f9d9e | ||
|
|
b2a2c3a1e9 | ||
|
|
f915a4bf0c | ||
|
|
91b220525b | ||
|
|
988c6bc433 | ||
|
|
1d858aa89e | ||
|
|
e24a077752 | ||
|
|
645fe9013f | ||
|
|
896c1da7da | ||
|
|
d24bd7394d | ||
|
|
aebb17dc75 | ||
|
|
d9d2f84a4b | ||
|
|
068d1b97b2 | ||
|
|
4bf6f2706e | ||
|
|
9f39652d87 | ||
|
|
c48440fd40 | ||
|
|
1afe71cc0a | ||
|
|
0e1b339c10 | ||
|
|
3dceddd70e | ||
|
|
2595718dd3 | ||
|
|
6ebd737590 | ||
|
|
e64d078a4c | ||
|
|
ae0b7c7d72 | ||
|
|
a770ef3e2a | ||
|
|
b95d1de8fd | ||
|
|
7e5262ae9a | ||
|
|
14ecb5032e | ||
|
|
1bd66b65a3 | ||
|
|
051a29ca03 | ||
|
|
c6975b3bb4 | ||
|
|
68bf7c532b | ||
|
|
9b73d76ddd | ||
|
|
5d616f4c72 | ||
|
|
b5c0b2cae2 | ||
|
|
803b8815bd | ||
|
|
640d97afd0 | ||
|
|
194e9f611b | ||
|
|
5512de6a61 | ||
|
|
26792b9035 | ||
|
|
919f55ac4a | ||
|
|
80283f99fb |
38
CHANGES
38
CHANGES
@@ -1,9 +1,45 @@
|
||||
CHANGES FROM 2.7 to 2.8
|
||||
|
||||
* Make display-panes block the client until a pane is chosen or it
|
||||
times out.
|
||||
|
||||
* Clear history on RIS like most other terminals do.
|
||||
|
||||
* Add an "Any" key to run a command if a key is pressed that is not
|
||||
bound in the current key table.
|
||||
|
||||
* Expand formats in load-buffer and save-buffer.
|
||||
|
||||
* Add a rectangle_toggle format.
|
||||
|
||||
* Add set-hook -R to run a hook immediately.
|
||||
|
||||
* Add README.ja.
|
||||
|
||||
* Add pane focus hooks.
|
||||
|
||||
* Allow any punctuation as separator for s/x/y not only /.
|
||||
|
||||
* Improve resizing with the mouse (fix resizing the wrong pane in some
|
||||
layouts, and allow resizing multiple panes at the same time).
|
||||
|
||||
* Allow , and } to be escaped in formats as #, and #}.
|
||||
|
||||
* Add KRB5CCNAME to update-environment.
|
||||
|
||||
* Change meaning of -c to display-message so the client is used if it
|
||||
matches the session given to -t.
|
||||
|
||||
* Fixes to : form of SGR.
|
||||
|
||||
* Add x and X to choose-tree to kill sessions, windows or panes.
|
||||
|
||||
CHANGES FROM 2.6 TO 2.7
|
||||
|
||||
* Remove EVENT_* variables from environment on platforms where tmux uses them
|
||||
so they do not pass on to panes.
|
||||
|
||||
* Fixed for hooks at server exit.
|
||||
* Fixes for hooks at server exit.
|
||||
|
||||
* Remove SGR 10 (was equivalent to SGR 0 but no other terminal seems to do
|
||||
this).
|
||||
|
||||
@@ -6,7 +6,7 @@ CLEANFILES = tmux.1.mdoc tmux.1.man
|
||||
|
||||
# Distribution tarball options.
|
||||
EXTRA_DIST = \
|
||||
CHANGES README COPYING example_tmux.conf compat/*.[ch] \
|
||||
CHANGES README README.ja COPYING example_tmux.conf compat/*.[ch] \
|
||||
osdep-*.c mdoc2man.awk tmux.1
|
||||
|
||||
# Preprocessor flags.
|
||||
|
||||
6
README
6
README
@@ -1,8 +1,8 @@
|
||||
Welcome to tmux!
|
||||
|
||||
tmux is a "terminal multiplexer", it enables a number of terminals (or windows)
|
||||
to be accessed and controlled from a single terminal. tmux is intended to be a
|
||||
simple, modern, BSD-licensed alternative to programs such as GNU screen.
|
||||
tmux is a terminal multiplexer: it enables a number of terminals to be created,
|
||||
accessed, and controlled from a single screen. tmux may be detached from a
|
||||
screen and continue running in the background, then later reattached.
|
||||
|
||||
This release runs on OpenBSD, FreeBSD, NetBSD, Linux, OS X and Solaris.
|
||||
|
||||
|
||||
62
README.ja
Normal file
62
README.ja
Normal file
@@ -0,0 +1,62 @@
|
||||
tmuxへようこそ!
|
||||
|
||||
tmuxはターミナルマルチプレクサーです。複数のターミナルを一つのスクリーン内に作成し、操作することができます。
|
||||
バックグラウンドで処理を実行中に一度スクリーンから離れて後から復帰することも可能です。
|
||||
|
||||
OpenBSD、FreeBSD、NetBSD、Linux、OS X、Solarisで実行できます。
|
||||
|
||||
tmuxはlibevent 2.x.に依存します。 下記からダウンロードしてください。
|
||||
|
||||
http://libevent.org
|
||||
|
||||
また、ncursesも必要です。こちらからどうぞ。
|
||||
|
||||
http://invisible-island.net/ncurses/
|
||||
|
||||
tarballでのtmuxのビルドとインストール方法。
|
||||
|
||||
$ ./configure && make
|
||||
$ sudo make install
|
||||
|
||||
tmuxはutmp(5)をアップデートするためにutempterを使うことができます。もしインストール済みであればオプション「--enable-utempter」をつけて実行してください。
|
||||
|
||||
リポジトリから最新バージョンを手に入れるためには下記を実行。
|
||||
|
||||
$ git clone https://github.com/tmux/tmux.git
|
||||
$ cd tmux
|
||||
$ sh autogen.sh
|
||||
$ ./configure && make
|
||||
|
||||
(ビルドのためにはlibevent、ncurses libraries、headersに加えて、C compiler、make、autoconf、automake、pkg-configが必要です。)
|
||||
|
||||
詳しい情報はhttp://git-scm.comをご覧ください。修正はメール<tmux-users@googlegroups.com>宛、もしくはhttps://github.com/tmux/tmux/issuesにて受け付けています。
|
||||
|
||||
tmuxのドキュメントについてはtmux.1マニュアルをご覧ください。こちらのコマンドで参照可能です。
|
||||
|
||||
$ nroff -mdoc tmux.1|less
|
||||
|
||||
サンプル設定は本リポジトリのexample_tmux.confに
|
||||
また、bash-completionファイルは下記にあります。
|
||||
|
||||
https://github.com/imomaliev/tmux-bash-completion
|
||||
|
||||
「-v」や「-vv」を指定することでデバッグモードでの起動が可能です。カレントディレクトリにサーバーやクライアントのログファイルが生成されます。
|
||||
|
||||
議論やバグレポート用のメーリングリストにはこちらから参加可能です。
|
||||
|
||||
https://groups.google.com/forum/#!forum/tmux-users
|
||||
|
||||
gitコミットについての連絡先
|
||||
|
||||
https://groups.google.com/forum/#!forum/tmux-git
|
||||
|
||||
購読は<tmux-users+subscribe@googlegroups.com>までメールをお願いします。
|
||||
|
||||
バグレポートや機能追加(特にコードへの貢献)は大歓迎です。こちらにご連絡ください。
|
||||
|
||||
tmux-users@googlegroups.com
|
||||
|
||||
本ファイル、CHANGES、 FAQ、SYNCINGそしてTODOはISC licenseで保護されています。
|
||||
その他のファイルのライセンスや著作権については、ファイルの上部に明記されています。
|
||||
|
||||
-- Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
3
client.c
3
client.c
@@ -17,11 +17,10 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <event.h>
|
||||
|
||||
@@ -100,6 +100,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
s->cwd = format_single(item, cflag, c, s, wl, wp);
|
||||
}
|
||||
|
||||
c->last_session = c->session;
|
||||
if (c->session != NULL) {
|
||||
if (dflag) {
|
||||
TAILQ_FOREACH(c_loop, &clients, entry) {
|
||||
|
||||
@@ -53,7 +53,7 @@ static enum cmd_retval
|
||||
cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c;
|
||||
struct client *c, *target_c;
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
@@ -65,7 +65,6 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cmdq_error(item, "only one of -F or argument must be given");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
c = cmd_find_client(item, args_get(args, 'c'), 1);
|
||||
|
||||
template = args_get(args, 'F');
|
||||
if (args->argc != 0)
|
||||
@@ -73,8 +72,19 @@ cmd_display_message_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (template == NULL)
|
||||
template = DISPLAY_MESSAGE_TEMPLATE;
|
||||
|
||||
/*
|
||||
* -c is intended to be the client where the message should be
|
||||
* displayed if -p is not given. But it makes sense to use it for the
|
||||
* formats too, assuming it matches the session. If it doesn't, use the
|
||||
* best client for the session.
|
||||
*/
|
||||
c = cmd_find_client(item, args_get(args, 'c'), 1);
|
||||
if (c != NULL && c->session == s)
|
||||
target_c = c;
|
||||
else
|
||||
target_c = cmd_find_best_client(s);
|
||||
ft = format_create(item->client, item, FORMAT_NONE, 0);
|
||||
format_defaults(ft, c, s, wl, wp);
|
||||
format_defaults(ft, target_c, s, wl, wp);
|
||||
|
||||
msg = format_expand_time(ft, template, time(NULL));
|
||||
if (args_has(self->args, 'p'))
|
||||
|
||||
@@ -55,6 +55,7 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
|
||||
return (CMD_RETURN_ERROR);
|
||||
s = c->session;
|
||||
|
||||
if (c->identify_callback != NULL)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
@@ -64,7 +65,7 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||
c->identify_callback_data = xstrdup(args->argv[0]);
|
||||
else
|
||||
c->identify_callback_data = xstrdup("select-pane -t '%%'");
|
||||
s = c->session;
|
||||
c->identify_callback_item = item;
|
||||
|
||||
if (args_has(args, 'd')) {
|
||||
delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
|
||||
@@ -77,7 +78,7 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
|
||||
delay = options_get_number(s->options, "display-panes-time");
|
||||
server_client_set_identify(c, delay);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
@@ -96,34 +97,36 @@ cmd_display_panes_callback(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
struct cmd_list *cmdlist;
|
||||
struct cmdq_item *new_item;
|
||||
char *template, *cmd, *expanded, *cause;
|
||||
char *cmd, *expanded, *cause;
|
||||
|
||||
template = c->identify_callback_data;
|
||||
if (wp == NULL)
|
||||
goto out;
|
||||
|
||||
xasprintf(&expanded, "%%%u", wp->id);
|
||||
cmd = cmd_template_replace(template, expanded, 1);
|
||||
cmd = cmd_template_replace(c->identify_callback_data, expanded, 1);
|
||||
|
||||
cmdlist = cmd_string_parse(cmd, NULL, 0, &cause);
|
||||
if (cmdlist == NULL) {
|
||||
if (cause != NULL) {
|
||||
new_item = cmdq_get_callback(cmd_display_panes_error,
|
||||
cause);
|
||||
} else
|
||||
new_item = NULL;
|
||||
} else {
|
||||
if (cmdlist == NULL && cause != NULL)
|
||||
new_item = cmdq_get_callback(cmd_display_panes_error, cause);
|
||||
else if (cmdlist == NULL)
|
||||
new_item = NULL;
|
||||
else {
|
||||
new_item = cmdq_get_command(cmdlist, NULL, NULL, 0);
|
||||
cmd_list_free(cmdlist);
|
||||
}
|
||||
|
||||
if (new_item != NULL)
|
||||
cmdq_append(c, new_item);
|
||||
cmdq_insert_after(c->identify_callback_item, new_item);
|
||||
|
||||
free(cmd);
|
||||
free(expanded);
|
||||
|
||||
out:
|
||||
c->identify_callback_item->flags &= ~CMDQ_WAITING;
|
||||
c->identify_callback_item = NULL;
|
||||
|
||||
free(c->identify_callback_data);
|
||||
c->identify_callback_data = NULL;
|
||||
|
||||
c->identify_callback = NULL;
|
||||
}
|
||||
|
||||
49
cmd-find.c
49
cmd-find.c
@@ -34,6 +34,7 @@ static int cmd_find_best_winlink_with_window(struct cmd_find_state *);
|
||||
|
||||
static const char *cmd_find_map_table(const char *[][2], const char *);
|
||||
|
||||
static void cmd_find_log_state(const char *, struct cmd_find_state *);
|
||||
static int cmd_find_get_session(struct cmd_find_state *, const char *);
|
||||
static int cmd_find_get_window(struct cmd_find_state *, const char *, int);
|
||||
static int cmd_find_get_window_with_session(struct cmd_find_state *,
|
||||
@@ -82,6 +83,7 @@ cmd_find_try_TMUX(struct client *c)
|
||||
char tmp[256];
|
||||
long long pid;
|
||||
u_int session;
|
||||
struct session *s;
|
||||
|
||||
envent = environ_find(c->environ, "TMUX");
|
||||
if (envent == NULL)
|
||||
@@ -91,8 +93,13 @@ cmd_find_try_TMUX(struct client *c)
|
||||
return (NULL);
|
||||
if (pid != getpid())
|
||||
return (NULL);
|
||||
log_debug("client %p TMUX %s (session @%u)", c, envent->value, session);
|
||||
return (session_find_by_id(session));
|
||||
log_debug("%s: client %p TMUX %s (session $%u)", __func__, c,
|
||||
envent->value, session);
|
||||
|
||||
s = session_find_by_id(session);
|
||||
if (s != NULL)
|
||||
log_debug("%s: session $%u still exists", __func__, s->id);
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Find pane containing client if any. */
|
||||
@@ -105,9 +112,11 @@ cmd_find_inside_pane(struct client *c)
|
||||
return (NULL);
|
||||
|
||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
|
||||
if (strcmp(wp->tty, c->ttyname) == 0)
|
||||
if (wp->fd != -1 && strcmp(wp->tty, c->ttyname) == 0)
|
||||
break;
|
||||
}
|
||||
if (wp != NULL)
|
||||
log_debug("%s: got pane %%%u (%s)", __func__, wp->id, wp->tty);
|
||||
return (wp);
|
||||
}
|
||||
|
||||
@@ -121,7 +130,7 @@ cmd_find_client_better(struct client *c, struct client *than)
|
||||
}
|
||||
|
||||
/* Find best client for session. */
|
||||
static struct client *
|
||||
struct client *
|
||||
cmd_find_best_client(struct session *s)
|
||||
{
|
||||
struct client *c_loop, *c;
|
||||
@@ -166,6 +175,8 @@ cmd_find_best_session(struct session **slist, u_int ssize, int flags)
|
||||
struct session *s_loop, *s;
|
||||
u_int i;
|
||||
|
||||
log_debug("%s: %u sessions to try", __func__, ssize);
|
||||
|
||||
s = NULL;
|
||||
if (slist != NULL) {
|
||||
for (i = 0; i < ssize; i++) {
|
||||
@@ -189,6 +200,8 @@ cmd_find_best_session_with_window(struct cmd_find_state *fs)
|
||||
u_int ssize;
|
||||
struct session *s;
|
||||
|
||||
log_debug("%s: window is @%u", __func__, fs->w->id);
|
||||
|
||||
ssize = 0;
|
||||
RB_FOREACH(s, sessions, &sessions) {
|
||||
if (!session_has(s, fs->w))
|
||||
@@ -210,7 +223,7 @@ fail:
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the best winlink for a window (the current if it contains the pane,
|
||||
* Find the best winlink for a window (the current if it contains the window,
|
||||
* otherwise the first).
|
||||
*/
|
||||
static int
|
||||
@@ -218,6 +231,8 @@ cmd_find_best_winlink_with_window(struct cmd_find_state *fs)
|
||||
{
|
||||
struct winlink *wl, *wl_loop;
|
||||
|
||||
log_debug("%s: window is @%u", __func__, fs->w->id);
|
||||
|
||||
wl = NULL;
|
||||
if (fs->s->curw != NULL && fs->s->curw->window == fs->w)
|
||||
wl = fs->s->curw;
|
||||
@@ -436,15 +451,15 @@ cmd_find_get_window_with_session(struct cmd_find_state *fs, const char *window)
|
||||
if (window[0] != '+' && window[0] != '-') {
|
||||
idx = strtonum(window, 0, INT_MAX, &errstr);
|
||||
if (errstr == NULL) {
|
||||
if (fs->flags & CMD_FIND_WINDOW_INDEX) {
|
||||
fs->idx = idx;
|
||||
return (0);
|
||||
}
|
||||
fs->wl = winlink_find_by_index(&fs->s->windows, idx);
|
||||
if (fs->wl != NULL) {
|
||||
fs->w = fs->wl->window;
|
||||
return (0);
|
||||
}
|
||||
if (fs->flags & CMD_FIND_WINDOW_INDEX) {
|
||||
fs->idx = idx;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,11 +716,11 @@ cmd_find_copy_state(struct cmd_find_state *dst, struct cmd_find_state *src)
|
||||
}
|
||||
|
||||
/* Log the result. */
|
||||
void
|
||||
static void
|
||||
cmd_find_log_state(const char *prefix, struct cmd_find_state *fs)
|
||||
{
|
||||
if (fs->s != NULL)
|
||||
log_debug("%s: s=$%u", prefix, fs->s->id);
|
||||
log_debug("%s: s=$%u %s", prefix, fs->s->id, fs->s->name);
|
||||
else
|
||||
log_debug("%s: s=none", prefix);
|
||||
if (fs->wl != NULL) {
|
||||
@@ -894,6 +909,9 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
||||
break;
|
||||
}
|
||||
if (wl != NULL) {
|
||||
log_debug("%s: session $%u has pane %%%u", __func__,
|
||||
s->id, wp->id);
|
||||
|
||||
fs->s = s;
|
||||
fs->wl = s->curw; /* use current session */
|
||||
fs->w = fs->wl->window;
|
||||
@@ -901,6 +919,9 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
|
||||
|
||||
cmd_find_log_state(__func__, fs);
|
||||
return (0);
|
||||
} else {
|
||||
log_debug("%s: session $%u does not have pane %%%u",
|
||||
__func__, s->id, wp->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,7 +1162,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||
/* This will fill in winlink and window. */
|
||||
if (cmd_find_get_window_with_session(fs, window) != 0)
|
||||
goto no_window;
|
||||
fs->wp = fs->wl->window->active;
|
||||
if (fs->wl != NULL) /* can be NULL if index only */
|
||||
fs->wp = fs->wl->window->active;
|
||||
goto found;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1203,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||
/* This will fill in session, winlink and window. */
|
||||
if (cmd_find_get_window(fs, window, window_only) != 0)
|
||||
goto no_window;
|
||||
fs->wp = fs->wl->window->active;
|
||||
if (fs->wl != NULL) /* can be NULL if index only */
|
||||
fs->wp = fs->wl->window->active;
|
||||
goto found;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,14 +73,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
const char *cwd;
|
||||
|
||||
if (item->client != NULL && item->client->session == NULL)
|
||||
cwd = item->client->cwd;
|
||||
else if (s != NULL)
|
||||
cwd = s->cwd;
|
||||
else
|
||||
cwd = NULL;
|
||||
|
||||
shellcmd = format_single(item, args->argv[0], c, s, wl, wp);
|
||||
if (args_has(args, 'F')) {
|
||||
@@ -128,8 +120,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cdata->item = NULL;
|
||||
memcpy(&cdata->mouse, &shared->mouse, sizeof cdata->mouse);
|
||||
|
||||
job_run(shellcmd, s, cwd, NULL, cmd_if_shell_callback,
|
||||
cmd_if_shell_free, cdata, 0);
|
||||
job_run(shellcmd, s, server_client_get_cwd(item->client, s), NULL,
|
||||
cmd_if_shell_callback, cmd_if_shell_free, cdata, 0);
|
||||
free(shellcmd);
|
||||
|
||||
if (args_has(args, 'b'))
|
||||
|
||||
@@ -47,9 +47,8 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *loopwp, *tmpwp, *wp = item->target.wp;
|
||||
|
||||
server_unzoom_window(wl->window);
|
||||
|
||||
if (args_has(self->args, 'a')) {
|
||||
server_unzoom_window(wl->window);
|
||||
TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) {
|
||||
if (loopwp == wp)
|
||||
continue;
|
||||
@@ -60,13 +59,6 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (window_count_panes(wl->window) == 1) {
|
||||
server_kill_window(wl->window);
|
||||
recalculate_sizes();
|
||||
} else {
|
||||
layout_close_pane(wp);
|
||||
window_remove_pane(wl->window, wp);
|
||||
server_redraw_window(wl->window);
|
||||
}
|
||||
server_kill_pane(wp);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -75,10 +75,14 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
repeat = 0;
|
||||
tablewidth = keywidth = 0;
|
||||
RB_FOREACH(table, key_tables, &key_tables) {
|
||||
if (tablename != NULL && strcmp(table->name, tablename) != 0)
|
||||
table = key_bindings_first_table ();
|
||||
while (table != NULL) {
|
||||
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
|
||||
table = key_bindings_next_table(table);
|
||||
continue;
|
||||
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
|
||||
}
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
key = key_string_lookup_key(bd->key);
|
||||
|
||||
if (bd->flags & KEY_BINDING_REPEAT)
|
||||
@@ -90,13 +94,20 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
width = utf8_cstrwidth(key);
|
||||
if (width > keywidth)
|
||||
keywidth = width;
|
||||
|
||||
bd = key_bindings_next(table, bd);
|
||||
}
|
||||
table = key_bindings_next_table(table);
|
||||
}
|
||||
|
||||
RB_FOREACH(table, key_tables, &key_tables) {
|
||||
if (tablename != NULL && strcmp(table->name, tablename) != 0)
|
||||
table = key_bindings_first_table ();
|
||||
while (table != NULL) {
|
||||
if (tablename != NULL && strcmp(table->name, tablename) != 0) {
|
||||
table = key_bindings_next_table(table);
|
||||
continue;
|
||||
RB_FOREACH(bd, key_bindings, &table->key_bindings) {
|
||||
}
|
||||
bd = key_bindings_first(table);
|
||||
while (bd != NULL) {
|
||||
key = key_string_lookup_key(bd->key);
|
||||
|
||||
if (!repeat)
|
||||
@@ -122,7 +133,9 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
free(cp);
|
||||
|
||||
cmdq_print(item, "bind-key %s", tmp);
|
||||
bd = key_bindings_next(table, bd);
|
||||
}
|
||||
table = key_bindings_next_table(table);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -56,11 +56,14 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct cmd_load_buffer_data *cdata;
|
||||
struct client *c = item->client;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
FILE *f;
|
||||
const char *path, *bufname;
|
||||
const char *bufname;
|
||||
char *pdata = NULL, *new_pdata, *cause;
|
||||
char *file;
|
||||
char *path, *file;
|
||||
size_t psize;
|
||||
int ch, error;
|
||||
|
||||
@@ -68,8 +71,11 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (args_has(args, 'b'))
|
||||
bufname = args_get(args, 'b');
|
||||
|
||||
path = args->argv[0];
|
||||
path = format_single(item, args->argv[0], c, s, wl, wp);
|
||||
if (strcmp(path, "-") == 0) {
|
||||
free(path);
|
||||
c = item->client;
|
||||
|
||||
cdata = xcalloc(1, sizeof *cdata);
|
||||
cdata->item = item;
|
||||
|
||||
@@ -79,7 +85,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
error = server_set_stdin_callback(c, cmd_load_buffer_callback,
|
||||
cdata, &cause);
|
||||
if (error != 0) {
|
||||
cmdq_error(item, "%s: %s", path, cause);
|
||||
cmdq_error(item, "-: %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
@@ -87,6 +93,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
file = server_client_get_path(c, path);
|
||||
free(path);
|
||||
|
||||
f = fopen(file, "rb");
|
||||
if (f == NULL) {
|
||||
cmdq_error(item, "%s: %s", file, strerror(errno));
|
||||
|
||||
@@ -156,10 +156,8 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
/* Get the new session working directory. */
|
||||
if ((tmp = args_get(args, 'c')) != NULL)
|
||||
cwd = format_single(item, tmp, c, NULL, NULL, NULL);
|
||||
else if (c != NULL && c->session == NULL && c->cwd != NULL)
|
||||
cwd = xstrdup(c->cwd);
|
||||
else
|
||||
cwd = xstrdup(".");
|
||||
cwd = xstrdup(server_client_get_cwd(c, NULL));
|
||||
|
||||
/*
|
||||
* If this is a new client, check for nesting and save the termios
|
||||
@@ -204,17 +202,29 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
sy = 24;
|
||||
}
|
||||
if ((is_control || detached) && args_has(args, 'x')) {
|
||||
sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "width %s", errstr);
|
||||
goto error;
|
||||
tmp = args_get(args, 'x');
|
||||
if (strcmp(tmp, "-") == 0) {
|
||||
if (c != NULL)
|
||||
sx = c->tty.sx;
|
||||
} else {
|
||||
sx = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "width %s", errstr);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((is_control || detached) && args_has(args, 'y')) {
|
||||
sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "height %s", errstr);
|
||||
goto error;
|
||||
tmp = args_get(args, 'y');
|
||||
if (strcmp(tmp, "-") == 0) {
|
||||
if (c != NULL)
|
||||
sy = c->tty.sy;
|
||||
} else {
|
||||
sy = strtonum(tmp, 1, USHRT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(item, "height %s", errstr);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sx == 0)
|
||||
|
||||
@@ -63,7 +63,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct environ_entry *envent;
|
||||
struct cmd_find_state fs;
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
if (args_has(args, 'a') && wl != NULL) {
|
||||
if ((idx = winlink_shuffle_up(s, wl)) == -1) {
|
||||
cmdq_error(item, "no free window indexes");
|
||||
return (CMD_RETURN_ERROR);
|
||||
@@ -95,17 +95,14 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if ((tmp = args_get(args, 'c')) != NULL)
|
||||
cwd = format_single(item, tmp, c, s, NULL, NULL);
|
||||
else if (item->client != NULL && item->client->session == NULL)
|
||||
cwd = xstrdup(item->client->cwd);
|
||||
else
|
||||
cwd = xstrdup(s->cwd);
|
||||
cwd = xstrdup(server_client_get_cwd(item->client, s));
|
||||
|
||||
if ((tmp = args_get(args, 'n')) != NULL)
|
||||
name = format_single(item, tmp, c, s, NULL, NULL);
|
||||
else
|
||||
name = NULL;
|
||||
|
||||
wl = NULL;
|
||||
if (idx != -1)
|
||||
wl = winlink_find_by_index(&s->windows, idx);
|
||||
if (wl != NULL && args_has(args, 'k')) {
|
||||
|
||||
@@ -47,7 +47,7 @@ static enum cmd_retval
|
||||
cmd_rename_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmd_find_client(item, NULL, 0);
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct session *s = item->target.s;
|
||||
char *newname;
|
||||
|
||||
|
||||
@@ -129,14 +129,21 @@ static void
|
||||
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
|
||||
{
|
||||
struct winlink *wl;
|
||||
struct window_pane *loop, *wp_x, *wp_y;
|
||||
u_int y, ly, x, lx, sx, sy, ex, ey;
|
||||
struct window *w;
|
||||
u_int y, ly, x, lx;
|
||||
static const int offsets[][2] = {
|
||||
{ 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 },
|
||||
};
|
||||
struct layout_cell *cells[nitems(offsets)], *lc;
|
||||
u_int ncells = 0, i, j, resizes = 0;
|
||||
enum layout_type type;
|
||||
|
||||
wl = cmd_mouse_window(m, NULL);
|
||||
if (wl == NULL) {
|
||||
c->tty.mouse_drag_update = NULL;
|
||||
return;
|
||||
}
|
||||
w = wl->window;
|
||||
|
||||
y = m->y; x = m->x;
|
||||
if (m->statusat == 0 && y > 0)
|
||||
@@ -149,37 +156,37 @@ cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
|
||||
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
||||
ly = m->statusat - 1;
|
||||
|
||||
wp_x = wp_y = NULL;
|
||||
TAILQ_FOREACH(loop, &wl->window->panes, entry) {
|
||||
if (!window_pane_visible(loop))
|
||||
for (i = 0; i < nitems(cells); i++) {
|
||||
lc = layout_search_by_border(w->layout_root, lx + offsets[i][0],
|
||||
ly + offsets[i][1]);
|
||||
if (lc == NULL)
|
||||
continue;
|
||||
|
||||
sx = loop->xoff;
|
||||
if (sx != 0)
|
||||
sx--;
|
||||
ex = loop->xoff + loop->sx;
|
||||
for (j = 0; j < ncells; j++) {
|
||||
if (cells[j] == lc) {
|
||||
lc = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lc == NULL)
|
||||
continue;
|
||||
|
||||
sy = loop->yoff;
|
||||
if (sy != 0)
|
||||
sy--;
|
||||
ey = loop->yoff + loop->sy;
|
||||
|
||||
if ((lx == sx || lx == ex) &&
|
||||
(ly >= sy && ly <= ey) &&
|
||||
(wp_x == NULL || loop->sy > wp_x->sy))
|
||||
wp_x = loop;
|
||||
if ((ly == sy || ly == ey) &&
|
||||
(lx >= sx && lx <= ex) &&
|
||||
(wp_y == NULL || loop->sx > wp_y->sx))
|
||||
wp_y = loop;
|
||||
cells[ncells] = lc;
|
||||
ncells++;
|
||||
}
|
||||
if (wp_x == NULL && wp_y == NULL) {
|
||||
c->tty.mouse_drag_update = NULL;
|
||||
if (ncells == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ncells; i++) {
|
||||
type = cells[i]->parent->type;
|
||||
if (y != ly && type == LAYOUT_TOPBOTTOM) {
|
||||
layout_resize_layout(w, cells[i], type, y - ly, 0);
|
||||
resizes++;
|
||||
} else if (x != lx && type == LAYOUT_LEFTRIGHT) {
|
||||
layout_resize_layout(w, cells[i], type, x - lx, 0);
|
||||
resizes++;
|
||||
}
|
||||
}
|
||||
if (wp_x != NULL)
|
||||
layout_resize_pane(wp_x, LAYOUT_LEFTRIGHT, x - lx, 0);
|
||||
if (wp_y != NULL)
|
||||
layout_resize_pane(wp_y, LAYOUT_TOPBOTTOM, y - ly, 0);
|
||||
server_redraw_window(wl->window);
|
||||
if (resizes != 0)
|
||||
server_redraw_window(w);
|
||||
}
|
||||
|
||||
@@ -90,14 +90,6 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
const char *cwd;
|
||||
|
||||
if (item->client != NULL && item->client->session == NULL)
|
||||
cwd = item->client->cwd;
|
||||
else if (s != NULL)
|
||||
cwd = s->cwd;
|
||||
else
|
||||
cwd = NULL;
|
||||
|
||||
cdata = xcalloc(1, sizeof *cdata);
|
||||
cdata->cmd = format_single(item, args->argv[0], c, s, wl, wp);
|
||||
@@ -110,8 +102,8 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (!args_has(args, 'b'))
|
||||
cdata->item = item;
|
||||
|
||||
job_run(cdata->cmd, s, cwd, NULL, cmd_run_shell_callback,
|
||||
cmd_run_shell_free, cdata, 0);
|
||||
job_run(cdata->cmd, s, server_client_get_cwd(item->client, s), NULL,
|
||||
cmd_run_shell_callback, cmd_run_shell_free, cdata, 0);
|
||||
|
||||
if (args_has(args, 'b'))
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
@@ -59,11 +59,13 @@ static enum cmd_retval
|
||||
cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = item->client;
|
||||
struct client *c = cmd_find_client(item, NULL, 1);
|
||||
struct session *s = item->target.s;
|
||||
struct winlink *wl = item->target.wl;
|
||||
struct window_pane *wp = item->target.wp;
|
||||
struct paste_buffer *pb;
|
||||
const char *path, *bufname, *bufdata, *start, *end;
|
||||
const char *flags;
|
||||
char *msg, *file;
|
||||
const char *bufname, *bufdata, *start, *end, *flags;
|
||||
char *msg, *path, *file;
|
||||
size_t size, used, msglen, bufsize;
|
||||
FILE *f;
|
||||
|
||||
@@ -83,10 +85,12 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
bufdata = paste_buffer_data(pb, &bufsize);
|
||||
|
||||
if (self->entry == &cmd_show_buffer_entry)
|
||||
path = "-";
|
||||
path = xstrdup("-");
|
||||
else
|
||||
path = args->argv[0];
|
||||
path = format_single(item, args->argv[0], c, s, wl, wp);
|
||||
if (strcmp(path, "-") == 0) {
|
||||
free(path);
|
||||
c = item->client;
|
||||
if (c == NULL) {
|
||||
cmdq_error(item, "can't write to stdout");
|
||||
return (CMD_RETURN_ERROR);
|
||||
@@ -101,6 +105,8 @@ cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags = "ab";
|
||||
|
||||
file = server_client_get_path(c, path);
|
||||
free(path);
|
||||
|
||||
f = fopen(file, flags);
|
||||
if (f == NULL) {
|
||||
cmdq_error(item, "%s: %s", file, strerror(errno));
|
||||
|
||||
@@ -136,6 +136,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
|
||||
changed:
|
||||
free(oldlayout);
|
||||
server_redraw_window(w);
|
||||
notify_window("window-layout-changed", w);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
|
||||
@@ -69,6 +69,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
|
||||
lastwp = w->last;
|
||||
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);
|
||||
}
|
||||
if (lastwp == NULL) {
|
||||
cmdq_error(item, "no last pane");
|
||||
return (CMD_RETURN_ERROR);
|
||||
@@ -157,6 +162,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
screen_set_title(&wp->base, pane_title);
|
||||
server_status_window(wp->window);
|
||||
free(pane_title);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (wp == w->active)
|
||||
|
||||
@@ -61,7 +61,7 @@ cmd_send_keys_inject(struct client *c, struct cmdq_item *item, key_code key)
|
||||
struct window_pane *wp = item->target.wp;
|
||||
struct session *s = item->target.s;
|
||||
struct key_table *table;
|
||||
struct key_binding *bd, bd_find;
|
||||
struct key_binding *bd;
|
||||
|
||||
if (wp->mode == NULL || wp->mode->key_table == NULL) {
|
||||
if (options_get_number(wp->window->options, "xterm-keys"))
|
||||
@@ -71,8 +71,7 @@ cmd_send_keys_inject(struct client *c, struct cmdq_item *item, key_code key)
|
||||
}
|
||||
table = key_bindings_get_table(wp->mode->key_table(wp), 1);
|
||||
|
||||
bd_find.key = (key & ~KEYC_XTERM);
|
||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||
bd = key_bindings_get(table, key & ~KEYC_XTERM);
|
||||
if (bd != NULL) {
|
||||
table->references++;
|
||||
key_bindings_dispatch(bd, item, c, NULL, &item->target);
|
||||
|
||||
@@ -33,8 +33,8 @@ const struct cmd_entry cmd_set_hook_entry = {
|
||||
.name = "set-hook",
|
||||
.alias = NULL,
|
||||
|
||||
.args = { "gt:u", 1, 2 },
|
||||
.usage = "[-gu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
|
||||
.args = { "gRt:u", 1, 2 },
|
||||
.usage = "[-gRu] " CMD_TARGET_SESSION_USAGE " hook-name [command]",
|
||||
|
||||
.target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
|
||||
|
||||
@@ -101,18 +101,21 @@ cmd_set_hook_exec(struct cmd *self, struct cmdq_item *item)
|
||||
else
|
||||
cmd = args->argv[1];
|
||||
|
||||
if (cmd != NULL && (args_has(args, 'R') || args_has(args, 'u'))) {
|
||||
cmdq_error(item, "no command allowed");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (args_has(args, 'R')) {
|
||||
notify_hook(item, name);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (args_has(args, 'u')) {
|
||||
if (cmd != NULL) {
|
||||
cmdq_error(item, "command passed to unset hook: %s",
|
||||
name);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
hooks_remove(hooks, name);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (cmd == NULL) {
|
||||
cmdq_error(item, "no command to set hook: %s", name);
|
||||
cmdq_error(item, "no command given");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
cmdlist = cmd_string_parse(cmd, NULL, 0, &cause);
|
||||
|
||||
@@ -60,7 +60,7 @@ cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (*path == '/')
|
||||
pattern = xstrdup(path);
|
||||
else {
|
||||
utf8_stravis(&tmp, server_client_get_cwd(c), VIS_GLOB);
|
||||
utf8_stravis(&tmp, server_client_get_cwd(c, NULL), VIS_GLOB);
|
||||
xasprintf(&pattern, "%s/%s", tmp, path);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
@@ -87,10 +87,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
|
||||
if ((tmp = args_get(args, 'c')) != NULL)
|
||||
cwd = format_single(item, tmp, c, s, NULL, NULL);
|
||||
else if (item->client != NULL && item->client->session == NULL)
|
||||
cwd = xstrdup(item->client->cwd);
|
||||
else
|
||||
cwd = xstrdup(s->cwd);
|
||||
cwd = xstrdup(server_client_get_cwd(item->client, s));
|
||||
|
||||
type = LAYOUT_TOPBOTTOM;
|
||||
if (args_has(args, 'h'))
|
||||
|
||||
13
cmd.c
13
cmd.c
@@ -200,6 +200,15 @@ const struct cmd_entry *cmd_table[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
cmd_log_argv(int argc, char **argv, const char *prefix)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
log_debug("%s: argv[%d]=%s", prefix, i, argv[i]);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
||||
{
|
||||
@@ -208,6 +217,7 @@ cmd_pack_argv(int argc, char **argv, char *buf, size_t len)
|
||||
|
||||
if (argc == 0)
|
||||
return (0);
|
||||
cmd_log_argv(argc, argv, __func__);
|
||||
|
||||
*buf = '\0';
|
||||
for (i = 0; i < argc; i++) {
|
||||
@@ -240,9 +250,11 @@ cmd_unpack_argv(char *buf, size_t len, int argc, char ***argv)
|
||||
|
||||
arglen = strlen(buf) + 1;
|
||||
(*argv)[i] = xstrdup(buf);
|
||||
|
||||
buf += arglen;
|
||||
len -= arglen;
|
||||
}
|
||||
cmd_log_argv(argc, *argv, __func__);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -401,6 +413,7 @@ retry:
|
||||
xasprintf(cause, "unknown command: %s", name);
|
||||
return (NULL);
|
||||
}
|
||||
cmd_log_argv(argc, argv, entry->name);
|
||||
|
||||
args = args_parse(entry->args.template, argc, argv);
|
||||
if (args == NULL)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: imsg-buffer.c,v 1.10 2017/04/11 09:57:19 reyk Exp $ */
|
||||
/* $OpenBSD: imsg-buffer.c,v 1.11 2017/12/14 09:27:44 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@@ -29,9 +29,9 @@
|
||||
#include "compat.h"
|
||||
#include "imsg.h"
|
||||
|
||||
int ibuf_realloc(struct ibuf *, size_t);
|
||||
void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
||||
void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
||||
static int ibuf_realloc(struct ibuf *, size_t);
|
||||
static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
|
||||
static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
|
||||
|
||||
struct ibuf *
|
||||
ibuf_open(size_t len)
|
||||
@@ -67,7 +67,7 @@ ibuf_dynamic(size_t len, size_t max)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ibuf_realloc(struct ibuf *buf, size_t len)
|
||||
{
|
||||
u_char *b;
|
||||
@@ -289,14 +289,14 @@ again:
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
|
||||
msgbuf->queued++;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
|
||||
{
|
||||
TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: imsg.c,v 1.15 2017/04/11 09:57:19 reyk Exp $ */
|
||||
/* $OpenBSD: imsg.c,v 1.16 2017/12/14 09:27:44 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
int imsg_fd_overhead = 0;
|
||||
|
||||
int imsg_get_fd(struct imsgbuf *);
|
||||
static int imsg_get_fd(struct imsgbuf *);
|
||||
|
||||
void
|
||||
imsg_init(struct imsgbuf *ibuf, int fd)
|
||||
@@ -266,7 +266,7 @@ imsg_free(struct imsg *imsg)
|
||||
freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
imsg_get_fd(struct imsgbuf *ibuf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
13
configure.ac
13
configure.ac
@@ -1,6 +1,6 @@
|
||||
# configure.ac
|
||||
|
||||
AC_INIT(tmux, 2.7-rc)
|
||||
AC_INIT(tmux, 2.8)
|
||||
AC_PREREQ([2.60])
|
||||
|
||||
AC_CONFIG_AUX_DIR(etc)
|
||||
@@ -610,7 +610,16 @@ case "$host_os" in
|
||||
*solaris*)
|
||||
AC_MSG_RESULT(sunos)
|
||||
PLATFORM=sunos
|
||||
MANFORMAT=man
|
||||
case `/usr/bin/nroff --version 2>&1` in
|
||||
*GNU*)
|
||||
# Solaris 11.4 and later use GNU groff.
|
||||
MANFORMAT=mdoc
|
||||
;;
|
||||
*)
|
||||
# Solaris 2.0 to 11.3 use AT&T nroff.
|
||||
MANFORMAT=man
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*hpux*)
|
||||
AC_MSG_RESULT(hpux)
|
||||
|
||||
79
format.c
79
format.c
@@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <libgen.h>
|
||||
@@ -562,11 +563,11 @@ format_cb_history_bytes(struct format_tree *ft, struct format_entry *fe)
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < gd->hsize; i++) {
|
||||
gl = &gd->linedata[i];
|
||||
gl = grid_get_line(gd, i);
|
||||
size += gl->cellsize * sizeof *gl->celldata;
|
||||
size += gl->extdsize * sizeof *gl->extddata;
|
||||
}
|
||||
size += gd->hsize * sizeof *gd->linedata;
|
||||
size += gd->hsize * sizeof *gl;
|
||||
|
||||
xasprintf(&fe->value, "%llu", size);
|
||||
}
|
||||
@@ -853,18 +854,22 @@ found:
|
||||
return (copy);
|
||||
}
|
||||
|
||||
/* Skip until comma. */
|
||||
static char *
|
||||
format_skip(char *s)
|
||||
/* Skip until end. */
|
||||
static const char *
|
||||
format_skip(const char *s, char end)
|
||||
{
|
||||
int brackets = 0;
|
||||
|
||||
for (; *s != '\0'; s++) {
|
||||
if (*s == '{')
|
||||
if (*s == '#' && s[1] == '{')
|
||||
brackets++;
|
||||
if (*s == '#' && strchr(",#{}", s[1]) != NULL) {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
if (*s == '}')
|
||||
brackets--;
|
||||
if (*s == ',' && brackets == 0)
|
||||
if (*s == end && brackets == 0)
|
||||
break;
|
||||
}
|
||||
if (*s == '\0')
|
||||
@@ -878,7 +883,7 @@ format_choose(char *s, char **left, char **right)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
cp = format_skip(s);
|
||||
cp = (char *)format_skip(s, ',');
|
||||
if (cp == NULL)
|
||||
return (-1);
|
||||
*cp = '\0';
|
||||
@@ -903,11 +908,12 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
char **buf, size_t *len, size_t *off)
|
||||
{
|
||||
struct window_pane *wp = ft->wp;
|
||||
char *copy, *copy0, *endptr, *ptr, *found, *new;
|
||||
char *copy, *copy0, *endptr, *ptr, *found, *new, sep;
|
||||
char *value, *from = NULL, *to = NULL, *left, *right;
|
||||
size_t valuelen, newlen, fromlen, tolen, used;
|
||||
long limit = 0;
|
||||
int modifiers = 0, compare = 0, search = 0;
|
||||
int literal = 0;
|
||||
|
||||
/* Make a copy of the key. */
|
||||
copy0 = copy = xmalloc(keylen + 1);
|
||||
@@ -916,6 +922,12 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
|
||||
/* Is there a length limit or whatnot? */
|
||||
switch (copy[0]) {
|
||||
case 'l':
|
||||
if (copy[1] != ':')
|
||||
break;
|
||||
literal = 1;
|
||||
copy += 2;
|
||||
break;
|
||||
case 'm':
|
||||
if (copy[1] != ':')
|
||||
break;
|
||||
@@ -980,20 +992,21 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
copy += 2;
|
||||
break;
|
||||
case 's':
|
||||
if (copy[1] != '/')
|
||||
sep = copy[1];
|
||||
if (sep == ':' || !ispunct((u_char)sep))
|
||||
break;
|
||||
from = copy + 2;
|
||||
for (copy = from; *copy != '\0' && *copy != '/'; copy++)
|
||||
for (copy = from; *copy != '\0' && *copy != sep; copy++)
|
||||
/* nothing */;
|
||||
if (copy[0] != '/' || copy == from) {
|
||||
if (copy[0] != sep || copy == from) {
|
||||
copy = copy0;
|
||||
break;
|
||||
}
|
||||
copy[0] = '\0';
|
||||
to = copy + 1;
|
||||
for (copy = to; *copy != '\0' && *copy != '/'; copy++)
|
||||
for (copy = to; *copy != '\0' && *copy != sep; copy++)
|
||||
/* nothing */;
|
||||
if (copy[0] != '/' || copy[1] != ':') {
|
||||
if (copy[0] != sep || copy[1] != ':') {
|
||||
copy = copy0;
|
||||
break;
|
||||
}
|
||||
@@ -1004,6 +1017,12 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is this a literal string? */
|
||||
if (literal) {
|
||||
value = xstrdup(copy);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Is this a comparison or a conditional? */
|
||||
if (search) {
|
||||
/* Search in pane. */
|
||||
@@ -1035,14 +1054,24 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
free(left);
|
||||
} else if (*copy == '?') {
|
||||
/* Conditional: check first and choose second or third. */
|
||||
ptr = format_skip(copy);
|
||||
ptr = (char *)format_skip(copy, ',');
|
||||
if (ptr == NULL)
|
||||
goto fail;
|
||||
*ptr = '\0';
|
||||
|
||||
found = format_find(ft, copy + 1, modifiers);
|
||||
if (found == NULL)
|
||||
if (found == NULL) {
|
||||
/*
|
||||
* If the conditional not found, try to expand it. If
|
||||
* the expansion doesn't have any effect, then assume
|
||||
* false.
|
||||
*/
|
||||
found = format_expand(ft, copy + 1);
|
||||
if (strcmp(found, copy + 1) == 0) {
|
||||
free(found);
|
||||
found = xstrdup("");
|
||||
}
|
||||
}
|
||||
if (format_choose(ptr + 1, &left, &right) != 0)
|
||||
goto fail;
|
||||
|
||||
@@ -1097,6 +1126,7 @@ format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
value = new;
|
||||
}
|
||||
|
||||
done:
|
||||
/* Expand the buffer and copy in the value. */
|
||||
valuelen = strlen(value);
|
||||
while (*len - *off < valuelen + 1) {
|
||||
@@ -1195,14 +1225,8 @@ format_expand(struct format_tree *ft, const char *fmt)
|
||||
fmt += n + 1;
|
||||
continue;
|
||||
case '{':
|
||||
brackets = 1;
|
||||
for (ptr = fmt; *ptr != '\0'; ptr++) {
|
||||
if (*ptr == '{')
|
||||
brackets++;
|
||||
if (*ptr == '}' && --brackets == 0)
|
||||
break;
|
||||
}
|
||||
if (*ptr != '}' || brackets != 0)
|
||||
ptr = format_skip(fmt - 2, '}');
|
||||
if (ptr == NULL)
|
||||
break;
|
||||
n = ptr - fmt;
|
||||
|
||||
@@ -1210,12 +1234,14 @@ format_expand(struct format_tree *ft, const char *fmt)
|
||||
break;
|
||||
fmt += n + 1;
|
||||
continue;
|
||||
case '}':
|
||||
case '#':
|
||||
case ',':
|
||||
while (len - off < 2) {
|
||||
buf = xreallocarray(buf, 2, len);
|
||||
len *= 2;
|
||||
}
|
||||
buf[off++] = '#';
|
||||
buf[off++] = ch;
|
||||
continue;
|
||||
default:
|
||||
s = NULL;
|
||||
@@ -1270,6 +1296,9 @@ void
|
||||
format_defaults(struct format_tree *ft, struct client *c, struct session *s,
|
||||
struct winlink *wl, struct window_pane *wp)
|
||||
{
|
||||
if (c != NULL && s != NULL && c->session != s)
|
||||
log_debug("%s: session does not match", __func__);
|
||||
|
||||
format_add(ft, "session_format", "%d", s != NULL);
|
||||
format_add(ft, "window_format", "%d", wl != NULL);
|
||||
format_add(ft, "pane_format", "%d", wp != NULL);
|
||||
|
||||
@@ -64,7 +64,7 @@ grid_view_clear_history(struct grid *gd, u_int bg)
|
||||
/* Find the last used line. */
|
||||
last = 0;
|
||||
for (yy = 0; yy < gd->sy; yy++) {
|
||||
gl = &gd->linedata[grid_view_y(gd, yy)];
|
||||
gl = grid_get_line(gd, grid_view_y(gd, yy));
|
||||
if (gl->cellused != 0)
|
||||
last = yy + 1;
|
||||
}
|
||||
|
||||
69
grid.c
69
grid.c
@@ -145,6 +145,20 @@ grid_extended_cell(struct grid_line *gl, struct grid_cell_entry *gce,
|
||||
return (gcp);
|
||||
}
|
||||
|
||||
/* Get line data. */
|
||||
struct grid_line *
|
||||
grid_get_line(struct grid *gd, u_int line)
|
||||
{
|
||||
return (&gd->linedata[line]);
|
||||
}
|
||||
|
||||
/* Adjust number of lines. */
|
||||
void
|
||||
grid_adjust_lines(struct grid *gd, u_int lines)
|
||||
{
|
||||
gd->linedata = xreallocarray(gd->linedata, lines, sizeof *gd->linedata);
|
||||
}
|
||||
|
||||
/* Copy default into a cell. */
|
||||
static void
|
||||
grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
|
||||
@@ -166,10 +180,10 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg)
|
||||
|
||||
/* Check grid y position. */
|
||||
static int
|
||||
grid_check_y(struct grid *gd, u_int py)
|
||||
grid_check_y(struct grid *gd, const char* from, u_int py)
|
||||
{
|
||||
if (py >= gd->hsize + gd->sy) {
|
||||
log_debug("y out of range: %u", py);
|
||||
log_debug("%s: y out of range: %u", from, py);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
@@ -272,6 +286,15 @@ grid_compare(struct grid *ga, struct grid *gb)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Trim lines from the history. */
|
||||
static void
|
||||
grid_trim_history(struct grid *gd, u_int ny)
|
||||
{
|
||||
grid_free_lines(gd, 0, ny);
|
||||
memmove(&gd->linedata[0], &gd->linedata[ny],
|
||||
(gd->hsize + gd->sy - ny) * (sizeof *gd->linedata));
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect lines from the history if at the limit. Free the top (oldest) 10%
|
||||
* and shift up.
|
||||
@@ -294,9 +317,7 @@ grid_collect_history(struct grid *gd)
|
||||
* Free the lines from 0 to ny then move the remaining lines over
|
||||
* them.
|
||||
*/
|
||||
grid_free_lines(gd, 0, ny);
|
||||
memmove(&gd->linedata[0], &gd->linedata[ny],
|
||||
(gd->hsize + gd->sy - ny) * (sizeof *gd->linedata));
|
||||
grid_trim_history(gd, ny);
|
||||
|
||||
gd->hsize -= ny;
|
||||
if (gd->hscrolled > gd->hsize)
|
||||
@@ -326,9 +347,7 @@ grid_scroll_history(struct grid *gd, u_int bg)
|
||||
void
|
||||
grid_clear_history(struct grid *gd)
|
||||
{
|
||||
grid_free_lines(gd, 0, gd->hsize);
|
||||
memmove(&gd->linedata[0], &gd->linedata[gd->hsize],
|
||||
gd->sy * (sizeof *gd->linedata));
|
||||
grid_trim_history(gd, gd->hsize);
|
||||
|
||||
gd->hscrolled = 0;
|
||||
gd->hsize = 0;
|
||||
@@ -407,7 +426,7 @@ grid_empty_line(struct grid *gd, u_int py, u_int bg)
|
||||
const struct grid_line *
|
||||
grid_peek_line(struct grid *gd, u_int py)
|
||||
{
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return (NULL);
|
||||
return (&gd->linedata[py]);
|
||||
}
|
||||
@@ -441,7 +460,8 @@ grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
||||
void
|
||||
grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
|
||||
{
|
||||
if (grid_check_y(gd, py) != 0 || px >= gd->linedata[py].cellsize) {
|
||||
if (grid_check_y(gd, __func__, py) != 0 ||
|
||||
px >= gd->linedata[py].cellsize) {
|
||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||
return;
|
||||
}
|
||||
@@ -455,7 +475,7 @@ grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
struct grid_line *gl;
|
||||
struct grid_cell_entry *gce;
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
|
||||
grid_expand_line(gd, py, px + 1, 8);
|
||||
@@ -481,7 +501,7 @@ grid_set_cells(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc,
|
||||
struct grid_cell *gcp;
|
||||
u_int i;
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
|
||||
grid_expand_line(gd, py, px + slen, 8);
|
||||
@@ -514,9 +534,9 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, py + ny - 1) != 0)
|
||||
if (grid_check_y(gd, __func__, py + ny - 1) != 0)
|
||||
return;
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
@@ -543,9 +563,9 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg)
|
||||
if (ny == 0)
|
||||
return;
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, py + ny - 1) != 0)
|
||||
if (grid_check_y(gd, __func__, py + ny - 1) != 0)
|
||||
return;
|
||||
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
@@ -563,13 +583,13 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg)
|
||||
if (ny == 0 || py == dy)
|
||||
return;
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, py + ny - 1) != 0)
|
||||
if (grid_check_y(gd, __func__, py + ny - 1) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, dy) != 0)
|
||||
if (grid_check_y(gd, __func__, dy) != 0)
|
||||
return;
|
||||
if (grid_check_y(gd, dy + ny - 1) != 0)
|
||||
if (grid_check_y(gd, __func__, dy + ny - 1) != 0)
|
||||
return;
|
||||
|
||||
/* Free any lines which are being replaced. */
|
||||
@@ -603,7 +623,7 @@ grid_move_cells(struct grid *gd, u_int dx, u_int px, u_int py, u_int nx,
|
||||
if (nx == 0 || px == dx)
|
||||
return;
|
||||
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
if (grid_check_y(gd, __func__, py) != 0)
|
||||
return;
|
||||
gl = &gd->linedata[py];
|
||||
|
||||
@@ -983,9 +1003,9 @@ static void
|
||||
grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
|
||||
u_int width, u_int *cy, int already)
|
||||
{
|
||||
struct grid_line *gl, *from;
|
||||
struct grid_line *gl, *from = NULL;
|
||||
struct grid_cell gc;
|
||||
u_int lines, want, left, i, to, line;
|
||||
u_int lines, left, i, to, line, want = 0;
|
||||
u_int at;
|
||||
int wrapped = 1;
|
||||
|
||||
@@ -1010,7 +1030,7 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
|
||||
* If this is now the last line, there is nothing more to be
|
||||
* done.
|
||||
*/
|
||||
if (yy + lines == gd->hsize + gd->sy)
|
||||
if (yy + 1 + lines == gd->hsize + gd->sy)
|
||||
break;
|
||||
line = yy + 1 + lines;
|
||||
|
||||
@@ -1020,6 +1040,7 @@ grid_reflow_join(struct grid *target, struct grid *gd, u_int sx, u_int yy,
|
||||
if (gd->linedata[line].cellused == 0) {
|
||||
if (!wrapped)
|
||||
break;
|
||||
lines++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
30
input.c
30
input.c
@@ -30,7 +30,7 @@
|
||||
/*
|
||||
* Based on the description by Paul Williams at:
|
||||
*
|
||||
* http://vt100.net/emu/dec_ansi_parser
|
||||
* https://vt100.net/emu/dec_ansi_parser
|
||||
*
|
||||
* With the following changes:
|
||||
*
|
||||
@@ -1188,6 +1188,7 @@ input_esc_dispatch(struct input_ctx *ictx)
|
||||
window_pane_reset_palette(ictx->wp);
|
||||
input_reset_cell(ictx);
|
||||
screen_write_reset(sctx);
|
||||
screen_write_clearhistory(sctx);
|
||||
break;
|
||||
case INPUT_ESC_IND:
|
||||
screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
|
||||
@@ -1845,10 +1846,12 @@ input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
|
||||
|
||||
ptr = copy = xstrdup(s);
|
||||
while ((out = strsep(&ptr, ":")) != NULL) {
|
||||
p[n++] = strtonum(out, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL || n == nitems(p)) {
|
||||
free(copy);
|
||||
return;
|
||||
if (*out != '\0') {
|
||||
p[n++] = strtonum(out, 0, INT_MAX, &errstr);
|
||||
if (errstr != NULL || n == nitems(p)) {
|
||||
free(copy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
log_debug("%s: %u = %d", __func__, n - 1, p[n - 1]);
|
||||
}
|
||||
@@ -1856,16 +1859,21 @@ input_csi_dispatch_sgr_colon(struct input_ctx *ictx, u_int i)
|
||||
|
||||
if (n == 0 || (p[0] != 38 && p[0] != 48))
|
||||
return;
|
||||
switch (p[1]) {
|
||||
if (p[1] == -1)
|
||||
i = 2;
|
||||
else
|
||||
i = 1;
|
||||
switch (p[i]) {
|
||||
case 2:
|
||||
if (n != 5)
|
||||
if (n < i + 4)
|
||||
break;
|
||||
input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[2], p[3], p[4]);
|
||||
input_csi_dispatch_sgr_rgb_do(ictx, p[0], p[i + 1], p[i + 2],
|
||||
p[i + 3]);
|
||||
break;
|
||||
case 5:
|
||||
if (n != 3)
|
||||
if (n < i + 2)
|
||||
break;
|
||||
input_csi_dispatch_sgr_256_do(ictx, p[0], p[2]);
|
||||
input_csi_dispatch_sgr_256_do(ictx, p[0], p[i + 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2227,7 +2235,7 @@ bad:
|
||||
free(copy);
|
||||
}
|
||||
|
||||
/* Handle the OSC 10 sequence for setting background colour. */
|
||||
/* Handle the OSC 10 sequence for setting foreground colour. */
|
||||
static void
|
||||
input_osc_10(struct window_pane *wp, const char *p)
|
||||
{
|
||||
|
||||
@@ -24,17 +24,19 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp);
|
||||
RB_GENERATE(key_tables, key_table, entry, key_table_cmp);
|
||||
struct key_tables key_tables = RB_INITIALIZER(&key_tables);
|
||||
static int key_bindings_cmp(struct key_binding *, struct key_binding *);
|
||||
RB_GENERATE_STATIC(key_bindings, key_binding, entry, key_bindings_cmp);
|
||||
static int key_table_cmp(struct key_table *, struct key_table *);
|
||||
RB_GENERATE_STATIC(key_tables, key_table, entry, key_table_cmp);
|
||||
static struct key_tables key_tables = RB_INITIALIZER(&key_tables);
|
||||
|
||||
int
|
||||
key_table_cmp(struct key_table *e1, struct key_table *e2)
|
||||
static int
|
||||
key_table_cmp(struct key_table *table1, struct key_table *table2)
|
||||
{
|
||||
return (strcmp(e1->name, e2->name));
|
||||
return (strcmp(table1->name, table2->name));
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2)
|
||||
{
|
||||
if (bd1->key < bd2->key)
|
||||
@@ -64,6 +66,18 @@ key_bindings_get_table(const char *name, int create)
|
||||
return (table);
|
||||
}
|
||||
|
||||
struct key_table *
|
||||
key_bindings_first_table(void)
|
||||
{
|
||||
return (RB_MIN(key_tables, &key_tables));
|
||||
}
|
||||
|
||||
struct key_table *
|
||||
key_bindings_next_table(struct key_table *table)
|
||||
{
|
||||
return (RB_NEXT(key_tables, &key_tables, table));
|
||||
}
|
||||
|
||||
void
|
||||
key_bindings_unref_table(struct key_table *table)
|
||||
{
|
||||
@@ -83,6 +97,27 @@ key_bindings_unref_table(struct key_table *table)
|
||||
free(table);
|
||||
}
|
||||
|
||||
struct key_binding *
|
||||
key_bindings_get(struct key_table *table, key_code key)
|
||||
{
|
||||
struct key_binding bd;
|
||||
|
||||
bd.key = key;
|
||||
return (RB_FIND(key_bindings, &table->key_bindings, &bd));
|
||||
}
|
||||
|
||||
struct key_binding *
|
||||
key_bindings_first(struct key_table *table)
|
||||
{
|
||||
return (RB_MIN(key_bindings, &table->key_bindings));
|
||||
}
|
||||
|
||||
struct key_binding *
|
||||
key_bindings_next(__unused struct key_table *table, struct key_binding *bd)
|
||||
{
|
||||
return (RB_NEXT(key_bindings, &table->key_bindings, bd));
|
||||
}
|
||||
|
||||
void
|
||||
key_bindings_add(const char *name, key_code key, int repeat,
|
||||
struct cmd_list *cmdlist)
|
||||
|
||||
@@ -166,9 +166,11 @@ key_string_lookup_string(const char *string)
|
||||
enum utf8_state more;
|
||||
wchar_t wc;
|
||||
|
||||
/* Is this no key? */
|
||||
/* Is this no key or any key? */
|
||||
if (strcasecmp(string, "None") == 0)
|
||||
return (KEYC_NONE);
|
||||
if (strcasecmp(string, "Any") == 0)
|
||||
return (KEYC_ANY);
|
||||
|
||||
/* Is this a hexadecimal value? */
|
||||
if (string[0] == '0' && string[1] == 'x') {
|
||||
@@ -251,6 +253,8 @@ key_string_lookup_key(key_code key)
|
||||
/* Handle special keys. */
|
||||
if (key == KEYC_UNKNOWN)
|
||||
return ("Unknown");
|
||||
if (key == KEYC_ANY)
|
||||
return ("Any");
|
||||
if (key == KEYC_FOCUS_IN)
|
||||
return ("FocusIn");
|
||||
if (key == KEYC_FOCUS_OUT)
|
||||
|
||||
91
layout.c
91
layout.c
@@ -127,6 +127,42 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
||||
}
|
||||
}
|
||||
|
||||
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 (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));
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
last = lcchild;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (x < lcchild->xoff && x >= last->xoff + last->sx)
|
||||
return (last);
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (y < lcchild->yoff && y >= last->yoff + last->sy)
|
||||
return (last);
|
||||
break;
|
||||
case LAYOUT_WINDOWPANE:
|
||||
break;
|
||||
}
|
||||
|
||||
last = lcchild;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void
|
||||
layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, u_int xoff,
|
||||
u_int yoff)
|
||||
@@ -550,29 +586,11 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type,
|
||||
layout_resize_pane(wp, type, change, 1);
|
||||
}
|
||||
|
||||
/* Resize a single pane within the layout. */
|
||||
void
|
||||
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
||||
int opposite)
|
||||
layout_resize_layout(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, int change, int opposite)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
struct layout_cell *lc, *lcparent;
|
||||
int needed, size;
|
||||
|
||||
lc = wp->layout_cell;
|
||||
|
||||
/* Find next parent of the same type. */
|
||||
lcparent = lc->parent;
|
||||
while (lcparent != NULL && lcparent->type != type) {
|
||||
lc = lcparent;
|
||||
lcparent = lc->parent;
|
||||
}
|
||||
if (lcparent == NULL)
|
||||
return;
|
||||
|
||||
/* If this is the last cell, move back one. */
|
||||
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
|
||||
lc = TAILQ_PREV(lc, layout_cells, entry);
|
||||
int needed, size;
|
||||
|
||||
/* Grow or shrink the cell. */
|
||||
needed = change;
|
||||
@@ -591,9 +609,34 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
||||
}
|
||||
|
||||
/* Fix cell offsets. */
|
||||
layout_fix_offsets(wp->window->layout_root);
|
||||
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
|
||||
notify_window("window-layout-changed", wp->window);
|
||||
layout_fix_offsets(w->layout_root);
|
||||
layout_fix_panes(w, w->sx, w->sy);
|
||||
notify_window("window-layout-changed", w);
|
||||
}
|
||||
|
||||
/* Resize a single pane within the layout. */
|
||||
void
|
||||
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change,
|
||||
int opposite)
|
||||
{
|
||||
struct layout_cell *lc, *lcparent;
|
||||
|
||||
lc = wp->layout_cell;
|
||||
|
||||
/* Find next parent of the same type. */
|
||||
lcparent = lc->parent;
|
||||
while (lcparent != NULL && lcparent->type != type) {
|
||||
lc = lcparent;
|
||||
lcparent = lc->parent;
|
||||
}
|
||||
if (lcparent == NULL)
|
||||
return;
|
||||
|
||||
/* If this is the last cell, move back one. */
|
||||
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
|
||||
lc = TAILQ_PREV(lc, layout_cells, entry);
|
||||
|
||||
layout_resize_layout(wp->window, lc, type, change, opposite);
|
||||
}
|
||||
|
||||
/* Helper function to grow pane. */
|
||||
|
||||
@@ -192,7 +192,7 @@ mode_tree_clear_tagged(struct mode_tree_list *mtl)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
mode_tree_up(struct mode_tree_data *mtd, int wrap)
|
||||
{
|
||||
if (mtd->current == 0) {
|
||||
|
||||
22
notify.c
22
notify.c
@@ -35,7 +35,7 @@ struct notify_entry {
|
||||
};
|
||||
|
||||
static void
|
||||
notify_hook(struct cmdq_item *item, struct notify_entry *ne)
|
||||
notify_hook1(struct cmdq_item *item, struct notify_entry *ne)
|
||||
{
|
||||
struct cmd_find_state fs;
|
||||
struct hook *hook;
|
||||
@@ -101,7 +101,7 @@ notify_callback(struct cmdq_item *item, void *data)
|
||||
if (strcmp(ne->name, "session-window-changed") == 0)
|
||||
control_notify_session_window_changed(ne->session);
|
||||
|
||||
notify_hook(item, ne);
|
||||
notify_hook1(item, ne);
|
||||
|
||||
if (ne->client != NULL)
|
||||
server_client_unref(ne->client);
|
||||
@@ -153,6 +153,24 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c,
|
||||
cmdq_append(NULL, new_item);
|
||||
}
|
||||
|
||||
void
|
||||
notify_hook(struct cmdq_item *item, const char *name)
|
||||
{
|
||||
struct notify_entry ne;
|
||||
|
||||
memset(&ne, 0, sizeof ne);
|
||||
|
||||
ne.name = name;
|
||||
cmd_find_copy_state(&ne.fs, &item->target);
|
||||
|
||||
ne.client = item->client;
|
||||
ne.session = item->target.s;
|
||||
ne.window = item->target.w;
|
||||
ne.pane = item->target.wp->id;
|
||||
|
||||
notify_hook1(item, &ne);
|
||||
}
|
||||
|
||||
void
|
||||
notify_input(struct window_pane *wp, struct evbuffer *input)
|
||||
{
|
||||
|
||||
@@ -513,8 +513,8 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "update-environment",
|
||||
.type = OPTIONS_TABLE_ARRAY,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "DISPLAY SSH_ASKPASS SSH_AUTH_SOCK SSH_AGENT_PID "
|
||||
"SSH_CONNECTION WINDOWID XAUTHORITY"
|
||||
.default_str = "DISPLAY KRB5CCNAME SSH_ASKPASS SSH_AUTH_SOCK "
|
||||
"SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY"
|
||||
},
|
||||
|
||||
{ .name = "visual-activity",
|
||||
|
||||
183
regress/format-strings.sh
Normal file
183
regress/format-strings.sh
Normal file
@@ -0,0 +1,183 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Tests of formats as described in tmux(1) FORMATS
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
|
||||
# test_format $format $expected_result
|
||||
test_format()
|
||||
{
|
||||
fmt="$1"
|
||||
exp="$2"
|
||||
|
||||
out=$($TMUX display-message -p "$fmt")
|
||||
|
||||
if [ "$out" != "$exp" ]; then
|
||||
echo "Format test failed for '$fmt'."
|
||||
echo "Expected: '$exp'"
|
||||
echo "But got '$out'"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# test_conditional_with_pane_in_mode $format $exp1 $exp2
|
||||
#
|
||||
# Tests the format string $format to yield $exp1 if #{pane_in_mode} is true and
|
||||
# $exp2 when #{pane_in_mode} is false.
|
||||
test_conditional_with_pane_in_mode()
|
||||
{
|
||||
fmt="$1"
|
||||
exp_true="$2"
|
||||
exp_false="$3"
|
||||
|
||||
$TMUX copy-mode # enter copy mode
|
||||
test_format "$fmt" "$exp_true"
|
||||
$TMUX send-keys -X cancel # leave copy mode
|
||||
test_format "$fmt" "$exp_false"
|
||||
}
|
||||
|
||||
# test_conditional_with_session_name #format $exp_summer $exp_winter
|
||||
#
|
||||
# Tests the format string $format to yield $exp_summer if the session name is
|
||||
# 'Summer' and $exp_winter if the session name is 'Winter'.
|
||||
test_conditional_with_session_name()
|
||||
{
|
||||
fmt="$1"
|
||||
exp_summer="$2"
|
||||
exp_winter="$3"
|
||||
|
||||
$TMUX rename-session "Summer"
|
||||
test_format "$fmt" "$exp_summer"
|
||||
$TMUX rename-session "Winter"
|
||||
test_format "$fmt" "$exp_winter"
|
||||
$TMUX rename-session "Summer" # restore default
|
||||
}
|
||||
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX -f/dev/null new-session -d || exit 1
|
||||
$TMUX rename-session "Summer" || exit 1 # used later in conditionals
|
||||
|
||||
# Plain string without substitutions et al
|
||||
test_format "abc xyz" "abc xyz"
|
||||
|
||||
# Test basic escapes for "#", "{", "#{" "}", "#}", ","
|
||||
test_format "##" "#"
|
||||
test_format "#," ","
|
||||
test_format "{" "{"
|
||||
test_format "##{" "#{"
|
||||
test_format "#}" "}"
|
||||
test_format "###}" "#}" # not a "basic" one but interesting nevertheless
|
||||
|
||||
# Simple expansion
|
||||
test_format "#{pane_in_mode}" "0"
|
||||
|
||||
# Simple conditionals
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,xyz}" "abc" "xyz"
|
||||
|
||||
# Expansion in conditionals
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#{session_name},xyz}" "Summer" "xyz"
|
||||
|
||||
# Basic escapes in conditionals
|
||||
# First argument
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,##,xyz}" "#" "xyz"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#,,xyz}" "," "xyz"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,{,xyz}" "{" "xyz"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,##{,xyz}" "#{" "xyz"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#},xyz}" "}" "xyz"
|
||||
# not a "basic" one but interesting nevertheless
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,###},xyz}" "#}" "xyz"
|
||||
# Second argument
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,##}" "abc" "#"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,#,}" "abc" ","
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,{}" "abc" "{"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,##{}" "abc" "#{"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,#}}" "abc" "}"
|
||||
# not a "basic" one but interesting nevertheless
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,###}}" "abc" "#}"
|
||||
# mixed
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,{,#}}" "{" "}"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#},{}" "}" "{"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,##{,###}}" "#{" "#}"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,###},##{}" "#}" "#{"
|
||||
|
||||
# Conditionals split on the second comma (this is not documented)
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,xyz,bonus}" "abc" "xyz,bonus"
|
||||
|
||||
# Curly brackets {...} do not capture a comma inside of conditionals as the
|
||||
# conditional ends on the first '}'
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,{abc,xyz},bonus}" "{abc,bonus}" "xyz,bonus}"
|
||||
|
||||
# Substitutions '#{...}' capture the comma
|
||||
# invalid format: #{abc,xyz} is not a known variable name.
|
||||
#test_conditional_with_pane_in_mode "#{?pane_in_mode,#{abc,xyz},bonus}" "" "bonus"
|
||||
|
||||
# Parenthesis (...) do not captura a comma
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,(abc,xyz),bonus}" "(abc" "xyz),bonus"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,(abc#,xyz),bonus}" "(abc,xyz)" "bonus"
|
||||
|
||||
# Brackets [...] do not captura a comma
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,[abc,xyz],bonus}" "[abc" "xyz],bonus"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,[abc#,xyz],bonus}" "[abc,xyz]" "bonus"
|
||||
|
||||
|
||||
# Escape comma inside of #(...)
|
||||
# Note: #() commands are run asynchronous and are substituted with result of the
|
||||
# *previous* run or a placeholder (like "<'echo ,' not ready") if the command
|
||||
# has not been run before. The format is updated as soon as the command
|
||||
# finishes. As we are printing the message only once it never gets updated
|
||||
# and the displayed message is "<'echo ,' not ready>"
|
||||
test_format "#{?pane_in_mode,#(echo #,),xyz}" "xyz"
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#(echo #,),xyz}" "<'echo ,' not ready>" "xyz"
|
||||
# This caching does not work :-(
|
||||
#$TMUX display-message -p "#(echo #,)" > /dev/null
|
||||
#test_conditional_with_pane_in_mode "#{?pane_in_mode,#(echo #,),xyz}" "," "xyz"
|
||||
#test_conditional_with_pane_in_mode "#{?pane_in_mode,#(echo #,),xyz}" "," "xyz"
|
||||
|
||||
# invalid format: '#(' is not closed in the first argument of #{?,,}.
|
||||
#test_conditional_with_pane_in_mode "#{?pane_in_mode,#(echo ,),xyz}" "" "),xyz"
|
||||
|
||||
# Escape comma inside of #[...]
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#[fg=default#,bg=default]abc,xyz}" "#[fg=default,bg=default]abc" "xyz"
|
||||
# invalid format: '#[' is not closed in the first argument of #{?,,}
|
||||
#test_conditional_with_pane_in_mode "#{?pane_in_mode,#[fg=default,bg=default]abc,xyz}" "" "bg=default]abc,xyz"
|
||||
|
||||
# Conditionals with comparison
|
||||
test_conditional_with_session_name "#{?#{==:#{session_name},Summer},abc,xyz}" "abc" "xyz"
|
||||
# Conditionals with comparison and escaped commas
|
||||
$TMUX rename-session ","
|
||||
test_format "#{?#{==:#,,#{session_name}},abc,xyz}" "abc"
|
||||
$TMUX rename-session "Summer" # reset to default
|
||||
|
||||
# Conditional in conditional
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}" "ABC" "xyz"
|
||||
test_conditional_with_session_name "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}" "xyz" "xyz"
|
||||
|
||||
test_conditional_with_pane_in_mode "#{?pane_in_mode,abc,#{?#{==:#{session_name},Summer},ABC,XYZ}}" "abc" "ABC"
|
||||
test_conditional_with_session_name "#{?pane_in_mode,abc,#{?#{==:#{session_name},Summer},ABC,XYZ}}" "ABC" "XYZ"
|
||||
|
||||
# Some fancy stackings
|
||||
test_conditional_with_pane_in_mode "#{?#{==:#{?pane_in_mode,#{session_name},#(echo Spring)},Summer},abc,xyz}" "abc" "xyz"
|
||||
|
||||
|
||||
|
||||
# Format test for the literal option
|
||||
# Note: The behavior for #{l:...} with escapes is sometimes weird as #{l:...}
|
||||
# respects the escapes.
|
||||
test_format "#{l:#{}}" "#{}"
|
||||
test_format "#{l:#{pane_in_mode}}" "#{pane_in_mode}"
|
||||
test_format "#{l:#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}}" "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}"
|
||||
|
||||
# With escapes (which escape but are returned literally)
|
||||
test_format "#{l:##{}" "##{"
|
||||
test_format "#{l:#{#}}}" "#{#}}"
|
||||
|
||||
# Invalid formats:
|
||||
#test_format "#{l:#{}" ""
|
||||
#test_format "#{l:#{#}}" ""
|
||||
|
||||
exit 0
|
||||
189
screen-redraw.c
189
screen-redraw.c
@@ -23,6 +23,18 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
struct screen_redraw_ctx {
|
||||
struct client *c;
|
||||
|
||||
u_int lines;
|
||||
int top;
|
||||
|
||||
int pane_status;
|
||||
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
};
|
||||
|
||||
static int screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
|
||||
static int screen_redraw_cell_border(struct client *, u_int, u_int);
|
||||
static int screen_redraw_check_cell(struct client *, u_int, u_int, int,
|
||||
@@ -34,11 +46,11 @@ static int screen_redraw_make_pane_status(struct client *, struct window *,
|
||||
struct window_pane *);
|
||||
static void screen_redraw_draw_pane_status(struct client *, int);
|
||||
|
||||
static void screen_redraw_draw_borders(struct client *, int, u_int, u_int);
|
||||
static void screen_redraw_draw_panes(struct client *, u_int, u_int);
|
||||
static void screen_redraw_draw_status(struct client *, u_int, u_int);
|
||||
static void screen_redraw_draw_number(struct client *, struct window_pane *,
|
||||
u_int, u_int);
|
||||
static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
|
||||
static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
|
||||
static void screen_redraw_draw_status(struct screen_redraw_ctx *);
|
||||
static void screen_redraw_draw_number(struct screen_redraw_ctx *,
|
||||
struct window_pane *);
|
||||
|
||||
#define CELL_INSIDE 0
|
||||
#define CELL_LEFTRIGHT 1
|
||||
@@ -375,42 +387,44 @@ void
|
||||
screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
|
||||
int draw_borders)
|
||||
{
|
||||
struct options *oo = c->session->options;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct options *wo = w->options;
|
||||
u_int top, lines;
|
||||
int position, pane_status;
|
||||
struct options *oo = c->session->options;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct options *wo = w->options;
|
||||
struct screen_redraw_ctx ctx;
|
||||
|
||||
if (c->flags & CLIENT_SUSPENDED)
|
||||
return;
|
||||
|
||||
memset(&ctx, 0, sizeof ctx);
|
||||
ctx.c = c;
|
||||
|
||||
if (c->flags & CLIENT_STATUSOFF)
|
||||
lines = 0;
|
||||
ctx.lines = 0;
|
||||
else
|
||||
lines = status_line_size(c->session);
|
||||
ctx.lines = status_line_size(c->session);
|
||||
if (c->message_string != NULL || c->prompt_string != NULL)
|
||||
lines = (lines == 0) ? 1 : lines;
|
||||
ctx.lines = (ctx.lines == 0) ? 1 : ctx.lines;
|
||||
|
||||
position = options_get_number(oo, "status-position");
|
||||
if (lines != 0 && position == 0)
|
||||
top = 1;
|
||||
else
|
||||
top = 0;
|
||||
if (ctx.lines != 0 && options_get_number(oo, "status-position") == 0)
|
||||
ctx.top = 1;
|
||||
ctx.pane_status = options_get_number(wo, "pane-border-status");
|
||||
|
||||
if (lines == 0)
|
||||
ctx.sx = tty->sx;
|
||||
ctx.sy = tty->sy - ctx.lines;
|
||||
|
||||
if (ctx.lines == 0)
|
||||
draw_status = 0;
|
||||
|
||||
if (draw_borders) {
|
||||
pane_status = options_get_number(wo, "pane-border-status");
|
||||
screen_redraw_draw_borders(c, pane_status, lines, top);
|
||||
if (pane_status != CELL_STATUS_OFF)
|
||||
screen_redraw_draw_pane_status(c, pane_status);
|
||||
if (ctx.pane_status != CELL_STATUS_OFF)
|
||||
screen_redraw_draw_pane_status(c, ctx.pane_status);
|
||||
screen_redraw_draw_borders(&ctx);
|
||||
}
|
||||
if (draw_panes)
|
||||
screen_redraw_draw_panes(c, lines, top);
|
||||
screen_redraw_draw_panes(&ctx);
|
||||
if (draw_status)
|
||||
screen_redraw_draw_status(c, lines, top);
|
||||
screen_redraw_draw_status(&ctx);
|
||||
tty_reset(tty);
|
||||
}
|
||||
|
||||
@@ -435,25 +449,65 @@ screen_redraw_pane(struct client *c, struct window_pane *wp)
|
||||
tty_reset(&c->tty);
|
||||
}
|
||||
|
||||
/* Draw a border cell. */
|
||||
static void
|
||||
screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
|
||||
int small, u_int msgx, u_int msgy, struct grid_cell *m_active_gc,
|
||||
struct grid_cell *active_gc, struct grid_cell *m_other_gc,
|
||||
struct grid_cell *other_gc)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct session *s = c->session;
|
||||
struct window *w = s->curw->window;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window_pane *wp;
|
||||
struct window_pane *active = w->active;
|
||||
struct window_pane *marked = marked_pane.wp;
|
||||
u_int type;
|
||||
int flag, pane_status = ctx->pane_status;
|
||||
|
||||
type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
|
||||
if (type == CELL_INSIDE)
|
||||
return;
|
||||
if (type == CELL_OUTSIDE && small && x > msgx && y == msgy)
|
||||
return;
|
||||
flag = screen_redraw_check_is(x, y, type, pane_status, w, active, wp);
|
||||
|
||||
if (server_is_marked(s, s->curw, marked_pane.wp) &&
|
||||
screen_redraw_check_is(x, y, type, pane_status, w, marked, wp)) {
|
||||
if (flag)
|
||||
tty_attributes(tty, m_active_gc, NULL);
|
||||
else
|
||||
tty_attributes(tty, m_other_gc, NULL);
|
||||
} else if (flag)
|
||||
tty_attributes(tty, active_gc, NULL);
|
||||
else
|
||||
tty_attributes(tty, other_gc, NULL);
|
||||
if (ctx->top)
|
||||
tty_cursor(tty, x, ctx->lines + y);
|
||||
else
|
||||
tty_cursor(tty, x, y);
|
||||
tty_putc(tty, CELL_BORDERS[type]);
|
||||
}
|
||||
|
||||
/* Draw the borders. */
|
||||
static void
|
||||
screen_redraw_draw_borders(struct client *c, int pane_status, u_int lines,
|
||||
u_int top)
|
||||
screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct session *s = c->session;
|
||||
struct window *w = s->curw->window;
|
||||
struct options *oo = w->options;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window_pane *wp;
|
||||
struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc;
|
||||
struct grid_cell msg_gc;
|
||||
u_int i, j, type, msgx = 0, msgy = 0;
|
||||
int active, small, flags;
|
||||
u_int i, j, msgx = 0, msgy = 0;
|
||||
int small, flags;
|
||||
char msg[256];
|
||||
const char *tmp;
|
||||
size_t msglen = 0;
|
||||
|
||||
small = (tty->sy - lines + top > w->sy) || (tty->sx > w->sx);
|
||||
small = (ctx->sy + ctx->top > w->sy) || (ctx->sx > w->sx);
|
||||
if (small) {
|
||||
flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
|
||||
if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
|
||||
@@ -470,12 +524,12 @@ screen_redraw_draw_borders(struct client *c, int pane_status, u_int lines,
|
||||
w->sx, w->sy, tmp);
|
||||
msglen = strlen(msg);
|
||||
|
||||
if (tty->sy - 1 - lines + top > w->sy && tty->sx >= msglen) {
|
||||
msgx = tty->sx - msglen;
|
||||
msgy = tty->sy - 1 - lines + top;
|
||||
} else if (tty->sx - w->sx > msglen) {
|
||||
msgx = tty->sx - msglen;
|
||||
msgy = tty->sy - 1 - lines + top;
|
||||
if (ctx->sy - 1 + ctx->top > w->sy && ctx->sx >= msglen) {
|
||||
msgx = ctx->sx - msglen;
|
||||
msgy = ctx->sy - 1 + ctx->top;
|
||||
} else if (ctx->sx - w->sx > msglen) {
|
||||
msgx = ctx->sx - msglen;
|
||||
msgy = ctx->sy - 1 + ctx->top;
|
||||
} else
|
||||
small = 0;
|
||||
}
|
||||
@@ -489,33 +543,11 @@ screen_redraw_draw_borders(struct client *c, int pane_status, u_int lines,
|
||||
memcpy(&m_active_gc, &active_gc, sizeof m_active_gc);
|
||||
m_active_gc.attr ^= GRID_ATTR_REVERSE;
|
||||
|
||||
for (j = 0; j < tty->sy - lines; j++) {
|
||||
for (i = 0; i < tty->sx; i++) {
|
||||
type = screen_redraw_check_cell(c, i, j, pane_status,
|
||||
&wp);
|
||||
if (type == CELL_INSIDE)
|
||||
continue;
|
||||
if (type == CELL_OUTSIDE && small &&
|
||||
i > msgx && j == msgy)
|
||||
continue;
|
||||
active = screen_redraw_check_is(i, j, type, pane_status,
|
||||
w, w->active, wp);
|
||||
if (server_is_marked(s, s->curw, marked_pane.wp) &&
|
||||
screen_redraw_check_is(i, j, type, pane_status, w,
|
||||
marked_pane.wp, wp)) {
|
||||
if (active)
|
||||
tty_attributes(tty, &m_active_gc, NULL);
|
||||
else
|
||||
tty_attributes(tty, &m_other_gc, NULL);
|
||||
} else if (active)
|
||||
tty_attributes(tty, &active_gc, NULL);
|
||||
else
|
||||
tty_attributes(tty, &other_gc, NULL);
|
||||
if (top)
|
||||
tty_cursor(tty, i, lines + j);
|
||||
else
|
||||
tty_cursor(tty, i, j);
|
||||
tty_putc(tty, CELL_BORDERS[type]);
|
||||
for (j = 0; j < ctx->sy; j++) {
|
||||
for (i = 0; i < ctx->sx; i++) {
|
||||
screen_redraw_draw_borders_cell(ctx, i, j, small,
|
||||
msgx, msgy, &m_active_gc, &active_gc, &m_other_gc,
|
||||
&other_gc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,48 +561,49 @@ screen_redraw_draw_borders(struct client *c, int pane_status, u_int lines,
|
||||
|
||||
/* Draw the panes. */
|
||||
static void
|
||||
screen_redraw_draw_panes(struct client *c, u_int lines, u_int top)
|
||||
screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct tty *tty = &c->tty;
|
||||
struct window_pane *wp;
|
||||
u_int i, y;
|
||||
|
||||
if (top)
|
||||
y = lines;
|
||||
if (ctx->top)
|
||||
y = ctx->lines;
|
||||
else
|
||||
y = 0;
|
||||
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
for (i = 0; i < wp->sy; i++)
|
||||
tty_draw_pane(tty, wp, i, wp->xoff, y + wp->yoff);
|
||||
if (c->flags & CLIENT_IDENTIFY)
|
||||
screen_redraw_draw_number(c, wp, lines, top);
|
||||
screen_redraw_draw_number(ctx, wp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw the status line. */
|
||||
static void
|
||||
screen_redraw_draw_status(struct client *c, u_int lines, u_int top)
|
||||
screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct tty *tty = &c->tty;
|
||||
u_int i, y;
|
||||
|
||||
if (top)
|
||||
if (ctx->top)
|
||||
y = 0;
|
||||
else
|
||||
y = tty->sy - lines;
|
||||
for (i = 0; i < lines; i++)
|
||||
y = ctx->sy;
|
||||
for (i = 0; i < ctx->lines; i++)
|
||||
tty_draw_line(tty, NULL, &c->status.status, i, 0, y);
|
||||
}
|
||||
|
||||
/* Draw number on a pane. */
|
||||
static void
|
||||
screen_redraw_draw_number(struct client *c, struct window_pane *wp,
|
||||
u_int lines, u_int top)
|
||||
screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
|
||||
{
|
||||
struct client *c = ctx->c;
|
||||
struct tty *tty = &c->tty;
|
||||
struct session *s = c->session;
|
||||
struct options *oo = s->options;
|
||||
@@ -593,8 +626,8 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp,
|
||||
px = wp->sx / 2; py = wp->sy / 2;
|
||||
xoff = wp->xoff; yoff = wp->yoff;
|
||||
|
||||
if (top)
|
||||
yoff += lines;
|
||||
if (ctx->top)
|
||||
yoff += ctx->lines;
|
||||
|
||||
if (wp->sx < len * 6 || wp->sy < 5) {
|
||||
tty_cursor(tty, xoff + px - len / 2, yoff + py);
|
||||
|
||||
@@ -408,7 +408,7 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
||||
break;
|
||||
cx = s->cx;
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= gd->linedata[yy].cellsize)
|
||||
if (xx >= grid_get_line(gd, yy)->cellsize)
|
||||
break;
|
||||
grid_get_cell(gd, xx, yy, &gc);
|
||||
if (xx + gc.data.width > px + nx)
|
||||
@@ -694,7 +694,7 @@ screen_write_backspace(struct screen_write_ctx *ctx)
|
||||
if (s->cx == 0) {
|
||||
if (s->cy == 0)
|
||||
return;
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy - 1];
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy - 1);
|
||||
if (gl->flags & GRID_LINE_WRAPPED) {
|
||||
s->cy--;
|
||||
s->cx = screen_size_x(s) - 1;
|
||||
@@ -917,7 +917,7 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
if (gl->cellsize == 0 && bg == 8)
|
||||
return;
|
||||
|
||||
@@ -940,7 +940,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
if (s->cx > sx - 1 || (s->cx >= gl->cellsize && bg == 8))
|
||||
return;
|
||||
|
||||
@@ -1043,7 +1043,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_line *gl;
|
||||
|
||||
gl = &gd->linedata[gd->hsize + s->cy];
|
||||
gl = grid_get_line(gd, gd->hsize + s->cy);
|
||||
if (wrapped)
|
||||
gl->flags |= GRID_LINE_WRAPPED;
|
||||
else
|
||||
@@ -1343,7 +1343,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
|
||||
collect = 0;
|
||||
else if (s->mode & MODE_INSERT)
|
||||
collect = 0;
|
||||
else if (s->sel.flag)
|
||||
else if (s->sel != NULL)
|
||||
collect = 0;
|
||||
if (!collect) {
|
||||
screen_write_collect_end(ctx);
|
||||
@@ -1433,7 +1433,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
screen_write_initctx(ctx, &ttyctx);
|
||||
|
||||
/* Handle overwriting of UTF-8 characters. */
|
||||
gl = &s->grid->linedata[s->grid->hsize + s->cy];
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
if (gl->flags & GRID_LINE_EXTENDED) {
|
||||
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
|
||||
if (screen_write_overwrite(ctx, &now_gc, width))
|
||||
|
||||
67
screen.c
67
screen.c
@@ -24,6 +24,22 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Selected area in screen. */
|
||||
struct screen_sel {
|
||||
int hidden;
|
||||
int rectangle;
|
||||
int modekeys;
|
||||
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int ex;
|
||||
u_int ey;
|
||||
|
||||
struct grid_cell cell;
|
||||
};
|
||||
|
||||
/* Entry on title stack. */
|
||||
struct screen_title_entry {
|
||||
char *text;
|
||||
|
||||
@@ -66,6 +82,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
s->cstyle = 0;
|
||||
s->ccolour = xstrdup("");
|
||||
s->tabs = NULL;
|
||||
s->sel = NULL;
|
||||
|
||||
screen_reinit(s);
|
||||
}
|
||||
@@ -94,6 +111,7 @@ screen_reinit(struct screen *s)
|
||||
void
|
||||
screen_free(struct screen *s)
|
||||
{
|
||||
free(s->sel);
|
||||
free(s->tabs);
|
||||
free(s->title);
|
||||
free(s->ccolour);
|
||||
@@ -280,9 +298,8 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
s->cy -= needed;
|
||||
}
|
||||
|
||||
/* Resize line arrays. */
|
||||
gd->linedata = xreallocarray(gd->linedata, gd->hsize + sy,
|
||||
sizeof *gd->linedata);
|
||||
/* Resize line array. */
|
||||
grid_adjust_lines(gd, gd->hsize + sy);
|
||||
|
||||
/* Size increasing. */
|
||||
if (sy > oldy) {
|
||||
@@ -305,7 +322,7 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
|
||||
/* Then fill the rest in with blanks. */
|
||||
for (i = gd->hsize + sy - needed; i < gd->hsize + sy; i++)
|
||||
memset(&gd->linedata[i], 0, sizeof gd->linedata[i]);
|
||||
memset(grid_get_line(gd, i), 0, sizeof(struct grid_line));
|
||||
}
|
||||
|
||||
/* Set the new size, and reset the scroll region. */
|
||||
@@ -317,51 +334,49 @@ screen_resize_y(struct screen *s, u_int sy)
|
||||
/* Set selection. */
|
||||
void
|
||||
screen_set_selection(struct screen *s, u_int sx, u_int sy,
|
||||
u_int ex, u_int ey, u_int rectflag, struct grid_cell *gc)
|
||||
u_int ex, u_int ey, u_int rectangle, int modekeys, struct grid_cell *gc)
|
||||
{
|
||||
struct screen_sel *sel = &s->sel;
|
||||
if (s->sel == NULL)
|
||||
s->sel = xcalloc(1, sizeof *s->sel);
|
||||
|
||||
memcpy(&sel->cell, gc, sizeof sel->cell);
|
||||
sel->flag = 1;
|
||||
sel->hidden = 0;
|
||||
memcpy(&s->sel->cell, gc, sizeof s->sel->cell);
|
||||
s->sel->hidden = 0;
|
||||
s->sel->rectangle = rectangle;
|
||||
s->sel->modekeys = modekeys;
|
||||
|
||||
sel->rectflag = rectflag;
|
||||
|
||||
sel->sx = sx; sel->sy = sy;
|
||||
sel->ex = ex; sel->ey = ey;
|
||||
s->sel->sx = sx;
|
||||
s->sel->sy = sy;
|
||||
s->sel->ex = ex;
|
||||
s->sel->ey = ey;
|
||||
}
|
||||
|
||||
/* Clear selection. */
|
||||
void
|
||||
screen_clear_selection(struct screen *s)
|
||||
{
|
||||
struct screen_sel *sel = &s->sel;
|
||||
|
||||
sel->flag = 0;
|
||||
sel->hidden = 0;
|
||||
sel->lineflag = LINE_SEL_NONE;
|
||||
free(s->sel);
|
||||
s->sel = NULL;
|
||||
}
|
||||
|
||||
/* Hide selection. */
|
||||
void
|
||||
screen_hide_selection(struct screen *s)
|
||||
{
|
||||
struct screen_sel *sel = &s->sel;
|
||||
|
||||
sel->hidden = 1;
|
||||
if (s->sel != NULL)
|
||||
s->sel->hidden = 1;
|
||||
}
|
||||
|
||||
/* Check if cell in selection. */
|
||||
int
|
||||
screen_check_selection(struct screen *s, u_int px, u_int py)
|
||||
{
|
||||
struct screen_sel *sel = &s->sel;
|
||||
struct screen_sel *sel = s->sel;
|
||||
u_int xx;
|
||||
|
||||
if (!sel->flag || sel->hidden)
|
||||
if (sel == NULL || sel->hidden)
|
||||
return (0);
|
||||
|
||||
if (sel->rectflag) {
|
||||
if (sel->rectangle) {
|
||||
if (sel->sy < sel->ey) {
|
||||
/* start line < end line -- downward selection. */
|
||||
if (py < sel->sy || py > sel->ey)
|
||||
@@ -454,10 +469,10 @@ void
|
||||
screen_select_cell(struct screen *s, struct grid_cell *dst,
|
||||
const struct grid_cell *src)
|
||||
{
|
||||
if (!s->sel.flag || s->sel.hidden)
|
||||
if (s->sel == NULL || s->sel->hidden)
|
||||
return;
|
||||
|
||||
memcpy(dst, &s->sel.cell, sizeof *dst);
|
||||
memcpy(dst, &s->sel->cell, sizeof *dst);
|
||||
|
||||
utf8_copy(&dst->data, &src->data);
|
||||
dst->attr = dst->attr & ~GRID_ATTR_CHARSET;
|
||||
|
||||
@@ -41,6 +41,8 @@ static void server_client_check_redraw(struct client *);
|
||||
static void server_client_set_title(struct client *);
|
||||
static void server_client_reset_state(struct client *);
|
||||
static int server_client_assume_paste(struct session *);
|
||||
static void server_client_clear_identify(struct client *,
|
||||
struct window_pane *);
|
||||
|
||||
static void server_client_dispatch(struct imsg *, void *);
|
||||
static void server_client_dispatch_command(struct client *, struct imsg *);
|
||||
@@ -91,7 +93,7 @@ server_client_set_identify(struct client *c, u_int delay)
|
||||
}
|
||||
|
||||
/* Clear identify mode on client. */
|
||||
void
|
||||
static void
|
||||
server_client_clear_identify(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
if (~c->flags & CLIENT_IDENTIFY)
|
||||
@@ -813,7 +815,7 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
struct window_pane *wp;
|
||||
struct timeval tv;
|
||||
struct key_table *table, *first;
|
||||
struct key_binding bd_find, *bd;
|
||||
struct key_binding *bd;
|
||||
int xtimeout, flags;
|
||||
struct cmd_find_state fs;
|
||||
key_code key0;
|
||||
@@ -882,11 +884,11 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
|
||||
/* Forward mouse keys if disabled. */
|
||||
if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
|
||||
goto forward;
|
||||
goto forward_key;
|
||||
|
||||
/* Treat everything as a regular key when pasting is detected. */
|
||||
if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
|
||||
goto forward;
|
||||
goto forward_key;
|
||||
|
||||
/*
|
||||
* Work out the current key table. If the pane is in a mode, use
|
||||
@@ -901,11 +903,11 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
table = c->keytable;
|
||||
first = table;
|
||||
|
||||
table_changed:
|
||||
/*
|
||||
* The prefix always takes precedence and forces a switch to the prefix
|
||||
* table, unless we are already there.
|
||||
*/
|
||||
retry:
|
||||
key0 = (key & ~KEYC_XTERM);
|
||||
if ((key0 == (key_code)options_get_number(s->options, "prefix") ||
|
||||
key0 == (key_code)options_get_number(s->options, "prefix2")) &&
|
||||
@@ -924,9 +926,9 @@ retry:
|
||||
if (c->flags & CLIENT_REPEAT)
|
||||
log_debug("currently repeating");
|
||||
|
||||
try_again:
|
||||
/* Try to see if there is a key binding in the current table. */
|
||||
bd_find.key = key0;
|
||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||
bd = key_bindings_get(table, key0);
|
||||
if (bd != NULL) {
|
||||
/*
|
||||
* Key was matched in this table. If currently repeating but a
|
||||
@@ -939,7 +941,7 @@ retry:
|
||||
c->flags &= ~CLIENT_REPEAT;
|
||||
server_status_client(c);
|
||||
table = c->keytable;
|
||||
goto retry;
|
||||
goto table_changed;
|
||||
}
|
||||
log_debug("found in key table %s", table->name);
|
||||
|
||||
@@ -973,6 +975,14 @@ retry:
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* No match, try the ANY key.
|
||||
*/
|
||||
if (key0 != KEYC_ANY) {
|
||||
key0 = KEYC_ANY;
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/*
|
||||
* No match in this table. If not in the root table or if repeating,
|
||||
* switch the client back to the root table and try again.
|
||||
@@ -984,7 +994,7 @@ retry:
|
||||
c->flags &= ~CLIENT_REPEAT;
|
||||
server_status_client(c);
|
||||
table = c->keytable;
|
||||
goto retry;
|
||||
goto table_changed;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -997,7 +1007,7 @@ retry:
|
||||
return;
|
||||
}
|
||||
|
||||
forward:
|
||||
forward_key:
|
||||
if (c->flags & CLIENT_READONLY)
|
||||
return;
|
||||
if (wp != NULL)
|
||||
@@ -1158,10 +1168,6 @@ server_client_check_focus(struct window_pane *wp)
|
||||
push = wp->flags & PANE_FOCUSPUSH;
|
||||
wp->flags &= ~PANE_FOCUSPUSH;
|
||||
|
||||
/* If we don't care about focus, forget it. */
|
||||
if (!(wp->base.mode & MODE_FOCUSON))
|
||||
return;
|
||||
|
||||
/* If we're not the active pane in our window, we're not focused. */
|
||||
if (wp->window->active != wp)
|
||||
goto not_focused;
|
||||
@@ -1185,14 +1191,20 @@ server_client_check_focus(struct window_pane *wp)
|
||||
}
|
||||
|
||||
not_focused:
|
||||
if (push || (wp->flags & PANE_FOCUSED))
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
if (push || (wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
notify_pane("pane-focus-out", wp);
|
||||
}
|
||||
wp->flags &= ~PANE_FOCUSED;
|
||||
return;
|
||||
|
||||
focused:
|
||||
if (push || !(wp->flags & PANE_FOCUSED))
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
if (push || !(wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
notify_pane("pane-focus-in", wp);
|
||||
}
|
||||
wp->flags |= PANE_FOCUSED;
|
||||
}
|
||||
|
||||
@@ -1861,15 +1873,19 @@ server_client_add_message(struct client *c, const char *fmt, ...)
|
||||
|
||||
/* Get client working directory. */
|
||||
const char *
|
||||
server_client_get_cwd(struct client *c)
|
||||
server_client_get_cwd(struct client *c, struct session *s)
|
||||
{
|
||||
struct session *s;
|
||||
const char *home;
|
||||
|
||||
if (c != NULL && c->session == NULL && c->cwd != NULL)
|
||||
return (c->cwd);
|
||||
if (s != NULL && s->cwd != NULL)
|
||||
return (s->cwd);
|
||||
if (c != NULL && (s = c->session) != NULL && s->cwd != NULL)
|
||||
return (s->cwd);
|
||||
return (".");
|
||||
if ((home = find_home()) != NULL)
|
||||
return (home);
|
||||
return ("/");
|
||||
}
|
||||
|
||||
/* Resolve an absolute path or relative to client working directory. */
|
||||
@@ -1881,7 +1897,7 @@ server_client_get_path(struct client *c, const char *file)
|
||||
if (*file == '/')
|
||||
path = xstrdup(file);
|
||||
else
|
||||
xasprintf(&path, "%s/%s", server_client_get_cwd(c), file);
|
||||
xasprintf(&path, "%s/%s", server_client_get_cwd(c, NULL), file);
|
||||
if (realpath(path, resolved) == NULL)
|
||||
return (path);
|
||||
free(path);
|
||||
|
||||
16
server-fn.c
16
server-fn.c
@@ -175,6 +175,22 @@ server_lock_client(struct client *c)
|
||||
proc_send(c->peer, MSG_LOCK, -1, cmd, strlen(cmd) + 1);
|
||||
}
|
||||
|
||||
void
|
||||
server_kill_pane(struct window_pane *wp)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
|
||||
if (window_count_panes(w) == 1) {
|
||||
server_kill_window(w);
|
||||
recalculate_sizes();
|
||||
} else {
|
||||
server_unzoom_window(w);
|
||||
layout_close_pane(wp);
|
||||
window_remove_pane(w, wp);
|
||||
server_redraw_window(w);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
server_kill_window(struct window *w)
|
||||
{
|
||||
|
||||
1
server.c
1
server.c
@@ -201,7 +201,6 @@ server_start(struct tmuxproc *client, struct event_base *base, int lockfd,
|
||||
RB_INIT(&all_window_panes);
|
||||
TAILQ_INIT(&clients);
|
||||
RB_INIT(&sessions);
|
||||
RB_INIT(&session_groups);
|
||||
key_bindings_init();
|
||||
|
||||
gettimeofday(&start_time, NULL);
|
||||
|
||||
17
session.c
17
session.c
@@ -28,7 +28,7 @@
|
||||
|
||||
struct sessions sessions;
|
||||
static u_int next_session_id;
|
||||
struct session_groups session_groups;
|
||||
struct session_groups session_groups = RB_INITIALIZER(&session_groups);
|
||||
|
||||
static void session_free(int, short, void *);
|
||||
|
||||
@@ -40,21 +40,19 @@ static struct winlink *session_previous_alert(struct winlink *);
|
||||
static void session_group_remove(struct session *);
|
||||
static void session_group_synchronize1(struct session *, struct session *);
|
||||
|
||||
RB_GENERATE(sessions, session, entry, session_cmp);
|
||||
|
||||
int
|
||||
session_cmp(struct session *s1, struct session *s2)
|
||||
{
|
||||
return (strcmp(s1->name, s2->name));
|
||||
}
|
||||
RB_GENERATE(sessions, session, entry, session_cmp);
|
||||
|
||||
RB_GENERATE(session_groups, session_group, entry, session_group_cmp);
|
||||
|
||||
int
|
||||
static int
|
||||
session_group_cmp(struct session_group *s1, struct session_group *s2)
|
||||
{
|
||||
return (strcmp(s1->name, s2->name));
|
||||
}
|
||||
RB_GENERATE_STATIC(session_groups, session_group, entry, session_group_cmp);
|
||||
|
||||
/*
|
||||
* Find if session is still alive. This is true if it is still on the global
|
||||
@@ -290,9 +288,10 @@ session_update_activity(struct session *s, struct timeval *from)
|
||||
else
|
||||
memcpy(&s->activity_time, from, sizeof s->activity_time);
|
||||
|
||||
log_debug("session %s activity %lld.%06d (last %lld.%06d)", s->name,
|
||||
(long long)s->activity_time.tv_sec, (int)s->activity_time.tv_usec,
|
||||
(long long)last->tv_sec, (int)last->tv_usec);
|
||||
log_debug("session $%u %s activity %lld.%06d (last %lld.%06d)", s->id,
|
||||
s->name, (long long)s->activity_time.tv_sec,
|
||||
(int)s->activity_time.tv_usec, (long long)last->tv_sec,
|
||||
(int)last->tv_usec);
|
||||
|
||||
if (evtimer_initialized(&s->lock_timer))
|
||||
evtimer_del(&s->lock_timer);
|
||||
|
||||
64
tmux.1
64
tmux.1
@@ -855,6 +855,8 @@ the initial size is 80 x 24;
|
||||
and
|
||||
.Fl y
|
||||
can be used to specify a different size.
|
||||
.Ql -
|
||||
uses the size of the current client if any.
|
||||
.Pp
|
||||
If run from a terminal, any
|
||||
.Xr termios 4
|
||||
@@ -966,7 +968,7 @@ show debugging information about jobs and terminals.
|
||||
Execute commands from
|
||||
.Ar path
|
||||
(which may be a
|
||||
.Xr glob 3
|
||||
.Xr glob 7
|
||||
pattern).
|
||||
If
|
||||
.Fl q
|
||||
@@ -1463,6 +1465,8 @@ The following keys may be used in tree mode:
|
||||
.It Li "Enter" Ta "Choose selected item"
|
||||
.It Li "Up" Ta "Select previous item"
|
||||
.It Li "Down" Ta "Select next item"
|
||||
.It Li "x" Ta "Kill selected item"
|
||||
.It Li "X" Ta "Kill tagged items"
|
||||
.It Li "<" Ta "Scroll list of previews left"
|
||||
.It Li ">" Ta "Scroll list of previews right"
|
||||
.It Li "C-s" Ta "Search by name"
|
||||
@@ -2753,8 +2757,7 @@ to
|
||||
from the 256-colour set,
|
||||
.Ic default ,
|
||||
or a hexadecimal RGB string such as
|
||||
.Ql #ffffff ,
|
||||
which chooses the closest match from the default 256-colour set.
|
||||
.Ql #ffffff .
|
||||
.Pp
|
||||
The attributes is either
|
||||
.Ic none
|
||||
@@ -3424,6 +3427,14 @@ Run when the program running in a pane exits, but
|
||||
is on so the pane has not closed.
|
||||
.It pane-exited
|
||||
Run when the program running in a pane exits.
|
||||
.It pane-focus-in
|
||||
Run when the focus enters a pane, if the
|
||||
.Ic focus-events
|
||||
option is on.
|
||||
.It pane-focus-out
|
||||
Run when the focus exits a pane, if the
|
||||
.Ic focus-events
|
||||
option is on.
|
||||
.It pane-set-clipboard
|
||||
Run when the terminal clipboard is set using the
|
||||
.Xr xterm 1
|
||||
@@ -3445,12 +3456,14 @@ Run when a window is unlinked from a session.
|
||||
Hooks are managed with these commands:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic set-hook
|
||||
.Op Fl gu
|
||||
.Op Fl gRu
|
||||
.Op Fl t Ar target-session
|
||||
.Ar hook-name
|
||||
.Ar command
|
||||
.Xc
|
||||
Sets (or with
|
||||
Without
|
||||
.Fl R ,
|
||||
sets (or with
|
||||
.Fl u
|
||||
unsets) hook
|
||||
.Ar hook-name
|
||||
@@ -3466,6 +3479,12 @@ hooks (for
|
||||
with
|
||||
.Fl t ) .
|
||||
Like options, session hooks inherit from the global ones.
|
||||
.Pp
|
||||
With
|
||||
.Fl R ,
|
||||
run
|
||||
.Ar hook-name
|
||||
immediately.
|
||||
.It Xo Ic show-hooks
|
||||
.Op Fl g
|
||||
.Op Fl t Ar target-session
|
||||
@@ -3545,11 +3564,17 @@ The possible variables are listed in the table below, or the name of a
|
||||
.Nm
|
||||
option may be used for an option's value.
|
||||
Some variables have a shorter alias such as
|
||||
.Ql #S ,
|
||||
and
|
||||
.Ql #S ;
|
||||
.Ql ##
|
||||
is replaced by a single
|
||||
.Ql # .
|
||||
.Ql # ,
|
||||
.Ql #,
|
||||
by a
|
||||
.Ql \&,
|
||||
and
|
||||
.Ql #}
|
||||
by a
|
||||
.Ql } .
|
||||
.Pp
|
||||
Conditionals are available by prefixing with
|
||||
.Ql \&?
|
||||
@@ -3571,6 +3596,22 @@ if
|
||||
is enabled, or
|
||||
.Ql no
|
||||
if not.
|
||||
Conditionals can be nested arbitrarily.
|
||||
Inside a conditional,
|
||||
.Ql \&,
|
||||
and
|
||||
.Ql }
|
||||
must be escaped as
|
||||
.Ql #,
|
||||
and
|
||||
.Ql #} ,
|
||||
unless they are part of a
|
||||
.Ql #{...}
|
||||
replacement.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
#{?pane_in_mode,#[fg=white#,bg=red],#[fg=red#,bg=white]}#W .
|
||||
.Ed
|
||||
.Pp
|
||||
Comparisons may be expressed by prefixing two comma-separated
|
||||
alternatives by
|
||||
@@ -3598,7 +3639,7 @@ and
|
||||
.Ql &&
|
||||
evaluate to true if either or both of two comma-separated alternatives are
|
||||
true, for example
|
||||
.Ql #{||,#{pane_in_mode},#{alternate_on}} .
|
||||
.Ql #{||:#{pane_in_mode},#{alternate_on}} .
|
||||
A
|
||||
.Ql C
|
||||
performs a search for an
|
||||
@@ -3745,6 +3786,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
|
||||
.It Li "pane_width" Ta "" Ta "Width of pane"
|
||||
.It Li "pid" Ta "" Ta "Server PID"
|
||||
.It Li "rectangle_toggle" Ta "" Ta "1 if rectangle selection is activated"
|
||||
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
|
||||
.It Li "scroll_region_upper" Ta "" Ta "Top of scroll region in pane"
|
||||
.It Li "scroll_position" Ta "" Ta "Scroll position in copy mode"
|
||||
@@ -3826,7 +3868,9 @@ for
|
||||
or
|
||||
.Ic new-session ) .
|
||||
.It
|
||||
An escape sequence:
|
||||
An escape sequence (if the
|
||||
.Ic allow-rename
|
||||
option is turned on):
|
||||
.Bd -literal -offset indent
|
||||
$ printf '\e033kWINDOW_NAME\e033\e\e'
|
||||
.Ed
|
||||
|
||||
109
tmux.h
109
tmux.h
@@ -19,8 +19,6 @@
|
||||
#ifndef TMUX_H
|
||||
#define TMUX_H
|
||||
|
||||
#define PROTOCOL_VERSION 8
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
@@ -56,6 +54,9 @@ struct session;
|
||||
struct tmuxpeer;
|
||||
struct tmuxproc;
|
||||
|
||||
/* Client-server protocol version. */
|
||||
#define PROTOCOL_VERSION 8
|
||||
|
||||
/* Default global configuration file. */
|
||||
#ifndef TMUX_CONF
|
||||
#define TMUX_CONF "/etc/tmux.conf"
|
||||
@@ -140,6 +141,9 @@ enum {
|
||||
KEYC_FOCUS_IN = KEYC_BASE,
|
||||
KEYC_FOCUS_OUT,
|
||||
|
||||
/* "Any" key, used if not found in key table. */
|
||||
KEYC_ANY,
|
||||
|
||||
/* Paste brackets. */
|
||||
KEYC_PASTE_START,
|
||||
KEYC_PASTE_END,
|
||||
@@ -511,10 +515,11 @@ struct msg_stderr_data {
|
||||
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ALL)
|
||||
|
||||
/*
|
||||
* A single UTF-8 character. UTF8_SIZE must be big enough to hold at least one
|
||||
* combining character as well.
|
||||
* A single UTF-8 character. UTF8_SIZE must be big enough to hold
|
||||
* combining characters as well, currently at most five (of three
|
||||
* bytes) are supported.
|
||||
*/
|
||||
#define UTF8_SIZE 9
|
||||
#define UTF8_SIZE 18
|
||||
struct utf8_data {
|
||||
u_char data[UTF8_SIZE];
|
||||
|
||||
@@ -645,30 +650,8 @@ struct job {
|
||||
};
|
||||
LIST_HEAD(joblist, job);
|
||||
|
||||
/* Screen selection. */
|
||||
struct screen_sel {
|
||||
int flag;
|
||||
int hidden;
|
||||
|
||||
int rectflag;
|
||||
enum {
|
||||
LINE_SEL_NONE,
|
||||
LINE_SEL_LEFT_RIGHT,
|
||||
LINE_SEL_RIGHT_LEFT,
|
||||
} lineflag;
|
||||
|
||||
int modekeys;
|
||||
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int ex;
|
||||
u_int ey;
|
||||
|
||||
struct grid_cell cell;
|
||||
};
|
||||
|
||||
/* Virtual screen. */
|
||||
struct screen_sel;
|
||||
struct screen_titles;
|
||||
struct screen {
|
||||
char *title;
|
||||
@@ -689,7 +672,7 @@ struct screen {
|
||||
|
||||
bitstr_t *tabs;
|
||||
|
||||
struct screen_sel sel;
|
||||
struct screen_sel *sel;
|
||||
};
|
||||
|
||||
/* Screen write context. */
|
||||
@@ -736,28 +719,6 @@ struct window_mode {
|
||||
};
|
||||
#define WINDOW_MODE_TIMEOUT 180
|
||||
|
||||
/* Structures for choose mode. */
|
||||
struct window_choose_data {
|
||||
struct client *start_client;
|
||||
struct session *start_session;
|
||||
|
||||
u_int idx;
|
||||
int type;
|
||||
#define TREE_OTHER 0x0
|
||||
#define TREE_WINDOW 0x1
|
||||
#define TREE_SESSION 0x2
|
||||
|
||||
struct session *tree_session; /* session of items in tree */
|
||||
|
||||
struct winlink *wl;
|
||||
int pane_id;
|
||||
|
||||
char *ft_template;
|
||||
struct format_tree *ft;
|
||||
|
||||
char *command;
|
||||
};
|
||||
|
||||
/* Child window structure. */
|
||||
struct window_pane {
|
||||
u_int id;
|
||||
@@ -866,12 +827,11 @@ struct window {
|
||||
int flags;
|
||||
#define WINDOW_BELL 0x1
|
||||
#define WINDOW_ACTIVITY 0x2
|
||||
/* 0x4 unused */
|
||||
#define WINDOW_SILENCE 0x8
|
||||
#define WINDOW_ZOOMED 0x1000
|
||||
#define WINDOW_FORCEWIDTH 0x2000
|
||||
#define WINDOW_FORCEHEIGHT 0x4000
|
||||
#define WINDOW_STYLECHANGED 0x8000
|
||||
#define WINDOW_SILENCE 0x4
|
||||
#define WINDOW_ZOOMED 0x8
|
||||
#define WINDOW_FORCEWIDTH 0x10
|
||||
#define WINDOW_FORCEHEIGHT 0x20
|
||||
#define WINDOW_STYLECHANGED 0x40
|
||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
|
||||
|
||||
int alerts_queued;
|
||||
@@ -1402,6 +1362,7 @@ struct client {
|
||||
void (*identify_callback)(struct client *,
|
||||
struct window_pane *);
|
||||
void *identify_callback_data;
|
||||
struct cmdq_item *identify_callback_item;
|
||||
|
||||
char *message_string;
|
||||
struct event message_timer;
|
||||
@@ -1447,7 +1408,7 @@ struct key_binding {
|
||||
RB_HEAD(key_bindings, key_binding);
|
||||
|
||||
struct key_table {
|
||||
const char *name;
|
||||
const char *name;
|
||||
struct key_bindings key_bindings;
|
||||
|
||||
u_int references;
|
||||
@@ -1468,6 +1429,7 @@ enum options_table_type {
|
||||
OPTIONS_TABLE_STYLE,
|
||||
OPTIONS_TABLE_ARRAY,
|
||||
};
|
||||
|
||||
enum options_table_scope {
|
||||
OPTIONS_TABLE_NONE,
|
||||
OPTIONS_TABLE_SERVER,
|
||||
@@ -1598,6 +1560,7 @@ void printflike(4, 5) hooks_insert(struct hooks *, struct cmdq_item *,
|
||||
struct cmd_find_state *, const char *, ...);
|
||||
|
||||
/* notify.c */
|
||||
void notify_hook(struct cmdq_item *, const char *);
|
||||
void notify_input(struct window_pane *, struct evbuffer *);
|
||||
void notify_client(const char *, struct client *);
|
||||
void notify_session(const char *, struct session *);
|
||||
@@ -1776,13 +1739,13 @@ long long args_strtonum(struct args *, u_char, long long, long long,
|
||||
/* cmd-find.c */
|
||||
int cmd_find_target(struct cmd_find_state *, struct cmdq_item *,
|
||||
const char *, enum cmd_find_type, int);
|
||||
struct client *cmd_find_best_client(struct session *);
|
||||
struct client *cmd_find_client(struct cmdq_item *, const char *, int);
|
||||
void cmd_find_clear_state(struct cmd_find_state *, int);
|
||||
int cmd_find_empty_state(struct cmd_find_state *);
|
||||
int cmd_find_valid_state(struct cmd_find_state *);
|
||||
void cmd_find_copy_state(struct cmd_find_state *,
|
||||
struct cmd_find_state *);
|
||||
void cmd_find_log_state(const char *, struct cmd_find_state *);
|
||||
void cmd_find_from_session(struct cmd_find_state *,
|
||||
struct session *, int);
|
||||
void cmd_find_from_winlink(struct cmd_find_state *,
|
||||
@@ -1802,6 +1765,7 @@ int cmd_find_from_mouse(struct cmd_find_state *,
|
||||
int cmd_find_from_nothing(struct cmd_find_state *, int);
|
||||
|
||||
/* cmd.c */
|
||||
void cmd_log_argv(int, char **, const char *);
|
||||
int cmd_pack_argv(int, char **, char *, size_t);
|
||||
int cmd_unpack_argv(char *, size_t, int, char ***);
|
||||
char **cmd_copy_argv(int, char **);
|
||||
@@ -1851,13 +1815,13 @@ void cmd_wait_for_flush(void);
|
||||
int client_main(struct event_base *, int, char **, int);
|
||||
|
||||
/* key-bindings.c */
|
||||
RB_PROTOTYPE(key_bindings, key_binding, entry, key_bindings_cmp);
|
||||
RB_PROTOTYPE(key_tables, key_table, entry, key_table_cmp);
|
||||
extern struct key_tables key_tables;
|
||||
int key_table_cmp(struct key_table *, struct key_table *);
|
||||
int key_bindings_cmp(struct key_binding *, struct key_binding *);
|
||||
struct key_table *key_bindings_get_table(const char *, int);
|
||||
struct key_table *key_bindings_first_table(void);
|
||||
struct key_table *key_bindings_next_table(struct key_table *);
|
||||
void key_bindings_unref_table(struct key_table *);
|
||||
struct key_binding *key_bindings_get(struct key_table *, key_code);
|
||||
struct key_binding *key_bindings_first(struct key_table *);
|
||||
struct key_binding *key_bindings_next(struct key_table *, struct key_binding *);
|
||||
void key_bindings_add(const char *, key_code, int, struct cmd_list *);
|
||||
void key_bindings_remove(const char *, key_code);
|
||||
void key_bindings_remove_table(const char *);
|
||||
@@ -1891,7 +1855,6 @@ void server_add_accept(int);
|
||||
/* server-client.c */
|
||||
u_int server_client_how_many(void);
|
||||
void server_client_set_identify(struct client *, u_int);
|
||||
void server_client_clear_identify(struct client *, struct window_pane *);
|
||||
void server_client_set_key_table(struct client *, const char *);
|
||||
const char *server_client_get_key_table(struct client *);
|
||||
int server_client_check_nested(struct client *);
|
||||
@@ -1909,7 +1872,7 @@ void server_client_push_stderr(struct client *);
|
||||
void printflike(2, 3) server_client_add_message(struct client *, const char *,
|
||||
...);
|
||||
char *server_client_get_path(struct client *, const char *);
|
||||
const char *server_client_get_cwd(struct client *);
|
||||
const char *server_client_get_cwd(struct client *, struct session *);
|
||||
|
||||
/* server-fn.c */
|
||||
void server_redraw_client(struct client *);
|
||||
@@ -1924,6 +1887,7 @@ void server_status_window(struct window *);
|
||||
void server_lock(void);
|
||||
void server_lock_session(struct session *);
|
||||
void server_lock_client(struct client *);
|
||||
void server_kill_pane(struct window_pane *);
|
||||
void server_kill_window(struct window *);
|
||||
int server_link_window(struct session *,
|
||||
struct winlink *, struct session *, int, int, int, char **);
|
||||
@@ -2008,6 +1972,8 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int,
|
||||
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
|
||||
u_int);
|
||||
void grid_reflow(struct grid *, u_int, u_int *);
|
||||
struct grid_line *grid_get_line(struct grid *, u_int);
|
||||
void grid_adjust_lines(struct grid *, u_int);
|
||||
|
||||
/* grid-view.c */
|
||||
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||
@@ -2104,8 +2070,8 @@ void screen_set_title(struct screen *, const char *);
|
||||
void screen_push_title(struct screen *);
|
||||
void screen_pop_title(struct screen *);
|
||||
void screen_resize(struct screen *, u_int, u_int, int);
|
||||
void screen_set_selection(struct screen *,
|
||||
u_int, u_int, u_int, u_int, u_int, struct grid_cell *);
|
||||
void screen_set_selection(struct screen *, u_int, u_int, u_int, u_int,
|
||||
u_int, int, struct grid_cell *);
|
||||
void screen_clear_selection(struct screen *);
|
||||
void screen_hide_selection(struct screen *);
|
||||
int screen_check_selection(struct screen *, u_int, u_int);
|
||||
@@ -2205,6 +2171,9 @@ void layout_free_cell(struct layout_cell *);
|
||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||
void layout_destroy_cell(struct window *, struct layout_cell *,
|
||||
struct layout_cell **);
|
||||
void layout_resize_layout(struct window *, struct layout_cell *,
|
||||
enum layout_type, int, int);
|
||||
struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int);
|
||||
void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
|
||||
u_int);
|
||||
void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
||||
@@ -2249,7 +2218,6 @@ void mode_tree_expand_current(struct mode_tree_data *);
|
||||
void mode_tree_set_current(struct mode_tree_data *, uint64_t);
|
||||
void mode_tree_each_tagged(struct mode_tree_data *, mode_tree_each_cb,
|
||||
struct client *, key_code, int);
|
||||
void mode_tree_up(struct mode_tree_data *, int);
|
||||
void mode_tree_down(struct mode_tree_data *, int);
|
||||
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
|
||||
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
|
||||
@@ -2319,11 +2287,8 @@ void control_notify_session_window_changed(struct session *);
|
||||
|
||||
/* session.c */
|
||||
extern struct sessions sessions;
|
||||
extern struct session_groups session_groups;
|
||||
int session_cmp(struct session *, struct session *);
|
||||
RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
||||
int session_group_cmp(struct session_group *, struct session_group *);
|
||||
RB_PROTOTYPE(session_groups, session_group, entry, session_group_cmp);
|
||||
int session_alive(struct session *);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_find_by_id_str(const char *);
|
||||
|
||||
114
tty-keys.c
114
tty-keys.c
@@ -171,7 +171,12 @@ static const struct tty_default_key_raw tty_default_raw_keys[] = {
|
||||
{ "\033[201~", KEYC_PASTE_END },
|
||||
};
|
||||
|
||||
/* Default terminfo(5) keys. */
|
||||
/*
|
||||
* Default terminfo(5) keys. Any keys that have builtin modifiers
|
||||
* (that is, where the key itself contains the modifiers) has the
|
||||
* KEYC_XTERM flag set so a leading escape is not treated as meta (and
|
||||
* probably removed).
|
||||
*/
|
||||
struct tty_default_key_code {
|
||||
enum tty_code_code code;
|
||||
key_code key;
|
||||
@@ -191,61 +196,61 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
|
||||
{ TTYC_KF11, KEYC_F11 },
|
||||
{ TTYC_KF12, KEYC_F12 },
|
||||
|
||||
{ TTYC_KF13, KEYC_F1|KEYC_SHIFT },
|
||||
{ TTYC_KF14, KEYC_F2|KEYC_SHIFT },
|
||||
{ TTYC_KF15, KEYC_F3|KEYC_SHIFT },
|
||||
{ TTYC_KF16, KEYC_F4|KEYC_SHIFT },
|
||||
{ TTYC_KF17, KEYC_F5|KEYC_SHIFT },
|
||||
{ TTYC_KF18, KEYC_F6|KEYC_SHIFT },
|
||||
{ TTYC_KF19, KEYC_F7|KEYC_SHIFT },
|
||||
{ TTYC_KF20, KEYC_F8|KEYC_SHIFT },
|
||||
{ TTYC_KF21, KEYC_F9|KEYC_SHIFT },
|
||||
{ TTYC_KF22, KEYC_F10|KEYC_SHIFT },
|
||||
{ TTYC_KF23, KEYC_F11|KEYC_SHIFT },
|
||||
{ TTYC_KF24, KEYC_F12|KEYC_SHIFT },
|
||||
{ TTYC_KF13, KEYC_F1|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF14, KEYC_F2|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF15, KEYC_F3|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF16, KEYC_F4|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF17, KEYC_F5|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF18, KEYC_F6|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF19, KEYC_F7|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF20, KEYC_F8|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF21, KEYC_F9|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF22, KEYC_F10|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF23, KEYC_F11|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF24, KEYC_F12|KEYC_SHIFT|KEYC_XTERM },
|
||||
|
||||
{ TTYC_KF25, KEYC_F1|KEYC_CTRL },
|
||||
{ TTYC_KF26, KEYC_F2|KEYC_CTRL },
|
||||
{ TTYC_KF27, KEYC_F3|KEYC_CTRL },
|
||||
{ TTYC_KF28, KEYC_F4|KEYC_CTRL },
|
||||
{ TTYC_KF29, KEYC_F5|KEYC_CTRL },
|
||||
{ TTYC_KF30, KEYC_F6|KEYC_CTRL },
|
||||
{ TTYC_KF31, KEYC_F7|KEYC_CTRL },
|
||||
{ TTYC_KF32, KEYC_F8|KEYC_CTRL },
|
||||
{ TTYC_KF33, KEYC_F9|KEYC_CTRL },
|
||||
{ TTYC_KF34, KEYC_F10|KEYC_CTRL },
|
||||
{ TTYC_KF35, KEYC_F11|KEYC_CTRL },
|
||||
{ TTYC_KF36, KEYC_F12|KEYC_CTRL },
|
||||
{ TTYC_KF25, KEYC_F1|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF26, KEYC_F2|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF27, KEYC_F3|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF28, KEYC_F4|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF29, KEYC_F5|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF30, KEYC_F6|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF31, KEYC_F7|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF32, KEYC_F8|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF33, KEYC_F9|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF34, KEYC_F10|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF35, KEYC_F11|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF36, KEYC_F12|KEYC_CTRL|KEYC_XTERM },
|
||||
|
||||
{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL },
|
||||
{ TTYC_KF37, KEYC_F1|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF38, KEYC_F2|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF39, KEYC_F3|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF40, KEYC_F4|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF41, KEYC_F5|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF42, KEYC_F6|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF43, KEYC_F7|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF44, KEYC_F8|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF45, KEYC_F9|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF46, KEYC_F10|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF47, KEYC_F11|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
{ TTYC_KF48, KEYC_F12|KEYC_SHIFT|KEYC_CTRL|KEYC_XTERM },
|
||||
|
||||
{ TTYC_KF49, KEYC_F1|KEYC_ESCAPE },
|
||||
{ TTYC_KF50, KEYC_F2|KEYC_ESCAPE },
|
||||
{ TTYC_KF51, KEYC_F3|KEYC_ESCAPE },
|
||||
{ TTYC_KF52, KEYC_F4|KEYC_ESCAPE },
|
||||
{ TTYC_KF53, KEYC_F5|KEYC_ESCAPE },
|
||||
{ TTYC_KF54, KEYC_F6|KEYC_ESCAPE },
|
||||
{ TTYC_KF55, KEYC_F7|KEYC_ESCAPE },
|
||||
{ TTYC_KF56, KEYC_F8|KEYC_ESCAPE },
|
||||
{ TTYC_KF57, KEYC_F9|KEYC_ESCAPE },
|
||||
{ TTYC_KF58, KEYC_F10|KEYC_ESCAPE },
|
||||
{ TTYC_KF59, KEYC_F11|KEYC_ESCAPE },
|
||||
{ TTYC_KF60, KEYC_F12|KEYC_ESCAPE },
|
||||
{ TTYC_KF49, KEYC_F1|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF50, KEYC_F2|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF51, KEYC_F3|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF52, KEYC_F4|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF53, KEYC_F5|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF54, KEYC_F6|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF55, KEYC_F7|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF56, KEYC_F8|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF57, KEYC_F9|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF58, KEYC_F10|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF59, KEYC_F11|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KF60, KEYC_F12|KEYC_ESCAPE|KEYC_XTERM },
|
||||
|
||||
{ TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT },
|
||||
{ TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT },
|
||||
{ TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT },
|
||||
{ TTYC_KF61, KEYC_F1|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF62, KEYC_F2|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KF63, KEYC_F3|KEYC_ESCAPE|KEYC_SHIFT|KEYC_XTERM },
|
||||
|
||||
{ TTYC_KICH1, KEYC_IC },
|
||||
{ TTYC_KDCH1, KEYC_DC },
|
||||
@@ -261,10 +266,7 @@ static const struct tty_default_key_code tty_default_code_keys[] = {
|
||||
{ TTYC_KCUB1, KEYC_LEFT },
|
||||
{ TTYC_KCUF1, KEYC_RIGHT },
|
||||
|
||||
/*
|
||||
* Key and modifier capabilities. We set the xterm flag to mark that
|
||||
* any leading escape means an escape key press and not the modifier.
|
||||
*/
|
||||
/* Key and modifier capabilities. */
|
||||
{ TTYC_KDC2, KEYC_DC|KEYC_SHIFT|KEYC_XTERM },
|
||||
{ TTYC_KDC3, KEYC_DC|KEYC_ESCAPE|KEYC_XTERM },
|
||||
{ TTYC_KDC4, KEYC_DC|KEYC_SHIFT|KEYC_ESCAPE|KEYC_XTERM },
|
||||
|
||||
@@ -494,8 +494,9 @@ tty_term_find(char *name, int fd, char **cause)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Figure out if we have 256. */
|
||||
if (tty_term_number(term, TTYC_COLORS) == 256)
|
||||
/* Figure out if we have 256 colours (or more). */
|
||||
if (tty_term_number(term, TTYC_COLORS) >= 256 ||
|
||||
tty_term_has(term, TTYC_RGB))
|
||||
term->flags |= TERM_256COLOURS;
|
||||
|
||||
/*
|
||||
|
||||
41
tty.c
41
tty.c
@@ -913,6 +913,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
||||
int flags, cleared = 0;
|
||||
char buf[512];
|
||||
size_t len, old_len;
|
||||
u_int cellsize;
|
||||
|
||||
flags = (tty->flags & TTY_NOCURSOR);
|
||||
tty->flags |= TTY_NOCURSOR;
|
||||
@@ -926,15 +927,17 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
|
||||
* there may be empty background cells after it (from BCE).
|
||||
*/
|
||||
sx = screen_size_x(s);
|
||||
if (sx > gd->linedata[gd->hsize + py].cellsize)
|
||||
sx = gd->linedata[gd->hsize + py].cellsize;
|
||||
|
||||
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
|
||||
if (sx > cellsize)
|
||||
sx = cellsize;
|
||||
if (sx > tty->sx)
|
||||
sx = tty->sx;
|
||||
ux = 0;
|
||||
|
||||
if (wp == NULL ||
|
||||
py == 0 ||
|
||||
(~gd->linedata[gd->hsize + py - 1].flags & GRID_LINE_WRAPPED) ||
|
||||
(~grid_get_line(gd, gd->hsize + py - 1)->flags & GRID_LINE_WRAPPED) ||
|
||||
ox != 0 ||
|
||||
tty->cx < tty->sx ||
|
||||
screen_size_x(s) < tty->sx) {
|
||||
@@ -1244,13 +1247,18 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_margin_pane(tty, ctx);
|
||||
|
||||
/*
|
||||
* If we want to wrap a pane, the cursor needs to be exactly on the
|
||||
* right of the region. But if the pane isn't on the right, it may be
|
||||
* off the edge - if so, move the cursor back to the right.
|
||||
* If we want to wrap a pane while using margins, the cursor needs to
|
||||
* be exactly on the right of the region. If the cursor is entirely off
|
||||
* the edge - move it back to the right. Some terminals are funny about
|
||||
* this and insert extra spaces, so only use the right if margins are
|
||||
* enabled.
|
||||
*/
|
||||
if (ctx->xoff + ctx->ocx > tty->rright)
|
||||
tty_cursor(tty, tty->rright, ctx->yoff + ctx->ocy);
|
||||
else
|
||||
if (ctx->xoff + ctx->ocx > tty->rright) {
|
||||
if (!tty_use_margin(tty))
|
||||
tty_cursor(tty, 0, ctx->yoff + ctx->ocy);
|
||||
else
|
||||
tty_cursor(tty, tty->rright, ctx->yoff + ctx->ocy);
|
||||
} else
|
||||
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
tty_putc(tty, '\n');
|
||||
@@ -1275,11 +1283,16 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_margin_pane(tty, ctx);
|
||||
|
||||
if (ctx->num == 1 || !tty_term_has(tty->term, TTYC_INDN)) {
|
||||
tty_cursor(tty, tty->rright, tty->rlower);
|
||||
if (!tty_use_margin(tty))
|
||||
tty_cursor(tty, 0, tty->rlower);
|
||||
else
|
||||
tty_cursor(tty, tty->rright, tty->rlower);
|
||||
for (i = 0; i < ctx->num; i++)
|
||||
tty_putc(tty, '\n');
|
||||
} else
|
||||
} else {
|
||||
tty_cursor(tty, 0, tty->cy);
|
||||
tty_putcode1(tty, TTYC_INDN, ctx->num);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1990,8 +2003,7 @@ tty_colours_fg(struct tty *tty, const struct grid_cell *gc)
|
||||
char s[32];
|
||||
|
||||
/* Is this a 24-bit or 256-colour colour? */
|
||||
if (gc->fg & COLOUR_FLAG_RGB ||
|
||||
gc->fg & COLOUR_FLAG_256) {
|
||||
if (gc->fg & COLOUR_FLAG_RGB || gc->fg & COLOUR_FLAG_256) {
|
||||
if (tty_try_colour(tty, gc->fg, "38") == 0)
|
||||
goto save_fg;
|
||||
/* Should not get here, already converted in tty_check_fg. */
|
||||
@@ -2020,8 +2032,7 @@ tty_colours_bg(struct tty *tty, const struct grid_cell *gc)
|
||||
char s[32];
|
||||
|
||||
/* Is this a 24-bit or 256-colour colour? */
|
||||
if (gc->bg & COLOUR_FLAG_RGB ||
|
||||
gc->bg & COLOUR_FLAG_256) {
|
||||
if (gc->bg & COLOUR_FLAG_RGB || gc->bg & COLOUR_FLAG_256) {
|
||||
if (tty_try_colour(tty, gc->bg, "48") == 0)
|
||||
goto save_bg;
|
||||
/* Should not get here, already converted in tty_check_bg. */
|
||||
|
||||
154
window-copy.c
154
window-copy.c
@@ -65,8 +65,9 @@ static void window_copy_update_cursor(struct window_pane *, u_int, u_int);
|
||||
static void window_copy_start_selection(struct window_pane *);
|
||||
static int window_copy_adjust_selection(struct window_pane *, u_int *,
|
||||
u_int *);
|
||||
static int window_copy_set_selection(struct window_pane *, int);
|
||||
static int window_copy_update_selection(struct window_pane *, int);
|
||||
static void window_copy_synchronize_cursor(struct window_pane *wp);
|
||||
static void window_copy_synchronize_cursor(struct window_pane *);
|
||||
static void *window_copy_get_selection(struct window_pane *, size_t *);
|
||||
static void window_copy_copy_buffer(struct window_pane *, const char *,
|
||||
void *, size_t);
|
||||
@@ -151,12 +152,12 @@ struct window_copy_mode_data {
|
||||
struct screen *backing;
|
||||
int backing_written; /* backing display started */
|
||||
|
||||
u_int oy; /* number of lines scrolled up */
|
||||
u_int oy; /* number of lines scrolled up */
|
||||
|
||||
u_int selx; /* beginning of selection */
|
||||
u_int selx; /* beginning of selection */
|
||||
u_int sely;
|
||||
|
||||
u_int endselx; /* end of selection */
|
||||
u_int endselx; /* end of selection */
|
||||
u_int endsely;
|
||||
|
||||
enum {
|
||||
@@ -165,14 +166,20 @@ struct window_copy_mode_data {
|
||||
CURSORDRAG_SEL, /* start is synchronized with cursor */
|
||||
} cursordrag;
|
||||
|
||||
int modekeys;
|
||||
enum {
|
||||
LINE_SEL_NONE,
|
||||
LINE_SEL_LEFT_RIGHT,
|
||||
LINE_SEL_RIGHT_LEFT,
|
||||
} lineflag; /* line selection mode */
|
||||
int rectflag; /* in rectangle copy mode? */
|
||||
int scroll_exit; /* exit on scroll to end? */
|
||||
|
||||
u_int cx;
|
||||
u_int cy;
|
||||
|
||||
u_int lastcx; /* position in last line w/ content */
|
||||
u_int lastsx; /* size of last line w/ content */
|
||||
u_int lastcx; /* position in last line w/ content */
|
||||
u_int lastsx; /* size of last line w/ content */
|
||||
|
||||
int searchtype;
|
||||
char *searchstr;
|
||||
@@ -194,21 +201,10 @@ window_copy_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
struct window_copy_mode_data *data;
|
||||
struct screen *s;
|
||||
|
||||
wp->modedata = data = xmalloc(sizeof *data);
|
||||
|
||||
data->oy = 0;
|
||||
data->cx = 0;
|
||||
data->cy = 0;
|
||||
wp->modedata = data = xcalloc(1, sizeof *data);
|
||||
|
||||
data->cursordrag = CURSORDRAG_NONE;
|
||||
|
||||
data->lastcx = 0;
|
||||
data->lastsx = 0;
|
||||
|
||||
data->backing_written = 0;
|
||||
|
||||
data->rectflag = 0;
|
||||
data->scroll_exit = 0;
|
||||
data->lineflag = LINE_SEL_NONE;
|
||||
|
||||
if (wp->searchstr != NULL) {
|
||||
data->searchtype = WINDOW_COPY_SEARCHUP;
|
||||
@@ -228,7 +224,7 @@ window_copy_init(struct window_pane *wp, __unused struct cmd_find_state *fs,
|
||||
|
||||
s = &data->screen;
|
||||
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
|
||||
s->sel.modekeys = options_get_number(wp->window->options, "mode-keys");
|
||||
data->modekeys = options_get_number(wp->window->options, "mode-keys");
|
||||
|
||||
data->backing = NULL;
|
||||
|
||||
@@ -357,7 +353,7 @@ window_copy_pageup(struct window_pane *wp, int half_page)
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wp, oy);
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
window_copy_other_end(wp);
|
||||
|
||||
if (data->cx != ox) {
|
||||
@@ -379,7 +375,7 @@ window_copy_pageup(struct window_pane *wp, int half_page)
|
||||
else
|
||||
data->oy += n;
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
if (data->screen.sel == NULL || !data->rectflag) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
@@ -401,7 +397,7 @@ window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit)
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wp, oy);
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT && oy == data->sely)
|
||||
if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->sely)
|
||||
window_copy_other_end(wp);
|
||||
|
||||
if (data->cx != ox) {
|
||||
@@ -423,7 +419,7 @@ window_copy_pagedown(struct window_pane *wp, int half_page, int scroll_exit)
|
||||
else
|
||||
data->oy -= n;
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
if (data->screen.sel == NULL || !data->rectflag) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
@@ -554,7 +550,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s,
|
||||
if (m != NULL)
|
||||
window_copy_start_drag(c, m);
|
||||
else {
|
||||
sn->sel.lineflag = LINE_SEL_NONE;
|
||||
data->lineflag = LINE_SEL_NONE;
|
||||
window_copy_start_selection(wp);
|
||||
redraw = 1;
|
||||
}
|
||||
@@ -763,7 +759,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s,
|
||||
window_copy_cursor_previous_word(wp, ws);
|
||||
}
|
||||
if (strcmp(command, "rectangle-toggle") == 0) {
|
||||
sn->sel.lineflag = LINE_SEL_NONE;
|
||||
data->lineflag = LINE_SEL_NONE;
|
||||
window_copy_rectangle_toggle(wp);
|
||||
}
|
||||
if (strcmp(command, "scroll-down") == 0 ||
|
||||
@@ -800,7 +796,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s,
|
||||
}
|
||||
}
|
||||
if (strcmp(command, "select-line") == 0) {
|
||||
sn->sel.lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
data->lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
data->rectflag = 0;
|
||||
window_copy_cursor_start_of_line(wp);
|
||||
window_copy_start_selection(wp);
|
||||
@@ -810,7 +806,7 @@ window_copy_command(struct window_pane *wp, struct client *c, struct session *s,
|
||||
redraw = 1;
|
||||
}
|
||||
if (strcmp(command, "select-word") == 0) {
|
||||
sn->sel.lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
data->lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
data->rectflag = 0;
|
||||
ws = options_get_string(s->options, "word-separators");
|
||||
window_copy_cursor_previous_word(wp, ws);
|
||||
@@ -1434,7 +1430,6 @@ static void
|
||||
window_copy_start_selection(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
data->selx = data->cx;
|
||||
data->sely = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
@@ -1444,8 +1439,7 @@ window_copy_start_selection(struct window_pane *wp)
|
||||
|
||||
data->cursordrag = CURSORDRAG_ENDSEL;
|
||||
|
||||
s->sel.flag = 1;
|
||||
window_copy_update_selection(wp, 1);
|
||||
window_copy_set_selection(wp, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1482,6 +1476,17 @@ window_copy_adjust_selection(struct window_pane *wp, u_int *selx, u_int *sely)
|
||||
|
||||
static int
|
||||
window_copy_update_selection(struct window_pane *wp, int may_redraw)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
if (s->sel == NULL && data->lineflag == LINE_SEL_NONE)
|
||||
return (0);
|
||||
return (window_copy_set_selection(wp, may_redraw));
|
||||
}
|
||||
|
||||
static int
|
||||
window_copy_set_selection(struct window_pane *wp, int may_redraw)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
@@ -1490,9 +1495,6 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw)
|
||||
u_int sx, sy, cy, endsx, endsy;
|
||||
int startrelpos, endrelpos;
|
||||
|
||||
if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
|
||||
return (0);
|
||||
|
||||
window_copy_synchronize_cursor(wp);
|
||||
|
||||
/* Adjust the selection. */
|
||||
@@ -1515,7 +1517,8 @@ window_copy_update_selection(struct window_pane *wp, int may_redraw)
|
||||
/* Set colours and selection. */
|
||||
style_apply(&gc, oo, "mode-style");
|
||||
gc.flags |= GRID_FLAG_NOPALETTE;
|
||||
screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag, &gc);
|
||||
screen_set_selection(s, sx, sy, endsx, endsy, data->rectflag,
|
||||
data->modekeys, &gc);
|
||||
|
||||
if (data->rectflag && may_redraw) {
|
||||
/*
|
||||
@@ -1548,10 +1551,10 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
|
||||
char *buf;
|
||||
size_t off;
|
||||
u_int i, xx, yy, sx, sy, ex, ey, ey_last;
|
||||
u_int firstsx, lastex, restex, restsx;
|
||||
u_int firstsx, lastex, restex, restsx, selx;
|
||||
int keys;
|
||||
|
||||
if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
|
||||
if (data->screen.sel == NULL && data->lineflag == LINE_SEL_NONE)
|
||||
return (NULL);
|
||||
|
||||
buf = xmalloc(1);
|
||||
@@ -1599,7 +1602,11 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
|
||||
* Need to ignore the column with the cursor in it, which for
|
||||
* rectangular copy means knowing which side the cursor is on.
|
||||
*/
|
||||
if (data->selx < data->cx) {
|
||||
if (data->cursordrag == CURSORDRAG_ENDSEL)
|
||||
selx = data->selx;
|
||||
else
|
||||
selx = data->endselx;
|
||||
if (selx < data->cx) {
|
||||
/* Selection start is on the left. */
|
||||
if (keys == MODEKEY_EMACS) {
|
||||
lastex = data->cx;
|
||||
@@ -1609,12 +1616,12 @@ window_copy_get_selection(struct window_pane *wp, size_t *len)
|
||||
lastex = data->cx + 1;
|
||||
restex = data->cx + 1;
|
||||
}
|
||||
firstsx = data->selx;
|
||||
restsx = data->selx;
|
||||
firstsx = selx;
|
||||
restsx = selx;
|
||||
} else {
|
||||
/* Cursor is on the left. */
|
||||
lastex = data->selx + 1;
|
||||
restex = data->selx + 1;
|
||||
lastex = selx + 1;
|
||||
restex = selx + 1;
|
||||
firstsx = data->cx;
|
||||
restsx = data->cx;
|
||||
}
|
||||
@@ -1751,7 +1758,7 @@ window_copy_copy_line(struct window_pane *wp, char **buf, size_t *off, u_int sy,
|
||||
* Work out if the line was wrapped at the screen edge and all of it is
|
||||
* on screen.
|
||||
*/
|
||||
gl = &gd->linedata[sy];
|
||||
gl = grid_get_line(gd, sy);
|
||||
if (gl->flags & GRID_LINE_WRAPPED && gl->cellsize <= gd->sx)
|
||||
wrapped = 1;
|
||||
|
||||
@@ -1839,7 +1846,7 @@ window_copy_find_length(struct window_pane *wp, u_int py)
|
||||
* width of the grid, and screen_write_copy treats them as spaces, so
|
||||
* ignore them here too.
|
||||
*/
|
||||
px = s->grid->linedata[py].cellsize;
|
||||
px = grid_get_line(s->grid, py)->cellsize;
|
||||
if (px > screen_size_x(s))
|
||||
px = screen_size_x(s);
|
||||
while (px > 0) {
|
||||
@@ -1856,14 +1863,13 @@ window_copy_cursor_start_of_line(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *back_s = data->backing;
|
||||
struct screen *s = &data->screen;
|
||||
struct grid *gd = back_s->grid;
|
||||
u_int py;
|
||||
|
||||
if (data->cx == 0 && s->sel.lineflag == LINE_SEL_NONE) {
|
||||
if (data->cx == 0 && data->lineflag == LINE_SEL_NONE) {
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
while (py > 0 &&
|
||||
gd->linedata[py-1].flags & GRID_LINE_WRAPPED) {
|
||||
grid_get_line(gd, py - 1)->flags & GRID_LINE_WRAPPED) {
|
||||
window_copy_cursor_up(wp, 0);
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
}
|
||||
@@ -1901,22 +1907,24 @@ window_copy_cursor_end_of_line(struct window_pane *wp)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *back_s = data->backing;
|
||||
struct screen *s = &data->screen;
|
||||
struct grid *gd = back_s->grid;
|
||||
struct grid_line *gl;
|
||||
u_int px, py;
|
||||
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
|
||||
if (data->cx == px && s->sel.lineflag == LINE_SEL_NONE) {
|
||||
if (data->screen.sel.flag && data->rectflag)
|
||||
if (data->cx == px && data->lineflag == LINE_SEL_NONE) {
|
||||
if (data->screen.sel != NULL && data->rectflag)
|
||||
px = screen_size_x(back_s);
|
||||
if (gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||
while (py < gd->sy + gd->hsize &&
|
||||
gd->linedata[py].flags & GRID_LINE_WRAPPED) {
|
||||
gl = grid_get_line(gd, py);
|
||||
if (gl->flags & GRID_LINE_WRAPPED) {
|
||||
while (py < gd->sy + gd->hsize) {
|
||||
gl = grid_get_line(gd, py);
|
||||
if (~gl->flags & GRID_LINE_WRAPPED)
|
||||
break;
|
||||
window_copy_cursor_down(wp, 0);
|
||||
py = screen_hsize(back_s)
|
||||
+ data->cy - data->oy;
|
||||
py = screen_hsize(back_s) + data->cy - data->oy;
|
||||
}
|
||||
px = window_copy_find_length(wp, py);
|
||||
}
|
||||
@@ -1934,13 +1942,13 @@ window_copy_other_end(struct window_pane *wp)
|
||||
struct screen *s = &data->screen;
|
||||
u_int selx, sely, cy, yy, hsize;
|
||||
|
||||
if (!s->sel.flag && s->sel.lineflag == LINE_SEL_NONE)
|
||||
if (s->sel == NULL && data->lineflag == LINE_SEL_NONE)
|
||||
return;
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
s->sel.lineflag = LINE_SEL_RIGHT_LEFT;
|
||||
else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
s->sel.lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
data->lineflag = LINE_SEL_RIGHT_LEFT;
|
||||
else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
data->lineflag = LINE_SEL_LEFT_RIGHT;
|
||||
|
||||
switch (data->cursordrag) {
|
||||
case CURSORDRAG_NONE:
|
||||
@@ -2012,7 +2020,7 @@ window_copy_cursor_right(struct window_pane *wp)
|
||||
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
yy = screen_hsize(data->backing) + screen_size_y(data->backing) - 1;
|
||||
if (data->screen.sel.flag && data->rectflag)
|
||||
if (data->screen.sel != NULL && data->rectflag)
|
||||
px = screen_size_x(&data->screen);
|
||||
else
|
||||
px = window_copy_find_length(wp, py);
|
||||
@@ -2049,7 +2057,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
||||
data->lastsx = ox;
|
||||
}
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
window_copy_other_end(wp);
|
||||
|
||||
data->cx = data->lastcx;
|
||||
@@ -2071,7 +2079,7 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
if (data->screen.sel != NULL || !data->rectflag) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
@@ -2079,9 +2087,9 @@ window_copy_cursor_up(struct window_pane *wp, int scroll_only)
|
||||
window_copy_cursor_end_of_line(wp);
|
||||
}
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
window_copy_cursor_end_of_line(wp);
|
||||
else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
window_copy_cursor_start_of_line(wp);
|
||||
}
|
||||
|
||||
@@ -2099,7 +2107,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
data->lastsx = ox;
|
||||
}
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
|
||||
if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
|
||||
window_copy_other_end(wp);
|
||||
|
||||
data->cx = data->lastcx;
|
||||
@@ -2113,7 +2121,7 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
window_copy_redraw_lines(wp, data->cy - 1, 2);
|
||||
}
|
||||
|
||||
if (!data->screen.sel.flag || !data->rectflag) {
|
||||
if (data->screen.sel == NULL || !data->rectflag) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wp, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
@@ -2121,9 +2129,9 @@ window_copy_cursor_down(struct window_pane *wp, int scroll_only)
|
||||
window_copy_cursor_end_of_line(wp);
|
||||
}
|
||||
|
||||
if (s->sel.lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT)
|
||||
window_copy_cursor_end_of_line(wp);
|
||||
else if (s->sel.lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
else if (data->lineflag == LINE_SEL_RIGHT_LEFT)
|
||||
window_copy_cursor_start_of_line(wp);
|
||||
}
|
||||
|
||||
@@ -2394,7 +2402,7 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny)
|
||||
window_copy_write_line(wp, &ctx, 1);
|
||||
if (screen_size_y(s) > 3)
|
||||
window_copy_write_line(wp, &ctx, screen_size_y(s) - 2);
|
||||
if (s->sel.flag && screen_size_y(s) > ny)
|
||||
if (s->sel != NULL && screen_size_y(s) > ny)
|
||||
window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
|
||||
screen_write_cursormove(&ctx, data->cx, data->cy);
|
||||
screen_write_stop(&ctx);
|
||||
@@ -2422,7 +2430,7 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
|
||||
screen_write_cursormove(&ctx, 0, 0);
|
||||
screen_write_insertline(&ctx, ny, 8);
|
||||
window_copy_write_lines(wp, &ctx, 0, ny);
|
||||
if (s->sel.flag && screen_size_y(s) > ny)
|
||||
if (s->sel != NULL && screen_size_y(s) > ny)
|
||||
window_copy_write_line(wp, &ctx, ny);
|
||||
else if (ny == 1) /* nuke position */
|
||||
window_copy_write_line(wp, &ctx, 1);
|
||||
@@ -2434,13 +2442,13 @@ void
|
||||
window_copy_add_formats(struct window_pane *wp, struct format_tree *ft)
|
||||
{
|
||||
struct window_copy_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
if (wp->mode != &window_copy_mode)
|
||||
return;
|
||||
|
||||
format_add(ft, "selection_present", "%d", s->sel.flag);
|
||||
format_add(ft, "selection_present", "%d", data->screen.sel != NULL);
|
||||
format_add(ft, "scroll_position", "%d", data->oy);
|
||||
format_add(ft, "rectangle_toggle", "%d", data->rectflag);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
124
window-tree.c
124
window-tree.c
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -860,8 +861,6 @@ window_tree_destroy(struct window_tree_modedata *data)
|
||||
if (--data->references != 0)
|
||||
return;
|
||||
|
||||
mode_tree_free(data->data);
|
||||
|
||||
for (i = 0; i < data->item_size; i++)
|
||||
window_tree_free_item(data->item_list[i]);
|
||||
free(data->item_list);
|
||||
@@ -881,6 +880,7 @@ window_tree_free(struct window_pane *wp)
|
||||
return;
|
||||
|
||||
data->dead = 1;
|
||||
mode_tree_free(data->data);
|
||||
window_tree_destroy(data);
|
||||
}
|
||||
|
||||
@@ -965,7 +965,7 @@ window_tree_command_callback(struct client *c, void *modedata, const char *s,
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
|
||||
if (s == NULL || data->dead)
|
||||
if (s == NULL || *s == '\0' || data->dead)
|
||||
return (0);
|
||||
|
||||
data->entered = s;
|
||||
@@ -987,6 +987,77 @@ window_tree_command_free(void *modedata)
|
||||
window_tree_destroy(data);
|
||||
}
|
||||
|
||||
static void
|
||||
window_tree_kill_each(__unused void* modedata, void* itemdata,
|
||||
__unused struct client *c, __unused key_code key)
|
||||
{
|
||||
struct window_tree_itemdata *item = itemdata;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
|
||||
window_tree_pull_item(item, &s, &wl, &wp);
|
||||
|
||||
switch (item->type) {
|
||||
case WINDOW_TREE_NONE:
|
||||
break;
|
||||
case WINDOW_TREE_SESSION:
|
||||
if (s != NULL) {
|
||||
server_destroy_session(s);
|
||||
session_destroy(s, __func__);
|
||||
}
|
||||
break;
|
||||
case WINDOW_TREE_WINDOW:
|
||||
if (wl != NULL)
|
||||
server_kill_window(wl->window);
|
||||
break;
|
||||
case WINDOW_TREE_PANE:
|
||||
if (wp != NULL)
|
||||
server_kill_pane(wp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_kill_current_callback(struct client *c, void *modedata,
|
||||
const char *s, __unused int done)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct mode_tree_data *mtd = data->data;
|
||||
|
||||
if (s == NULL || *s == '\0' || data->dead)
|
||||
return (0);
|
||||
if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
|
||||
return (0);
|
||||
|
||||
window_tree_kill_each(data, mode_tree_get_current(mtd), c, KEYC_NONE);
|
||||
|
||||
data->references++;
|
||||
cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
window_tree_kill_tagged_callback(struct client *c, void *modedata,
|
||||
const char *s, __unused int done)
|
||||
{
|
||||
struct window_tree_modedata *data = modedata;
|
||||
struct mode_tree_data *mtd = data->data;
|
||||
|
||||
if (s == NULL || *s == '\0' || data->dead)
|
||||
return (0);
|
||||
if (tolower((u_char) s[0]) != 'y' || s[1] != '\0')
|
||||
return (0);
|
||||
|
||||
mode_tree_each_tagged(mtd, window_tree_kill_each, c, KEYC_NONE, 1);
|
||||
|
||||
data->references++;
|
||||
cmdq_append(c, cmdq_get_callback(window_tree_command_done, data));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static key_code
|
||||
window_tree_mouse(struct window_tree_modedata *data, key_code key, u_int x,
|
||||
struct window_tree_itemdata *item)
|
||||
@@ -1054,10 +1125,13 @@ window_tree_key(struct window_pane *wp, struct client *c,
|
||||
{
|
||||
struct window_tree_modedata *data = wp->modedata;
|
||||
struct window_tree_itemdata *item, *new_item;
|
||||
char *name, *prompt;
|
||||
char *name, *prompt = NULL;
|
||||
struct cmd_find_state fs;
|
||||
int finished;
|
||||
u_int tagged, x, y;
|
||||
u_int tagged, x, y, idx;
|
||||
struct session *ns;
|
||||
struct winlink *nwl;
|
||||
struct window_pane *nwp;
|
||||
|
||||
item = mode_tree_get_current(data->data);
|
||||
finished = mode_tree_key(data->data, c, &key, m, &x, &y);
|
||||
@@ -1074,6 +1148,46 @@ window_tree_key(struct window_pane *wp, struct client *c,
|
||||
case '>':
|
||||
data->offset++;
|
||||
break;
|
||||
case 'x':
|
||||
window_tree_pull_item(item, &ns, &nwl, &nwp);
|
||||
switch (item->type) {
|
||||
case WINDOW_TREE_NONE:
|
||||
break;
|
||||
case WINDOW_TREE_SESSION:
|
||||
if (ns == NULL)
|
||||
break;
|
||||
xasprintf(&prompt, "Kill session %s? ", ns->name);
|
||||
break;
|
||||
case WINDOW_TREE_WINDOW:
|
||||
if (nwl == NULL)
|
||||
break;
|
||||
xasprintf(&prompt, "Kill window %u? ", nwl->idx);
|
||||
break;
|
||||
case WINDOW_TREE_PANE:
|
||||
if (nwp == NULL || window_pane_index(nwp, &idx) != 0)
|
||||
break;
|
||||
xasprintf(&prompt, "Kill pane %u? ", idx);
|
||||
break;
|
||||
}
|
||||
if (prompt == NULL)
|
||||
break;
|
||||
data->references++;
|
||||
status_prompt_set(c, prompt, "",
|
||||
window_tree_kill_current_callback, window_tree_command_free,
|
||||
data, PROMPT_SINGLE|PROMPT_NOFORMAT);
|
||||
free(prompt);
|
||||
break;
|
||||
case 'X':
|
||||
tagged = mode_tree_count_tagged(data->data);
|
||||
if (tagged == 0)
|
||||
break;
|
||||
xasprintf(&prompt, "Kill %u tagged? ", tagged);
|
||||
data->references++;
|
||||
status_prompt_set(c, prompt, "",
|
||||
window_tree_kill_tagged_callback, window_tree_command_free,
|
||||
data, PROMPT_SINGLE|PROMPT_NOFORMAT);
|
||||
free(prompt);
|
||||
break;
|
||||
case ':':
|
||||
tagged = mode_tree_count_tagged(data->data);
|
||||
if (tagged != 0)
|
||||
|
||||
11
window.c
11
window.c
@@ -921,10 +921,11 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
wp->flags &= ~(PANE_STATUSREADY|PANE_STATUSDRAWN);
|
||||
|
||||
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||
log_debug("spawn: %s -- %s", wp->shell, cmd);
|
||||
for (i = 0; i < wp->argc; i++)
|
||||
log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
|
||||
environ_log(env, "spawn: ");
|
||||
log_debug("%s: shell=%s", __func__, wp->shell);
|
||||
log_debug("%s: cmd=%s", __func__, cmd);
|
||||
log_debug("%s: cwd=%s", __func__, cwd);
|
||||
cmd_log_argv(wp->argc, wp->argv, __func__);
|
||||
environ_log(env, "%s: environment ", __func__);
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = screen_size_x(&wp->base);
|
||||
@@ -1005,6 +1006,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
execl(wp->shell, argv0, (char *)NULL);
|
||||
fatal("execl failed");
|
||||
}
|
||||
log_debug("%s: master=%s", __func__, ttyname(wp->fd));
|
||||
log_debug("%s: slave=%s", __func__, wp->tty);
|
||||
|
||||
#ifdef HAVE_UTEMPTER
|
||||
xsnprintf(s, sizeof s, "tmux(%lu).%%%u", (long) getpid(), wp->id);
|
||||
|
||||
Reference in New Issue
Block a user