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
);
48 enum window_choose_input_type
{
49 WINDOW_CHOOSE_NORMAL
= -1,
50 WINDOW_CHOOSE_GOTO_ITEM
,
53 const struct window_mode window_choose_mode
= {
62 struct window_choose_mode_data
{
65 struct mode_key_data mdata
;
67 ARRAY_DECL(, struct window_choose_mode_item
) list
;
68 ARRAY_DECL(, struct window_choose_mode_item
) old_list
;
72 enum window_choose_input_type input_type
;
73 const char *input_prompt
;
76 void (*callbackfn
)(struct window_choose_data
*);
79 void window_choose_free1(struct window_choose_mode_data
*);
80 int window_choose_key_index(struct window_choose_mode_data
*, u_int
);
81 int window_choose_index_key(struct window_choose_mode_data
*, int);
82 void window_choose_prompt_input(enum window_choose_input_type
,
83 const char *, struct window_pane
*, int);
86 window_choose_add(struct window_pane
*wp
, struct window_choose_data
*wcd
)
88 struct window_choose_mode_data
*data
= wp
->modedata
;
89 struct window_choose_mode_item
*item
;
92 ARRAY_EXPAND(&data
->list
, 1);
93 item
= &ARRAY_LAST(&data
->list
);
95 item
->name
= format_expand(wcd
->ft
, wcd
->ft_template
);
97 item
->pos
= ARRAY_LENGTH(&data
->list
) - 1;
100 data
->width
= xsnprintf (tmp
, sizeof tmp
, "%u", item
->pos
);
104 window_choose_set_current(struct window_pane
*wp
, u_int cur
)
106 struct window_choose_mode_data
*data
= wp
->modedata
;
107 struct screen
*s
= &data
->screen
;
109 data
->selected
= cur
;
110 if (data
->selected
> screen_size_y(s
) - 1)
111 data
->top
= ARRAY_LENGTH(&data
->list
) - screen_size_y(s
);
113 window_choose_redraw_screen(wp
);
117 window_choose_ready(struct window_pane
*wp
, u_int cur
,
118 void (*callbackfn
)(struct window_choose_data
*))
120 struct window_choose_mode_data
*data
= wp
->modedata
;
122 data
->callbackfn
= callbackfn
;
123 if (data
->callbackfn
== NULL
)
124 data
->callbackfn
= window_choose_default_callback
;
126 ARRAY_CONCAT(&data
->old_list
, &data
->list
);
128 window_choose_set_current(wp
, cur
);
129 window_choose_collapse_all(wp
);
133 window_choose_init(struct window_pane
*wp
)
135 struct window_choose_mode_data
*data
;
139 wp
->modedata
= data
= xmalloc(sizeof *data
);
141 data
->callbackfn
= NULL
;
142 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
143 data
->input_str
= xstrdup("");
144 data
->input_prompt
= NULL
;
146 ARRAY_INIT(&data
->list
);
147 ARRAY_INIT(&data
->old_list
);
151 screen_init(s
, screen_size_x(&wp
->base
), screen_size_y(&wp
->base
), 0);
152 s
->mode
&= ~MODE_CURSOR
;
153 if (options_get_number(&wp
->window
->options
, "mode-mouse"))
154 s
->mode
|= MODE_MOUSE_STANDARD
;
156 keys
= options_get_number(&wp
->window
->options
, "mode-keys");
157 if (keys
== MODEKEY_EMACS
)
158 mode_key_init(&data
->mdata
, &mode_key_tree_emacs_choice
);
160 mode_key_init(&data
->mdata
, &mode_key_tree_vi_choice
);
165 struct window_choose_data
*
166 window_choose_data_create(int type
, struct client
*c
, struct session
*s
)
168 struct window_choose_data
*wcd
;
170 wcd
= xmalloc(sizeof *wcd
);
173 wcd
->ft
= format_create();
174 wcd
->ft_template
= NULL
;
182 wcd
->tree_session
= NULL
;
184 wcd
->start_client
= c
;
185 wcd
->start_client
->references
++;
186 wcd
->start_session
= s
;
187 wcd
->start_session
->references
++;
193 window_choose_data_free(struct window_choose_data
*wcd
)
195 wcd
->start_client
->references
--;
196 wcd
->start_session
->references
--;
198 if (wcd
->tree_session
!= NULL
)
199 wcd
->tree_session
->references
--;
201 free(wcd
->ft_template
);
202 format_free(wcd
->ft
);
209 window_choose_data_run(struct window_choose_data
*cdata
)
211 struct cmd_list
*cmdlist
;
215 * The command template will have already been replaced. But if it's
218 if (cdata
->command
== NULL
)
221 if (cmd_string_parse(cdata
->command
, &cmdlist
, NULL
, 0, &cause
) != 0) {
223 *cause
= toupper((u_char
) *cause
);
224 status_message_set(cdata
->start_client
, "%s", cause
);
230 cmdq_run(cdata
->start_client
->cmdq
, cmdlist
);
231 cmd_list_free(cmdlist
);
235 window_choose_default_callback(struct window_choose_data
*wcd
)
239 if (wcd
->start_client
->flags
& CLIENT_DEAD
)
242 window_choose_data_run(wcd
);
246 window_choose_free(struct window_pane
*wp
)
248 if (wp
->modedata
!= NULL
)
249 window_choose_free1(wp
->modedata
);
253 window_choose_free1(struct window_choose_mode_data
*data
)
255 struct window_choose_mode_item
*item
;
261 for (i
= 0; i
< ARRAY_LENGTH(&data
->old_list
); i
++) {
262 item
= &ARRAY_ITEM(&data
->old_list
, i
);
263 window_choose_data_free(item
->wcd
);
266 ARRAY_FREE(&data
->list
);
267 ARRAY_FREE(&data
->old_list
);
268 free(data
->input_str
);
270 screen_free(&data
->screen
);
275 window_choose_resize(struct window_pane
*wp
, u_int sx
, u_int sy
)
277 struct window_choose_mode_data
*data
= wp
->modedata
;
278 struct screen
*s
= &data
->screen
;
281 if (data
->selected
> sy
- 1)
282 data
->top
= data
->selected
- (sy
- 1);
284 screen_resize(s
, sx
, sy
, 0);
285 window_choose_redraw_screen(wp
);
289 window_choose_fire_callback(
290 struct window_pane
*wp
, struct window_choose_data
*wcd
)
292 struct window_choose_mode_data
*data
= wp
->modedata
;
295 window_pane_reset_mode(wp
);
297 data
->callbackfn(wcd
);
299 window_choose_free1(data
);
303 window_choose_prompt_input(enum window_choose_input_type input_type
,
304 const char *prompt
, struct window_pane
*wp
, int key
)
306 struct window_choose_mode_data
*data
= wp
->modedata
;
309 data
->input_type
= input_type
;
310 data
->input_prompt
= prompt
;
311 input_len
= strlen(data
->input_str
) + 2;
313 data
->input_str
= xrealloc(data
->input_str
, 1, input_len
);
314 data
->input_str
[input_len
- 2] = key
;
315 data
->input_str
[input_len
- 1] = '\0';
317 window_choose_redraw_screen(wp
);
321 window_choose_collapse(struct window_pane
*wp
, struct session
*s
)
323 struct window_choose_mode_data
*data
= wp
->modedata
;
324 struct window_choose_mode_item
*item
, *chosen
;
325 struct window_choose_data
*wcd
;
328 ARRAY_DECL(, struct window_choose_mode_item
) list_copy
;
329 ARRAY_INIT(&list_copy
);
331 pos
= data
->selected
;
333 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
334 chosen
->state
&= ~TREE_EXPANDED
;
337 * Trying to mangle the &data->list in-place has lots of problems, so
338 * assign the actual result we want to render and copy the new one over
341 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++)
343 item
= &ARRAY_ITEM(&data
->list
, i
);
346 if (s
== wcd
->tree_session
) {
347 /* We only show the session when collapsed. */
348 if (wcd
->type
& TREE_SESSION
) {
349 item
->state
&= ~TREE_EXPANDED
;
351 ARRAY_ADD(&list_copy
,
352 ARRAY_ITEM(&data
->list
, i
));
354 * Update the selection to this session item so
355 * we don't end up highlighting a non-existent
361 ARRAY_ADD(&list_copy
, ARRAY_ITEM(&data
->list
, i
));
364 if (!ARRAY_EMPTY(&list_copy
)) {
365 ARRAY_FREE(&data
->list
);
366 ARRAY_CONCAT(&data
->list
, &list_copy
);
367 ARRAY_FREE(&list_copy
);
372 window_choose_collapse_all(struct window_pane
*wp
)
374 struct window_choose_mode_data
*data
= wp
->modedata
;
375 struct window_choose_mode_item
*item
;
376 struct session
*s
, *chosen
;
379 chosen
= ARRAY_ITEM(&data
->list
, data
->selected
).wcd
->start_session
;
381 RB_FOREACH(s
, sessions
, &sessions
)
382 window_choose_collapse(wp
, s
);
384 /* Reset the selection back to the starting session. */
385 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
386 item
= &ARRAY_ITEM(&data
->list
, i
);
388 if (chosen
!= item
->wcd
->tree_session
)
391 if (item
->wcd
->type
& TREE_SESSION
)
394 window_choose_redraw_screen(wp
);
398 window_choose_expand_all(struct window_pane
*wp
)
400 struct window_choose_mode_data
*data
= wp
->modedata
;
401 struct window_choose_mode_item
*item
;
405 RB_FOREACH(s
, sessions
, &sessions
) {
406 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
407 item
= &ARRAY_ITEM(&data
->list
, i
);
409 if (s
!= item
->wcd
->tree_session
)
412 if (item
->wcd
->type
& TREE_SESSION
)
413 window_choose_expand(wp
, s
, i
);
417 window_choose_redraw_screen(wp
);
421 window_choose_expand(struct window_pane
*wp
, struct session
*s
, u_int pos
)
423 struct window_choose_mode_data
*data
= wp
->modedata
;
424 struct window_choose_mode_item
*item
, *chosen
;
425 struct window_choose_data
*wcd
;
428 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
429 items
= ARRAY_LENGTH(&data
->old_list
) - 1;
431 /* It's not possible to expand anything other than sessions. */
432 if (!(chosen
->wcd
->type
& TREE_SESSION
))
435 /* Don't re-expand a session which is already expanded. */
436 if (chosen
->state
& TREE_EXPANDED
)
439 /* Mark the session entry as expanded. */
440 chosen
->state
|= TREE_EXPANDED
;
443 * Go back through the original list of all sessions and windows, and
444 * pull out the windows where the session matches the selection chosen
447 for (i
= items
; i
> 0; i
--) {
448 item
= &ARRAY_ITEM(&data
->old_list
, i
);
449 item
->state
|= TREE_EXPANDED
;
452 if (s
== wcd
->tree_session
) {
454 * Since the session is already displayed, we only care
455 * to add back in window for it.
457 if (wcd
->type
& TREE_WINDOW
) {
459 * If the insertion point for adding the
460 * windows to the session falls inside the
461 * range of the list, then we insert these
462 * entries in order *AFTER* the selected
466 ARRAY_INSERT(&data
->list
,
468 ARRAY_ITEM(&data
->old_list
,
471 /* Ran out of room, add to the end. */
472 ARRAY_ADD(&data
->list
,
473 ARRAY_ITEM(&data
->old_list
,
482 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
484 struct window_choose_mode_data
*data
= wp
->modedata
;
485 struct screen
*s
= &data
->screen
;
486 struct screen_write_ctx ctx
;
487 struct window_choose_mode_item
*item
;
492 items
= ARRAY_LENGTH(&data
->list
);
494 if (data
->input_type
== WINDOW_CHOOSE_GOTO_ITEM
) {
495 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
496 case MODEKEYCHOICE_CANCEL
:
497 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
498 window_choose_redraw_screen(wp
);
500 case MODEKEYCHOICE_CHOOSE
:
501 n
= strtonum(data
->input_str
, 0, INT_MAX
, NULL
);
503 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
504 window_choose_redraw_screen(wp
);
507 item
= &ARRAY_ITEM(&data
->list
, n
);
508 window_choose_fire_callback(wp
, item
->wcd
);
510 case MODEKEYCHOICE_BACKSPACE
:
511 input_len
= strlen(data
->input_str
);
513 data
->input_str
[input_len
- 1] = '\0';
514 window_choose_redraw_screen(wp
);
517 if (key
< '0' || key
> '9')
519 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
520 "Goto Item", wp
, key
);
526 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
527 case MODEKEYCHOICE_CANCEL
:
528 window_choose_fire_callback(wp
, NULL
);
530 case MODEKEYCHOICE_CHOOSE
:
531 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
532 window_choose_fire_callback(wp
, item
->wcd
);
534 case MODEKEYCHOICE_TREE_TOGGLE
:
535 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
536 if (item
->state
& TREE_EXPANDED
)
537 window_choose_collapse(wp
, item
->wcd
->tree_session
);
539 window_choose_expand(wp
, item
->wcd
->tree_session
,
542 window_choose_redraw_screen(wp
);
544 case MODEKEYCHOICE_TREE_COLLAPSE
:
545 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
546 if (item
->state
& TREE_EXPANDED
) {
547 window_choose_collapse(wp
, item
->wcd
->tree_session
);
548 window_choose_redraw_screen(wp
);
551 case MODEKEYCHOICE_TREE_COLLAPSE_ALL
:
552 window_choose_collapse_all(wp
);
554 case MODEKEYCHOICE_TREE_EXPAND
:
555 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
556 if (!(item
->state
& TREE_EXPANDED
)) {
557 window_choose_expand(wp
, item
->wcd
->tree_session
,
559 window_choose_redraw_screen(wp
);
562 case MODEKEYCHOICE_TREE_EXPAND_ALL
:
563 window_choose_expand_all(wp
);
565 case MODEKEYCHOICE_UP
:
568 if (data
->selected
== 0) {
569 data
->selected
= items
- 1;
570 if (data
->selected
> screen_size_y(s
) - 1)
571 data
->top
= items
- screen_size_y(s
);
572 window_choose_redraw_screen(wp
);
576 if (data
->selected
< data
->top
)
577 window_choose_scroll_up(wp
);
579 screen_write_start(&ctx
, wp
, NULL
);
580 window_choose_write_line(
581 wp
, &ctx
, data
->selected
- data
->top
);
582 window_choose_write_line(
583 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
584 screen_write_stop(&ctx
);
587 case MODEKEYCHOICE_DOWN
:
590 if (data
->selected
== items
- 1) {
593 window_choose_redraw_screen(wp
);
598 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
599 screen_write_start(&ctx
, wp
, NULL
);
600 window_choose_write_line(
601 wp
, &ctx
, data
->selected
- data
->top
);
602 window_choose_write_line(
603 wp
, &ctx
, data
->selected
- 1 - data
->top
);
604 screen_write_stop(&ctx
);
606 window_choose_scroll_down(wp
);
608 case MODEKEYCHOICE_SCROLLUP
:
609 if (items
== 0 || data
->top
== 0)
611 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
613 window_choose_scroll_up(wp
);
614 screen_write_start(&ctx
, wp
, NULL
);
615 window_choose_write_line(
616 wp
, &ctx
, screen_size_y(s
) - 1);
617 screen_write_stop(&ctx
);
619 window_choose_scroll_up(wp
);
621 case MODEKEYCHOICE_SCROLLDOWN
:
623 data
->top
+ screen_size_y(&data
->screen
) >= items
)
625 if (data
->selected
== data
->top
) {
627 window_choose_scroll_down(wp
);
628 screen_write_start(&ctx
, wp
, NULL
);
629 window_choose_write_line(wp
, &ctx
, 0);
630 screen_write_stop(&ctx
);
632 window_choose_scroll_down(wp
);
634 case MODEKEYCHOICE_PAGEUP
:
635 if (data
->selected
< screen_size_y(s
)) {
639 data
->selected
-= screen_size_y(s
);
640 if (data
->top
< screen_size_y(s
))
643 data
->top
-= screen_size_y(s
);
645 window_choose_redraw_screen(wp
);
647 case MODEKEYCHOICE_PAGEDOWN
:
648 data
->selected
+= screen_size_y(s
);
649 if (data
->selected
> items
- 1)
650 data
->selected
= items
- 1;
651 data
->top
+= screen_size_y(s
);
652 if (screen_size_y(s
) < items
) {
653 if (data
->top
+ screen_size_y(s
) > items
)
654 data
->top
= items
- screen_size_y(s
);
657 if (data
->selected
< data
->top
)
658 data
->top
= data
->selected
;
659 window_choose_redraw_screen(wp
);
661 case MODEKEYCHOICE_BACKSPACE
:
662 input_len
= strlen(data
->input_str
);
664 data
->input_str
[input_len
- 1] = '\0';
665 window_choose_redraw_screen(wp
);
667 case MODEKEYCHOICE_STARTNUMBERPREFIX
:
668 key
&= KEYC_MASK_KEY
;
669 if (key
< '0' || key
> '9')
671 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
672 "Goto Item", wp
, key
);
675 idx
= window_choose_index_key(data
, key
);
676 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
678 data
->selected
= idx
;
680 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
681 window_choose_fire_callback(wp
, item
->wcd
);
688 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
690 struct window_choose_mode_data
*data
= wp
->modedata
;
691 struct screen
*s
= &data
->screen
;
692 struct window_choose_mode_item
*item
;
695 if (~m
->event
& MOUSE_EVENT_CLICK
)
697 if (m
->x
>= screen_size_x(s
))
699 if (m
->y
>= screen_size_y(s
))
702 idx
= data
->top
+ m
->y
;
703 if (idx
>= ARRAY_LENGTH(&data
->list
))
705 data
->selected
= idx
;
707 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
708 window_choose_fire_callback(wp
, item
->wcd
);
712 window_choose_write_line(
713 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
715 struct window_choose_mode_data
*data
= wp
->modedata
;
716 struct window_choose_mode_item
*item
;
717 struct options
*oo
= &wp
->window
->options
;
718 struct screen
*s
= &data
->screen
;
720 size_t last
, xoff
= 0;
721 char hdr
[32], label
[32];
724 if (data
->callbackfn
== NULL
)
725 fatalx("called before callback assigned");
727 last
= screen_size_y(s
) - 1;
728 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
729 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
730 if (data
->selected
== data
->top
+ py
)
731 window_mode_attrs(&gc
, oo
);
733 screen_write_cursormove(ctx
, 0, py
);
734 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
735 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
736 if (item
->wcd
->wl
!= NULL
&&
737 item
->wcd
->wl
->flags
& WINLINK_ALERTFLAGS
)
738 gc
.attr
|= GRID_ATTR_BRIGHT
;
740 key
= window_choose_key_index(data
, data
->top
+ py
);
742 xsnprintf (label
, sizeof label
, "(%c)", key
);
744 xsnprintf (label
, sizeof label
, "(%d)", item
->pos
);
745 screen_write_nputs(ctx
, screen_size_x(s
) - 1, &gc
, utf8flag
,
746 "%*s %s %s", data
->width
+ 2, label
,
748 * Add indication to tree if necessary about whether it's
751 (item
->wcd
->type
& TREE_SESSION
) ?
752 (item
->state
& TREE_EXPANDED
? "-" : "+") : "", item
->name
);
754 while (s
->cx
< screen_size_x(s
) - 1)
755 screen_write_putc(ctx
, &gc
, ' ');
757 if (data
->input_type
!= WINDOW_CHOOSE_NORMAL
) {
758 window_mode_attrs(&gc
, oo
);
760 xoff
= xsnprintf(hdr
, sizeof hdr
,
761 "%s: %s", data
->input_prompt
, data
->input_str
);
762 screen_write_cursormove(ctx
, 0, last
);
763 screen_write_puts(ctx
, &gc
, "%s", hdr
);
764 screen_write_cursormove(ctx
, xoff
, py
);
765 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
771 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
773 static const char keys
[] = "0123456789"
774 "abcdefghijklmnopqrstuvwxyz"
775 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
779 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
780 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
781 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
790 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
792 static const char keys
[] = "0123456789"
793 "abcdefghijklmnopqrstuvwxyz"
794 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
799 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
800 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
801 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
811 window_choose_redraw_screen(struct window_pane
*wp
)
813 struct window_choose_mode_data
*data
= wp
->modedata
;
814 struct screen
*s
= &data
->screen
;
815 struct screen_write_ctx ctx
;
818 screen_write_start(&ctx
, wp
, NULL
);
819 for (i
= 0; i
< screen_size_y(s
); i
++)
820 window_choose_write_line(wp
, &ctx
, i
);
821 screen_write_stop(&ctx
);
825 window_choose_scroll_up(struct window_pane
*wp
)
827 struct window_choose_mode_data
*data
= wp
->modedata
;
828 struct screen_write_ctx ctx
;
834 screen_write_start(&ctx
, wp
, NULL
);
835 screen_write_cursormove(&ctx
, 0, 0);
836 screen_write_insertline(&ctx
, 1);
837 window_choose_write_line(wp
, &ctx
, 0);
838 if (screen_size_y(&data
->screen
) > 1)
839 window_choose_write_line(wp
, &ctx
, 1);
840 screen_write_stop(&ctx
);
844 window_choose_scroll_down(struct window_pane
*wp
)
846 struct window_choose_mode_data
*data
= wp
->modedata
;
847 struct screen
*s
= &data
->screen
;
848 struct screen_write_ctx ctx
;
850 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
854 screen_write_start(&ctx
, wp
, NULL
);
855 screen_write_cursormove(&ctx
, 0, 0);
856 screen_write_deleteline(&ctx
, 1);
857 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
858 if (screen_size_y(&data
->screen
) > 1)
859 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
860 screen_write_stop(&ctx
);
863 struct window_choose_data
*
864 window_choose_add_session(struct window_pane
*wp
, struct client
*c
,
865 struct session
*s
, const char *template, const char *action
, u_int idx
)
867 struct window_choose_data
*wcd
;
869 wcd
= window_choose_data_create(TREE_SESSION
, c
, c
->session
);
872 wcd
->tree_session
= s
;
873 wcd
->tree_session
->references
++;
875 wcd
->ft_template
= xstrdup(template);
876 format_add(wcd
->ft
, "line", "%u", idx
);
877 format_session(wcd
->ft
, s
);
879 wcd
->command
= cmd_template_replace(action
, s
->name
, 1);
881 window_choose_add(wp
, wcd
);
886 struct window_choose_data
*
887 window_choose_add_item(struct window_pane
*wp
, struct client
*c
,
888 struct winlink
*wl
, const char *template, const char *action
, u_int idx
)
890 struct window_choose_data
*wcd
;
893 wcd
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
896 wcd
->ft_template
= xstrdup(template);
897 format_add(wcd
->ft
, "line", "%u", idx
);
898 format_session(wcd
->ft
, wcd
->start_session
);
899 format_winlink(wcd
->ft
, wcd
->start_session
, wl
);
900 format_window_pane(wcd
->ft
, wl
->window
->active
);
903 * Interpolate action here, since the data we pass back is the expanded
906 xasprintf(&expanded
, "%s", format_expand(wcd
->ft
, wcd
->ft_template
));
907 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
910 window_choose_add(wp
, wcd
);
916 struct window_choose_data
*
917 window_choose_add_window(struct window_pane
*wp
, struct client
*c
,
918 struct session
*s
, struct winlink
*wl
, const char *template,
919 const char *action
, u_int idx
)
921 struct window_choose_data
*wcd
;
924 wcd
= window_choose_data_create(TREE_WINDOW
, c
, c
->session
);
929 wcd
->tree_session
= s
;
930 wcd
->tree_session
->references
++;
932 wcd
->ft_template
= xstrdup(template);
933 format_add(wcd
->ft
, "line", "%u", idx
);
934 format_session(wcd
->ft
, s
);
935 format_winlink(wcd
->ft
, s
, wl
);
936 format_window_pane(wcd
->ft
, wl
->window
->active
);
938 xasprintf(&expanded
, "%s:%d", s
->name
, wl
->idx
);
939 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
942 window_choose_add(wp
, wcd
);