=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/Attic/window-choose.c,v retrieving revision 1.26 retrieving revision 1.27 diff -c -r1.26 -r1.27 *** src/usr.bin/tmux/Attic/window-choose.c 2012/09/03 09:57:57 1.26 --- src/usr.bin/tmux/Attic/window-choose.c 2012/10/02 08:16:28 1.27 *************** *** 1,4 **** ! /* $OpenBSD: window-choose.c,v 1.26 2012/09/03 09:57:57 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: window-choose.c,v 1.27 2012/10/02 08:16:28 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott *************** *** 40,45 **** --- 40,50 ---- void window_choose_scroll_up(struct window_pane *); void window_choose_scroll_down(struct window_pane *); + void window_choose_collapse(struct window_pane *, struct session *); + void window_choose_expand(struct window_pane *, struct session *, u_int); + void window_choose_collapse_all(struct window_pane *); + void window_choose_expand_all(struct window_pane *); + enum window_choose_input_type { WINDOW_CHOOSE_NORMAL = -1, WINDOW_CHOOSE_GOTO_ITEM, *************** *** 60,65 **** --- 65,71 ---- struct mode_key_data mdata; ARRAY_DECL(, struct window_choose_mode_item) list; + ARRAY_DECL(, struct window_choose_mode_item) old_list; int width; u_int top; u_int selected; *************** *** 89,94 **** --- 95,101 ---- item->name = format_expand(wcd->ft, wcd->ft_template); item->wcd = wcd; item->pos = ARRAY_LENGTH(&data->list) - 1; + item->state = 0; data->width = xsnprintf (tmp, sizeof tmp , "%u", item->pos); } *************** *** 108,113 **** --- 115,123 ---- data->callbackfn = callbackfn; data->freefn = freefn; + ARRAY_CONCAT(&data->old_list, &data->list); + + window_choose_collapse_all(wp); window_choose_redraw_screen(wp); } *************** *** 127,132 **** --- 137,143 ---- data->input_prompt = NULL; ARRAY_INIT(&data->list); + ARRAY_INIT(&data->old_list); data->top = 0; s = &data->screen; *************** *** 154,162 **** --- 165,175 ---- wcd->ft_template = NULL; wcd->command = NULL; wcd->wl = NULL; + wcd->tree_session = NULL; wcd->client = ctx->curclient; wcd->session = ctx->curclient->session; wcd->idx = -1; + wcd->type = 0; return (wcd); } *************** *** 175,180 **** --- 188,194 ---- free(item->name); } ARRAY_FREE(&data->list); + ARRAY_FREE(&data->old_list); free(data->input_str); screen_free(&data->screen); *************** *** 228,233 **** --- 242,407 ---- window_choose_redraw_screen(wp); } + void + window_choose_collapse(struct window_pane *wp, struct session *s) + { + struct window_choose_mode_data *data = wp->modedata; + struct window_choose_mode_item *item, *chosen; + struct window_choose_data *wcd; + u_int i, pos; + + ARRAY_DECL(, struct window_choose_mode_item) list_copy; + ARRAY_INIT(&list_copy); + + pos = data->selected; + + chosen = &ARRAY_ITEM(&data->list, pos); + chosen->state &= ~TREE_EXPANDED; + + /* + * Trying to mangle the &data->list in-place has lots of problems, so + * assign the actual result we want to render and copy the new one over + * the top of it. + */ + for (i = 0; i < ARRAY_LENGTH(&data->list); i++) + { + item = &ARRAY_ITEM(&data->list, i); + wcd = item->wcd; + + if (s == wcd->tree_session) { + /* We only show the session when collapsed. */ + if (wcd->type & TREE_SESSION) { + item->state &= ~TREE_EXPANDED; + + ARRAY_ADD(&list_copy, + ARRAY_ITEM(&data->list, i)); + /* + * Update the selection to this session item so + * we don't end up highlighting a non-existent + * item. + */ + data->selected = i; + } + } else + ARRAY_ADD(&list_copy, ARRAY_ITEM(&data->list, i)); + } + + if (!ARRAY_EMPTY(&list_copy)) { + ARRAY_FREE(&data->list); + ARRAY_CONCAT(&data->list, &list_copy); + } + } + + void + window_choose_collapse_all(struct window_pane *wp) + { + struct window_choose_mode_data *data = wp->modedata; + struct window_choose_mode_item *item, *chosen; + struct session *s; + u_int i; + + chosen = &ARRAY_ITEM(&data->list, data->selected); + + RB_FOREACH(s, sessions, &sessions) + window_choose_collapse(wp, s); + + /* Reset the selection back to the starting session. */ + for (i = 0; i < ARRAY_LENGTH(&data->list); i++) { + item = &ARRAY_ITEM(&data->list, i); + + if (chosen->wcd->session != item->wcd->tree_session) + continue; + + if (item->wcd->type & TREE_SESSION) + data->selected = i; + } + window_choose_redraw_screen(wp); + } + + void + window_choose_expand_all(struct window_pane *wp) + { + struct window_choose_mode_data *data = wp->modedata; + struct window_choose_mode_item *item; + struct session *s; + u_int i; + + RB_FOREACH(s, sessions, &sessions) { + for (i = 0; i < ARRAY_LENGTH(&data->list); i++) { + item = &ARRAY_ITEM(&data->list, i); + + if (s != item->wcd->tree_session) + continue; + + if (item->wcd->type & TREE_SESSION) + window_choose_expand(wp, s, i); + } + } + + window_choose_redraw_screen(wp); + } + + void + window_choose_expand(struct window_pane *wp, struct session *s, u_int pos) + { + struct window_choose_mode_data *data = wp->modedata; + struct window_choose_mode_item *item, *chosen; + struct window_choose_data *wcd; + u_int i, items; + + chosen = &ARRAY_ITEM(&data->list, pos); + items = ARRAY_LENGTH(&data->old_list) - 1; + + /* It's not possible to expand anything other than sessions. */ + if (!(chosen->wcd->type & TREE_SESSION)) + return; + + /* Don't re-expand a session which is already expanded. */ + if (chosen->state & TREE_EXPANDED) + return; + + /* Mark the session entry as expanded. */ + chosen->state |= TREE_EXPANDED; + + /* + * Go back through the original list of all sessions and windows, and + * pull out the windows where the session matches the selection chosen + * to expand. + */ + for (i = items; i > 0; i--) { + item = &ARRAY_ITEM(&data->old_list, i); + item->state |= TREE_EXPANDED; + wcd = item->wcd; + + if (s == wcd->tree_session) { + /* + * Since the session is already displayed, we only care + * to add back in window for it. + */ + if (wcd->type & TREE_WINDOW) { + /* + * If the insertion point for adding the + * windows to the session falls inside the + * range of the list, then we insert these + * entries in order *AFTER* the selected + * session. + */ + if (pos < i ) { + ARRAY_INSERT(&data->list, + pos + 1, + ARRAY_ITEM(&data->old_list, + i)); + } else { + /* Ran out of room, add to the end. */ + ARRAY_ADD(&data->list, + ARRAY_ITEM(&data->old_list, + i)); + } + } + } + } + } + /* ARGSUSED */ void window_choose_key(struct window_pane *wp, unused struct session *sess, int key) *************** *** 237,243 **** struct screen_write_ctx ctx; struct window_choose_mode_item *item; size_t input_len; ! u_int items, n; int idx; items = ARRAY_LENGTH(&data->list); --- 411,417 ---- struct screen_write_ctx ctx; struct window_choose_mode_item *item; size_t input_len; ! u_int items, n; int idx; items = ARRAY_LENGTH(&data->list); *************** *** 285,290 **** --- 459,495 ---- window_choose_fire_callback(wp, item->wcd); window_pane_reset_mode(wp); break; + case MODEKEYCHOICE_TREE_TOGGLE: + item = &ARRAY_ITEM(&data->list, data->selected); + if (item->state & TREE_EXPANDED) + window_choose_collapse(wp, item->wcd->tree_session); + else { + window_choose_expand(wp, item->wcd->tree_session, + data->selected); + } + window_choose_redraw_screen(wp); + break; + case MODEKEYCHOICE_TREE_COLLAPSE: + item = &ARRAY_ITEM(&data->list, data->selected); + if (item->state & TREE_EXPANDED) { + window_choose_collapse(wp, item->wcd->tree_session); + window_choose_redraw_screen(wp); + } + break; + case MODEKEYCHOICE_TREE_COLLAPSE_ALL: + window_choose_collapse_all(wp); + break; + case MODEKEYCHOICE_TREE_EXPAND: + item = &ARRAY_ITEM(&data->list, data->selected); + if (!(item->state & TREE_EXPANDED)) { + window_choose_expand(wp, item->wcd->tree_session, + data->selected); + window_choose_redraw_screen(wp); + } + break; + case MODEKEYCHOICE_TREE_EXPAND_ALL: + window_choose_expand_all(wp); + break; case MODEKEYCHOICE_UP: if (items == 0) break; *************** *** 469,475 **** else xsnprintf (label, sizeof label, "(%d)", item->pos); screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag, ! "%*s %s", data->width + 2, label, item->name); } while (s->cx < screen_size_x(s)) screen_write_putc(ctx, &gc, ' '); --- 674,686 ---- else xsnprintf (label, sizeof label, "(%d)", item->pos); screen_write_nputs(ctx, screen_size_x(s) - 1, &gc, utf8flag, ! "%*s %s %s", data->width + 2, label, ! /* ! * Add indication to tree if necessary about whether it's ! * expanded or not. ! */ ! (item->wcd->type & TREE_SESSION) ? ! (item->state & TREE_EXPANDED ? "-" : "+") : "", item->name); } while (s->cx < screen_size_x(s)) screen_write_putc(ctx, &gc, ' '); *************** *** 623,628 **** --- 834,841 ---- wcd = window_choose_data_create(ctx); wcd->idx = s->idx; + wcd->tree_session = s; + wcd->type = TREE_SESSION; wcd->command = cmd_template_replace(action, s->name, 1); wcd->ft_template = xstrdup(template); format_add(wcd->ft, "line", "%u", idx); *************** *** 684,689 **** --- 897,904 ---- wcd->idx = wl->idx; wcd->wl = wl; + wcd->tree_session = s; + wcd->type = TREE_WINDOW; wcd->ft_template = xstrdup(template); format_add(wcd->ft, "line", "%u", idx); format_session(wcd->ft, s);