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
++) {
349 item
= &ARRAY_ITEM(&data
->list
, i
);
352 if (s
== wcd
->tree_session
) {
353 /* We only show the session when collapsed. */
354 if (wcd
->type
& TREE_SESSION
) {
355 item
->state
&= ~TREE_EXPANDED
;
357 ARRAY_ADD(&list_copy
,
358 ARRAY_ITEM(&data
->list
, i
));
360 * Update the selection to this session item so
361 * we don't end up highlighting a non-existent
367 ARRAY_ADD(&list_copy
, ARRAY_ITEM(&data
->list
, i
));
370 if (!ARRAY_EMPTY(&list_copy
)) {
371 ARRAY_FREE(&data
->list
);
372 ARRAY_CONCAT(&data
->list
, &list_copy
);
373 ARRAY_FREE(&list_copy
);
378 window_choose_collapse_all(struct window_pane
*wp
)
380 struct window_choose_mode_data
*data
= wp
->modedata
;
381 struct window_choose_mode_item
*item
;
382 struct screen
*scr
= &data
->screen
;
383 struct session
*s
, *chosen
;
386 chosen
= ARRAY_ITEM(&data
->list
, data
->selected
).wcd
->start_session
;
388 RB_FOREACH(s
, sessions
, &sessions
)
389 window_choose_collapse(wp
, s
);
391 /* Reset the selection back to the starting session. */
392 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
393 item
= &ARRAY_ITEM(&data
->list
, i
);
395 if (chosen
!= item
->wcd
->tree_session
)
398 if (item
->wcd
->type
& TREE_SESSION
)
401 window_choose_reset_top(wp
, screen_size_y(scr
));
405 window_choose_expand_all(struct window_pane
*wp
)
407 struct window_choose_mode_data
*data
= wp
->modedata
;
408 struct window_choose_mode_item
*item
;
409 struct screen
*scr
= &data
->screen
;
413 RB_FOREACH(s
, sessions
, &sessions
) {
414 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
415 item
= &ARRAY_ITEM(&data
->list
, i
);
417 if (s
!= item
->wcd
->tree_session
)
420 if (item
->wcd
->type
& TREE_SESSION
)
421 window_choose_expand(wp
, s
, i
);
425 window_choose_reset_top(wp
, screen_size_y(scr
));
429 window_choose_expand(struct window_pane
*wp
, struct session
*s
, u_int pos
)
431 struct window_choose_mode_data
*data
= wp
->modedata
;
432 struct window_choose_mode_item
*item
, *chosen
;
433 struct window_choose_data
*wcd
;
436 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
437 items
= ARRAY_LENGTH(&data
->old_list
) - 1;
439 /* It's not possible to expand anything other than sessions. */
440 if (!(chosen
->wcd
->type
& TREE_SESSION
))
443 /* Don't re-expand a session which is already expanded. */
444 if (chosen
->state
& TREE_EXPANDED
)
447 /* Mark the session entry as expanded. */
448 chosen
->state
|= TREE_EXPANDED
;
451 * Go back through the original list of all sessions and windows, and
452 * pull out the windows where the session matches the selection chosen
455 for (i
= items
; i
> 0; i
--) {
456 item
= &ARRAY_ITEM(&data
->old_list
, i
);
457 item
->state
|= TREE_EXPANDED
;
460 if (s
== wcd
->tree_session
) {
462 * Since the session is already displayed, we only care
463 * to add back in window for it.
465 if (wcd
->type
& TREE_WINDOW
) {
467 * If the insertion point for adding the
468 * windows to the session falls inside the
469 * range of the list, then we insert these
470 * entries in order *AFTER* the selected
474 ARRAY_INSERT(&data
->list
,
476 ARRAY_ITEM(&data
->old_list
,
479 /* Ran out of room, add to the end. */
480 ARRAY_ADD(&data
->list
,
481 ARRAY_ITEM(&data
->old_list
,
490 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
492 struct window_choose_mode_data
*data
= wp
->modedata
;
493 struct screen
*s
= &data
->screen
;
494 struct screen_write_ctx ctx
;
495 struct window_choose_mode_item
*item
;
500 items
= ARRAY_LENGTH(&data
->list
);
502 if (data
->input_type
== WINDOW_CHOOSE_GOTO_ITEM
) {
503 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
504 case MODEKEYCHOICE_CANCEL
:
505 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
506 window_choose_redraw_screen(wp
);
508 case MODEKEYCHOICE_CHOOSE
:
509 n
= strtonum(data
->input_str
, 0, INT_MAX
, NULL
);
511 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
512 window_choose_redraw_screen(wp
);
515 item
= &ARRAY_ITEM(&data
->list
, n
);
516 window_choose_fire_callback(wp
, item
->wcd
);
518 case MODEKEYCHOICE_BACKSPACE
:
519 input_len
= strlen(data
->input_str
);
521 data
->input_str
[input_len
- 1] = '\0';
522 window_choose_redraw_screen(wp
);
525 if (key
< '0' || key
> '9')
527 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
528 "Goto Item", wp
, key
);
534 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
535 case MODEKEYCHOICE_CANCEL
:
536 window_choose_fire_callback(wp
, NULL
);
538 case MODEKEYCHOICE_CHOOSE
:
539 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
540 window_choose_fire_callback(wp
, item
->wcd
);
542 case MODEKEYCHOICE_TREE_TOGGLE
:
543 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
544 if (item
->state
& TREE_EXPANDED
)
545 window_choose_collapse(wp
, item
->wcd
->tree_session
);
547 window_choose_expand(wp
, item
->wcd
->tree_session
,
550 window_choose_redraw_screen(wp
);
552 case MODEKEYCHOICE_TREE_COLLAPSE
:
553 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
554 if (item
->state
& TREE_EXPANDED
) {
555 window_choose_collapse(wp
, item
->wcd
->tree_session
);
556 window_choose_redraw_screen(wp
);
559 case MODEKEYCHOICE_TREE_COLLAPSE_ALL
:
560 window_choose_collapse_all(wp
);
562 case MODEKEYCHOICE_TREE_EXPAND
:
563 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
564 if (!(item
->state
& TREE_EXPANDED
)) {
565 window_choose_expand(wp
, item
->wcd
->tree_session
,
567 window_choose_redraw_screen(wp
);
570 case MODEKEYCHOICE_TREE_EXPAND_ALL
:
571 window_choose_expand_all(wp
);
573 case MODEKEYCHOICE_UP
:
576 if (data
->selected
== 0) {
577 data
->selected
= items
- 1;
578 if (data
->selected
> screen_size_y(s
) - 1)
579 data
->top
= items
- screen_size_y(s
);
580 window_choose_redraw_screen(wp
);
584 if (data
->selected
< data
->top
)
585 window_choose_scroll_up(wp
);
587 screen_write_start(&ctx
, wp
, NULL
);
588 window_choose_write_line(
589 wp
, &ctx
, data
->selected
- data
->top
);
590 window_choose_write_line(
591 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
592 screen_write_stop(&ctx
);
595 case MODEKEYCHOICE_DOWN
:
598 if (data
->selected
== items
- 1) {
601 window_choose_redraw_screen(wp
);
606 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
607 screen_write_start(&ctx
, wp
, NULL
);
608 window_choose_write_line(
609 wp
, &ctx
, data
->selected
- data
->top
);
610 window_choose_write_line(
611 wp
, &ctx
, data
->selected
- 1 - data
->top
);
612 screen_write_stop(&ctx
);
614 window_choose_scroll_down(wp
);
616 case MODEKEYCHOICE_SCROLLUP
:
617 if (items
== 0 || data
->top
== 0)
619 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
621 window_choose_scroll_up(wp
);
622 screen_write_start(&ctx
, wp
, NULL
);
623 window_choose_write_line(
624 wp
, &ctx
, screen_size_y(s
) - 1);
625 screen_write_stop(&ctx
);
627 window_choose_scroll_up(wp
);
629 case MODEKEYCHOICE_SCROLLDOWN
:
631 data
->top
+ screen_size_y(&data
->screen
) >= items
)
633 if (data
->selected
== data
->top
) {
635 window_choose_scroll_down(wp
);
636 screen_write_start(&ctx
, wp
, NULL
);
637 window_choose_write_line(wp
, &ctx
, 0);
638 screen_write_stop(&ctx
);
640 window_choose_scroll_down(wp
);
642 case MODEKEYCHOICE_PAGEUP
:
643 if (data
->selected
< screen_size_y(s
)) {
647 data
->selected
-= screen_size_y(s
);
648 if (data
->top
< screen_size_y(s
))
651 data
->top
-= screen_size_y(s
);
653 window_choose_redraw_screen(wp
);
655 case MODEKEYCHOICE_PAGEDOWN
:
656 data
->selected
+= screen_size_y(s
);
657 if (data
->selected
> items
- 1)
658 data
->selected
= items
- 1;
659 data
->top
+= screen_size_y(s
);
660 if (screen_size_y(s
) < items
) {
661 if (data
->top
+ screen_size_y(s
) > items
)
662 data
->top
= items
- screen_size_y(s
);
665 if (data
->selected
< data
->top
)
666 data
->top
= data
->selected
;
667 window_choose_redraw_screen(wp
);
669 case MODEKEYCHOICE_BACKSPACE
:
670 input_len
= strlen(data
->input_str
);
672 data
->input_str
[input_len
- 1] = '\0';
673 window_choose_redraw_screen(wp
);
675 case MODEKEYCHOICE_STARTNUMBERPREFIX
:
676 key
&= KEYC_MASK_KEY
;
677 if (key
< '0' || key
> '9')
679 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
680 "Goto Item", wp
, key
);
683 idx
= window_choose_index_key(data
, key
);
684 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
686 data
->selected
= idx
;
688 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
689 window_choose_fire_callback(wp
, item
->wcd
);
696 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
698 struct window_choose_mode_data
*data
= wp
->modedata
;
699 struct screen
*s
= &data
->screen
;
700 struct window_choose_mode_item
*item
;
703 if (~m
->event
& MOUSE_EVENT_CLICK
)
705 if (m
->x
>= screen_size_x(s
))
707 if (m
->y
>= screen_size_y(s
))
710 idx
= data
->top
+ m
->y
;
711 if (idx
>= ARRAY_LENGTH(&data
->list
))
713 data
->selected
= idx
;
715 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
716 window_choose_fire_callback(wp
, item
->wcd
);
720 window_choose_write_line(
721 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
723 struct window_choose_mode_data
*data
= wp
->modedata
;
724 struct window_choose_mode_item
*item
;
725 struct options
*oo
= &wp
->window
->options
;
726 struct screen
*s
= &data
->screen
;
728 size_t last
, xoff
= 0;
729 char hdr
[32], label
[32];
732 if (data
->callbackfn
== NULL
)
733 fatalx("called before callback assigned");
735 last
= screen_size_y(s
) - 1;
736 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
737 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
738 if (data
->selected
== data
->top
+ py
)
739 style_apply(&gc
, oo
, "mode-style");
741 screen_write_cursormove(ctx
, 0, py
);
742 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
743 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
744 if (item
->wcd
->wl
!= NULL
&&
745 item
->wcd
->wl
->flags
& WINLINK_ALERTFLAGS
)
746 gc
.attr
|= GRID_ATTR_BRIGHT
;
748 key
= window_choose_key_index(data
, data
->top
+ py
);
750 xsnprintf (label
, sizeof label
, "(%c)", key
);
752 xsnprintf (label
, sizeof label
, "(%d)", item
->pos
);
753 screen_write_nputs(ctx
, screen_size_x(s
) - 1, &gc
, utf8flag
,
754 "%*s %s %s", data
->width
+ 2, label
,
756 * Add indication to tree if necessary about whether it's
759 (item
->wcd
->type
& TREE_SESSION
) ?
760 (item
->state
& TREE_EXPANDED
? "-" : "+") : "", item
->name
);
762 while (s
->cx
< screen_size_x(s
) - 1)
763 screen_write_putc(ctx
, &gc
, ' ');
765 if (data
->input_type
!= WINDOW_CHOOSE_NORMAL
) {
766 style_apply(&gc
, oo
, "mode-style");
768 xoff
= xsnprintf(hdr
, sizeof hdr
,
769 "%s: %s", data
->input_prompt
, data
->input_str
);
770 screen_write_cursormove(ctx
, 0, last
);
771 screen_write_puts(ctx
, &gc
, "%s", hdr
);
772 screen_write_cursormove(ctx
, xoff
, py
);
773 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
779 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
781 static const char keys
[] = "0123456789"
782 "abcdefghijklmnopqrstuvwxyz"
783 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
787 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
788 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
789 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
798 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
800 static const char keys
[] = "0123456789"
801 "abcdefghijklmnopqrstuvwxyz"
802 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
807 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
808 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
809 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
819 window_choose_redraw_screen(struct window_pane
*wp
)
821 struct window_choose_mode_data
*data
= wp
->modedata
;
822 struct screen
*s
= &data
->screen
;
823 struct screen_write_ctx ctx
;
826 screen_write_start(&ctx
, wp
, NULL
);
827 for (i
= 0; i
< screen_size_y(s
); i
++)
828 window_choose_write_line(wp
, &ctx
, i
);
829 screen_write_stop(&ctx
);
833 window_choose_scroll_up(struct window_pane
*wp
)
835 struct window_choose_mode_data
*data
= wp
->modedata
;
836 struct screen_write_ctx ctx
;
842 screen_write_start(&ctx
, wp
, NULL
);
843 screen_write_cursormove(&ctx
, 0, 0);
844 screen_write_insertline(&ctx
, 1);
845 window_choose_write_line(wp
, &ctx
, 0);
846 if (screen_size_y(&data
->screen
) > 1)
847 window_choose_write_line(wp
, &ctx
, 1);
848 screen_write_stop(&ctx
);
852 window_choose_scroll_down(struct window_pane
*wp
)
854 struct window_choose_mode_data
*data
= wp
->modedata
;
855 struct screen
*s
= &data
->screen
;
856 struct screen_write_ctx ctx
;
858 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
862 screen_write_start(&ctx
, wp
, NULL
);
863 screen_write_cursormove(&ctx
, 0, 0);
864 screen_write_deleteline(&ctx
, 1);
865 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
866 if (screen_size_y(&data
->screen
) > 1)
867 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
868 screen_write_stop(&ctx
);
871 struct window_choose_data
*
872 window_choose_add_session(struct window_pane
*wp
, struct client
*c
,
873 struct session
*s
, const char *template, const char *action
, u_int idx
)
875 struct window_choose_data
*wcd
;
877 wcd
= window_choose_data_create(TREE_SESSION
, c
, c
->session
);
880 wcd
->tree_session
= s
;
881 wcd
->tree_session
->references
++;
883 wcd
->ft_template
= xstrdup(template);
884 format_add(wcd
->ft
, "line", "%u", idx
);
885 format_session(wcd
->ft
, s
);
887 wcd
->command
= cmd_template_replace(action
, s
->name
, 1);
889 window_choose_add(wp
, wcd
);
894 struct window_choose_data
*
895 window_choose_add_item(struct window_pane
*wp
, struct client
*c
,
896 struct winlink
*wl
, const char *template, const char *action
, u_int idx
)
898 struct window_choose_data
*wcd
;
901 wcd
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
904 wcd
->ft_template
= xstrdup(template);
905 format_add(wcd
->ft
, "line", "%u", idx
);
906 format_session(wcd
->ft
, wcd
->start_session
);
907 format_winlink(wcd
->ft
, wcd
->start_session
, wl
);
908 format_window_pane(wcd
->ft
, wl
->window
->active
);
911 * Interpolate action here, since the data we pass back is the expanded
914 xasprintf(&expanded
, "%s", format_expand(wcd
->ft
, wcd
->ft_template
));
915 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
918 window_choose_add(wp
, wcd
);
924 struct window_choose_data
*
925 window_choose_add_window(struct window_pane
*wp
, struct client
*c
,
926 struct session
*s
, struct winlink
*wl
, const char *template,
927 const char *action
, u_int idx
)
929 struct window_choose_data
*wcd
;
932 wcd
= window_choose_data_create(TREE_WINDOW
, c
, c
->session
);
937 wcd
->tree_session
= s
;
938 wcd
->tree_session
->references
++;
940 wcd
->ft_template
= xstrdup(template);
941 format_add(wcd
->ft
, "line", "%u", idx
);
942 format_session(wcd
->ft
, s
);
943 format_winlink(wcd
->ft
, s
, wl
);
944 format_window_pane(wcd
->ft
, wl
->window
->active
);
946 xasprintf(&expanded
, "%s:%d", s
->name
, wl
->idx
);
947 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
950 window_choose_add(wp
, wcd
);