list_input.h (6444B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2022 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 #include <stdlib.h> 30 31 /** 32 * Resets the list controls. 33 */ 34 #define list_input_reset(list) { \ 35 (list)->line_prev = 0; \ 36 (list)->line_next = 0; \ 37 (list)->line_index = 0; \ 38 (list)->selected = 0; \ 39 } 40 41 /** 42 * Handles the list controls selection and 43 * indices to move the selection via events. 44 */ 45 #define list_input_select(list, line_width, item) { \ 46 const bool selected = ( \ 47 ((list)->line_selected >= (list)->line_index) && \ 48 ((list)->line_selected < (list)->line_index + (line_width)) \ 49 ); \ 50 \ 51 if ((!selected) && ((list)->line_selected > (list)->line_index)) \ 52 (list)->line_prev = (list)->line_index; \ 53 \ 54 (list)->line_index += (line_width); \ 55 \ 56 if (selected) { \ 57 (list)->line_next = (list)->line_index; \ 58 (list)->selected = item; \ 59 } \ 60 } 61 62 /** 63 * Handles the key event to move the selection 64 * of list controls and adjust its view area. 65 */ 66 #define list_input_event(list, key) { \ 67 int count = (list)->line_index; \ 68 \ 69 switch (key) \ 70 { \ 71 case KEY_UP: \ 72 { \ 73 (list)->line_selected = (list)->line_prev; \ 74 break; \ 75 } \ 76 case KEY_DOWN: \ 77 { \ 78 (list)->line_selected = (list)->line_next; \ 79 break; \ 80 } \ 81 default: \ 82 break; \ 83 } \ 84 \ 85 if ((list)->line_selected < 0) \ 86 (list)->line_selected = 0; \ 87 else if ((list)->line_selected >= count) \ 88 (list)->line_selected = count - 1; \ 89 \ 90 if ((list)->window) \ 91 { \ 92 const int height = getmaxy((list)->window); \ 93 const int y = (list)->line_selected - (list)->line_offset; \ 94 \ 95 if (y < 0) \ 96 (list)->line_offset += y; \ 97 else if (y + 1 >= height) \ 98 (list)->line_offset += y + 1 - height; \ 99 \ 100 if ((list)->line_offset < 0) \ 101 (list)->line_offset = 0; \ 102 else if ((list)->line_offset >= count) \ 103 (list)->line_offset = count - 1; \ 104 } \ 105 } 106 107 /** 108 * Prepares for printing an item in list controls 109 * as well as providing its selection and its 110 * y location in the current view. 111 */ 112 #define list_input_print_(list, line_width, yes_res, no_res) \ 113 const bool selected = ( \ 114 ((list)->line_selected >= (list)->line_index) && \ 115 ((list)->line_selected < (list)->line_index + (line_width)) \ 116 ); \ 117 \ 118 const int y = (list)->line_index - (list)->line_offset; { \ 119 \ 120 (list)->line_index += (line_width); \ 121 \ 122 if (y + (line_width) < 1) \ 123 return yes_res; \ 124 \ 125 const int height = getmaxy((list)->window); \ 126 \ 127 if (y >= height) \ 128 return no_res; \ 129 } 130 131 #define list_input_print_gnunet(list, line_width) \ 132 list_input_print_(list, line_width, GNUNET_YES, GNUNET_NO) 133 134 #define list_input_print(list, line_width) \ 135 list_input_print_(list, line_width, , ) 136 137 #endif /* UI_LIST_INPUT_H_ */