mirror of
https://github.com/tmux/tmux.git
synced 2026-10-07 01:55:49 +00:00
Merge branch 'obsd-master'
This commit is contained in:
170
window.c
170
window.c
@@ -78,6 +78,14 @@ RB_GENERATE(windows, window, entry, window_cmp);
|
||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
||||
RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp);
|
||||
|
||||
struct window_pane_prompt {
|
||||
u_int wp_id;
|
||||
struct client *c;
|
||||
status_prompt_input_cb inputcb;
|
||||
prompt_free_cb freecb;
|
||||
void *data;
|
||||
};
|
||||
|
||||
int
|
||||
window_cmp(struct window *w1, struct window *w2)
|
||||
{
|
||||
@@ -1155,6 +1163,8 @@ window_pane_destroy(struct window_pane *wp)
|
||||
window_pane_wait_finish(wp);
|
||||
spawn_editor_finish(wp);
|
||||
|
||||
window_pane_clear_prompt(wp);
|
||||
|
||||
window_pane_free_modes(wp);
|
||||
free(wp->searchstr);
|
||||
|
||||
@@ -1371,6 +1381,7 @@ window_pane_reset_mode(struct window_pane *wp)
|
||||
server_kill_pane(wp);
|
||||
}
|
||||
|
||||
/* Reset all modes. */
|
||||
void
|
||||
window_pane_reset_mode_all(struct window_pane *wp)
|
||||
{
|
||||
@@ -1378,6 +1389,165 @@ window_pane_reset_mode_all(struct window_pane *wp)
|
||||
window_pane_reset_mode(wp);
|
||||
}
|
||||
|
||||
/* Prompt input callback. */
|
||||
static enum prompt_result
|
||||
window_pane_prompt_input_callback(void *data, const char *s,
|
||||
enum prompt_key_result key)
|
||||
{
|
||||
struct window_pane_prompt *wpp = data;
|
||||
|
||||
if (wpp->inputcb != NULL)
|
||||
return (wpp->inputcb(wpp->c, wpp->data, s, key));
|
||||
return (PROMPT_CLOSE);
|
||||
}
|
||||
|
||||
/* Prompt free callback. */
|
||||
static void
|
||||
window_pane_prompt_free_callback(void *data)
|
||||
{
|
||||
struct window_pane_prompt *wpp = data;
|
||||
struct window_pane *wp;
|
||||
|
||||
wp = window_pane_find_by_id(wpp->wp_id);
|
||||
if (wp != NULL && wp->prompt_data == wpp)
|
||||
wp->prompt_data = NULL;
|
||||
if (wpp->freecb != NULL)
|
||||
wpp->freecb(wpp->data);
|
||||
free(wpp);
|
||||
}
|
||||
|
||||
/* Open a prompt owned by a pane, drawn over the pane instead of the status. */
|
||||
void
|
||||
window_pane_set_prompt(struct window_pane *wp, struct client *c,
|
||||
struct cmd_find_state *fs, const char *msg, const char *input,
|
||||
status_prompt_input_cb inputcb, prompt_free_cb freecb, void *data,
|
||||
int flags, enum prompt_type type)
|
||||
{
|
||||
struct session *s = NULL;
|
||||
struct prompt_create_data pd;
|
||||
struct window_pane_prompt *wpp;
|
||||
|
||||
if (c != NULL)
|
||||
s = c->session;
|
||||
|
||||
window_pane_clear_prompt(wp);
|
||||
|
||||
wpp = xcalloc(1, sizeof *wpp);
|
||||
wpp->wp_id = wp->id;
|
||||
wpp->c = c;
|
||||
wpp->inputcb = inputcb;
|
||||
wpp->freecb = freecb;
|
||||
wpp->data = data;
|
||||
|
||||
memset(&pd, 0, sizeof pd);
|
||||
prompt_set_options(&pd, s);
|
||||
pd.fs = fs;
|
||||
pd.prompt = msg;
|
||||
pd.input = input;
|
||||
pd.type = type;
|
||||
pd.flags = flags;
|
||||
pd.inputcb = window_pane_prompt_input_callback;
|
||||
pd.freecb = window_pane_prompt_free_callback;
|
||||
pd.data = wpp;
|
||||
|
||||
wp->prompt = prompt_create(&pd);
|
||||
wp->prompt_data = wpp;
|
||||
wp->flags |= PANE_REDRAW;
|
||||
|
||||
prompt_incremental_start(wp->prompt);
|
||||
}
|
||||
|
||||
/* Close a pane prompt. */
|
||||
void
|
||||
window_pane_clear_prompt(struct window_pane *wp)
|
||||
{
|
||||
struct prompt *prompt = wp->prompt;
|
||||
|
||||
if (prompt == NULL)
|
||||
return;
|
||||
wp->prompt = NULL;
|
||||
prompt_free(prompt);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
/* Does this pane have an open prompt? */
|
||||
int
|
||||
window_pane_has_prompt(struct window_pane *wp)
|
||||
{
|
||||
return (wp->prompt != NULL);
|
||||
}
|
||||
|
||||
/* Replace the message and input of an open pane prompt. */
|
||||
void
|
||||
window_pane_update_prompt(struct window_pane *wp, const char *msg,
|
||||
const char *input)
|
||||
{
|
||||
if (wp->prompt != NULL) {
|
||||
prompt_update(wp->prompt, msg, input);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass a key to a pane prompt. The client is set transiently for the duration
|
||||
* of the key in case the prompt or pane is destroyed by the callback.
|
||||
*/
|
||||
enum prompt_key_result
|
||||
window_pane_prompt_key(struct window_pane *wp, struct client *c, key_code key,
|
||||
struct mouse_event *m)
|
||||
{
|
||||
struct prompt *prompt = wp->prompt;
|
||||
struct window_pane_prompt *wpp = wp->prompt_data;
|
||||
enum prompt_key_result result;
|
||||
u_int wp_id = wp->id, x, y, py;
|
||||
int redraw = 0;
|
||||
|
||||
if (prompt == NULL)
|
||||
return (PROMPT_KEY_NOT_HANDLED);
|
||||
|
||||
if (wpp != NULL)
|
||||
wpp->c = c;
|
||||
if (KEYC_IS_MOUSE(key)) {
|
||||
if (m == NULL ||
|
||||
MOUSE_BUTTONS(m->b) != MOUSE_BUTTON_1 ||
|
||||
MOUSE_DRAG(m->b) ||
|
||||
MOUSE_RELEASE(m->b) ||
|
||||
cmd_mouse_at(wp, m, &x, &y, 0) != 0)
|
||||
result = PROMPT_KEY_NOT_HANDLED;
|
||||
else {
|
||||
if (c != NULL && status_at_line(c) == 0)
|
||||
py = 0;
|
||||
else
|
||||
py = wp->sy - 1;
|
||||
if (y == py) {
|
||||
result = prompt_mouse(prompt, x, 0, wp->sx,
|
||||
&redraw);
|
||||
} else
|
||||
result = PROMPT_KEY_NOT_HANDLED;
|
||||
}
|
||||
} else
|
||||
result = prompt_key(prompt, key, &redraw);
|
||||
|
||||
wp = window_pane_find_by_id(wp_id);
|
||||
if (wp == NULL)
|
||||
return (result);
|
||||
if (wpp != NULL && wp->prompt_data == wpp)
|
||||
wpp->c = NULL;
|
||||
|
||||
/*
|
||||
* Only an explicit close or the prompt marking itself closed ends it;
|
||||
* cursor movement and editing keep it open.
|
||||
*/
|
||||
if (wp->prompt == prompt &&
|
||||
(result == PROMPT_KEY_CLOSE || prompt_closed(prompt)))
|
||||
window_pane_clear_prompt(wp);
|
||||
|
||||
if (redraw || wp->prompt != prompt)
|
||||
wp->flags |= PANE_REDRAW;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_copy_paste(struct window_pane *wp, char *buf, size_t len)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user