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
)
203 struct cmd_list
*cmdlist
;
207 * The command template will have already been replaced. But if it's
210 if (cdata
->command
== NULL
)
213 if (cmd_string_parse(cdata
->command
, &cmdlist
, NULL
, 0, &cause
) != 0) {
215 *cause
= toupper((u_char
) *cause
);
216 status_message_set(cdata
->start_client
, "%s", cause
);
222 cmdq_run(cdata
->start_client
->cmdq
, cmdlist
);
223 cmd_list_free(cmdlist
);
227 window_choose_default_callback(struct window_choose_data
*wcd
)
231 if (wcd
->start_client
->flags
& CLIENT_DEAD
)
234 window_choose_data_run(wcd
);
238 window_choose_free(struct window_pane
*wp
)
240 if (wp
->modedata
!= NULL
)
241 window_choose_free1(wp
->modedata
);
245 window_choose_free1(struct window_choose_mode_data
*data
)
247 struct window_choose_mode_item
*item
;
253 for (i
= 0; i
< ARRAY_LENGTH(&data
->old_list
); i
++) {
254 item
= &ARRAY_ITEM(&data
->old_list
, i
);
255 window_choose_data_free(item
->wcd
);
258 ARRAY_FREE(&data
->list
);
259 ARRAY_FREE(&data
->old_list
);
260 free(data
->input_str
);
262 screen_free(&data
->screen
);
267 window_choose_resize(struct window_pane
*wp
, u_int sx
, u_int sy
)
269 struct window_choose_mode_data
*data
= wp
->modedata
;
270 struct screen
*s
= &data
->screen
;
273 if (data
->selected
> sy
- 1)
274 data
->top
= data
->selected
- (sy
- 1);
276 screen_resize(s
, sx
, sy
, 0);
277 window_choose_redraw_screen(wp
);
281 window_choose_fire_callback(
282 struct window_pane
*wp
, struct window_choose_data
*wcd
)
284 struct window_choose_mode_data
*data
= wp
->modedata
;
287 window_pane_reset_mode(wp
);
289 data
->callbackfn(wcd
);
291 window_choose_free1(data
);
295 window_choose_prompt_input(enum window_choose_input_type input_type
,
296 const char *prompt
, struct window_pane
*wp
, int key
)
298 struct window_choose_mode_data
*data
= wp
->modedata
;
301 data
->input_type
= input_type
;
302 data
->input_prompt
= prompt
;
303 input_len
= strlen(data
->input_str
) + 2;
305 data
->input_str
= xrealloc(data
->input_str
, 1, input_len
);
306 data
->input_str
[input_len
- 2] = key
;
307 data
->input_str
[input_len
- 1] = '\0';
309 window_choose_redraw_screen(wp
);
313 window_choose_collapse(struct window_pane
*wp
, struct session
*s
)
315 struct window_choose_mode_data
*data
= wp
->modedata
;
316 struct window_choose_mode_item
*item
, *chosen
;
317 struct window_choose_data
*wcd
;
320 ARRAY_DECL(, struct window_choose_mode_item
) list_copy
;
321 ARRAY_INIT(&list_copy
);
323 pos
= data
->selected
;
325 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
326 chosen
->state
&= ~TREE_EXPANDED
;
329 * Trying to mangle the &data->list in-place has lots of problems, so
330 * assign the actual result we want to render and copy the new one over
333 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++)
335 item
= &ARRAY_ITEM(&data
->list
, i
);
338 if (s
== wcd
->tree_session
) {
339 /* We only show the session when collapsed. */
340 if (wcd
->type
& TREE_SESSION
) {
341 item
->state
&= ~TREE_EXPANDED
;
343 ARRAY_ADD(&list_copy
,
344 ARRAY_ITEM(&data
->list
, i
));
346 * Update the selection to this session item so
347 * we don't end up highlighting a non-existent
353 ARRAY_ADD(&list_copy
, ARRAY_ITEM(&data
->list
, i
));
356 if (!ARRAY_EMPTY(&list_copy
)) {
357 ARRAY_FREE(&data
->list
);
358 ARRAY_CONCAT(&data
->list
, &list_copy
);
359 ARRAY_FREE(&list_copy
);
364 window_choose_collapse_all(struct window_pane
*wp
)
366 struct window_choose_mode_data
*data
= wp
->modedata
;
367 struct window_choose_mode_item
*item
;
368 struct session
*s
, *chosen
;
371 chosen
= ARRAY_ITEM(&data
->list
, data
->selected
).wcd
->start_session
;
373 RB_FOREACH(s
, sessions
, &sessions
)
374 window_choose_collapse(wp
, s
);
376 /* Reset the selection back to the starting session. */
377 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
378 item
= &ARRAY_ITEM(&data
->list
, i
);
380 if (chosen
!= item
->wcd
->tree_session
)
383 if (item
->wcd
->type
& TREE_SESSION
)
386 window_choose_redraw_screen(wp
);
390 window_choose_expand_all(struct window_pane
*wp
)
392 struct window_choose_mode_data
*data
= wp
->modedata
;
393 struct window_choose_mode_item
*item
;
397 RB_FOREACH(s
, sessions
, &sessions
) {
398 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++) {
399 item
= &ARRAY_ITEM(&data
->list
, i
);
401 if (s
!= item
->wcd
->tree_session
)
404 if (item
->wcd
->type
& TREE_SESSION
)
405 window_choose_expand(wp
, s
, i
);
409 window_choose_redraw_screen(wp
);
413 window_choose_expand(struct window_pane
*wp
, struct session
*s
, u_int pos
)
415 struct window_choose_mode_data
*data
= wp
->modedata
;
416 struct window_choose_mode_item
*item
, *chosen
;
417 struct window_choose_data
*wcd
;
420 chosen
= &ARRAY_ITEM(&data
->list
, pos
);
421 items
= ARRAY_LENGTH(&data
->old_list
) - 1;
423 /* It's not possible to expand anything other than sessions. */
424 if (!(chosen
->wcd
->type
& TREE_SESSION
))
427 /* Don't re-expand a session which is already expanded. */
428 if (chosen
->state
& TREE_EXPANDED
)
431 /* Mark the session entry as expanded. */
432 chosen
->state
|= TREE_EXPANDED
;
435 * Go back through the original list of all sessions and windows, and
436 * pull out the windows where the session matches the selection chosen
439 for (i
= items
; i
> 0; i
--) {
440 item
= &ARRAY_ITEM(&data
->old_list
, i
);
441 item
->state
|= TREE_EXPANDED
;
444 if (s
== wcd
->tree_session
) {
446 * Since the session is already displayed, we only care
447 * to add back in window for it.
449 if (wcd
->type
& TREE_WINDOW
) {
451 * If the insertion point for adding the
452 * windows to the session falls inside the
453 * range of the list, then we insert these
454 * entries in order *AFTER* the selected
458 ARRAY_INSERT(&data
->list
,
460 ARRAY_ITEM(&data
->old_list
,
463 /* Ran out of room, add to the end. */
464 ARRAY_ADD(&data
->list
,
465 ARRAY_ITEM(&data
->old_list
,
474 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
476 struct window_choose_mode_data
*data
= wp
->modedata
;
477 struct screen
*s
= &data
->screen
;
478 struct screen_write_ctx ctx
;
479 struct window_choose_mode_item
*item
;
484 items
= ARRAY_LENGTH(&data
->list
);
486 if (data
->input_type
== WINDOW_CHOOSE_GOTO_ITEM
) {
487 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
488 case MODEKEYCHOICE_CANCEL
:
489 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
490 window_choose_redraw_screen(wp
);
492 case MODEKEYCHOICE_CHOOSE
:
493 n
= strtonum(data
->input_str
, 0, INT_MAX
, NULL
);
495 data
->input_type
= WINDOW_CHOOSE_NORMAL
;
496 window_choose_redraw_screen(wp
);
499 item
= &ARRAY_ITEM(&data
->list
, n
);
500 window_choose_fire_callback(wp
, item
->wcd
);
502 case MODEKEYCHOICE_BACKSPACE
:
503 input_len
= strlen(data
->input_str
);
505 data
->input_str
[input_len
- 1] = '\0';
506 window_choose_redraw_screen(wp
);
509 if (key
< '0' || key
> '9')
511 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
512 "Goto Item", wp
, key
);
518 switch (mode_key_lookup(&data
->mdata
, key
, NULL
)) {
519 case MODEKEYCHOICE_CANCEL
:
520 window_choose_fire_callback(wp
, NULL
);
522 case MODEKEYCHOICE_CHOOSE
:
523 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
524 window_choose_fire_callback(wp
, item
->wcd
);
526 case MODEKEYCHOICE_TREE_TOGGLE
:
527 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
528 if (item
->state
& TREE_EXPANDED
)
529 window_choose_collapse(wp
, item
->wcd
->tree_session
);
531 window_choose_expand(wp
, item
->wcd
->tree_session
,
534 window_choose_redraw_screen(wp
);
536 case MODEKEYCHOICE_TREE_COLLAPSE
:
537 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
538 if (item
->state
& TREE_EXPANDED
) {
539 window_choose_collapse(wp
, item
->wcd
->tree_session
);
540 window_choose_redraw_screen(wp
);
543 case MODEKEYCHOICE_TREE_COLLAPSE_ALL
:
544 window_choose_collapse_all(wp
);
546 case MODEKEYCHOICE_TREE_EXPAND
:
547 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
548 if (!(item
->state
& TREE_EXPANDED
)) {
549 window_choose_expand(wp
, item
->wcd
->tree_session
,
551 window_choose_redraw_screen(wp
);
554 case MODEKEYCHOICE_TREE_EXPAND_ALL
:
555 window_choose_expand_all(wp
);
557 case MODEKEYCHOICE_UP
:
560 if (data
->selected
== 0) {
561 data
->selected
= items
- 1;
562 if (data
->selected
> screen_size_y(s
) - 1)
563 data
->top
= items
- screen_size_y(s
);
564 window_choose_redraw_screen(wp
);
568 if (data
->selected
< data
->top
)
569 window_choose_scroll_up(wp
);
571 screen_write_start(&ctx
, wp
, NULL
);
572 window_choose_write_line(
573 wp
, &ctx
, data
->selected
- data
->top
);
574 window_choose_write_line(
575 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
576 screen_write_stop(&ctx
);
579 case MODEKEYCHOICE_DOWN
:
582 if (data
->selected
== items
- 1) {
585 window_choose_redraw_screen(wp
);
590 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
591 screen_write_start(&ctx
, wp
, NULL
);
592 window_choose_write_line(
593 wp
, &ctx
, data
->selected
- data
->top
);
594 window_choose_write_line(
595 wp
, &ctx
, data
->selected
- 1 - data
->top
);
596 screen_write_stop(&ctx
);
598 window_choose_scroll_down(wp
);
600 case MODEKEYCHOICE_SCROLLUP
:
601 if (items
== 0 || data
->top
== 0)
603 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
605 window_choose_scroll_up(wp
);
606 screen_write_start(&ctx
, wp
, NULL
);
607 window_choose_write_line(
608 wp
, &ctx
, screen_size_y(s
) - 1);
609 screen_write_stop(&ctx
);
611 window_choose_scroll_up(wp
);
613 case MODEKEYCHOICE_SCROLLDOWN
:
615 data
->top
+ screen_size_y(&data
->screen
) >= items
)
617 if (data
->selected
== data
->top
) {
619 window_choose_scroll_down(wp
);
620 screen_write_start(&ctx
, wp
, NULL
);
621 window_choose_write_line(wp
, &ctx
, 0);
622 screen_write_stop(&ctx
);
624 window_choose_scroll_down(wp
);
626 case MODEKEYCHOICE_PAGEUP
:
627 if (data
->selected
< screen_size_y(s
)) {
631 data
->selected
-= screen_size_y(s
);
632 if (data
->top
< screen_size_y(s
))
635 data
->top
-= screen_size_y(s
);
637 window_choose_redraw_screen(wp
);
639 case MODEKEYCHOICE_PAGEDOWN
:
640 data
->selected
+= screen_size_y(s
);
641 if (data
->selected
> items
- 1)
642 data
->selected
= items
- 1;
643 data
->top
+= screen_size_y(s
);
644 if (screen_size_y(s
) < items
) {
645 if (data
->top
+ screen_size_y(s
) > items
)
646 data
->top
= items
- screen_size_y(s
);
649 if (data
->selected
< data
->top
)
650 data
->top
= data
->selected
;
651 window_choose_redraw_screen(wp
);
653 case MODEKEYCHOICE_BACKSPACE
:
654 input_len
= strlen(data
->input_str
);
656 data
->input_str
[input_len
- 1] = '\0';
657 window_choose_redraw_screen(wp
);
659 case MODEKEYCHOICE_STARTNUMBERPREFIX
:
660 key
&= KEYC_MASK_KEY
;
661 if (key
< '0' || key
> '9')
663 window_choose_prompt_input(WINDOW_CHOOSE_GOTO_ITEM
,
664 "Goto Item", wp
, key
);
667 idx
= window_choose_index_key(data
, key
);
668 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
670 data
->selected
= idx
;
672 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
673 window_choose_fire_callback(wp
, item
->wcd
);
680 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
682 struct window_choose_mode_data
*data
= wp
->modedata
;
683 struct screen
*s
= &data
->screen
;
684 struct window_choose_mode_item
*item
;
687 if (~m
->event
& MOUSE_EVENT_CLICK
)
689 if (m
->x
>= screen_size_x(s
))
691 if (m
->y
>= screen_size_y(s
))
694 idx
= data
->top
+ m
->y
;
695 if (idx
>= ARRAY_LENGTH(&data
->list
))
697 data
->selected
= idx
;
699 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
700 window_choose_fire_callback(wp
, item
->wcd
);
704 window_choose_write_line(
705 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
707 struct window_choose_mode_data
*data
= wp
->modedata
;
708 struct window_choose_mode_item
*item
;
709 struct options
*oo
= &wp
->window
->options
;
710 struct screen
*s
= &data
->screen
;
712 size_t last
, xoff
= 0;
713 char hdr
[32], label
[32];
716 if (data
->callbackfn
== NULL
)
717 fatalx("called before callback assigned");
719 last
= screen_size_y(s
) - 1;
720 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
721 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
722 if (data
->selected
== data
->top
+ py
)
723 window_mode_attrs(&gc
, oo
);
725 screen_write_cursormove(ctx
, 0, py
);
726 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
727 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
728 if (item
->wcd
->wl
!= NULL
&&
729 item
->wcd
->wl
->flags
& WINLINK_ALERTFLAGS
)
730 gc
.attr
|= GRID_ATTR_BRIGHT
;
732 key
= window_choose_key_index(data
, data
->top
+ py
);
734 xsnprintf (label
, sizeof label
, "(%c)", key
);
736 xsnprintf (label
, sizeof label
, "(%d)", item
->pos
);
737 screen_write_nputs(ctx
, screen_size_x(s
) - 1, &gc
, utf8flag
,
738 "%*s %s %s", data
->width
+ 2, label
,
740 * Add indication to tree if necessary about whether it's
743 (item
->wcd
->type
& TREE_SESSION
) ?
744 (item
->state
& TREE_EXPANDED
? "-" : "+") : "", item
->name
);
746 while (s
->cx
< screen_size_x(s
) - 1)
747 screen_write_putc(ctx
, &gc
, ' ');
749 if (data
->input_type
!= WINDOW_CHOOSE_NORMAL
) {
750 window_mode_attrs(&gc
, oo
);
752 xoff
= xsnprintf(hdr
, sizeof hdr
,
753 "%s: %s", data
->input_prompt
, data
->input_str
);
754 screen_write_cursormove(ctx
, 0, last
);
755 screen_write_puts(ctx
, &gc
, "%s", hdr
);
756 screen_write_cursormove(ctx
, xoff
, py
);
757 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
763 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
765 static const char keys
[] = "0123456789"
766 "abcdefghijklmnopqrstuvwxyz"
767 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
771 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
772 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
773 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
782 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
784 static const char keys
[] = "0123456789"
785 "abcdefghijklmnopqrstuvwxyz"
786 "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
791 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
792 mkey
= mode_key_lookup(&data
->mdata
, *ptr
, NULL
);
793 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
803 window_choose_redraw_screen(struct window_pane
*wp
)
805 struct window_choose_mode_data
*data
= wp
->modedata
;
806 struct screen
*s
= &data
->screen
;
807 struct screen_write_ctx ctx
;
810 screen_write_start(&ctx
, wp
, NULL
);
811 for (i
= 0; i
< screen_size_y(s
); i
++)
812 window_choose_write_line(wp
, &ctx
, i
);
813 screen_write_stop(&ctx
);
817 window_choose_scroll_up(struct window_pane
*wp
)
819 struct window_choose_mode_data
*data
= wp
->modedata
;
820 struct screen_write_ctx ctx
;
826 screen_write_start(&ctx
, wp
, NULL
);
827 screen_write_cursormove(&ctx
, 0, 0);
828 screen_write_insertline(&ctx
, 1);
829 window_choose_write_line(wp
, &ctx
, 0);
830 if (screen_size_y(&data
->screen
) > 1)
831 window_choose_write_line(wp
, &ctx
, 1);
832 screen_write_stop(&ctx
);
836 window_choose_scroll_down(struct window_pane
*wp
)
838 struct window_choose_mode_data
*data
= wp
->modedata
;
839 struct screen
*s
= &data
->screen
;
840 struct screen_write_ctx ctx
;
842 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
846 screen_write_start(&ctx
, wp
, NULL
);
847 screen_write_cursormove(&ctx
, 0, 0);
848 screen_write_deleteline(&ctx
, 1);
849 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
850 if (screen_size_y(&data
->screen
) > 1)
851 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
852 screen_write_stop(&ctx
);
855 struct window_choose_data
*
856 window_choose_add_session(struct window_pane
*wp
, struct client
*c
,
857 struct session
*s
, const char *template, const char *action
, u_int idx
)
859 struct window_choose_data
*wcd
;
861 wcd
= window_choose_data_create(TREE_SESSION
, c
, c
->session
);
864 wcd
->tree_session
= s
;
865 wcd
->tree_session
->references
++;
867 wcd
->ft_template
= xstrdup(template);
868 format_add(wcd
->ft
, "line", "%u", idx
);
869 format_session(wcd
->ft
, s
);
871 wcd
->command
= cmd_template_replace(action
, s
->name
, 1);
873 window_choose_add(wp
, wcd
);
878 struct window_choose_data
*
879 window_choose_add_item(struct window_pane
*wp
, struct client
*c
,
880 struct winlink
*wl
, const char *template, const char *action
, u_int idx
)
882 struct window_choose_data
*wcd
;
885 wcd
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
888 wcd
->ft_template
= xstrdup(template);
889 format_add(wcd
->ft
, "line", "%u", idx
);
890 format_session(wcd
->ft
, wcd
->start_session
);
891 format_winlink(wcd
->ft
, wcd
->start_session
, wl
);
892 format_window_pane(wcd
->ft
, wl
->window
->active
);
895 * Interpolate action here, since the data we pass back is the expanded
898 xasprintf(&expanded
, "%s", format_expand(wcd
->ft
, wcd
->ft_template
));
899 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
902 window_choose_add(wp
, wcd
);
908 struct window_choose_data
*
909 window_choose_add_window(struct window_pane
*wp
, struct client
*c
,
910 struct session
*s
, struct winlink
*wl
, const char *template,
911 const char *action
, u_int idx
)
913 struct window_choose_data
*wcd
;
916 wcd
= window_choose_data_create(TREE_WINDOW
, c
, c
->session
);
921 wcd
->tree_session
= s
;
922 wcd
->tree_session
->references
++;
924 wcd
->ft_template
= xstrdup(template);
925 format_add(wcd
->ft
, "line", "%u", idx
);
926 format_session(wcd
->ft
, s
);
927 format_winlink(wcd
->ft
, s
, wl
);
928 format_window_pane(wcd
->ft
, wl
->window
->active
);
930 xasprintf(&expanded
, "%s:%d", s
->name
, wl
->idx
);
931 wcd
->command
= cmd_template_replace(action
, expanded
, 1);
934 window_choose_add(wp
, wcd
);