version 1.84, 2017/01/15 22:00:56 |
version 1.85, 2017/01/24 21:50:23 |
|
|
struct window_choose_mode_data { |
struct window_choose_mode_data { |
struct screen screen; |
struct screen screen; |
|
|
struct mode_key_data mdata; |
|
|
|
struct window_choose_mode_item *list; |
struct window_choose_mode_item *list; |
u_int list_size; |
u_int list_size; |
struct window_choose_mode_item *old_list; |
struct window_choose_mode_item *old_list; |
|
|
void (*callbackfn)(struct window_choose_data *); |
void (*callbackfn)(struct window_choose_data *); |
}; |
}; |
|
|
|
static const char window_choose_keys_emacs[] = "0123456789" |
|
"abcdefghijklmnoprstuvwxyz" |
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
|
static const char window_choose_keys_vi[] = "0123456789" |
|
"abcdefhilmnoprstuvwxyz" |
|
"ABCDEFIJKMNOPQRSTUVWXYZ"; |
|
|
static void window_choose_free1(struct window_choose_mode_data *); |
static void window_choose_free1(struct window_choose_mode_data *); |
static int window_choose_key_index(struct window_choose_mode_data *, |
static int window_choose_key_index(struct window_pane *, u_int); |
u_int); |
static int window_choose_index_key(struct window_pane *, key_code); |
static int window_choose_index_key(struct window_choose_mode_data *, |
|
key_code); |
|
static void window_choose_prompt_input(enum window_choose_input_type, |
static void window_choose_prompt_input(enum window_choose_input_type, |
const char *, struct window_pane *, key_code); |
const char *, struct window_pane *, key_code); |
static void window_choose_reset_top(struct window_pane *, u_int); |
static void window_choose_reset_top(struct window_pane *, u_int); |
|
|
{ |
{ |
struct window_choose_mode_data *data; |
struct window_choose_mode_data *data; |
struct screen *s; |
struct screen *s; |
int keys; |
|
|
|
wp->modedata = data = xcalloc(1, sizeof *data); |
wp->modedata = data = xcalloc(1, sizeof *data); |
|
|
|
|
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); |
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0); |
s->mode &= ~MODE_CURSOR; |
s->mode &= ~MODE_CURSOR; |
|
|
keys = options_get_number(wp->window->options, "mode-keys"); |
|
if (keys == MODEKEY_EMACS) |
|
mode_key_init(&data->mdata, &mode_key_tree_emacs_choice); |
|
else |
|
mode_key_init(&data->mdata, &mode_key_tree_vi_choice); |
|
|
|
return (s); |
return (s); |
} |
} |
|
|
|
|
return (&data->list[idx]); |
return (&data->list[idx]); |
} |
} |
|
|
|
static key_code |
|
window_choose_translate_key(key_code key) |
|
{ |
|
switch (key) { |
|
case '0'|KEYC_ESCAPE: |
|
case '1'|KEYC_ESCAPE: |
|
case '2'|KEYC_ESCAPE: |
|
case '3'|KEYC_ESCAPE: |
|
case '4'|KEYC_ESCAPE: |
|
case '5'|KEYC_ESCAPE: |
|
case '6'|KEYC_ESCAPE: |
|
case '7'|KEYC_ESCAPE: |
|
case '8'|KEYC_ESCAPE: |
|
case '9'|KEYC_ESCAPE: |
|
case '\003': /* C-c */ |
|
case 'q': |
|
case '\n': |
|
case '\r': |
|
case KEYC_BSPACE: |
|
case ' ': |
|
case KEYC_LEFT: |
|
case KEYC_RIGHT: |
|
case KEYC_LEFT|KEYC_CTRL: |
|
case KEYC_RIGHT|KEYC_CTRL: |
|
case KEYC_MOUSEDOWN1_PANE: |
|
case KEYC_MOUSEDOWN3_PANE: |
|
case KEYC_WHEELUP_PANE: |
|
case KEYC_WHEELDOWN_PANE: |
|
return (key); |
|
case '\031': /* C-y */ |
|
case KEYC_UP|KEYC_CTRL: |
|
return (KEYC_UP|KEYC_CTRL); |
|
case '\002': /* C-b */ |
|
case KEYC_PPAGE: |
|
return (KEYC_PPAGE); |
|
case '\005': /* C-e */ |
|
case KEYC_DOWN|KEYC_CTRL: |
|
return (KEYC_DOWN|KEYC_CTRL); |
|
case '\006': /* C-f */ |
|
case KEYC_NPAGE: |
|
return (KEYC_NPAGE); |
|
case 'j': |
|
case KEYC_DOWN: |
|
return (KEYC_DOWN); |
|
case 'k': |
|
case KEYC_UP: |
|
return (KEYC_UP); |
|
case 'g': |
|
case KEYC_HOME: |
|
return (KEYC_HOME); |
|
case 'G': |
|
case KEYC_END: |
|
return (KEYC_END); |
|
case 'H': |
|
return ('R'|KEYC_ESCAPE); |
|
case 'L': |
|
return ('r'|KEYC_ESCAPE); |
|
} |
|
if ((key >= '0' && key <= '9') || |
|
(key >= 'a' && key <= 'z') || |
|
(key >= 'A' && key <= 'Z')) |
|
return (key); |
|
return (KEYC_NONE); |
|
} |
|
|
static void |
static void |
window_choose_key(struct window_pane *wp, __unused struct client *c, |
window_choose_key(struct window_pane *wp, __unused struct client *c, |
__unused struct session *sess, key_code key, struct mouse_event *m) |
__unused struct session *sp, key_code key, struct mouse_event *m) |
{ |
{ |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_data *data = wp->modedata; |
struct screen *s = &data->screen; |
struct screen *s = &data->screen; |
|
|
struct window_choose_mode_item *item; |
struct window_choose_mode_item *item; |
size_t input_len; |
size_t input_len; |
u_int items, n; |
u_int items, n; |
int idx; |
int idx, keys; |
|
|
|
keys = options_get_number(wp->window->options, "mode-keys"); |
|
if (keys == MODEKEY_VI) { |
|
key = window_choose_translate_key(key); |
|
if (key == KEYC_NONE) |
|
return; |
|
} |
items = data->list_size; |
items = data->list_size; |
|
|
if (data->input_type == WINDOW_CHOOSE_GOTO_ITEM) { |
if (data->input_type == WINDOW_CHOOSE_GOTO_ITEM) { |
switch (mode_key_lookup(&data->mdata, key)) { |
switch (key) { |
case MODEKEYCHOICE_CANCEL: |
case '\003': /* C-c */ |
|
case '\033': /* Escape */ |
|
case 'q': |
data->input_type = WINDOW_CHOOSE_NORMAL; |
data->input_type = WINDOW_CHOOSE_NORMAL; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_CHOOSE: |
case '\n': |
|
case '\r': |
n = strtonum(data->input_str, 0, INT_MAX, NULL); |
n = strtonum(data->input_str, 0, INT_MAX, NULL); |
if (n > items - 1) { |
if (n > items - 1) { |
data->input_type = WINDOW_CHOOSE_NORMAL; |
data->input_type = WINDOW_CHOOSE_NORMAL; |
|
|
} |
} |
window_choose_fire_callback(wp, data->list[n].wcd); |
window_choose_fire_callback(wp, data->list[n].wcd); |
break; |
break; |
case MODEKEYCHOICE_BACKSPACE: |
case KEYC_BSPACE: |
input_len = strlen(data->input_str); |
input_len = strlen(data->input_str); |
if (input_len > 0) |
if (input_len > 0) |
data->input_str[input_len - 1] = '\0'; |
data->input_str[input_len - 1] = '\0'; |
|
|
return; |
return; |
} |
} |
|
|
switch (mode_key_lookup(&data->mdata, key)) { |
switch (key) { |
case MODEKEYCHOICE_CANCEL: |
case '\003': /* C-c */ |
|
case '\033': /* Escape */ |
|
case 'q': |
window_choose_fire_callback(wp, NULL); |
window_choose_fire_callback(wp, NULL); |
break; |
break; |
case MODEKEYCHOICE_CHOOSE: |
case '\n': |
|
case '\r': |
|
case KEYC_MOUSEDOWN1_PANE: |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
break; |
break; |
window_choose_fire_callback(wp, item->wcd); |
window_choose_fire_callback(wp, item->wcd); |
break; |
break; |
case MODEKEYCHOICE_TREE_TOGGLE: |
case ' ': |
|
case KEYC_MOUSEDOWN3_PANE: |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
break; |
break; |
if (item->state & TREE_EXPANDED) { |
if (item->state & TREE_EXPANDED) { |
|
|
} |
} |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_TREE_COLLAPSE: |
case KEYC_LEFT: |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
break; |
break; |
if (item->state & TREE_EXPANDED) { |
if (item->state & TREE_EXPANDED) { |
|
|
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
} |
} |
break; |
break; |
case MODEKEYCHOICE_TREE_COLLAPSE_ALL: |
case KEYC_LEFT|KEYC_CTRL: |
window_choose_collapse_all(wp); |
window_choose_collapse_all(wp); |
break; |
break; |
case MODEKEYCHOICE_TREE_EXPAND: |
case KEYC_RIGHT: |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
if ((item = window_choose_get_item(wp, key, m)) == NULL) |
break; |
break; |
if (!(item->state & TREE_EXPANDED)) { |
if (!(item->state & TREE_EXPANDED)) { |
|
|
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
} |
} |
break; |
break; |
case MODEKEYCHOICE_TREE_EXPAND_ALL: |
case KEYC_RIGHT|KEYC_CTRL: |
window_choose_expand_all(wp); |
window_choose_expand_all(wp); |
break; |
break; |
case MODEKEYCHOICE_UP: |
case '\020': /* C-p */ |
|
case KEYC_UP: |
|
case KEYC_WHEELUP_PANE: |
if (items == 0) |
if (items == 0) |
break; |
break; |
if (data->selected == 0) { |
if (data->selected == 0) { |
|
|
screen_write_stop(&ctx); |
screen_write_stop(&ctx); |
} |
} |
break; |
break; |
case MODEKEYCHOICE_DOWN: |
case '\016': /* C-n */ |
|
case KEYC_DOWN: |
|
case KEYC_WHEELDOWN_PANE: |
if (items == 0) |
if (items == 0) |
break; |
break; |
if (data->selected == items - 1) { |
if (data->selected == items - 1) { |
|
|
} else |
} else |
window_choose_scroll_down(wp); |
window_choose_scroll_down(wp); |
break; |
break; |
case MODEKEYCHOICE_SCROLLUP: |
case KEYC_UP|KEYC_CTRL: |
if (items == 0 || data->top == 0) |
if (items == 0 || data->top == 0) |
break; |
break; |
if (data->selected == data->top + screen_size_y(s) - 1) { |
if (data->selected == data->top + screen_size_y(s) - 1) { |
|
|
} else |
} else |
window_choose_scroll_up(wp); |
window_choose_scroll_up(wp); |
break; |
break; |
case MODEKEYCHOICE_SCROLLDOWN: |
case KEYC_DOWN|KEYC_CTRL: |
if (items == 0 || |
if (items == 0 || |
data->top + screen_size_y(&data->screen) >= items) |
data->top + screen_size_y(&data->screen) >= items) |
break; |
break; |
|
|
} else |
} else |
window_choose_scroll_down(wp); |
window_choose_scroll_down(wp); |
break; |
break; |
case MODEKEYCHOICE_PAGEUP: |
case KEYC_PPAGE: |
if (data->selected < screen_size_y(s)) { |
if (data->selected < screen_size_y(s)) { |
data->selected = 0; |
data->selected = 0; |
data->top = 0; |
data->top = 0; |
|
|
} |
} |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_PAGEDOWN: |
case KEYC_NPAGE: |
data->selected += screen_size_y(s); |
data->selected += screen_size_y(s); |
if (data->selected > items - 1) |
if (data->selected > items - 1) |
data->selected = items - 1; |
data->selected = items - 1; |
|
|
data->top = data->selected; |
data->top = data->selected; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_BACKSPACE: |
case KEYC_BSPACE: |
input_len = strlen(data->input_str); |
input_len = strlen(data->input_str); |
if (input_len > 0) |
if (input_len > 0) |
data->input_str[input_len - 1] = '\0'; |
data->input_str[input_len - 1] = '\0'; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_STARTNUMBERPREFIX: |
case '0'|KEYC_ESCAPE: |
|
case '1'|KEYC_ESCAPE: |
|
case '2'|KEYC_ESCAPE: |
|
case '3'|KEYC_ESCAPE: |
|
case '4'|KEYC_ESCAPE: |
|
case '5'|KEYC_ESCAPE: |
|
case '6'|KEYC_ESCAPE: |
|
case '7'|KEYC_ESCAPE: |
|
case '8'|KEYC_ESCAPE: |
|
case '9'|KEYC_ESCAPE: |
key &= KEYC_MASK_KEY; |
key &= KEYC_MASK_KEY; |
if (key < '0' || key > '9') |
if (key < '0' || key > '9') |
break; |
break; |
window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM, |
window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM, |
"Goto Item", wp, key); |
"Goto Item", wp, key); |
break; |
break; |
case MODEKEYCHOICE_STARTOFLIST: |
case KEYC_HOME: |
|
case '<'|KEYC_ESCAPE: |
data->selected = 0; |
data->selected = 0; |
data->top = 0; |
data->top = 0; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_TOPLINE: |
case 'R'|KEYC_ESCAPE: |
data->selected = data->top; |
data->selected = data->top; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_BOTTOMLINE: |
case 'r'|KEYC_ESCAPE: |
data->selected = data->top + screen_size_y(s) - 1; |
data->selected = data->top + screen_size_y(s) - 1; |
if (data->selected > items - 1) |
if (data->selected > items - 1) |
data->selected = items - 1; |
data->selected = items - 1; |
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
case MODEKEYCHOICE_ENDOFLIST: |
case KEYC_END: |
|
case '>'|KEYC_ESCAPE: |
data->selected = items - 1; |
data->selected = items - 1; |
if (screen_size_y(s) < items) |
if (screen_size_y(s) < items) |
data->top = items - screen_size_y(s); |
data->top = items - screen_size_y(s); |
|
|
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
default: |
default: |
idx = window_choose_index_key(data, key); |
idx = window_choose_index_key(wp, key); |
if (idx < 0 || (u_int) idx >= data->list_size) |
if (idx < 0 || (u_int) idx >= data->list_size) |
break; |
break; |
data->selected = idx; |
data->selected = idx; |
|
|
item->wcd->wl->flags & WINLINK_ALERTFLAGS) |
item->wcd->wl->flags & WINLINK_ALERTFLAGS) |
gc.attr |= GRID_ATTR_BRIGHT; |
gc.attr |= GRID_ATTR_BRIGHT; |
|
|
key = window_choose_key_index(data, data->top + py); |
key = window_choose_key_index(wp, data->top + py); |
if (key != -1) |
if (key != -1) |
xsnprintf(label, sizeof label, "(%c)", key); |
xsnprintf(label, sizeof label, "(%c)", key); |
else |
else |
|
|
} |
} |
|
|
static int |
static int |
window_choose_key_index(struct window_choose_mode_data *data, u_int idx) |
window_choose_key_index(struct window_pane *wp, u_int idx) |
{ |
{ |
static const char keys[] = "0123456789" |
const char *ptr; |
"abcdefghijklmnopqrstuvwxyz" |
int keys; |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
|
const char *ptr; |
|
int mkey; |
|
|
|
for (ptr = keys; *ptr != '\0'; ptr++) { |
keys = options_get_number(wp->window->options, "mode-keys"); |
mkey = mode_key_lookup(&data->mdata, *ptr); |
if (keys == MODEKEY_VI) |
if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER) |
ptr = window_choose_keys_vi; |
continue; |
else |
|
ptr = window_choose_keys_emacs; |
|
for (; *ptr != '\0'; ptr++) { |
if (idx-- == 0) |
if (idx-- == 0) |
return (*ptr); |
return (*ptr); |
} |
} |
|
|
} |
} |
|
|
static int |
static int |
window_choose_index_key(struct window_choose_mode_data *data, key_code key) |
window_choose_index_key(struct window_pane *wp, key_code key) |
{ |
{ |
static const char keys[] = "0123456789" |
const char *ptr; |
"abcdefghijklmnopqrstuvwxyz" |
int keys; |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
u_int idx = 0; |
const char *ptr; |
|
int mkey; |
|
u_int idx = 0; |
|
|
|
for (ptr = keys; *ptr != '\0'; ptr++) { |
keys = options_get_number(wp->window->options, "mode-keys"); |
mkey = mode_key_lookup(&data->mdata, *ptr); |
if (keys == MODEKEY_VI) |
if (mkey != MODEKEY_NONE && mkey != MODEKEY_OTHER) |
ptr = window_choose_keys_vi; |
continue; |
else |
|
ptr = window_choose_keys_emacs; |
|
for (; *ptr != '\0'; ptr++) { |
if (key == (key_code)*ptr) |
if (key == (key_code)*ptr) |
return (idx); |
return (idx); |
idx++; |
idx++; |