david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[fbcon] Add support for displaying a cursor

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2013-12-02 17:27:37 +00:00
parent fb6edd4e13
commit a2638a8edd
2 changed files with 97 additions and 25 deletions

View File

@ -288,7 +288,7 @@ static void fbcon_redraw ( struct fbcon *fbcon ) {
*/ */
static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) { static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
struct fbcon_text_cell cell = { struct fbcon_text_cell cell = {
.foreground = 0, .foreground = fbcon->foreground,
.background = fbcon->background, .background = fbcon->background,
.character = ' ', .character = ' ',
}; };
@ -317,19 +317,40 @@ static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
static void fbcon_scroll ( struct fbcon *fbcon ) { static void fbcon_scroll ( struct fbcon *fbcon ) {
size_t row_len; size_t row_len;
/* If we are not yet at the bottom of the screen, just update /* Sanity check */
* the cursor position. assert ( fbcon->ypos == fbcon->character.height );
*/
if ( fbcon->ypos < ( fbcon->character.height - 1 ) ) {
fbcon->ypos++;
return;
}
/* Otherwise, scroll up character array */ /* Scroll up character array */
row_len = ( fbcon->character.width * sizeof ( struct fbcon_text_cell )); row_len = ( fbcon->character.width * sizeof ( struct fbcon_text_cell ));
memmove_user ( fbcon->text.start, 0, fbcon->text.start, row_len, memmove_user ( fbcon->text.start, 0, fbcon->text.start, row_len,
( row_len * ( fbcon->character.height - 1 ) ) ); ( row_len * ( fbcon->character.height - 1 ) ) );
fbcon_clear ( fbcon, ( fbcon->character.height - 1 ) ); fbcon_clear ( fbcon, ( fbcon->character.height - 1 ) );
/* Update cursor position */
fbcon->ypos--;
}
/**
* Draw character at cursor position
*
* @v fbcon Frame buffer console
* @v show_cursor Show cursor
*/
static void fbcon_draw_cursor ( struct fbcon *fbcon, int show_cursor ) {
struct fbcon_text_cell cell;
size_t offset;
uint32_t background;
offset = ( ( ( fbcon->ypos * fbcon->character.width ) + fbcon->xpos ) *
sizeof ( cell ) );
copy_from_user ( &cell, fbcon->text.start, offset, sizeof ( cell ) );
if ( show_cursor ) {
background = cell.background;
cell.background = cell.foreground;
cell.foreground = ( ( background == FBCON_TRANSPARENT ) ?
0 : background );
}
fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
} }
/** /**
@ -346,12 +367,14 @@ static void fbcon_handle_cup ( struct ansiesc_context *ctx,
int cx = ( params[1] - 1 ); int cx = ( params[1] - 1 );
int cy = ( params[0] - 1 ); int cy = ( params[0] - 1 );
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = cx; fbcon->xpos = cx;
if ( fbcon->xpos >= fbcon->character.width ) if ( fbcon->xpos >= fbcon->character.width )
fbcon->xpos = ( fbcon->character.width - 1 ); fbcon->xpos = ( fbcon->character.width - 1 );
fbcon->ypos = cy; fbcon->ypos = cy;
if ( fbcon->ypos >= fbcon->character.height ) if ( fbcon->ypos >= fbcon->character.height )
fbcon->ypos = ( fbcon->character.height - 1 ); fbcon->ypos = ( fbcon->character.height - 1 );
fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
} }
/** /**
@ -375,6 +398,7 @@ static void fbcon_handle_ed ( struct ansiesc_context *ctx,
/* Reset cursor position */ /* Reset cursor position */
fbcon->xpos = 0; fbcon->xpos = 0;
fbcon->ypos = 0; fbcon->ypos = 0;
fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
} }
/** /**
@ -437,11 +461,45 @@ static void fbcon_handle_sgr ( struct ansiesc_context *ctx, unsigned int count,
} }
} }
/**
* Handle ANSI DECTCEM set (show cursor)
*
* @v ctx ANSI escape sequence context
* @v count Parameter count
* @v params List of graphic rendition aspects
*/
static void fbcon_handle_dectcem_set ( struct ansiesc_context *ctx,
unsigned int count __unused,
int params[] __unused ) {
struct fbcon *fbcon = container_of ( ctx, struct fbcon, ctx );
fbcon->show_cursor = 1;
fbcon_draw_cursor ( fbcon, 1 );
}
/**
* Handle ANSI DECTCEM reset (hide cursor)
*
* @v ctx ANSI escape sequence context
* @v count Parameter count
* @v params List of graphic rendition aspects
*/
static void fbcon_handle_dectcem_reset ( struct ansiesc_context *ctx,
unsigned int count __unused,
int params[] __unused ) {
struct fbcon *fbcon = container_of ( ctx, struct fbcon, ctx );
fbcon->show_cursor = 0;
fbcon_draw_cursor ( fbcon, 0 );
}
/** ANSI escape sequence handlers */ /** ANSI escape sequence handlers */
static struct ansiesc_handler fbcon_ansiesc_handlers[] = { static struct ansiesc_handler fbcon_ansiesc_handlers[] = {
{ ANSIESC_CUP, fbcon_handle_cup }, { ANSIESC_CUP, fbcon_handle_cup },
{ ANSIESC_ED, fbcon_handle_ed }, { ANSIESC_ED, fbcon_handle_ed },
{ ANSIESC_SGR, fbcon_handle_sgr }, { ANSIESC_SGR, fbcon_handle_sgr },
{ ANSIESC_DECTCEM_SET, fbcon_handle_dectcem_set },
{ ANSIESC_DECTCEM_RESET, fbcon_handle_dectcem_reset },
{ 0, NULL } { 0, NULL }
}; };
@ -462,35 +520,46 @@ void fbcon_putchar ( struct fbcon *fbcon, int character ) {
/* Handle control characters */ /* Handle control characters */
switch ( character ) { switch ( character ) {
case '\r': case '\r':
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = 0; fbcon->xpos = 0;
return; break;
case '\n': case '\n':
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = 0; fbcon->xpos = 0;
fbcon_scroll ( fbcon ); fbcon->ypos++;
return; break;
case '\b': case '\b':
fbcon_draw_cursor ( fbcon, 0 );
if ( fbcon->xpos ) { if ( fbcon->xpos ) {
fbcon->xpos--; fbcon->xpos--;
} else if ( fbcon->ypos ) { } else if ( fbcon->ypos ) {
fbcon->xpos = ( fbcon->character.width - 1 ); fbcon->xpos = ( fbcon->character.width - 1 );
fbcon->ypos--; fbcon->ypos--;
} }
return; break;
default:
/* Print character at current cursor position */
cell.foreground = ( fbcon->foreground | fbcon->bold );
cell.background = fbcon->background;
cell.character = character;
fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos);
fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
/* Advance cursor */
fbcon->xpos++;
if ( fbcon->xpos >= fbcon->character.width ) {
fbcon->xpos = 0;
fbcon->ypos++;
}
break;
} }
/* Print character at current cursor position */ /* Scroll screen if necessary */
cell.foreground = ( fbcon->foreground | fbcon->bold ); if ( fbcon->ypos >= fbcon->character.height )
cell.background = fbcon->background;
cell.character = character;
fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
/* Advance cursor */
fbcon->xpos++;
if ( fbcon->xpos >= fbcon->character.width ) {
fbcon->xpos = 0;
fbcon_scroll ( fbcon ); fbcon_scroll ( fbcon );
}
/* Show cursor */
fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
} }
/** /**
@ -673,6 +742,7 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
fbcon->map = map; fbcon->map = map;
fbcon->font = font; fbcon->font = font;
fbcon->ctx.handlers = fbcon_ansiesc_handlers; fbcon->ctx.handlers = fbcon_ansiesc_handlers;
fbcon->show_cursor = 1;
/* Derive overall length */ /* Derive overall length */
fbcon->len = ( pixel->height * pixel->stride ); fbcon->len = ( pixel->height * pixel->stride );

View File

@ -147,6 +147,8 @@ struct fbcon {
struct fbcon_text text; struct fbcon_text text;
/** Background picture */ /** Background picture */
struct fbcon_picture picture; struct fbcon_picture picture;
/** Display cursor */
int show_cursor;
}; };
extern int fbcon_init ( struct fbcon *fbcon, userptr_t start, extern int fbcon_init ( struct fbcon *fbcon, userptr_t start,