| @@ -2,7 +2,8 @@ · 1 unmodified line |
| 2 | 2 | #include "oso.h" |
| 3 | 3 | #include <ctype.h> |
| 4 | 4 | #include <form.h> |
| 5 | | −#include <menu.h> |
| 5 | + |
| 6 | +ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm); |
| 6 | 7 | |
| 7 | 8 | void term_util_init_colors() { |
| 8 | 9 | if (has_colors()) { |
| @@ -38,20 +39,18 @@ struct Qmsg { · 29 unmodified lines |
| 38 | 39 | Qmsg_dismiss_mode dismiss_mode; |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | | −struct Qmenu_item_extra { |
| 42 | | − int user_id; |
| 42 | +typedef struct Qmenu_item { |
| 43 | + char const *text; |
| 44 | + int id; |
| 43 | 45 | U8 owns_string : 1, is_spacer : 1; |
| 44 | | −}; |
| 46 | +} Qmenu_item; |
| 45 | 47 | |
| 46 | 48 | struct Qmenu { |
| 47 | 49 | Qblock qblock; |
| 48 | | − MENU *ncurses_menu; |
| 49 | | − ITEM **ncurses_items; |
| 50 | + Qmenu_item *items; |
| 50 | 51 | Usz items_count, items_cap; |
| 51 | | − ITEM *initial_item; |
| 52 | | − int id; |
| 53 | | − // Flag for right-padding hack. Temp until we do our own menus |
| 54 | | − U8 has_submenu_item : 1; |
| 52 | + int current_item, id; |
| 53 | + U8 needs_reprint : 1, is_frontmost : 1; |
| 55 | 54 | }; |
| 56 | 55 | |
| 57 | 56 | struct Qform { |
| @@ -175,18 +174,26 @@ bool qnav_draw(void) { · 117 unmodified lines |
| 175 | 174 | getmaxyx(stdscr, term_h, term_w); |
| 176 | 175 | for (Usz i = 0; i < qnav_stack.count; ++i) { |
| 177 | 176 | Qblock *qb = qnav_stack.blocks[i]; |
| 178 | | − if (qnav_stack.occlusion_dirty) { |
| 179 | | − bool is_frontmost = i == qnav_stack.count - 1; |
| 177 | + bool is_frontmost = i == qnav_stack.count - 1; |
| 178 | + if (qnav_stack.occlusion_dirty) |
| 180 | 179 | qblock_print_frame(qb, is_frontmost); |
| 181 | | − switch (qb->tag) { |
| 182 | | − case Qblock_type_qmsg: |
| 183 | | − break; |
| 184 | | − case Qblock_type_qmenu: |
| 185 | | − qmenu_set_displayed_active(qmenu_of(qb), is_frontmost); |
| 186 | | − break; |
| 187 | | − case Qblock_type_qform: |
| 188 | | − break; |
| 180 | + switch (qb->tag) { |
| 181 | + case Qblock_type_qmsg: |
| 182 | + break; |
| 183 | + case Qblock_type_qmenu: { |
| 184 | + Qmenu *qm = qmenu_of(qb); |
| 185 | + if (qm->is_frontmost != is_frontmost) { |
| 186 | + qm->is_frontmost = is_frontmost; |
| 187 | + qm->needs_reprint = 1; |
| 188 | + } |
| 189 | + if (qm->needs_reprint) { |
| 190 | + qmenu_reprint(qm); |
| 191 | + qm->needs_reprint = 0; |
| 189 | 192 | } |
| 193 | + break; |
| 194 | + } |
| 195 | + case Qblock_type_qform: |
| 196 | + break; |
| 190 | 197 | } |
| 191 | 198 | touchwin(qb->outer_window); // here? or after continue? |
| 192 | 199 | if (term_h < 1 || term_w < 1) |
| @@ -222,7 +229,7 @@ void qblock_print_title(Qblock *qb, char const *title, int attr) { · 29 unmodified lines |
| 222 | 229 | wattr_get(qb->outer_window, &attrs, &pair, NULL); |
| 223 | 230 | wattrset(qb->outer_window, attr); |
| 224 | 231 | waddch(qb->outer_window, ' '); |
| 225 | | − wprintw(qb->outer_window, title); |
| 232 | + waddstr(qb->outer_window, title); |
| 226 | 233 | waddch(qb->outer_window, ' '); |
| 227 | 234 | wattr_set(qb->outer_window, attrs, pair, NULL); |
| 228 | 235 | } |
| @@ -343,91 +350,65 @@ Qmsg *qmsg_of(Qblock *qb) { return ORCA_CONTAINER_OF(qb, Qmsg, qblock); } · 114 unmodified lines |
| 343 | 350 | Qmenu *qmenu_create(int id) { |
| 344 | 351 | Qmenu *qm = (Qmenu *)malloc(sizeof(Qmenu)); |
| 345 | 352 | qblock_init(&qm->qblock, Qblock_type_qmenu); |
| 346 | | − qm->ncurses_menu = NULL; |
| 347 | | − qm->ncurses_items = NULL; |
| 353 | + qm->items = NULL; |
| 348 | 354 | qm->items_count = 0; |
| 349 | 355 | qm->items_cap = 0; |
| 350 | | − qm->initial_item = NULL; |
| 356 | + qm->current_item = 0; |
| 351 | 357 | qm->id = id; |
| 352 | | − qm->has_submenu_item = 0; |
| 358 | + qm->needs_reprint = 1; |
| 359 | + qm->is_frontmost = 0; |
| 353 | 360 | return qm; |
| 354 | 361 | } |
| 355 | 362 | void qmenu_destroy(Qmenu *qm) { qmenu_free(qm); } |
| 356 | 363 | int qmenu_id(Qmenu const *qm) { return qm->id; } |
| 357 | | −static ORCA_NOINLINE void |
| 358 | | −qmenu_allocitems(Qmenu *qm, Usz count, Usz *out_idx, ITEM ***out_items, |
| 359 | | − struct Qmenu_item_extra **out_extras) { |
| 364 | +static ORCA_NOINLINE Qmenu_item *qmenu_allocitems(Qmenu *qm, Usz count) { |
| 360 | 365 | Usz old_count = qm->items_count; |
| 361 | | − // Add 1 for the extra null terminator guy |
| 362 | | − Usz new_count = old_count + count + 1; |
| 366 | + if (old_count > SIZE_MAX - count) // overflow |
| 367 | + exit(1); |
| 368 | + Usz new_count = old_count + count; |
| 363 | 369 | Usz items_cap = qm->items_cap; |
| 364 | | − ITEM **items = qm->ncurses_items; |
| 370 | + Qmenu_item *items = qm->items; |
| 365 | 371 | if (new_count > items_cap) { |
| 366 | 372 | // todo overflow check, realloc fail check |
| 367 | | − Usz old_cap = items_cap; |
| 368 | 373 | Usz new_cap = new_count < 32 ? 32 : orca_round_up_power2(new_count); |
| 369 | | − Usz new_size = new_cap * (sizeof(ITEM *) + sizeof(struct Qmenu_item_extra)); |
| 370 | | − ITEM **new_items = (ITEM **)realloc(items, new_size); |
| 374 | + Usz new_size = new_cap * sizeof(Qmenu_item); |
| 375 | + Qmenu_item *new_items = (Qmenu_item *)realloc(items, new_size); |
| 371 | 376 | if (!new_items) |
| 372 | 377 | exit(1); |
| 373 | 378 | items = new_items; |
| 374 | 379 | items_cap = new_cap; |
| 375 | | − // Move old extras data to new position |
| 376 | | − Usz old_extras_offset = sizeof(ITEM *) * old_cap; |
| 377 | | − Usz new_extras_offset = sizeof(ITEM *) * new_cap; |
| 378 | | − Usz old_extras_size = sizeof(struct Qmenu_item_extra) * old_count; |
| 379 | | − memmove((char *)items + new_extras_offset, |
| 380 | | − (char *)items + old_extras_offset, old_extras_size); |
| 381 | | − qm->ncurses_items = new_items; |
| 380 | + qm->items = new_items; |
| 382 | 381 | qm->items_cap = new_cap; |
| 383 | 382 | } |
| 384 | | − // Not using new_count here in order to leave an extra 1 for the null |
| 385 | | − // terminator as required by ncurses. |
| 386 | | − qm->items_count = old_count + count; |
| 387 | | − Usz extras_offset = sizeof(ITEM *) * items_cap; |
| 388 | | − *out_idx = old_count; |
| 389 | | − *out_items = items + old_count; |
| 390 | | − *out_extras = |
| 391 | | − (struct Qmenu_item_extra *)((char *)items + extras_offset) + old_count; |
| 392 | | −} |
| 393 | | −ORCA_FORCEINLINE static struct Qmenu_item_extra * |
| 394 | | −qmenu_item_extras_ptr(Qmenu *qm) { |
| 395 | | − Usz offset = sizeof(ITEM *) * qm->items_cap; |
| 396 | | − return (struct Qmenu_item_extra *)((char *)qm->ncurses_items + offset); |
| 397 | | −} |
| 398 | | −// Get the curses menu item user pointer out, turn it to an int, and use it as |
| 399 | | −// an index into the 'extras' arrays. |
| 400 | | −ORCA_FORCEINLINE static struct Qmenu_item_extra * |
| 401 | | −qmenu_itemextra(struct Qmenu_item_extra *extras, ITEM *item) { |
| 402 | | − return extras + (int)(intptr_t)(item_userptr(item)); |
| 383 | + qm->items_count = new_count; |
| 384 | + return items + old_count; |
| 385 | +} |
| 386 | +ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm) { |
| 387 | + WINDOW *win = qm->qblock.content_window; |
| 388 | + Qmenu_item *items = qm->items; |
| 389 | + bool isfront = qm->is_frontmost; |
| 390 | + werase(win); |
| 391 | + for (Usz i = 0, n = qm->items_count; i < n; ++i) { |
| 392 | + bool iscur = items[i].id == qm->current_item; |
| 393 | + wattrset(win, isfront ? iscur ? A_BOLD : A_NORMAL : A_DIM); |
| 394 | + wmove(win, (int)i, iscur ? 1 : 3); |
| 395 | + if (iscur) |
| 396 | + waddstr(win, "> "); |
| 397 | + waddstr(win, items[i].text); |
| 398 | + } |
| 403 | 399 | } |
| 404 | 400 | void qmenu_set_title(Qmenu *qm, char const *title) { |
| 405 | 401 | qblock_set_title(&qm->qblock, title); |
| 406 | 402 | } |
| 407 | 403 | void qmenu_add_choice(Qmenu *qm, int id, char const *text) { |
| 408 | 404 | assert(id != 0); |
| 409 | | − Usz idx; |
| 410 | | − ITEM **items; |
| 411 | | − struct Qmenu_item_extra *extras; |
| 412 | | − qmenu_allocitems(qm, 1, &idx, &items, &extras); |
| 413 | | − items[0] = new_item(text, NULL); |
| 414 | | − set_item_userptr(items[0], (void *)(uintptr_t)idx); |
| 415 | | − extras[0].user_id = id; |
| 416 | | − extras[0].owns_string = false; |
| 417 | | − extras[0].is_spacer = false; |
| 418 | | −} |
| 419 | | −void qmenu_add_submenu(Qmenu *qm, int id, char const *text) { |
| 420 | | − assert(id != 0); |
| 421 | | − qm->has_submenu_item = true; // don't add +1 right padding to subwindow |
| 422 | | − Usz idx; |
| 423 | | − ITEM **items; |
| 424 | | − struct Qmenu_item_extra *extras; |
| 425 | | − qmenu_allocitems(qm, 1, &idx, &items, &extras); |
| 426 | | − items[0] = new_item(text, ">"); |
| 427 | | − set_item_userptr(items[0], (void *)(uintptr_t)idx); |
| 428 | | − extras[0].user_id = id; |
| 429 | | − extras[0].owns_string = false; |
| 430 | | − extras[0].is_spacer = false; |
| 405 | + Qmenu_item *item = qmenu_allocitems(qm, 1); |
| 406 | + item->text = text; |
| 407 | + item->id = id; |
| 408 | + item->owns_string = false; |
| 409 | + item->is_spacer = false; |
| 410 | + if (!qm->current_item) |
| 411 | + qm->current_item = id; |
| 431 | 412 | } |
| 432 | 413 | void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...) { |
| 433 | 414 | va_list ap; |
| @@ -442,85 +423,42 @@ void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...) { · 8 unmodified lines |
| 442 | 423 | va_end(ap); |
| 443 | 424 | if (printedsize != textsize) |
| 444 | 425 | exit(1); // todo better handling? |
| 445 | | − Usz idx; |
| 446 | | − ITEM **items; |
| 447 | | − struct Qmenu_item_extra *extras; |
| 448 | | − qmenu_allocitems(qm, 1, &idx, &items, &extras); |
| 449 | | − items[0] = new_item(buffer, NULL); |
| 450 | | − set_item_userptr(items[0], (void *)(uintptr_t)idx); |
| 451 | | − extras[0].user_id = id; |
| 452 | | − extras[0].owns_string = true; |
| 453 | | − extras[0].is_spacer = false; |
| 426 | + Qmenu_item *item = qmenu_allocitems(qm, 1); |
| 427 | + item->text = buffer; |
| 428 | + item->id = id; |
| 429 | + item->owns_string = true; |
| 430 | + item->is_spacer = false; |
| 431 | + if (!qm->current_item) |
| 432 | + qm->current_item = id; |
| 454 | 433 | } |
| 455 | 434 | void qmenu_add_spacer(Qmenu *qm) { |
| 456 | | − Usz idx; |
| 457 | | − ITEM **items; |
| 458 | | − struct Qmenu_item_extra *extras; |
| 459 | | − qmenu_allocitems(qm, 1, &idx, &items, &extras); |
| 460 | | − items[0] = new_item(" ", NULL); |
| 461 | | − item_opts_off(items[0], O_SELECTABLE); |
| 462 | | − set_item_userptr(items[0], (void *)(uintptr_t)idx); |
| 463 | | − extras[0].user_id = 0; |
| 464 | | − extras[0].owns_string = false; |
| 465 | | − extras[0].is_spacer = true; |
| 435 | + Qmenu_item *item = qmenu_allocitems(qm, 1); |
| 436 | + item->text = " "; |
| 437 | + item->id = 0; |
| 438 | + item->owns_string = false; |
| 439 | + item->is_spacer = true; |
| 466 | 440 | } |
| 467 | 441 | void qmenu_set_current_item(Qmenu *qm, int id) { |
| 468 | | − ITEM **items = qm->ncurses_items; |
| 469 | | − struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm); |
| 470 | | − ITEM *found = NULL; |
| 471 | | − for (Usz i = 0, n = qm->items_count; i < n; i++) { |
| 472 | | − ITEM *item = items[i]; |
| 473 | | − if (qmenu_itemextra(extras, item)->user_id == id) { |
| 474 | | − found = item; |
| 475 | | − break; |
| 476 | | − } |
| 477 | | − } |
| 478 | | − if (!found) |
| 442 | + if (qm->current_item == id) |
| 479 | 443 | return; |
| 480 | | − if (qm->ncurses_menu) { |
| 481 | | − set_current_item(qm->ncurses_menu, found); |
| 482 | | − } else { |
| 483 | | − qm->initial_item = found; |
| 484 | | − } |
| 485 | | −} |
| 486 | | −int qmenu_current_item(Qmenu *qm) { |
| 487 | | − ITEM *item = NULL; |
| 488 | | − if (qm->ncurses_menu) |
| 489 | | − item = current_item(qm->ncurses_menu); |
| 490 | | − if (!item) |
| 491 | | − item = qm->initial_item; |
| 492 | | − if (!item) |
| 493 | | − return 0; |
| 494 | | − struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm); |
| 495 | | − return qmenu_itemextra(extras, item)->user_id; |
| 496 | | −} |
| 497 | | −void qmenu_set_displayed_active(Qmenu *qm, bool active) { |
| 498 | | − // Could add a flag in the Qmenu to avoid redundantly changing this stuff. |
| 499 | | − set_menu_fore(qm->ncurses_menu, active ? A_BOLD : A_DIM); |
| 500 | | − set_menu_back(qm->ncurses_menu, active ? A_NORMAL : A_DIM); |
| 501 | | − set_menu_grey(qm->ncurses_menu, active ? A_DIM : A_DIM); |
| 444 | + qm->current_item = id; |
| 445 | + qm->needs_reprint = 1; |
| 502 | 446 | } |
| 447 | +int qmenu_current_item(Qmenu *qm) { return qm->current_item; } |
| 503 | 448 | void qmenu_push_to_nav(Qmenu *qm) { |
| 504 | | − // new_menu() will get angry if there are no items in the menu. We'll get a |
| 505 | | − // null pointer back, and our code will get angry. Instead, just add an empty |
| 506 | | − // spacer item. This will probably only ever occur as a programming error, |
| 507 | | − // but we should try to avoid having to deal with qmenu_push_to_nav() |
| 508 | | − // returning a non-ignorable error for now. |
| 449 | + // Probably a programming error if there are no items. Make the menu visible |
| 450 | + // so the programmer knows something went wrong. |
| 509 | 451 | if (qm->items_count == 0) |
| 510 | 452 | qmenu_add_spacer(qm); |
| 511 | | − // Allocating items always leaves an extra available item at the end. This is |
| 512 | | − // so we can assign a NULL to it here, since ncurses requires the array to be |
| 513 | | − // null terminated instead of using a count. |
| 514 | | − qm->ncurses_items[qm->items_count] = NULL; |
| 515 | | − qm->ncurses_menu = new_menu(qm->ncurses_items); |
| 516 | | − set_menu_mark(qm->ncurses_menu, " > "); |
| 517 | | − set_menu_fore(qm->ncurses_menu, A_BOLD); |
| 518 | | − set_menu_grey(qm->ncurses_menu, A_DIM); |
| 519 | | − set_menu_format(qm->ncurses_menu, 30, 1); // temp to allow large Y |
| 520 | | − int menu_min_h, menu_min_w; |
| 521 | | − scale_menu(qm->ncurses_menu, &menu_min_h, &menu_min_w); |
| 522 | | − if (!qm->has_submenu_item) |
| 523 | | − menu_min_w += 1; // temp hack |
| 453 | + Usz n = qm->items_count; |
| 454 | + Qmenu_item *items = qm->items; |
| 455 | + int menu_min_h = (int)n, menu_min_w = 0; |
| 456 | + for (Usz i = 0; i < n; ++i) { |
| 457 | + int item_w = (int)strlen(items[i].text); |
| 458 | + if (item_w > menu_min_w) |
| 459 | + menu_min_w = item_w; |
| 460 | + } |
| 461 | + menu_min_w += 3 + 1; // left " > " plus 1 empty space on right |
| 524 | 462 | if (qm->qblock.title) { |
| 525 | 463 | // Stupid lack of wcswidth() means we can't know how wide this string is |
| 526 | 464 | // actually displayed. Just fake it for now, until we have Unicode strings |
| @@ -529,58 +467,50 @@ void qmenu_push_to_nav(Qmenu *qm) { · 2 unmodified lines |
| 529 | 467 | if (title_w > menu_min_w) |
| 530 | 468 | menu_min_w = title_w; |
| 531 | 469 | } |
| 532 | | − if (qm->initial_item) |
| 533 | | − set_current_item(qm->ncurses_menu, qm->initial_item); |
| 534 | 470 | qnav_stack_push(&qm->qblock, menu_min_h, menu_min_w); |
| 535 | | − set_menu_win(qm->ncurses_menu, qm->qblock.outer_window); |
| 536 | | − set_menu_sub(qm->ncurses_menu, qm->qblock.content_window); |
| 537 | | − // TODO use this to set how "big" the menu is, visually, for scrolling. |
| 538 | | − // (ncurses can't figure that out on its own, aparently...) |
| 539 | | − // We'll need to split apart some work chunks so that we calculate the size |
| 540 | | − // beforehand. |
| 541 | | − // set_menu_format(qm->ncurses_menu, 5, 1); |
| 542 | | − post_menu(qm->ncurses_menu); |
| 543 | 471 | } |
| 544 | 472 | |
| 545 | 473 | void qmenu_free(Qmenu *qm) { |
| 546 | | − unpost_menu(qm->ncurses_menu); |
| 547 | | − free_menu(qm->ncurses_menu); |
| 548 | | − struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm); |
| 549 | | − for (Usz i = 0; i < qm->items_count; ++i) { |
| 550 | | − ITEM *item = qm->ncurses_items[i]; |
| 551 | | − struct Qmenu_item_extra *extra = qmenu_itemextra(extras, item); |
| 552 | | − char const *freed_str = NULL; |
| 553 | | − if (extra->owns_string) |
| 554 | | − freed_str = item_name(item); |
| 555 | | − free_item(qm->ncurses_items[i]); |
| 556 | | − if (freed_str) |
| 557 | | − free((void *)freed_str); |
| 474 | + Qmenu_item *items = qm->items; |
| 475 | + for (Usz i = 0, n = qm->items_count; i < n; ++i) { |
| 476 | + if (items[i].owns_string) |
| 477 | + free((void *)items[i].text); |
| 558 | 478 | } |
| 559 | | − free(qm->ncurses_items); |
| 479 | + free(qm->items); |
| 560 | 480 | free(qm); |
| 561 | 481 | } |
| 562 | 482 | |
| 563 | | −ORCA_NOINLINE |
| 564 | | −static void qmenu_drive_upordown(Qmenu *qm, int req_up_or_down) { |
| 565 | | − struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm); |
| 566 | | − ITEM *starting = current_item(qm->ncurses_menu); |
| 567 | | − menu_driver(qm->ncurses_menu, req_up_or_down); |
| 568 | | − ITEM *cur = current_item(qm->ncurses_menu); |
| 483 | +ORCA_NOINLINE static void qmenu_drive_upordown(Qmenu *qm, bool downwards) { |
| 484 | + Qmenu_item *items = qm->items; |
| 485 | + Usz n = qm->items_count; |
| 486 | + if (n <= 1) |
| 487 | + return; |
| 488 | + int cur_id = qm->current_item; |
| 489 | + Usz starting = 0; |
| 490 | + for (; starting < n; ++starting) { |
| 491 | + if (items[starting].id == cur_id) |
| 492 | + goto found; |
| 493 | + } |
| 494 | + return; |
| 495 | +found:; |
| 496 | + Usz current = starting; |
| 569 | 497 | for (;;) { |
| 570 | | − if (!cur || cur == starting) |
| 571 | | − break; |
| 572 | | − if (!qmenu_itemextra(extras, cur)->is_spacer) |
| 498 | + if (downwards && current < n - 1) |
| 499 | + current++; |
| 500 | + else if (!downwards && current > 0) |
| 501 | + current--; |
| 502 | + if (current == starting) |
| 573 | 503 | break; |
| 574 | | − ITEM *prev = cur; |
| 575 | | − menu_driver(qm->ncurses_menu, req_up_or_down); |
| 576 | | − cur = current_item(qm->ncurses_menu); |
| 577 | | − if (cur == prev) |
| 504 | + if (!items[current].is_spacer) |
| 578 | 505 | break; |
| 579 | 506 | } |
| 507 | + if (current != starting) { |
| 508 | + qm->current_item = items[current].id; |
| 509 | + qm->needs_reprint = 1; |
| 510 | + } |
| 580 | 511 | } |
| 581 | 512 | |
| 582 | 513 | bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action) { |
| 583 | | − struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm); |
| 584 | 514 | switch (key) { |
| 585 | 515 | case 27: { |
| 586 | 516 | out_action->any.type = Qmenu_action_type_canceled; |
| @@ -588,17 +518,15 @@ bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action) { · 1 unmodified line |
| 588 | 518 | } |
| 589 | 519 | case ' ': |
| 590 | 520 | case '\r': |
| 591 | | − case KEY_ENTER: { |
| 592 | | − ITEM *cur = current_item(qm->ncurses_menu); |
| 521 | + case KEY_ENTER: |
| 593 | 522 | out_action->picked.type = Qmenu_action_type_picked; |
| 594 | | − out_action->picked.id = cur ? qmenu_itemextra(extras, cur)->user_id : 0; |
| 523 | + out_action->picked.id = qm->current_item; |
| 595 | 524 | return true; |
| 596 | | − } |
| 597 | 525 | case KEY_UP: |
| 598 | | − qmenu_drive_upordown(qm, REQ_UP_ITEM); |
| 526 | + qmenu_drive_upordown(qm, false); |
| 599 | 527 | return false; |
| 600 | 528 | case KEY_DOWN: |
| 601 | | − qmenu_drive_upordown(qm, REQ_DOWN_ITEM); |
| 529 | + qmenu_drive_upordown(qm, true); |
| 602 | 530 | return false; |
| 603 | 531 | } |
| 604 | 532 | return false; |