mirror of https://github.com/ipxe/ipxe.git
[hci] Provide a general concept of a text widget set
Create a generic abstraction of a text widget, refactor the existing editable text box widget to use this abstraction, add an implementation of a non-editable text label widget, and generalise the login user interface to use this generic widget abstraction. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/1223/head
parent
d7e58c5a81
commit
dc118c5369
|
@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ipxe/ansicol.h>
|
||||
#include <ipxe/editbox.h>
|
||||
|
||||
/** @file
|
||||
|
@ -35,39 +36,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
|
||||
#define EDITBOX_MIN_CHARS 3
|
||||
|
||||
/**
|
||||
* Initialise text box widget
|
||||
*
|
||||
* @v box Editable text box widget
|
||||
* @v buf Dynamically allocated string buffer
|
||||
* @v win Containing window
|
||||
* @v row Row
|
||||
* @v col Starting column
|
||||
* @v width Width
|
||||
* @v flags Flags
|
||||
*/
|
||||
void init_editbox ( struct edit_box *box, char **buf,
|
||||
WINDOW *win, unsigned int row, unsigned int col,
|
||||
unsigned int width, unsigned int flags ) {
|
||||
memset ( box, 0, sizeof ( *box ) );
|
||||
init_editstring ( &box->string, buf );
|
||||
box->string.cursor = ( *buf ? strlen ( *buf ) : 0 );
|
||||
box->win = ( win ? win : stdscr );
|
||||
box->row = row;
|
||||
box->col = col;
|
||||
box->width = width;
|
||||
box->flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw text box widget
|
||||
*
|
||||
* @v box Editable text box widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
*/
|
||||
void draw_editbox ( struct edit_box *box ) {
|
||||
static void draw_editbox ( struct widgets *widgets, struct widget *widget ) {
|
||||
struct edit_box *box = container_of ( widget, struct edit_box, widget );
|
||||
const char *content = *(box->string.buf);
|
||||
size_t width = box->width;
|
||||
size_t width = widget->width;
|
||||
char buf[ width + 1 ];
|
||||
signed int cursor_offset, underflow, overflow, first;
|
||||
size_t len;
|
||||
|
@ -93,15 +71,36 @@ void draw_editbox ( struct edit_box *box ) {
|
|||
len = ( content ? ( strlen ( content ) - first ) : 0 );
|
||||
if ( len > width )
|
||||
len = width;
|
||||
if ( box->flags & EDITBOX_STARS ) {
|
||||
if ( widget->flags & WIDGET_SECRET ) {
|
||||
memset ( buf, '*', len );
|
||||
} else {
|
||||
memcpy ( buf, ( content + first ), len );
|
||||
}
|
||||
|
||||
/* Print box content and move cursor */
|
||||
if ( ! box->win )
|
||||
box->win = stdscr;
|
||||
mvwprintw ( box->win, box->row, box->col, "%s", buf );
|
||||
wmove ( box->win, box->row, ( box->col + cursor_offset ) );
|
||||
color_set ( CPAIR_EDIT, NULL );
|
||||
mvwprintw ( widgets->win, widget->row, widget->col, "%s", buf );
|
||||
wmove ( widgets->win, widget->row, ( widget->col + cursor_offset ) );
|
||||
color_set ( CPAIR_NORMAL, NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit text box widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
* @v key Key pressed by user
|
||||
* @ret key Key returned to application, or zero
|
||||
*/
|
||||
static int edit_editbox ( struct widgets *widgets __unused,
|
||||
struct widget *widget, int key ) {
|
||||
struct edit_box *box = container_of ( widget, struct edit_box, widget );
|
||||
|
||||
return edit_string ( &box->string, key );
|
||||
}
|
||||
|
||||
/** Text box widget operations */
|
||||
struct widget_operations editbox_operations = {
|
||||
.draw = draw_editbox,
|
||||
.edit = edit_editbox,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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 );
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ipxe/label.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Text label widget
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Draw text label widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
*/
|
||||
static void draw_label ( struct widgets *widgets, struct widget *widget ) {
|
||||
struct label *label = container_of ( widget, struct label, widget );
|
||||
unsigned int width = widget->width;
|
||||
unsigned int col = widget->col;
|
||||
const char *text = label->text;
|
||||
|
||||
/* Centre label if width is non-zero */
|
||||
if ( width )
|
||||
col += ( ( width - strlen ( text ) ) / 2 );
|
||||
|
||||
/* Print label content */
|
||||
attron ( A_BOLD );
|
||||
mvwprintw ( widgets->win, widget->row, col, "%s", text );
|
||||
attroff ( A_BOLD );
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit text label widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
* @v key Key pressed by user
|
||||
* @ret key Key returned to application, or zero
|
||||
*/
|
||||
static int edit_label ( struct widgets *widgets __unused,
|
||||
struct widget *widget __unused, int key ) {
|
||||
|
||||
/* Cannot be edited */
|
||||
return key;
|
||||
}
|
||||
|
||||
/** Text label widget operations */
|
||||
struct widget_operations label_operations = {
|
||||
.draw = draw_label,
|
||||
.edit = edit_label,
|
||||
};
|
|
@ -35,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <curses.h>
|
||||
#include <ipxe/console.h>
|
||||
#include <ipxe/settings.h>
|
||||
#include <ipxe/label.h>
|
||||
#include <ipxe/editbox.h>
|
||||
#include <ipxe/keys.h>
|
||||
#include <ipxe/ansicol.h>
|
||||
|
@ -45,90 +46,55 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#define USERNAME_ROW ( ( LINES / 2U ) - 2U )
|
||||
#define PASSWORD_LABEL_ROW ( ( LINES / 2U ) + 2U )
|
||||
#define PASSWORD_ROW ( ( LINES / 2U ) + 4U )
|
||||
#define LABEL_COL ( ( COLS / 2U ) - 4U )
|
||||
#define EDITBOX_COL ( ( COLS / 2U ) - 10U )
|
||||
#define EDITBOX_WIDTH 20U
|
||||
#define WIDGET_COL ( ( COLS / 2U ) - 10U )
|
||||
#define WIDGET_WIDTH 20U
|
||||
|
||||
int login_ui ( void ) {
|
||||
char *username;
|
||||
char *password;
|
||||
struct edit_box username_box;
|
||||
struct edit_box password_box;
|
||||
struct edit_box *current_box = &username_box;
|
||||
int key;
|
||||
int rc = -EINPROGRESS;
|
||||
struct {
|
||||
struct widgets widgets;
|
||||
struct label username_label;
|
||||
struct label password_label;
|
||||
struct edit_box username_box;
|
||||
struct edit_box password_box;
|
||||
} widgets;
|
||||
int rc;
|
||||
|
||||
/* Fetch current setting values */
|
||||
fetchf_setting_copy ( NULL, &username_setting, NULL, NULL, &username );
|
||||
fetchf_setting_copy ( NULL, &password_setting, NULL, NULL, &password );
|
||||
|
||||
/* Initialise UI */
|
||||
initscr();
|
||||
start_color();
|
||||
init_editbox ( &username_box, &username, NULL, USERNAME_ROW,
|
||||
EDITBOX_COL, EDITBOX_WIDTH, 0 );
|
||||
init_editbox ( &password_box, &password, NULL, PASSWORD_ROW,
|
||||
EDITBOX_COL, EDITBOX_WIDTH, EDITBOX_STARS );
|
||||
/* Construct user interface */
|
||||
memset ( &widgets, 0, sizeof ( widgets ) );
|
||||
init_widgets ( &widgets.widgets, NULL );
|
||||
init_label ( &widgets.username_label, USERNAME_LABEL_ROW, WIDGET_COL,
|
||||
WIDGET_WIDTH, "Username" );
|
||||
init_label ( &widgets.password_label, PASSWORD_LABEL_ROW, WIDGET_COL,
|
||||
WIDGET_WIDTH, "Password" );
|
||||
init_editbox ( &widgets.username_box, USERNAME_ROW, WIDGET_COL,
|
||||
WIDGET_WIDTH, 0, &username );
|
||||
init_editbox ( &widgets.password_box, PASSWORD_ROW, WIDGET_COL,
|
||||
WIDGET_WIDTH, WIDGET_SECRET, &password );
|
||||
add_widget ( &widgets.widgets, &widgets.username_label.widget );
|
||||
add_widget ( &widgets.widgets, &widgets.password_label.widget );
|
||||
add_widget ( &widgets.widgets, &widgets.username_box.widget );
|
||||
add_widget ( &widgets.widgets, &widgets.password_box.widget );
|
||||
|
||||
/* Draw initial UI */
|
||||
color_set ( CPAIR_NORMAL, NULL );
|
||||
erase();
|
||||
attron ( A_BOLD );
|
||||
mvprintw ( USERNAME_LABEL_ROW, LABEL_COL, "Username:" );
|
||||
mvprintw ( PASSWORD_LABEL_ROW, LABEL_COL, "Password:" );
|
||||
attroff ( A_BOLD );
|
||||
color_set ( CPAIR_EDIT, NULL );
|
||||
draw_editbox ( &username_box );
|
||||
draw_editbox ( &password_box );
|
||||
|
||||
/* Main loop */
|
||||
while ( rc == -EINPROGRESS ) {
|
||||
|
||||
draw_editbox ( current_box );
|
||||
|
||||
key = getkey ( 0 );
|
||||
switch ( key ) {
|
||||
case KEY_DOWN:
|
||||
current_box = &password_box;
|
||||
break;
|
||||
case KEY_UP:
|
||||
current_box = &username_box;
|
||||
break;
|
||||
case TAB:
|
||||
current_box = ( ( current_box == &username_box ) ?
|
||||
&password_box : &username_box );
|
||||
break;
|
||||
case KEY_ENTER:
|
||||
if ( current_box == &username_box ) {
|
||||
current_box = &password_box;
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
break;
|
||||
case CTRL_C:
|
||||
case ESC:
|
||||
rc = -ECANCELED;
|
||||
break;
|
||||
default:
|
||||
edit_editbox ( current_box, key );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate UI */
|
||||
color_set ( CPAIR_NORMAL, NULL );
|
||||
erase();
|
||||
endwin();
|
||||
/* Present user interface */
|
||||
if ( ( rc = widget_ui ( &widgets.widgets ) ) != 0 )
|
||||
goto err_ui;
|
||||
|
||||
/* Store settings on successful completion */
|
||||
if ( rc == 0 )
|
||||
rc = storef_setting ( NULL, &username_setting, username );
|
||||
if ( rc == 0 )
|
||||
rc = storef_setting ( NULL, &password_setting, password );
|
||||
if ( ( rc = storef_setting ( NULL, &username_setting, username ) ) !=0)
|
||||
goto err_store_username;
|
||||
if ( ( rc = storef_setting ( NULL, &password_setting, password ) ) !=0)
|
||||
goto err_store_password;
|
||||
|
||||
/* Free setting values */
|
||||
err_store_username:
|
||||
err_store_password:
|
||||
err_ui:
|
||||
free ( username );
|
||||
free ( password );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ struct settings_ui {
|
|||
struct jump_scroller scroll;
|
||||
/** Current row */
|
||||
struct settings_ui_row row;
|
||||
/** Widget set used for editing setting */
|
||||
struct widgets widgets;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -164,10 +166,11 @@ static unsigned int select_setting_row ( struct settings_ui *ui,
|
|||
}
|
||||
|
||||
/* Initialise edit box */
|
||||
init_editbox ( &ui->row.editbox, &ui->row.buf, NULL, ui->row.row,
|
||||
memset ( &ui->row.editbox, 0, sizeof ( ui->row.editbox ) );
|
||||
init_editbox ( &ui->row.editbox, ui->row.row,
|
||||
( SETTINGS_LIST_COL +
|
||||
offsetof ( typeof ( *text ), u.setting.value ) ),
|
||||
sizeof ( text->u.setting.value ), 0 );
|
||||
sizeof ( text->u.setting.value ), 0, &ui->row.buf );
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -250,7 +253,7 @@ static void draw_setting_row ( struct settings_ui *ui ) {
|
|||
static int edit_setting ( struct settings_ui *ui, int key ) {
|
||||
assert ( ui->row.setting.name != NULL );
|
||||
ui->row.editing = 1;
|
||||
return edit_editbox ( &ui->row.editbox, key );
|
||||
return edit_widget ( &ui->widgets, &ui->row.editbox.widget, key );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -454,6 +457,7 @@ static int main_loop ( struct settings *settings ) {
|
|||
/* Print initial screen content */
|
||||
color_set ( CPAIR_NORMAL, NULL );
|
||||
memset ( &ui, 0, sizeof ( ui ) );
|
||||
init_widgets ( &ui.widgets, NULL );
|
||||
select_settings ( &ui, settings );
|
||||
|
||||
while ( 1 ) {
|
||||
|
@ -477,9 +481,7 @@ static int main_loop ( struct settings *settings ) {
|
|||
assert ( ui.row.setting.name != NULL );
|
||||
|
||||
/* Redraw edit box */
|
||||
color_set ( CPAIR_EDIT, NULL );
|
||||
draw_editbox ( &ui.row.editbox );
|
||||
color_set ( CPAIR_NORMAL, NULL );
|
||||
draw_widget ( &ui.widgets, &ui.row.editbox.widget );
|
||||
|
||||
/* Process keypress */
|
||||
key = edit_setting ( &ui, getkey ( 0 ) );
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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 ( widgets, 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 ( widgets, widget );
|
||||
|
||||
/* Process keypress */
|
||||
key = edit_widget ( widgets, 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;
|
||||
}
|
|
@ -11,51 +11,39 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
|
||||
#include <curses.h>
|
||||
#include <ipxe/editstring.h>
|
||||
#include <ipxe/widget.h>
|
||||
|
||||
/** An editable text box widget */
|
||||
struct edit_box {
|
||||
/** Text widget */
|
||||
struct widget widget;
|
||||
/** Editable string */
|
||||
struct edit_string string;
|
||||
/** Containing window */
|
||||
WINDOW *win;
|
||||
/** Row */
|
||||
unsigned int row;
|
||||
/** Starting column */
|
||||
unsigned int col;
|
||||
/** Width */
|
||||
unsigned int width;
|
||||
/** First displayed character */
|
||||
unsigned int first;
|
||||
/** Flags */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/** Editable text box widget flags */
|
||||
enum edit_box_flags {
|
||||
/** Show stars instead of contents (for password widgets) */
|
||||
EDITBOX_STARS = 0x0001,
|
||||
};
|
||||
|
||||
extern void init_editbox ( struct edit_box *box, char **buf,
|
||||
WINDOW *win, unsigned int row, unsigned int col,
|
||||
unsigned int width, unsigned int flags )
|
||||
__attribute__ (( nonnull (1, 2) ));
|
||||
extern void draw_editbox ( struct edit_box *box ) __nonnull;
|
||||
static inline int edit_editbox ( struct edit_box *box, int key ) __nonnull;
|
||||
extern struct widget_operations editbox_operations;
|
||||
|
||||
/**
|
||||
* Edit text box widget
|
||||
* Initialise text box widget
|
||||
*
|
||||
* @v box Editable text box widget
|
||||
* @v key Key pressed by user
|
||||
* @ret key Key returned to application, or zero
|
||||
*
|
||||
* You must call draw_editbox() to update the display after calling
|
||||
* edit_editbox().
|
||||
*
|
||||
* @v row Row
|
||||
* @v col Starting column
|
||||
* @v width Width
|
||||
* @v flags Flags
|
||||
* @v buf Dynamically allocated string buffer
|
||||
*/
|
||||
static inline int edit_editbox ( struct edit_box *box, int key ) {
|
||||
return edit_string ( &box->string, key );
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
init_editbox ( struct edit_box *box, unsigned int row, unsigned int col,
|
||||
unsigned int width, unsigned int flags, char **buf ) {
|
||||
|
||||
init_widget ( &box->widget, &editbox_operations, row, col,
|
||||
width, ( flags | WIDGET_EDITABLE ) );
|
||||
init_editstring ( &box->string, buf );
|
||||
if ( *buf )
|
||||
box->string.cursor = strlen ( *buf );
|
||||
}
|
||||
|
||||
#endif /* _IPXE_EDITBOX_H */
|
||||
|
|
|
@ -417,6 +417,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#define ERRFILE_x25519 ( ERRFILE_OTHER | 0x005f0000 )
|
||||
#define ERRFILE_des ( ERRFILE_OTHER | 0x00600000 )
|
||||
#define ERRFILE_editstring ( ERRFILE_OTHER | 0x00610000 )
|
||||
#define ERRFILE_widget_ui ( ERRFILE_OTHER | 0x00620000 )
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef _IPXE_LABEL_H
|
||||
#define _IPXE_LABEL_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Text label widget
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <curses.h>
|
||||
#include <ipxe/widget.h>
|
||||
|
||||
/** A text label widget */
|
||||
struct label {
|
||||
/** Text widget */
|
||||
struct widget widget;
|
||||
/** Label text */
|
||||
const char *text;
|
||||
};
|
||||
|
||||
extern struct widget_operations label_operations;
|
||||
|
||||
/**
|
||||
* Initialise text label widget
|
||||
*
|
||||
* @v label Text label widget
|
||||
* @v row Row
|
||||
* @v col Starting column
|
||||
* @v width Width
|
||||
* @v text Label text
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
init_label ( struct label *label, unsigned int row, unsigned int col,
|
||||
unsigned int width, const char *text ) {
|
||||
|
||||
init_widget ( &label->widget, &label_operations, row, col, width, 0 );
|
||||
label->text = text;
|
||||
}
|
||||
|
||||
#endif /* _IPXE_LABEL_H */
|
|
@ -0,0 +1,151 @@
|
|||
#ifndef _IPXE_WIDGET_H
|
||||
#define _IPXE_WIDGET_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Text widgets
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <curses.h>
|
||||
#include <ipxe/list.h>
|
||||
|
||||
/** A text widget set */
|
||||
struct widgets {
|
||||
/** List of widgets (in tab order) */
|
||||
struct list_head list;
|
||||
/** Containing window */
|
||||
WINDOW *win;
|
||||
};
|
||||
|
||||
/** A text widget */
|
||||
struct widget {
|
||||
/** List of widgets (in tab order) */
|
||||
struct list_head list;
|
||||
/** Widget operations */
|
||||
struct widget_operations *op;
|
||||
|
||||
/** Row */
|
||||
unsigned int row;
|
||||
/** Starting column */
|
||||
unsigned int col;
|
||||
/** Width */
|
||||
unsigned int width;
|
||||
/** Flags */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/** Text widget flags */
|
||||
enum widget_flags {
|
||||
/** Widget may have input focus */
|
||||
WIDGET_EDITABLE = 0x0001,
|
||||
/** Widget contains a secret */
|
||||
WIDGET_SECRET = 0x0002,
|
||||
};
|
||||
|
||||
/** Text widget operations */
|
||||
struct widget_operations {
|
||||
/**
|
||||
* Draw widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
*/
|
||||
void ( * draw ) ( struct widgets *widgets, struct widget *widget );
|
||||
/**
|
||||
* Edit widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
* @v key Key pressed by user
|
||||
* @ret key Key returned to application, or zero
|
||||
*
|
||||
* This will not update the display: you must call the draw()
|
||||
* method to ensure that any changes to an editable widget are
|
||||
* displayed to the user.
|
||||
*/
|
||||
int ( * edit ) ( struct widgets *widgets, struct widget *widget,
|
||||
int key );
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise text widget set
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v win Containing window
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
init_widgets ( struct widgets *widgets, WINDOW *win ) {
|
||||
|
||||
INIT_LIST_HEAD ( &widgets->list );
|
||||
widgets->win = ( win ? win : stdscr );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise text widget
|
||||
*
|
||||
* @v widget Text widget
|
||||
* @v op Text widget operations
|
||||
* @v row Row
|
||||
* @v col Starting column
|
||||
* @v width Width
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
init_widget ( struct widget *widget, struct widget_operations *op,
|
||||
unsigned int row, unsigned int col, unsigned int width,
|
||||
unsigned int flags ) {
|
||||
|
||||
widget->op = op;
|
||||
widget->row = row;
|
||||
widget->col = col;
|
||||
widget->width = width;
|
||||
widget->flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
add_widget ( struct widgets *widgets, struct widget *widget ) {
|
||||
|
||||
list_add_tail ( &widget->list, &widgets->list );
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw text widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
draw_widget ( struct widgets *widgets, struct widget *widget ) {
|
||||
|
||||
widget->op->draw ( widgets, widget );
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit text widget
|
||||
*
|
||||
* @v widgets Text widget set
|
||||
* @v widget Text widget
|
||||
* @v key Key pressed by user
|
||||
* @ret key Key returned to application, or zero
|
||||
*
|
||||
* This will not update the display: you must call draw_widget() to
|
||||
* ensure that any changes to an editable widget are displayed to the
|
||||
* user.
|
||||
*/
|
||||
static inline __attribute__ (( always_inline )) int
|
||||
edit_widget ( struct widgets *widgets, struct widget *widget, int key ) {
|
||||
|
||||
return widget->op->edit ( widgets, widget, key );
|
||||
}
|
||||
|
||||
extern int widget_ui ( struct widgets *widgets );
|
||||
|
||||
#endif /* _IPXE_WIDGET_H */
|
Loading…
Reference in New Issue