version 1.74, 2016/01/19 15:59:12 |
version 1.75, 2016/04/26 10:18:57 |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "array.h" |
|
#include "tmux.h" |
#include "tmux.h" |
|
|
struct screen *window_choose_init(struct window_pane *); |
struct screen *window_choose_init(struct window_pane *); |
|
|
|
|
struct mode_key_data mdata; |
struct mode_key_data mdata; |
|
|
ARRAY_DECL(, struct window_choose_mode_item) list; |
struct window_choose_mode_item *list; |
ARRAY_DECL(, struct window_choose_mode_item) old_list; |
u_int list_size; |
|
struct window_choose_mode_item *old_list; |
|
u_int old_list_size; |
|
|
int width; |
int width; |
u_int top; |
u_int top; |
u_int selected; |
u_int selected; |
|
|
{ |
{ |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_item *item; |
struct window_choose_mode_item *item; |
char tmp[10]; |
char tmp[11]; |
|
|
ARRAY_EXPAND(&data->list, 1); |
data->list = xreallocarray(data->list, data->list_size + 1, |
item = &ARRAY_LAST(&data->list); |
sizeof *data->list); |
|
item = &data->list[data->list_size++]; |
|
|
item->name = format_expand(wcd->ft, wcd->ft_template); |
item->name = format_expand(wcd->ft, wcd->ft_template); |
item->wcd = wcd; |
item->wcd = wcd; |
item->pos = ARRAY_LENGTH(&data->list) - 1; |
item->pos = data->list_size - 1; |
item->state = 0; |
item->state = 0; |
|
|
data->width = xsnprintf(tmp, sizeof tmp , "%d", item->pos); |
data->width = xsnprintf(tmp, sizeof tmp, "%d", item->pos); |
} |
} |
|
|
void |
void |
|
|
void (*callbackfn)(struct window_choose_data *)) |
void (*callbackfn)(struct window_choose_data *)) |
{ |
{ |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_data *data = wp->modedata; |
|
u_int size; |
|
|
data->callbackfn = callbackfn; |
data->callbackfn = callbackfn; |
if (data->callbackfn == NULL) |
if (data->callbackfn == NULL) |
data->callbackfn = window_choose_default_callback; |
data->callbackfn = window_choose_default_callback; |
|
|
ARRAY_CONCAT(&data->old_list, &data->list); |
size = data->old_list_size; |
|
data->old_list_size += data->list_size; |
|
data->old_list = xreallocarray(data->old_list, data->old_list_size, |
|
sizeof *data->old_list); |
|
memcpy(data->old_list + size, data->list, data->list_size * |
|
sizeof *data->list); |
|
|
window_choose_set_current(wp, cur); |
window_choose_set_current(wp, cur); |
window_choose_collapse_all(wp); |
window_choose_collapse_all(wp); |
|
|
struct screen *s; |
struct screen *s; |
int keys; |
int keys; |
|
|
wp->modedata = data = xmalloc(sizeof *data); |
wp->modedata = data = xcalloc(1, sizeof *data); |
|
|
data->callbackfn = NULL; |
data->callbackfn = NULL; |
data->input_type = WINDOW_CHOOSE_NORMAL; |
data->input_type = WINDOW_CHOOSE_NORMAL; |
data->input_str = xstrdup(""); |
data->input_str = xstrdup(""); |
data->input_prompt = NULL; |
data->input_prompt = NULL; |
|
|
ARRAY_INIT(&data->list); |
data->list = NULL; |
ARRAY_INIT(&data->old_list); |
data->list_size = 0; |
|
|
|
data->old_list = NULL; |
|
data->old_list_size = 0; |
|
|
data->top = 0; |
data->top = 0; |
|
|
s = &data->screen; |
s = &data->screen; |
|
|
if (data == NULL) |
if (data == NULL) |
return; |
return; |
|
|
for (i = 0; i < ARRAY_LENGTH(&data->old_list); i++) { |
for (i = 0; i < data->old_list_size; i++) { |
item = &ARRAY_ITEM(&data->old_list, i); |
item = &data->old_list[i]; |
window_choose_data_free(item->wcd); |
window_choose_data_free(item->wcd); |
free(item->name); |
free(item->name); |
} |
} |
ARRAY_FREE(&data->list); |
free(data->list); |
ARRAY_FREE(&data->old_list); |
free(data->old_list); |
|
|
free(data->input_str); |
free(data->input_str); |
|
|
screen_free(&data->screen); |
screen_free(&data->screen); |
|
|
window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos) |
window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos) |
{ |
{ |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_data *data = wp->modedata; |
struct window_choose_mode_item *item, *chosen; |
struct window_choose_mode_item *item, *chosen, *copy = NULL; |
struct window_choose_data *wcd; |
struct window_choose_data *wcd; |
u_int i; |
u_int i, copy_size = 0; |
|
|
ARRAY_DECL(, struct window_choose_mode_item) list_copy; |
chosen = &data->list[pos]; |
ARRAY_INIT(&list_copy); |
|
|
|
chosen = &ARRAY_ITEM(&data->list, pos); |
|
chosen->state &= ~TREE_EXPANDED; |
chosen->state &= ~TREE_EXPANDED; |
|
|
/* |
/* |
|
|
* assign the actual result we want to render and copy the new one over |
* assign the actual result we want to render and copy the new one over |
* the top of it. |
* the top of it. |
*/ |
*/ |
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) { |
for (i = 0; i < data->list_size; i++) { |
item = &ARRAY_ITEM(&data->list, i); |
item = &data->list[i]; |
wcd = item->wcd; |
wcd = item->wcd; |
|
|
if (s == wcd->tree_session) { |
if (s == wcd->tree_session) { |
/* We only show the session when collapsed. */ |
/* We only show the session when collapsed. */ |
if (wcd->type & TREE_SESSION) { |
if (wcd->type & TREE_SESSION) { |
item->state &= ~TREE_EXPANDED; |
item->state &= ~TREE_EXPANDED; |
ARRAY_ADD(&list_copy, *item); |
|
|
|
|
copy = xreallocarray(copy, copy_size + 1, |
|
sizeof *copy); |
|
memcpy(©[copy_size], item, sizeof *copy); |
|
copy_size++; |
|
|
/* |
/* |
* Update the selection to this session item so |
* Update the selection to this session item so |
* we don't end up highlighting a non-existent |
* we don't end up highlighting a non-existent |
|
|
*/ |
*/ |
data->selected = i; |
data->selected = i; |
} |
} |
} else |
} else { |
ARRAY_ADD(&list_copy, ARRAY_ITEM(&data->list, i)); |
copy = xreallocarray(copy, copy_size + 1, sizeof *copy); |
|
memcpy(©[copy_size], item, sizeof *copy); |
|
copy_size++; |
|
} |
} |
} |
|
|
if (!ARRAY_EMPTY(&list_copy)) { |
if (copy_size != 0) { |
ARRAY_FREE(&data->list); |
free(data->list); |
ARRAY_CONCAT(&data->list, &list_copy); |
data->list = copy; |
ARRAY_FREE(&list_copy); |
data->list_size = copy_size; |
} |
} |
} |
} |
|
|
|
|
struct session *s, *chosen; |
struct session *s, *chosen; |
u_int i; |
u_int i; |
|
|
chosen = ARRAY_ITEM(&data->list, data->selected).wcd->start_session; |
chosen = data->list[data->selected].wcd->start_session; |
|
|
RB_FOREACH(s, sessions, &sessions) |
RB_FOREACH(s, sessions, &sessions) |
window_choose_collapse(wp, s, data->selected); |
window_choose_collapse(wp, s, data->selected); |
|
|
/* Reset the selection back to the starting session. */ |
/* Reset the selection back to the starting session. */ |
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) { |
for (i = 0; i < data->list_size; i++) { |
item = &ARRAY_ITEM(&data->list, i); |
item = &data->list[i]; |
|
|
if (chosen != item->wcd->tree_session) |
if (chosen != item->wcd->tree_session) |
continue; |
continue; |
|
|
u_int i; |
u_int i; |
|
|
RB_FOREACH(s, sessions, &sessions) { |
RB_FOREACH(s, sessions, &sessions) { |
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) { |
for (i = 0; i < data->list_size; i++) { |
item = &ARRAY_ITEM(&data->list, i); |
item = &data->list[i]; |
|
|
if (s != item->wcd->tree_session) |
if (s != item->wcd->tree_session) |
continue; |
continue; |
|
|
struct window_choose_data *wcd; |
struct window_choose_data *wcd; |
u_int i, items; |
u_int i, items; |
|
|
chosen = &ARRAY_ITEM(&data->list, pos); |
chosen = &data->list[pos]; |
items = ARRAY_LENGTH(&data->old_list) - 1; |
items = data->old_list_size - 1; |
|
|
/* It's not possible to expand anything other than sessions. */ |
/* It's not possible to expand anything other than sessions. */ |
if (!(chosen->wcd->type & TREE_SESSION)) |
if (!(chosen->wcd->type & TREE_SESSION)) |
|
|
* to expand. |
* to expand. |
*/ |
*/ |
for (i = items; i > 0; i--) { |
for (i = items; i > 0; i--) { |
item = &ARRAY_ITEM(&data->old_list, i); |
item = &data->old_list[i]; |
item->state |= TREE_EXPANDED; |
item->state |= TREE_EXPANDED; |
wcd = item->wcd; |
wcd = item->wcd; |
|
|
|
|
* entries in order *AFTER* the selected |
* entries in order *AFTER* the selected |
* session. |
* session. |
*/ |
*/ |
if (pos < i ) { |
if (pos < i) { |
ARRAY_INSERT(&data->list, |
data->list = xreallocarray(data->list, |
pos + 1, |
data->list_size + 1, |
ARRAY_ITEM(&data->old_list, |
sizeof *data->list); |
i)); |
memmove(&data->list[pos + 2], |
|
&data->list[pos + 1], |
|
(data->list_size - pos) * |
|
sizeof *data->list); |
|
memcpy(&data->list[pos + 1], |
|
&data->old_list[i], |
|
sizeof *data->list); |
|
data->list_size++; |
} else { |
} else { |
/* Ran out of room, add to the end. */ |
/* Ran out of room, add to the end. */ |
ARRAY_ADD(&data->list, |
data->list = xreallocarray(data->list, |
ARRAY_ITEM(&data->old_list, |
data->list_size + 1, |
i)); |
sizeof *data->list); |
|
memcpy(&data->list[data->list_size], |
|
&data->old_list[i], |
|
sizeof *data->list); |
|
data->list_size++; |
} |
} |
} |
} |
} |
} |
|
|
u_int x, y, idx; |
u_int x, y, idx; |
|
|
if (!KEYC_IS_MOUSE(key)) |
if (!KEYC_IS_MOUSE(key)) |
return (&ARRAY_ITEM(&data->list, data->selected)); |
return (&data->list[data->selected]); |
|
|
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0) |
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0) |
return (NULL); |
return (NULL); |
|
|
idx = data->top + y; |
idx = data->top + y; |
if (idx >= ARRAY_LENGTH(&data->list)) |
if (idx >= data->list_size) |
return (NULL); |
return (NULL); |
return (&ARRAY_ITEM(&data->list, idx)); |
return (&data->list[idx]); |
} |
} |
|
|
void |
void |
|
|
u_int items, n; |
u_int items, n; |
int idx; |
int idx; |
|
|
items = ARRAY_LENGTH(&data->list); |
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, NULL)) { |
switch (mode_key_lookup(&data->mdata, key, NULL)) { |
|
|
window_choose_redraw_screen(wp); |
window_choose_redraw_screen(wp); |
break; |
break; |
} |
} |
item = &ARRAY_ITEM(&data->list, n); |
window_choose_fire_callback(wp, data->list[n].wcd); |
window_choose_fire_callback(wp, item->wcd); |
|
break; |
break; |
case MODEKEYCHOICE_BACKSPACE: |
case MODEKEYCHOICE_BACKSPACE: |
input_len = strlen(data->input_str); |
input_len = strlen(data->input_str); |
|
|
break; |
break; |
default: |
default: |
idx = window_choose_index_key(data, key); |
idx = window_choose_index_key(data, key); |
if (idx < 0 || (u_int) idx >= ARRAY_LENGTH(&data->list)) |
if (idx < 0 || (u_int) idx >= data->list_size) |
break; |
break; |
data->selected = idx; |
data->selected = idx; |
|
window_choose_fire_callback(wp, data->list[idx].wcd); |
item = &ARRAY_ITEM(&data->list, data->selected); |
|
window_choose_fire_callback(wp, item->wcd); |
|
break; |
break; |
} |
} |
} |
} |
|
|
style_apply(&gc, oo, "mode-style"); |
style_apply(&gc, oo, "mode-style"); |
|
|
screen_write_cursormove(ctx, 0, py); |
screen_write_cursormove(ctx, 0, py); |
if (data->top + py < ARRAY_LENGTH(&data->list)) { |
if (data->top + py < data->list_size) { |
item = &ARRAY_ITEM(&data->list, data->top + py); |
item = &data->list[data->top + py]; |
if (item->wcd->wl != NULL && |
if (item->wcd->wl != NULL && |
item->wcd->wl->flags & WINLINK_ALERTFLAGS) |
item->wcd->wl->flags & WINLINK_ALERTFLAGS) |
gc.attr |= GRID_ATTR_BRIGHT; |
gc.attr |= GRID_ATTR_BRIGHT; |
|
|
struct screen *s = &data->screen; |
struct screen *s = &data->screen; |
struct screen_write_ctx ctx; |
struct screen_write_ctx ctx; |
|
|
if (data->top >= ARRAY_LENGTH(&data->list)) |
if (data->top >= data->list_size) |
return; |
return; |
data->top++; |
data->top++; |
|
|