list_input.h (6430B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2022, 2026 GNUnet e.V. 4 5 GNUnet is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Affero General Public License as published 7 by the Free Software Foundation, either version 3 of the License, 8 or (at your option) any later version. 9 10 GNUnet is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 SPDX-License-Identifier: AGPL3.0-or-later 19 */ 20 /* 21 * @author Tobias Frisch 22 * @file ui/list_input.h 23 */ 24 25 #ifndef UI_LIST_INPUT_H_ 26 #define UI_LIST_INPUT_H_ 27 28 #include <stdbool.h> 29 30 /** 31 * Resets the list controls. 32 */ 33 #define list_input_reset(list) { \ 34 (list)->line_prev = 0; \ 35 (list)->line_next = 0; \ 36 (list)->line_index = 0; \ 37 (list)->selected = 0; \ 38 } 39 40 /** 41 * Handles the list controls selection and 42 * indices to move the selection via events. 43 */ 44 #define list_input_select(list, line_width, item) { \ 45 const bool selected = ( \ 46 ((list)->line_selected >= (list)->line_index) && \ 47 ((list)->line_selected < (list)->line_index + (line_width)) \ 48 ); \ 49 \ 50 if ((!selected) && ((list)->line_selected > (list)->line_index)) \ 51 (list)->line_prev = (list)->line_index; \ 52 \ 53 (list)->line_index += (line_width); \ 54 \ 55 if (selected) { \ 56 (list)->line_next = (list)->line_index; \ 57 (list)->selected = item; \ 58 } \ 59 } 60 61 /** 62 * Handles the key event to move the selection 63 * of list controls and adjust its view area. 64 */ 65 #define list_input_event(list, key) { \ 66 int count = (list)->line_index; \ 67 \ 68 switch (key) \ 69 { \ 70 case KEY_UP: \ 71 { \ 72 (list)->line_selected = (list)->line_prev; \ 73 break; \ 74 } \ 75 case KEY_DOWN: \ 76 { \ 77 (list)->line_selected = (list)->line_next; \ 78 break; \ 79 } \ 80 default: \ 81 break; \ 82 } \ 83 \ 84 if ((list)->line_selected < 0) \ 85 (list)->line_selected = 0; \ 86 else if ((list)->line_selected >= count) \ 87 (list)->line_selected = count - 1; \ 88 \ 89 if ((list)->window) \ 90 { \ 91 const int height = getmaxy((list)->window); \ 92 const int y = (list)->line_selected - (list)->line_offset; \ 93 \ 94 if (y < 0) \ 95 (list)->line_offset += y; \ 96 else if (y + 1 >= height) \ 97 (list)->line_offset += y + 1 - height; \ 98 \ 99 if ((list)->line_offset < 0) \ 100 (list)->line_offset = 0; \ 101 else if ((list)->line_offset >= count) \ 102 (list)->line_offset = count - 1; \ 103 } \ 104 } 105 106 /** 107 * Prepares for printing an item in list controls 108 * as well as providing its selection and its 109 * y location in the current view. 110 */ 111 #define list_input_print_(list, line_width, yes_res, no_res) \ 112 const bool selected = ( \ 113 ((list)->line_selected >= (list)->line_index) && \ 114 ((list)->line_selected < (list)->line_index + (line_width)) \ 115 ); \ 116 \ 117 const int y = (list)->line_index - (list)->line_offset; { \ 118 \ 119 (list)->line_index += (line_width); \ 120 \ 121 if (y + (line_width) < 1) \ 122 return yes_res; \ 123 \ 124 const int height = getmaxy((list)->window); \ 125 \ 126 if (y >= height) \ 127 return no_res; \ 128 } 129 130 #define list_input_print_gnunet(list, line_width) \ 131 list_input_print_(list, line_width, GNUNET_YES, GNUNET_NO) 132 133 #define list_input_print(list, line_width) \ 134 list_input_print_(list, line_width, , ) 135 136 #endif /* UI_LIST_INPUT_H_ */