blob: 961545cf442847f9eafdde8aca429b691fcc2f32 [file] [log] [blame]
/*
* 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;
}