4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
27 struct screen
*window_choose_init(struct window_pane
*);
28 void window_choose_free(struct window_pane
*);
29 void window_choose_resize(struct window_pane
*, u_int
, u_int
);
30 void window_choose_key(struct window_pane
*, struct session
*, int);
31 void window_choose_mouse(
32 struct window_pane
*, struct session
*, struct mouse_event
*);
34 void window_choose_default_callback(struct window_choose_data
*);
36 void window_choose_fire_callback(
37 struct window_pane
*, struct window_choose_data
*);
38 void window_choose_redraw_screen(struct window_pane
*);
39 void window_choose_write_line(
40 struct window_pane
*, struct screen_write_ctx
*, u_int
);
42 void window_choose_scroll_up(struct window_pane
*);
43 void window_choose_scroll_down(struct window_pane
*);
45 void window_choose_collapse(struct window_pane
*, struct session
*);
46 void window_choose_expand(struct window_pane
*, struct session
*, u_int
);
47 void window_choose_collapse_all(struct window_pane
*);
49 enum window_choose_input_type
{
50 WINDOW_CHOOSE_NORMAL
= -1,
51 WINDOW_CHOOSE_GOTO_ITEM
,
54 const struct window_mode window_choose_mode
= {
63 struct window_choose_mode_data
{
66 struct mode_key_data mdata
;
68 ARRAY_DECL(, struct window_choose_mode_item
) list
;
69 ARRAY_DECL(, struct window_choose_mode_item
) old_list
;
73 enum window_choose_input_type input_type
;
74 const char *input_prompt
;
77 void (*callbackfn
)(struct window_choose_data
*);
80 void window_choose_free1(struct window_choose_mode_data
*);
81 int window_choose_key_index(struct window_choose_mode_data
*, u_int
);
82 int window_choose_index_key(struct window_choose_mode_data
*, int);
83 void window_choose_prompt_input(enum window_choose_input_type
,
84 const char *, struct window_pane
*, int);
87 window_choose_add(struct window_pane
*wp
, struct window_choose_data
*wcd
)
89 struct window_choose_mode_data
*data
= wp
->modedata
;
90 struct window_choose_mode_item
*item
;
93 ARRAY_EXPAND(&data
->list
, 1);
94 item
= &ARRAY_LAST(&data
->list
);
96 item
->name
= format_expand(wcd
->ft
, wcd
->ft_template
);
98 item
->pos
= ARRAY_LENGTH(&data
->list
) - 1;
101 data
->width
= xsnprintf (tmp
, sizeof tmp
, "%u", item
->pos
);
105 window_choose_ready(struct window_pane
*wp
, u_int cur
,
106 void (*callbackfn
)(struct window_choose_data
*))
108 struct window_choose_mode_data
*data
= wp
->modedata
;
109 struct screen
*s
= &data
->screen
;
111 data
->selected
= cur
;
112 if (data
->selected
> screen_size_y(s
) - 1)
113 data
->top
= ARRAY_LENGTH(&data
->list
) - screen_size_y(s
);
115 data
->callbackfn
= callbackfn
;
116 if (data
->callbackfn
== NULL
)
117 data
->callbackfn
= window_choose_default_callback
;
119 ARRAY_CONCAT(&data
->old_list
, &data
->list
);
121 window_choose_collapse_all(wp
);
125 window_choose_init(struct window_pane
*wp
)
127 struct window_choose_mode_data
*data
;
131 wp
->modedata
= data
= xmalloc(sizeof *data
);
133 data
->callbackfn
= NULL
;
134 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
135 data
->input_str
= xstrdup("");
136 data
->input_prompt
= NULL
;
138 ARRAY_INIT(&data
->list
);
139 ARRAY_INIT(&data
->old_list
);
143 screen_init(s
, screen_size_x(&wp
->base
), screen_size_y(&wp
->base
), 0);
144 s
->mode
&= ~MODE_CURSOR
;
145 if (options_get_number(&wp
->window
->options
, "mode-mouse"))
146 s
->mode
|= MODE_MOUSE_STANDARD
;
148 keys
= options_get_number(&wp
->window
->options
, "mode-keys");
149 if (keys
== MODEKEY_EMACS
)
150 mode_key_init(&data
->mdata
, &mode_key_tree_emacs_choice
);
152 mode_key_init(&data
->mdata
, &mode_key_tree_vi_choice
);
157 struct window_choose_data
*
158 window_choose_data_create(int type
, struct client
*c
, struct session
*s
)
160 struct window_choose_data
*wcd
;
162 wcd
= xmalloc(sizeof *wcd
);
165 wcd
->ft
= format_create();
166 wcd
->ft_template
= NULL
;
174 wcd
->tree_session
= NULL
;
176 wcd
->start_client
= c
;
177 wcd
->start_client
->references
++;
178 wcd
->start_session
= s
;
179 wcd
->start_session
->references
++;
185 window_choose_data_free(struct window_choose_data
*wcd
)
187 wcd
->start_client
->references
--;
188 wcd
->start_session
->references
--;
190 if (wcd
->tree_session
!= NULL
)
191 wcd
->tree_session
->references
--;
193 free(wcd
->ft_template
);
194 format_free(wcd
->ft
);
201 window_choose_data_run(struct window_choose_data
*cdata
)
204 struct cmd_list
*cmdlist
;
208 * The command template will have already been replaced. But if it's
211 if (cdata
->command
== NULL
)
214 if (cmd_string_parse(cdata
->command
, &cmdlist
, &cause
) != 0) {
216 *cause
= toupper((u_char
) *cause
);
217 status_message_set(cdata
->start_client
, "%s", cause
);
223 ctx
= cmd_get_ctx(NULL
, cdata
->start_client
);
224 ctx
->error
= key_bindings_error
;
225 ctx
->print
= key_bindings_print
;
226 ctx
->info
= key_bindings_info
;
228 cmd_list_exec(cmdlist
, ctx
);
229 cmd_list_free(cmdlist
);
234 window_choose_default_callback(struct window_choose_data
*wcd
)
238 if (wcd
->start_client
->flags
& CLIENT_DEAD
)
241 window_choose_data_run(wcd
);
245 window_choose_free(struct window_pane
*wp
)
247 if (wp
->modedata
!= NULL
)
248 window_choose_free1(wp
->modedata
);
252 window_choose_free1(struct window_choose_mode_data
*data
)
254 struct window_choose_mode_item
*item
;
260 for (i
= 0; i
< ARRAY_LENGTH(&data
->old_list
); i
++) {
261 item
= &ARRAY_ITEM(&data
->old_list
, i
);
262 window_choose_data_free(item
->wcd
);
265 ARRAY_FREE(&data
->list
);
266 ARRAY_FREE(&data
->old_list
);
267 free(data
->input_str
);
269 screen_free(&data
->screen
);
274 window_choose_resize(struct window_pane
*wp
, u_int sx
, u_int sy
)
276 struct window_choose_mode_data
*data
= wp
->modedata
;
277 struct screen
*s
= &data
->screen
;
280 if (data
->selected
> sy
- 1)
281 data
->top
= data
->selected
- (sy
- 1);
283 screen_resize(s
, sx
, sy
, 0);
284 window_choose_redraw_screen(wp
);
288 window_choose_fire_callback(
289 struct window_pane
*wp
, struct window_choose_data
*wcd
)
291 struct window_choose_mode_data
*data
= wp
->modedata
;
294 window_pane_reset_mode(wp
);
296 data
->callbackfn(wcd
);
298 window_choose_free1(data
);
302 window_choose_prompt_input(enum window_choose_input_type input_type
,
303 const char *prompt
, struct window_pane
*wp
, int key
)
305 struct window_choose_mode_data
*data
= wp
->modedata
;
308 data
->input_type
= input_type
;
309 data
->input_prompt
= prompt
;
310 input_len
= strlen(data
->input_str
) + 2;
312 data
->input_str
= xrealloc(data
->input_str
, 1, input_len
);
313 data
->input_str
[input_len
- 2] = key
;
314 data
->input_str
[input_len
- 1] = '\0';
316 window_choose_redraw_screen(wp
);
320 window_choose_collapse(struct window_pane
*wp
, struct session
*s
)
322 struct window_choose_mode_data
*data
= wp
->modedata
;
323 struct window_choose_mode_item
*item
, *chosen
;
324 struct window_choose_data
*wcd
;
327 ARRAY_DECL(, struct window_choose_mode_item
) list_copy
;
328 ARRAY_INIT(&list_copy
);
330 pos
= data
->selected
;
332 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
333 chosen
->state
&= ~TREE_EXPANDED
;
336 * Trying to mangle the &data->list in-place has lots of problems, so
337 * assign the actual result we want to render and copy the new one over
340 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++)
342 item
= &ARRAY_ITEM(&data
->list
, i
);
345 if (s
== wcd
->tree_session
) {
346 /* We only show the session when collapsed. */
347 if (wcd
->type
& TREE_SESSION
) {
348 item
->state
&= ~TREE_EXPANDED
;
350 ARRAY_ADD(&list_copy
,
351 ARRAY_ITEM(&data
->list
, i
));
353 * Update the selection to this session item so
354 * we don't end up highlighting a non-existent
360 ARRAY_ADD(&list_copy
, ARRAY_ITEM(&data
->list
, i
));
363 if (!ARRAY_EMPTY(&list_copy
)) {
364 ARRAY_FREE(&data
->list
);
365 ARRAY_CONCAT(&data
->list
, &list_copy
);
366 ARRAY_FREE(&list_copy
);
371 window_choose_collapse_all(struct window_pane
*wp
)
373 struct window_choose_mode_data
*data
= wp
->modedata
;
374 struct window_choose_mode_item
*item
;
375 struct session
*s
, *chosen
;
378 chosen
= ARRAY_ITEM(&data
->list
, data
->selected
).wcd
->start_session
;
380 RB_FOREACH(s
, sessions
, &sessions
)
381 window_choose_collapse(wp
, s
);
383 /* Reset the selection back to the starting session. */
384 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
385 item
= &ARRAY_ITEM(&data
->list
, i
);
387 if (chosen
!= item
->wcd
->tree_session
)
390 if (item
->wcd
->type
& TREE_SESSION
)
393 window_choose_redraw_screen(wp
);
397 window_choose_expand_all(struct window_pane
*wp
)
399 struct window_choose_mode_data
*data
= wp
->modedata
;
400 struct window_choose_mode_item
*item
;
404 RB_FOREACH(s
, sessions
, &sessions
) {
405 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
406 item
= &ARRAY_ITEM(&data
->list
, i
);
408 if (s
!= item
->wcd
->tree_session
)
411 if (item
->wcd
->type
& TREE_SESSION
)
412 window_choose_expand(wp
, s
, i
);
416 window_choose_redraw_screen(wp
);
420 window_choose_expand(struct window_pane
*wp
, struct session
*s
, u_int pos
)
422 struct window_choose_mode_data
*data
= wp
->modedata
;
423 struct window_choose_mode_item
*item
, *chosen
;
424 struct window_choose_data
*wcd
;
427 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
428 items
= ARRAY_LENGTH(&data
->old_list
) - 1;
430 /* It's not possible to expand anything other than sessions. */
431 if (!(chosen
->wcd
->type
& TREE_SESSION
))
434 /* Don't re-expand a session which is already expanded. */
435 if (chosen
->state
& TREE_EXPANDED
)
438 /* Mark the session entry as expanded. */
439 chosen
->state
|= TREE_EXPANDED
;
442 * Go back through the original list of all sessions and windows, and
443 * pull out the windows where the session matches the selection chosen
446 for (i
= items
; i
> 0; i
--) {
447 item
= &ARRAY_ITEM(&data
->old_list
, i
);
448 item
->state
|= TREE_EXPANDED
;
451 if (s
== wcd
->tree_session
) {
453 * Since the session is already displayed, we only care
454 * to add back in window for it.
456 if (wcd
->type
& TREE_WINDOW
) {
458 * If the insertion point for adding the
459 * windows to the session falls inside the
460 * range of the list, then we insert these
461 * entries in order *AFTER* the selected
465 ARRAY_INSERT(&data
->list
,
467 ARRAY_ITEM(&data
->old_list
,
470 /* Ran out of room, add to the end. */
471 ARRAY_ADD(&data
->list
,
472 ARRAY_ITEM(&data
->old_list
,
481 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
483 struct window_choose_mode_data
*data
= wp
->modedata
;
484 struct screen
*s
= &data
->screen
;
485 struct screen_write_ctx ctx
;
486 struct window_choose_mode_item
*item
;
491 items
= ARRAY_LENGTH(&data
->list
);
493 if (data
->input_type
== WINDOW_CHOOSE_GOTO_ITEM
) {
494 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
495 case MODEKEYCHOICE_CANCEL
:
496 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
497 window_choose_redraw_screen(wp
);
499 case MODEKEYCHOICE_CHOOSE
:
500 n
= strtonum(data
->input_str
, 0, INT_MAX
, NULL
);
502 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
503 window_choose_redraw_screen(wp
);
506 item
= &ARRAY_ITEM(&data
->list
, n
);
507 window_choose_fire_callback(wp
, item
->wcd
);
509 case MODEKEYCHOICE_BACKSPACE
:
510 input_len
= strlen(data
->input_str
);
512 data
->input_str
[input_len
- 1] = '\0';
513 window_choose_redraw_screen(wp
);
516 if (key
< '0' || key
> '9')
518 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
519 "Goto Item", wp
, key
);
525 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
526 case MODEKEYCHOICE_CANCEL
:
527 window_choose_fire_callback(wp
, NULL
);
529 case MODEKEYCHOICE_CHOOSE
:
530 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
531 window_choose_fire_callback(wp
, item
->wcd
);
533 case MODEKEYCHOICE_TREE_TOGGLE
:
534 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
535 if (item
->state
& TREE_EXPANDED
)
536 window_choose_collapse(wp
, item
->wcd
->tree_session
);
538 window_choose_expand(wp
, item
->wcd
->tree_session
,
541 window_choose_redraw_screen(wp
);
543 case MODEKEYCHOICE_TREE_COLLAPSE
:
544 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
545 if (item
->state
& TREE_EXPANDED
) {
546 window_choose_collapse(wp
, item
->wcd
->tree_session
);
547 window_choose_redraw_screen(wp
);
550 case MODEKEYCHOICE_TREE_COLLAPSE_ALL
:
551 window_choose_collapse_all(wp
);
553 case MODEKEYCHOICE_TREE_EXPAND
:
554 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
555 if (!(item
->state
& TREE_EXPANDED
)) {
556 window_choose_expand(wp
, item
->wcd
->tree_session
,
558 window_choose_redraw_screen(wp
);
561 case MODEKEYCHOICE_TREE_EXPAND_ALL
:
562 window_choose_expand_all(wp
);
564 case MODEKEYCHOICE_UP
:
567 if (data
->selected
== 0) {
568 data
->selected
= items
- 1;
569 if (data
->selected
> screen_size_y(s
) - 1)
570 data
->top
= items
- screen_size_y(s
);
571 window_choose_redraw_screen(wp
);
575 if (data
->selected
< data
->top
)
576 window_choose_scroll_up(wp
);
578 screen_write_start(&ctx
, wp
, NULL
);
579 window_choose_write_line(
580 wp
, &ctx
, data
->selected
- data
->top
);
581 window_choose_write_line(
582 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
583 screen_write_stop(&ctx
);
586 case MODEKEYCHOICE_DOWN
:
589 if (data
->selected
== items
- 1) {
592 window_choose_redraw_screen(wp
);
597 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
598 screen_write_start(&ctx
, wp
, NULL
);
599 window_choose_write_line(
600 wp
, &ctx
, data
->selected
- data
->top
);
601 window_choose_write_line(
602 wp
, &ctx
, data
->selected
- 1 - data
->top
);
603 screen_write_stop(&ctx
);
605 window_choose_scroll_down(wp
);
607 case MODEKEYCHOICE_SCROLLUP
:
608 if (items
== 0 || data
->top
== 0)
610 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
612 window_choose_scroll_up(wp
);
613 screen_write_start(&ctx
, wp
, NULL
);
614 window_choose_write_line(
615 wp
, &ctx
, screen_size_y(s
) - 1);
616 screen_write_stop(&ctx
);
618 window_choose_scroll_up(wp
);
620 case MODEKEYCHOICE_SCROLLDOWN
:
622 data
->top
+ screen_size_y(&data
->screen
) >= items
)
624 if (data
->selected
== data
->top
) {
626 window_choose_scroll_down(wp
);
627 screen_write_start(&ctx
, wp
, NULL
);
628 window_choose_write_line(wp
, &ctx
, 0);
629 screen_write_stop(&ctx
);
631 window_choose_scroll_down(wp
);
633 case MODEKEYCHOICE_PAGEUP
:
634 if (data
->selected
< screen_size_y(s
)) {
638 data
->selected
-= screen_size_y(s
);
639 if (data
->top
< screen_size_y(s
))
642 data
->top
-= screen_size_y(s
);
644 window_choose_redraw_screen(wp
);
646 case MODEKEYCHOICE_PAGEDOWN
:
647 data
->selected
+= screen_size_y(s
);
648 if (data
->selected
> items
- 1)
649 data
->selected
= items
- 1;
650 data
->top
+= screen_size_y(s
);
651 if (screen_size_y(s
) < items
) {
652 if (data
->top
+ screen_size_y(s
) > items
)
653 data
->top
= items
- screen_size_y(s
);
656 if (data
->selected
< data
->top
)
657 data
->top
= data
->selected
;
658 window_choose_redraw_screen(wp
);
660 case MODEKEYCHOICE_BACKSPACE
:
661 input_len
= strlen(data
->input_str
);
663 data
->input_str
[input_len
- 1] = '\0';
664 window_choose_redraw_screen(wp
);
666 case MODEKEYCHOICE_STARTNUMBERPREFIX
:
667 key
&= KEYC_MASK_KEY
;
668 if (key
< '0' || key
> '9')
670 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
671 "Goto Item", wp
, key
);
674 idx
= window_choose_index_key(data
, key
);
675 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
677 data
->selected
= idx
;
679 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
680 window_choose_fire_callback(wp
, item
->wcd
);
687 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
689 struct window_choose_mode_data
*data
= wp
->modedata
;
690 struct screen
*s
= &data
->screen
;
691 struct window_choose_mode_item
*item
;
694 if (~m
->event
& MOUSE_EVENT_CLICK
)
696 if (m
->x
>= screen_size_x(s
))
698 if (m
->y
>= screen_size_y(s
))
701 idx
= data
->top
+ m
->y
;
702 if (idx
>= ARRAY_LENGTH(&data
->list
))
704 data
->selected
= idx
;
706 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
707 window_choose_fire_callback(wp
, item
->wcd
);
711 window_choose_write_line(
712 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
714 struct window_choose_mode_data
*data
= wp
->modedata
;
715 struct window_choose_mode_item
*item
;
716 struct options
*oo
= &wp
->window
->options
;
717 struct screen
*s
= &data
->screen
;
719 size_t last
, xoff
= 0;
720 char hdr
[32], label
[32];
723 if (data
->callbackfn
== NULL
)
724 fatalx("called before callback assigned");
726 last
= screen_size_y(s
) - 1;
727 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
728 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
729 if (data
->selected
== data
->top
+ py
)
730 window_mode_attrs(&gc
, oo
);
732 screen_write_cursormove(ctx
, 0, py
);
733 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
734 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
735 if (item
->wcd
->wl
!= NULL
&&
736 item
->wcd
->wl
->flags
& WINLINK_ALERTFLAGS
)
737 gc
.attr
|= GRID_ATTR_BRIGHT
;
739 key
= window_choose_key_index(data
, data
->top
+ py
);
741 xsnprintf (label
, sizeof label
, "(%c)", key
);
743 xsnprintf (label
, sizeof label
, "(%d)", item
->pos
);
744 screen_write_nputs(ctx
, screen_size_x(s
) - 1, &gc
, utf8flag
,
745 "%*s %s %s", data
->width
+ 2, label
,
747 * Add indication to tree if necessary about whether it's
750 (item
->wcd
->type
& TREE_SESSION
) ?
751 (item
->state
& TREE_EXPANDED
? "-" : "+") : "", item
->name
);
753 while (s
->cx
< screen_size_x(s
) - 1)
754 screen_write_putc(ctx
, &gc
, ' ');
756 if (data
->input_type
!= WINDOW_CHOOSE_NORMAL
) {
757 window_mode_attrs(&gc
, oo
);
759 xoff
= xsnprintf(hdr
, sizeof hdr
,
760 "%s: %s", data
->input_prompt
, data
->input_str
);
761 screen_write_cursormove(ctx
, 0, last
);
762 screen_write_puts(ctx
, &gc
, "%s", hdr
);
763 screen_write_cursormove(ctx
, xoff
, py
);
764 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
770 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
772 static const char keys
[] = "0123456789"
773 "abcdefghijklmnopqrstuvwxyz"
774 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
778 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
779 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
780 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
789 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
791 static const char keys
[] = "0123456789"
792 "abcdefghijklmnopqrstuvwxyz"
793 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
798 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
799 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
800 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
810 window_choose_redraw_screen(struct window_pane
*wp
)
812 struct window_choose_mode_data
*data
= wp
->modedata
;
813 struct screen
*s
= &data
->screen
;
814 struct screen_write_ctx ctx
;
817 screen_write_start(&ctx
, wp
, NULL
);
818 for (i
= 0; i
< screen_size_y(s
); i
++)
819 window_choose_write_line(wp
, &ctx
, i
);
820 screen_write_stop(&ctx
);
824 window_choose_scroll_up(struct window_pane
*wp
)
826 struct window_choose_mode_data
*data
= wp
->modedata
;
827 struct screen_write_ctx ctx
;
833 screen_write_start(&ctx
, wp
, NULL
);
834 screen_write_cursormove(&ctx
, 0, 0);
835 screen_write_insertline(&ctx
, 1);
836 window_choose_write_line(wp
, &ctx
, 0);
837 if (screen_size_y(&data
->screen
) > 1)
838 window_choose_write_line(wp
, &ctx
, 1);
839 screen_write_stop(&ctx
);
843 window_choose_scroll_down(struct window_pane
*wp
)
845 struct window_choose_mode_data
*data
= wp
->modedata
;
846 struct screen
*s
= &data
->screen
;
847 struct screen_write_ctx ctx
;
849 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
853 screen_write_start(&ctx
, wp
, NULL
);
854 screen_write_cursormove(&ctx
, 0, 0);
855 screen_write_deleteline(&ctx
, 1);
856 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
857 if (screen_size_y(&data
->screen
) > 1)
858 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
859 screen_write_stop(&ctx
);
862 struct window_choose_data
*
863 window_choose_add_session(struct window_pane
*wp
, struct client
*c
,
864 struct session
*s
, const char *template, const char *action
, u_int idx
)
866 struct window_choose_data
*wcd
;
868 wcd
= window_choose_data_create(TREE_SESSION
, c
, c
->session
);
871 wcd
->tree_session
= s
;
872 wcd
->tree_session
->references
++;
874 wcd
->ft_template
= xstrdup(template);
875 format_add(wcd
->ft
, "line", "%u", idx
);
876 format_session(wcd
->ft
, s
);
878 wcd
->command
= cmd_template_replace(action
, s
->name
, 1);
880 window_choose_add(wp
, wcd
);
885 struct window_choose_data
*
886 window_choose_add_item(struct window_pane
*wp
, struct client
*c
,
887 struct winlink
*wl
, const char *template, const char *action
, u_int idx
)
889 struct window_choose_data
*wcd
;
892 wcd
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
895 wcd
->ft_template
= xstrdup(template);
896 format_add(wcd
->ft
, "line", "%u", idx
);
897 format_session(wcd
->ft
, wcd
->start_session
);
898 format_winlink(wcd
->ft
, wcd
->start_session
, wl
);
899 format_window_pane(wcd
->ft
, wl
->window
->active
);
902 * Interpolate action here, since the data we pass back is the expanded
905 xasprintf(&expanded
, "%s", format_expand(wcd
->ft
, wcd
->ft_template
));
906 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
909 window_choose_add(wp
, wcd
);
915 struct window_choose_data
*
916 window_choose_add_window(struct window_pane
*wp
, struct client
*c
,
917 struct session
*s
, struct winlink
*wl
, const char *template,
918 const char *action
, u_int idx
)
920 struct window_choose_data
*wcd
;
923 wcd
= window_choose_data_create(TREE_WINDOW
, c
, c
->session
);
928 wcd
->tree_session
= s
;
929 wcd
->tree_session
->references
++;
931 wcd
->ft_template
= xstrdup(template);
932 format_add(wcd
->ft
, "line", "%u", idx
);
933 format_session(wcd
->ft
, s
);
934 format_winlink(wcd
->ft
, s
, wl
);
935 format_window_pane(wcd
->ft
, wl
->window
->active
);
937 xasprintf(&expanded
, "%s:%d", s
->name
, wl
->idx
);
938 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
941 window_choose_add(wp
, wcd
);