/* * Copyright (C) 2024 Michael Brown . * * 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 #include #include #include /** * 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; }