| /* |
| * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301, USA. |
| * |
| * You can also choose to distribute this program under the terms of |
| * the Unmodified Binary Distribution Licence (as given in the file |
| * COPYING.UBDL), provided that you have satisfied its requirements. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| /** @file |
| * |
| * Text widget UI |
| * |
| */ |
| |
| #include <errno.h> |
| #include <curses.h> |
| #include <ipxe/ansicol.h> |
| #include <ipxe/widget.h> |
| |
| /** |
| * Find editable widget in widget set |
| * |
| * @v widgets Text widget set |
| * @v index Editable widget index |
| * @ret widget Editable widget, or NULL |
| */ |
| static struct widget * find_widget ( struct widgets *widgets, |
| unsigned int index ) { |
| struct widget *widget; |
| |
| list_for_each_entry ( widget, &widgets->list, list ) { |
| if ( ! ( widget->flags & WIDGET_EDITABLE ) ) |
| continue; |
| if ( index-- == 0 ) |
| return widget; |
| } |
| return NULL; |
| } |
| |
| /** |
| * Text widget user interface main loop |
| * |
| * @v widgets Text widget set |
| * @ret rc Return status code |
| */ |
| static int widget_ui_loop ( struct widgets *widgets ) { |
| struct widget *widget; |
| unsigned int current; |
| unsigned int count; |
| int key; |
| |
| /* Draw all widgets */ |
| list_for_each_entry ( widget, &widgets->list, list ) |
| draw_widget ( widget ); |
| |
| /* Count editable widgets */ |
| count = 0; |
| while ( find_widget ( widgets, count ) != NULL ) |
| count++; |
| |
| /* Main loop */ |
| current = 0; |
| while ( 1 ) { |
| |
| /* Identify current widget */ |
| widget = find_widget ( widgets, current ); |
| if ( ! widget ) |
| return -ENOENT; |
| |
| /* Redraw current widget */ |
| draw_widget ( widget ); |
| |
| /* Process keypress */ |
| key = edit_widget ( widget, getkey ( 0 ) ); |
| switch ( key ) { |
| case KEY_UP: |
| if ( current > 0 ) |
| current--; |
| break; |
| case KEY_DOWN: |
| if ( ++current == count ) |
| current--; |
| break; |
| case TAB: |
| if ( ++current == count ) |
| current = 0; |
| break; |
| case KEY_ENTER: |
| current++; |
| if ( current >= count ) |
| return 0; |
| break; |
| case CTRL_C: |
| case ESC: |
| return -ECANCELED; |
| default: |
| /* Do nothing for unrecognised keys or edit errors */ |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Present text widget user interface |
| * |
| * @v widgets Text widget set |
| * @ret rc Return status code |
| */ |
| int widget_ui ( struct widgets *widgets ) { |
| int rc; |
| |
| /* Initialise UI */ |
| initscr(); |
| start_color(); |
| color_set ( CPAIR_NORMAL, NULL ); |
| erase(); |
| |
| /* Run main loop */ |
| rc = widget_ui_loop ( widgets ); |
| |
| /* Terminate UI */ |
| color_set ( CPAIR_NORMAL, NULL ); |
| endwin(); |
| |
| return rc; |
| } |