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);
84 void window_choose_reset_top(struct window_pane
*, u_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_set_current(struct window_pane
*wp
, u_int cur
)
107 struct window_choose_mode_data
*data
= wp
->modedata
;
108 struct screen
*s
= &data
->screen
;
110 data
->selected
= cur
;
111 window_choose_reset_top(wp
, screen_size_y(s
));
115 window_choose_reset_top(struct window_pane
*wp
, u_int sy
)
117 struct window_choose_mode_data
*data
= wp
->modedata
;
120 if (data
->selected
> sy
- 1)
121 data
->top
= data
->selected
- (sy
- 1);
123 window_choose_redraw_screen(wp
);
127 window_choose_ready(struct window_pane
*wp
, u_int cur
,
128 void (*callbackfn
)(struct window_choose_data
*))
130 struct window_choose_mode_data
*data
= wp
->modedata
;
132 data
->callbackfn
= callbackfn
;
133 if (data
->callbackfn
== NULL
)
134 data
->callbackfn
= window_choose_default_callback
;
136 ARRAY_CONCAT(&data
->old_list
, &data
->list
);
138 window_choose_set_current(wp
, cur
);
139 window_choose_collapse_all(wp
);
143 window_choose_init(struct window_pane
*wp
)
145 struct window_choose_mode_data
*data
;
149 wp
->modedata
= data
= xmalloc(sizeof *data
);
151 data
->callbackfn
= NULL
;
152 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
153 data
->input_str
= xstrdup("");
154 data
->input_prompt
= NULL
;
156 ARRAY_INIT(&data
->list
);
157 ARRAY_INIT(&data
->old_list
);
161 screen_init(s
, screen_size_x(&wp
->base
), screen_size_y(&wp
->base
), 0);
162 s
->mode
&= ~MODE_CURSOR
;
163 if (options_get_number(&wp
->window
->options
, "mode-mouse"))
164 s
->mode
|= MODE_MOUSE_STANDARD
;
166 keys
= options_get_number(&wp
->window
->options
, "mode-keys");
167 if (keys
== MODEKEY_EMACS
)
168 mode_key_init(&data
->mdata
, &mode_key_tree_emacs_choice
);
170 mode_key_init(&data
->mdata
, &mode_key_tree_vi_choice
);
175 struct window_choose_data
*
176 window_choose_data_create(int type
, struct client
*c
, struct session
*s
)
178 struct window_choose_data
*wcd
;
180 wcd
= xmalloc(sizeof *wcd
);
183 wcd
->ft
= format_create();
184 wcd
->ft_template
= NULL
;
192 wcd
->tree_session
= NULL
;
194 wcd
->start_client
= c
;
195 wcd
->start_client
->references
++;
196 wcd
->start_session
= s
;
197 wcd
->start_session
->references
++;
203 window_choose_data_free(struct window_choose_data
*wcd
)
205 wcd
->start_client
->references
--;
206 wcd
->start_session
->references
--;
208 if (wcd
->tree_session
!= NULL
)
209 wcd
->tree_session
->references
--;
211 free(wcd
->ft_template
);
212 format_free(wcd
->ft
);
219 window_choose_data_run(struct window_choose_data
*cdata
)
221 struct cmd_list
*cmdlist
;
225 * The command template will have already been replaced. But if it's
228 if (cdata
->command
== NULL
)
231 if (cmd_string_parse(cdata
->command
, &cmdlist
, NULL
, 0, &cause
) != 0) {
233 *cause
= toupper((u_char
) *cause
);
234 status_message_set(cdata
->start_client
, "%s", cause
);
240 cmdq_run(cdata
->start_client
->cmdq
, cmdlist
);
241 cmd_list_free(cmdlist
);
245 window_choose_default_callback(struct window_choose_data
*wcd
)
249 if (wcd
->start_client
->flags
& CLIENT_DEAD
)
252 window_choose_data_run(wcd
);
256 window_choose_free(struct window_pane
*wp
)
258 if (wp
->modedata
!= NULL
)
259 window_choose_free1(wp
->modedata
);
263 window_choose_free1(struct window_choose_mode_data
*data
)
265 struct window_choose_mode_item
*item
;
271 for (i
= 0; i
< ARRAY_LENGTH(&data
->old_list
); i
++) {
272 item
= &ARRAY_ITEM(&data
->old_list
, i
);
273 window_choose_data_free(item
->wcd
);
276 ARRAY_FREE(&data
->list
);
277 ARRAY_FREE(&data
->old_list
);
278 free(data
->input_str
);
280 screen_free(&data
->screen
);
285 window_choose_resize(struct window_pane
*wp
, u_int sx
, u_int sy
)
287 struct window_choose_mode_data
*data
= wp
->modedata
;
288 struct screen
*s
= &data
->screen
;
290 window_choose_reset_top(wp
, sy
);
291 screen_resize(s
, sx
, sy
, 0);
292 window_choose_redraw_screen(wp
);
296 window_choose_fire_callback(
297 struct window_pane
*wp
, struct window_choose_data
*wcd
)
299 struct window_choose_mode_data
*data
= wp
->modedata
;
302 window_pane_reset_mode(wp
);
304 data
->callbackfn(wcd
);
306 window_choose_free1(data
);
310 window_choose_prompt_input(enum window_choose_input_type input_type
,
311 const char *prompt
, struct window_pane
*wp
, int key
)
313 struct window_choose_mode_data
*data
= wp
->modedata
;
316 data
->input_type
= input_type
;
317 data
->input_prompt
= prompt
;
318 input_len
= strlen(data
->input_str
) + 2;
320 data
->input_str
= xrealloc(data
->input_str
, 1, input_len
);
321 data
->input_str
[input_len
- 2] = key
;
322 data
->input_str
[input_len
- 1] = '\0';
324 window_choose_redraw_screen(wp
);
328 window_choose_collapse(struct window_pane
*wp
, struct session
*s
)
330 struct window_choose_mode_data
*data
= wp
->modedata
;
331 struct window_choose_mode_item
*item
, *chosen
;
332 struct window_choose_data
*wcd
;
335 ARRAY_DECL(, struct window_choose_mode_item
) list_copy
;
336 ARRAY_INIT(&list_copy
);
338 pos
= data
->selected
;
340 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
341 chosen
->state
&= ~TREE_EXPANDED
;
344 * Trying to mangle the &data->list in-place has lots of problems, so
345 * assign the actual result we want to render and copy the new one over
348 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++)
350 item
= &ARRAY_ITEM(&data
->list
, i
);
353 if (s
== wcd
->tree_session
) {
354 /* We only show the session when collapsed. */
355 if (wcd
->type
& TREE_SESSION
) {
356 item
->state
&= ~TREE_EXPANDED
;
358 ARRAY_ADD(&list_copy
,
359 ARRAY_ITEM(&data
->list
, i
));
361 * Update the selection to this session item so
362 * we don't end up highlighting a non-existent
368 ARRAY_ADD(&list_copy
, ARRAY_ITEM(&data
->list
, i
));
371 if (!ARRAY_EMPTY(&list_copy
)) {
372 ARRAY_FREE(&data
->list
);
373 ARRAY_CONCAT(&data
->list
, &list_copy
);
374 ARRAY_FREE(&list_copy
);
379 window_choose_collapse_all(struct window_pane
*wp
)
381 struct window_choose_mode_data
*data
= wp
->modedata
;
382 struct window_choose_mode_item
*item
;
383 struct screen
*scr
= &data
->screen
;
384 struct session
*s
, *chosen
;
387 chosen
= ARRAY_ITEM(&data
->list
, data
->selected
).wcd
->start_session
;
389 RB_FOREACH(s
, sessions
, &sessions
)
390 window_choose_collapse(wp
, s
);
392 /* Reset the selection back to the starting session. */
393 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
394 item
= &ARRAY_ITEM(&data
->list
, i
);
396 if (chosen
!= item
->wcd
->tree_session
)
399 if (item
->wcd
->type
& TREE_SESSION
)
402 window_choose_reset_top(wp
, screen_size_y(scr
));
406 window_choose_expand_all(struct window_pane
*wp
)
408 struct window_choose_mode_data
*data
= wp
->modedata
;
409 struct window_choose_mode_item
*item
;
410 struct screen
*scr
= &data
->screen
;
414 RB_FOREACH(s
, sessions
, &sessions
) {
415 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
416 item
= &ARRAY_ITEM(&data
->list
, i
);
418 if (s
!= item
->wcd
->tree_session
)
421 if (item
->wcd
->type
& TREE_SESSION
)
422 window_choose_expand(wp
, s
, i
);
426 window_choose_reset_top(wp
, screen_size_y(scr
));
430 window_choose_expand(struct window_pane
*wp
, struct session
*s
, u_int pos
)
432 struct window_choose_mode_data
*data
= wp
->modedata
;
433 struct window_choose_mode_item
*item
, *chosen
;
434 struct window_choose_data
*wcd
;
437 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
438 items
= ARRAY_LENGTH(&data
->old_list
) - 1;
440 /* It's not possible to expand anything other than sessions. */
441 if (!(chosen
->wcd
->type
& TREE_SESSION
))
444 /* Don't re-expand a session which is already expanded. */
445 if (chosen
->state
& TREE_EXPANDED
)
448 /* Mark the session entry as expanded. */
449 chosen
->state
|= TREE_EXPANDED
;
452 * Go back through the original list of all sessions and windows, and
453 * pull out the windows where the session matches the selection chosen
456 for (i
= items
; i
> 0; i
--) {
457 item
= &ARRAY_ITEM(&data
->old_list
, i
);
458 item
->state
|= TREE_EXPANDED
;
461 if (s
== wcd
->tree_session
) {
463 * Since the session is already displayed, we only care
464 * to add back in window for it.
466 if (wcd
->type
& TREE_WINDOW
) {
468 * If the insertion point for adding the
469 * windows to the session falls inside the
470 * range of the list, then we insert these
471 * entries in order *AFTER* the selected
475 ARRAY_INSERT(&data
->list
,
477 ARRAY_ITEM(&data
->old_list
,
480 /* Ran out of room, add to the end. */
481 ARRAY_ADD(&data
->list
,
482 ARRAY_ITEM(&data
->old_list
,
491 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
493 struct window_choose_mode_data
*data
= wp
->modedata
;
494 struct screen
*s
= &data
->screen
;
495 struct screen_write_ctx ctx
;
496 struct window_choose_mode_item
*item
;
501 items
= ARRAY_LENGTH(&data
->list
);
503 if (data
->input_type
== WINDOW_CHOOSE_GOTO_ITEM
) {
504 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
505 case MODEKEYCHOICE_CANCEL
:
506 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
507 window_choose_redraw_screen(wp
);
509 case MODEKEYCHOICE_CHOOSE
:
510 n
= strtonum(data
->input_str
, 0, INT_MAX
, NULL
);
512 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
513 window_choose_redraw_screen(wp
);
516 item
= &ARRAY_ITEM(&data
->list
, n
);
517 window_choose_fire_callback(wp
, item
->wcd
);
519 case MODEKEYCHOICE_BACKSPACE
:
520 input_len
= strlen(data
->input_str
);
522 data
->input_str
[input_len
- 1] = '\0';
523 window_choose_redraw_screen(wp
);
526 if (key
< '0' || key
> '9')
528 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
529 "Goto Item", wp
, key
);
535 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
536 case MODEKEYCHOICE_CANCEL
:
537 window_choose_fire_callback(wp
, NULL
);
539 case MODEKEYCHOICE_CHOOSE
:
540 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
541 window_choose_fire_callback(wp
, item
->wcd
);
543 case MODEKEYCHOICE_TREE_TOGGLE
:
544 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
545 if (item
->state
& TREE_EXPANDED
)
546 window_choose_collapse(wp
, item
->wcd
->tree_session
);
548 window_choose_expand(wp
, item
->wcd
->tree_session
,
551 window_choose_redraw_screen(wp
);
553 case MODEKEYCHOICE_TREE_COLLAPSE
:
554 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
555 if (item
->state
& TREE_EXPANDED
) {
556 window_choose_collapse(wp
, item
->wcd
->tree_session
);
557 window_choose_redraw_screen(wp
);
560 case MODEKEYCHOICE_TREE_COLLAPSE_ALL
:
561 window_choose_collapse_all(wp
);
563 case MODEKEYCHOICE_TREE_EXPAND
:
564 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
565 if (!(item
->state
& TREE_EXPANDED
)) {
566 window_choose_expand(wp
, item
->wcd
->tree_session
,
568 window_choose_redraw_screen(wp
);
571 case MODEKEYCHOICE_TREE_EXPAND_ALL
:
572 window_choose_expand_all(wp
);
574 case MODEKEYCHOICE_UP
:
577 if (data
->selected
== 0) {
578 data
->selected
= items
- 1;
579 if (data
->selected
> screen_size_y(s
) - 1)
580 data
->top
= items
- screen_size_y(s
);
581 window_choose_redraw_screen(wp
);
585 if (data
->selected
< data
->top
)
586 window_choose_scroll_up(wp
);
588 screen_write_start(&ctx
, wp
, NULL
);
589 window_choose_write_line(
590 wp
, &ctx
, data
->selected
- data
->top
);
591 window_choose_write_line(
592 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
593 screen_write_stop(&ctx
);
596 case MODEKEYCHOICE_DOWN
:
599 if (data
->selected
== items
- 1) {
602 window_choose_redraw_screen(wp
);
607 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
608 screen_write_start(&ctx
, wp
, NULL
);
609 window_choose_write_line(
610 wp
, &ctx
, data
->selected
- data
->top
);
611 window_choose_write_line(
612 wp
, &ctx
, data
->selected
- 1 - data
->top
);
613 screen_write_stop(&ctx
);
615 window_choose_scroll_down(wp
);
617 case MODEKEYCHOICE_SCROLLUP
:
618 if (items
== 0 || data
->top
== 0)
620 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
622 window_choose_scroll_up(wp
);
623 screen_write_start(&ctx
, wp
, NULL
);
624 window_choose_write_line(
625 wp
, &ctx
, screen_size_y(s
) - 1);
626 screen_write_stop(&ctx
);
628 window_choose_scroll_up(wp
);
630 case MODEKEYCHOICE_SCROLLDOWN
:
632 data
->top
+ screen_size_y(&data
->screen
) >= items
)
634 if (data
->selected
== data
->top
) {
636 window_choose_scroll_down(wp
);
637 screen_write_start(&ctx
, wp
, NULL
);
638 window_choose_write_line(wp
, &ctx
, 0);
639 screen_write_stop(&ctx
);
641 window_choose_scroll_down(wp
);
643 case MODEKEYCHOICE_PAGEUP
:
644 if (data
->selected
< screen_size_y(s
)) {
648 data
->selected
-= screen_size_y(s
);
649 if (data
->top
< screen_size_y(s
))
652 data
->top
-= screen_size_y(s
);
654 window_choose_redraw_screen(wp
);
656 case MODEKEYCHOICE_PAGEDOWN
:
657 data
->selected
+= screen_size_y(s
);
658 if (data
->selected
> items
- 1)
659 data
->selected
= items
- 1;
660 data
->top
+= screen_size_y(s
);
661 if (screen_size_y(s
) < items
) {
662 if (data
->top
+ screen_size_y(s
) > items
)
663 data
->top
= items
- screen_size_y(s
);
666 if (data
->selected
< data
->top
)
667 data
->top
= data
->selected
;
668 window_choose_redraw_screen(wp
);
670 case MODEKEYCHOICE_BACKSPACE
:
671 input_len
= strlen(data
->input_str
);
673 data
->input_str
[input_len
- 1] = '\0';
674 window_choose_redraw_screen(wp
);
676 case MODEKEYCHOICE_STARTNUMBERPREFIX
:
677 key
&= KEYC_MASK_KEY
;
678 if (key
< '0' || key
> '9')
680 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
681 "Goto Item", wp
, key
);
684 idx
= window_choose_index_key(data
, key
);
685 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
687 data
->selected
= idx
;
689 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
690 window_choose_fire_callback(wp
, item
->wcd
);
697 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
699 struct window_choose_mode_data
*data
= wp
->modedata
;
700 struct screen
*s
= &data
->screen
;
701 struct window_choose_mode_item
*item
;
704 if (~m
->event
& MOUSE_EVENT_CLICK
)
706 if (m
->x
>= screen_size_x(s
))
708 if (m
->y
>= screen_size_y(s
))
711 idx
= data
->top
+ m
->y
;
712 if (idx
>= ARRAY_LENGTH(&data
->list
))
714 data
->selected
= idx
;
716 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
717 window_choose_fire_callback(wp
, item
->wcd
);
721 window_choose_write_line(
722 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
724 struct window_choose_mode_data
*data
= wp
->modedata
;
725 struct window_choose_mode_item
*item
;
726 struct options
*oo
= &wp
->window
->options
;
727 struct screen
*s
= &data
->screen
;
729 size_t last
, xoff
= 0;
730 char hdr
[32], label
[32];
733 if (data
->callbackfn
== NULL
)
734 fatalx("called before callback assigned");
736 last
= screen_size_y(s
) - 1;
737 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
738 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
739 if (data
->selected
== data
->top
+ py
)
740 window_mode_attrs(&gc
, oo
);
742 screen_write_cursormove(ctx
, 0, py
);
743 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
744 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
745 if (item
->wcd
->wl
!= NULL
&&
746 item
->wcd
->wl
->flags
& WINLINK_ALERTFLAGS
)
747 gc
.attr
|= GRID_ATTR_BRIGHT
;
749 key
= window_choose_key_index(data
, data
->top
+ py
);
751 xsnprintf (label
, sizeof label
, "(%c)", key
);
753 xsnprintf (label
, sizeof label
, "(%d)", item
->pos
);
754 screen_write_nputs(ctx
, screen_size_x(s
) - 1, &gc
, utf8flag
,
755 "%*s %s %s", data
->width
+ 2, label
,
757 * Add indication to tree if necessary about whether it's
760 (item
->wcd
->type
& TREE_SESSION
) ?
761 (item
->state
& TREE_EXPANDED
? "-" : "+") : "", item
->name
);
763 while (s
->cx
< screen_size_x(s
) - 1)
764 screen_write_putc(ctx
, &gc
, ' ');
766 if (data
->input_type
!= WINDOW_CHOOSE_NORMAL
) {
767 window_mode_attrs(&gc
, oo
);
769 xoff
= xsnprintf(hdr
, sizeof hdr
,
770 "%s: %s", data
->input_prompt
, data
->input_str
);
771 screen_write_cursormove(ctx
, 0, last
);
772 screen_write_puts(ctx
, &gc
, "%s", hdr
);
773 screen_write_cursormove(ctx
, xoff
, py
);
774 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
780 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
782 static const char keys
[] = "0123456789"
783 "abcdefghijklmnopqrstuvwxyz"
784 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
788 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
789 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
790 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
799 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
801 static const char keys
[] = "0123456789"
802 "abcdefghijklmnopqrstuvwxyz"
803 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
808 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
809 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
810 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
820 window_choose_redraw_screen(struct window_pane
*wp
)
822 struct window_choose_mode_data
*data
= wp
->modedata
;
823 struct screen
*s
= &data
->screen
;
824 struct screen_write_ctx ctx
;
827 screen_write_start(&ctx
, wp
, NULL
);
828 for (i
= 0; i
< screen_size_y(s
); i
++)
829 window_choose_write_line(wp
, &ctx
, i
);
830 screen_write_stop(&ctx
);
834 window_choose_scroll_up(struct window_pane
*wp
)
836 struct window_choose_mode_data
*data
= wp
->modedata
;
837 struct screen_write_ctx ctx
;
843 screen_write_start(&ctx
, wp
, NULL
);
844 screen_write_cursormove(&ctx
, 0, 0);
845 screen_write_insertline(&ctx
, 1);
846 window_choose_write_line(wp
, &ctx
, 0);
847 if (screen_size_y(&data
->screen
) > 1)
848 window_choose_write_line(wp
, &ctx
, 1);
849 screen_write_stop(&ctx
);
853 window_choose_scroll_down(struct window_pane
*wp
)
855 struct window_choose_mode_data
*data
= wp
->modedata
;
856 struct screen
*s
= &data
->screen
;
857 struct screen_write_ctx ctx
;
859 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
863 screen_write_start(&ctx
, wp
, NULL
);
864 screen_write_cursormove(&ctx
, 0, 0);
865 screen_write_deleteline(&ctx
, 1);
866 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
867 if (screen_size_y(&data
->screen
) > 1)
868 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
869 screen_write_stop(&ctx
);
872 struct window_choose_data
*
873 window_choose_add_session(struct window_pane
*wp
, struct client
*c
,
874 struct session
*s
, const char *template, const char *action
, u_int idx
)
876 struct window_choose_data
*wcd
;
878 wcd
= window_choose_data_create(TREE_SESSION
, c
, c
->session
);
881 wcd
->tree_session
= s
;
882 wcd
->tree_session
->references
++;
884 wcd
->ft_template
= xstrdup(template);
885 format_add(wcd
->ft
, "line", "%u", idx
);
886 format_session(wcd
->ft
, s
);
888 wcd
->command
= cmd_template_replace(action
, s
->name
, 1);
890 window_choose_add(wp
, wcd
);
895 struct window_choose_data
*
896 window_choose_add_item(struct window_pane
*wp
, struct client
*c
,
897 struct winlink
*wl
, const char *template, const char *action
, u_int idx
)
899 struct window_choose_data
*wcd
;
902 wcd
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
905 wcd
->ft_template
= xstrdup(template);
906 format_add(wcd
->ft
, "line", "%u", idx
);
907 format_session(wcd
->ft
, wcd
->start_session
);
908 format_winlink(wcd
->ft
, wcd
->start_session
, wl
);
909 format_window_pane(wcd
->ft
, wl
->window
->active
);
912 * Interpolate action here, since the data we pass back is the expanded
915 xasprintf(&expanded
, "%s", format_expand(wcd
->ft
, wcd
->ft_template
));
916 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
919 window_choose_add(wp
, wcd
);
925 struct window_choose_data
*
926 window_choose_add_window(struct window_pane
*wp
, struct client
*c
,
927 struct session
*s
, struct winlink
*wl
, const char *template,
928 const char *action
, u_int idx
)
930 struct window_choose_data
*wcd
;
933 wcd
= window_choose_data_create(TREE_WINDOW
, c
, c
->session
);
938 wcd
->tree_session
= s
;
939 wcd
->tree_session
->references
++;
941 wcd
->ft_template
= xstrdup(template);
942 format_add(wcd
->ft
, "line", "%u", idx
);
943 format_session(wcd
->ft
, s
);
944 format_winlink(wcd
->ft
, s
, wl
);
945 format_window_pane(wcd
->ft
, wl
->window
->active
);
947 xasprintf(&expanded
, "%s:%d", s
->name
, wl
->idx
);
948 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
951 window_choose_add(wp
, wcd
);