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>
25 struct screen
*window_choose_init(struct window_pane
*);
26 void window_choose_free(struct window_pane
*);
27 void window_choose_resize(struct window_pane
*, u_int
, u_int
);
28 void window_choose_key(struct window_pane
*, struct session
*, int);
29 void window_choose_mouse(
30 struct window_pane
*, struct session
*, struct mouse_event
*);
32 void window_choose_redraw_screen(struct window_pane
*);
33 void window_choose_write_line(
34 struct window_pane
*, struct screen_write_ctx
*, u_int
);
36 void window_choose_scroll_up(struct window_pane
*);
37 void window_choose_scroll_down(struct window_pane
*);
39 const struct window_mode window_choose_mode
= {
48 struct window_choose_mode_item
{
53 struct window_choose_mode_data
{
56 struct mode_key_data mdata
;
58 ARRAY_DECL(, struct window_choose_mode_item
) list
;
62 void (*callbackfn
)(void *, int);
63 void (*freefn
)(void *);
67 int window_choose_key_index(struct window_choose_mode_data
*, u_int
);
68 int window_choose_index_key(struct window_choose_mode_data
*, int);
71 window_choose_vadd(struct window_pane
*wp
, int idx
, const char *fmt
, va_list ap
)
73 struct window_choose_mode_data
*data
= wp
->modedata
;
74 struct window_choose_mode_item
*item
;
76 ARRAY_EXPAND(&data
->list
, 1);
77 item
= &ARRAY_LAST(&data
->list
);
78 xvasprintf(&item
->name
, fmt
, ap
);
83 window_choose_add(struct window_pane
*wp
, int idx
, const char *fmt
, ...)
88 window_choose_vadd(wp
, idx
, fmt
, ap
);
93 window_choose_ready(struct window_pane
*wp
, u_int cur
,
94 void (*callbackfn
)(void *, int), void (*freefn
)(void *), void *cdata
)
96 struct window_choose_mode_data
*data
= wp
->modedata
;
97 struct screen
*s
= &data
->screen
;
100 if (data
->selected
> screen_size_y(s
) - 1)
101 data
->top
= ARRAY_LENGTH(&data
->list
) - screen_size_y(s
);
103 data
->callbackfn
= callbackfn
;
104 data
->freefn
= freefn
;
107 window_choose_redraw_screen(wp
);
111 window_choose_init(struct window_pane
*wp
)
113 struct window_choose_mode_data
*data
;
117 wp
->modedata
= data
= xmalloc(sizeof *data
);
119 data
->callbackfn
= NULL
;
123 ARRAY_INIT(&data
->list
);
127 screen_init(s
, screen_size_x(&wp
->base
), screen_size_y(&wp
->base
), 0);
128 s
->mode
&= ~MODE_CURSOR
;
129 if (options_get_number(&wp
->window
->options
, "mode-mouse"))
130 s
->mode
|= MODE_MOUSE
;
132 keys
= options_get_number(&wp
->window
->options
, "mode-keys");
133 if (keys
== MODEKEY_EMACS
)
134 mode_key_init(&data
->mdata
, &mode_key_tree_emacs_choice
);
136 mode_key_init(&data
->mdata
, &mode_key_tree_vi_choice
);
142 window_choose_free(struct window_pane
*wp
)
144 struct window_choose_mode_data
*data
= wp
->modedata
;
147 if (data
->freefn
!= NULL
&& data
->data
!= NULL
)
148 data
->freefn(data
->data
);
150 for (i
= 0; i
< ARRAY_LENGTH(&data
->list
); i
++)
151 xfree(ARRAY_ITEM(&data
->list
, i
).name
);
152 ARRAY_FREE(&data
->list
);
154 screen_free(&data
->screen
);
159 window_choose_resize(struct window_pane
*wp
, u_int sx
, u_int sy
)
161 struct window_choose_mode_data
*data
= wp
->modedata
;
162 struct screen
*s
= &data
->screen
;
165 if (data
->selected
> sy
- 1)
166 data
->top
= data
->selected
- (sy
- 1);
168 screen_resize(s
, sx
, sy
);
169 window_choose_redraw_screen(wp
);
174 window_choose_key(struct window_pane
*wp
, unused
struct session
*sess
, int key
)
176 struct window_choose_mode_data
*data
= wp
->modedata
;
177 struct screen
*s
= &data
->screen
;
178 struct screen_write_ctx ctx
;
179 struct window_choose_mode_item
*item
;
183 items
= ARRAY_LENGTH(&data
->list
);
185 switch (mode_key_lookup(&data
->mdata
, key
)) {
186 case MODEKEYCHOICE_CANCEL
:
187 data
->callbackfn(data
->data
, -1);
188 window_pane_reset_mode(wp
);
190 case MODEKEYCHOICE_CHOOSE
:
191 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
192 data
->callbackfn(data
->data
, item
->idx
);
193 window_pane_reset_mode(wp
);
195 case MODEKEYCHOICE_UP
:
198 if (data
->selected
== 0) {
199 data
->selected
= items
- 1;
200 if (data
->selected
> screen_size_y(s
) - 1)
201 data
->top
= items
- screen_size_y(s
);
202 window_choose_redraw_screen(wp
);
206 if (data
->selected
< data
->top
)
207 window_choose_scroll_up(wp
);
209 screen_write_start(&ctx
, wp
, NULL
);
210 window_choose_write_line(
211 wp
, &ctx
, data
->selected
- data
->top
);
212 window_choose_write_line(
213 wp
, &ctx
, data
->selected
+ 1 - data
->top
);
214 screen_write_stop(&ctx
);
217 case MODEKEYCHOICE_DOWN
:
220 if (data
->selected
== items
- 1) {
223 window_choose_redraw_screen(wp
);
228 if (data
->selected
< data
->top
+ screen_size_y(s
)) {
229 screen_write_start(&ctx
, wp
, NULL
);
230 window_choose_write_line(
231 wp
, &ctx
, data
->selected
- data
->top
);
232 window_choose_write_line(
233 wp
, &ctx
, data
->selected
- 1 - data
->top
);
234 screen_write_stop(&ctx
);
236 window_choose_scroll_down(wp
);
238 case MODEKEYCHOICE_SCROLLUP
:
239 if (items
== 0 || data
->top
== 0)
241 if (data
->selected
== data
->top
+ screen_size_y(s
) - 1) {
243 window_choose_scroll_up(wp
);
244 screen_write_start(&ctx
, wp
, NULL
);
245 window_choose_write_line(
246 wp
, &ctx
, screen_size_y(s
) - 1);
247 screen_write_stop(&ctx
);
249 window_choose_scroll_up(wp
);
251 case MODEKEYCHOICE_SCROLLDOWN
:
253 data
->top
+ screen_size_y(&data
->screen
) >= items
)
255 if (data
->selected
== data
->top
) {
257 window_choose_scroll_down(wp
);
258 screen_write_start(&ctx
, wp
, NULL
);
259 window_choose_write_line(wp
, &ctx
, 0);
260 screen_write_stop(&ctx
);
262 window_choose_scroll_down(wp
);
264 case MODEKEYCHOICE_PAGEUP
:
265 if (data
->selected
< screen_size_y(s
)) {
269 data
->selected
-= screen_size_y(s
);
270 if (data
->top
< screen_size_y(s
))
273 data
->top
-= screen_size_y(s
);
275 window_choose_redraw_screen(wp
);
277 case MODEKEYCHOICE_PAGEDOWN
:
278 data
->selected
+= screen_size_y(s
);
279 if (data
->selected
> items
- 1)
280 data
->selected
= items
- 1;
281 data
->top
+= screen_size_y(s
);
282 if (screen_size_y(s
) < items
) {
283 if (data
->top
+ screen_size_y(s
) > items
)
284 data
->top
= items
- screen_size_y(s
);
287 if (data
->selected
< data
->top
)
288 data
->top
= data
->selected
;
289 window_choose_redraw_screen(wp
);
292 idx
= window_choose_index_key(data
, key
);
293 if (idx
< 0 || (u_int
) idx
>= ARRAY_LENGTH(&data
->list
))
295 data
->selected
= idx
;
297 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
298 data
->callbackfn(data
->data
, item
->idx
);
299 window_pane_reset_mode(wp
);
307 struct window_pane
*wp
, unused
struct session
*sess
, struct mouse_event
*m
)
309 struct window_choose_mode_data
*data
= wp
->modedata
;
310 struct screen
*s
= &data
->screen
;
311 struct window_choose_mode_item
*item
;
316 if (m
->x
>= screen_size_x(s
))
318 if (m
->y
>= screen_size_y(s
))
321 idx
= data
->top
+ m
->y
;
322 if (idx
>= ARRAY_LENGTH(&data
->list
))
324 data
->selected
= idx
;
326 item
= &ARRAY_ITEM(&data
->list
, data
->selected
);
327 data
->callbackfn(data
->data
, item
->idx
);
328 window_pane_reset_mode(wp
);
332 window_choose_write_line(
333 struct window_pane
*wp
, struct screen_write_ctx
*ctx
, u_int py
)
335 struct window_choose_mode_data
*data
= wp
->modedata
;
336 struct window_choose_mode_item
*item
;
337 struct options
*oo
= &wp
->window
->options
;
338 struct screen
*s
= &data
->screen
;
342 if (data
->callbackfn
== NULL
)
343 fatalx("called before callback assigned");
345 utf8flag
= options_get_number(&wp
->window
->options
, "utf8");
346 memcpy(&gc
, &grid_default_cell
, sizeof gc
);
347 if (data
->selected
== data
->top
+ py
) {
348 colour_set_fg(&gc
, options_get_number(oo
, "mode-fg"));
349 colour_set_bg(&gc
, options_get_number(oo
, "mode-bg"));
350 gc
.attr
|= options_get_number(oo
, "mode-attr");
353 screen_write_cursormove(ctx
, 0, py
);
354 if (data
->top
+ py
< ARRAY_LENGTH(&data
->list
)) {
355 item
= &ARRAY_ITEM(&data
->list
, data
->top
+ py
);
356 key
= window_choose_key_index(data
, data
->top
+ py
);
358 screen_write_nputs(ctx
, screen_size_x(s
) - 1,
359 &gc
, utf8flag
, "(%c) %s", key
, item
->name
);
361 screen_write_nputs(ctx
, screen_size_x(s
) - 1,
362 &gc
, utf8flag
, " %s", item
->name
);
366 while (s
->cx
< screen_size_x(s
))
367 screen_write_putc(ctx
, &gc
, ' ');
371 window_choose_key_index(struct window_choose_mode_data
*data
, u_int idx
)
373 static const char keys
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
377 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
378 mkey
= mode_key_lookup(&data
->mdata
, *ptr
);
379 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
388 window_choose_index_key(struct window_choose_mode_data
*data
, int key
)
390 static const char keys
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
395 for (ptr
= keys
; *ptr
!= '\0'; ptr
++) {
396 mkey
= mode_key_lookup(&data
->mdata
, *ptr
);
397 if (mkey
!= MODEKEY_NONE
&& mkey
!= MODEKEY_OTHER
)
407 window_choose_redraw_screen(struct window_pane
*wp
)
409 struct window_choose_mode_data
*data
= wp
->modedata
;
410 struct screen
*s
= &data
->screen
;
411 struct screen_write_ctx ctx
;
414 screen_write_start(&ctx
, wp
, NULL
);
415 for (i
= 0; i
< screen_size_y(s
); i
++)
416 window_choose_write_line(wp
, &ctx
, i
);
417 screen_write_stop(&ctx
);
421 window_choose_scroll_up(struct window_pane
*wp
)
423 struct window_choose_mode_data
*data
= wp
->modedata
;
424 struct screen_write_ctx ctx
;
430 screen_write_start(&ctx
, wp
, NULL
);
431 screen_write_cursormove(&ctx
, 0, 0);
432 screen_write_insertline(&ctx
, 1);
433 window_choose_write_line(wp
, &ctx
, 0);
434 if (screen_size_y(&data
->screen
) > 1)
435 window_choose_write_line(wp
, &ctx
, 1);
436 screen_write_stop(&ctx
);
440 window_choose_scroll_down(struct window_pane
*wp
)
442 struct window_choose_mode_data
*data
= wp
->modedata
;
443 struct screen
*s
= &data
->screen
;
444 struct screen_write_ctx ctx
;
446 if (data
->top
>= ARRAY_LENGTH(&data
->list
))
450 screen_write_start(&ctx
, wp
, NULL
);
451 screen_write_cursormove(&ctx
, 0, 0);
452 screen_write_deleteline(&ctx
, 1);
453 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 1);
454 if (screen_size_y(&data
->screen
) > 1)
455 window_choose_write_line(wp
, &ctx
, screen_size_y(s
) - 2);
456 screen_write_stop(&ctx
);