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 ) {
struct fbcon_text_cell cell = {
.foreground = 0,
.foreground = fbcon->foreground,
.background = fbcon->background,
.character = ' ',
};
@ -317,19 +317,40 @@ static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
static void fbcon_scroll ( struct fbcon *fbcon ) {
size_t row_len;
/* If we are not yet at the bottom of the screen, just update
* the cursor position.
*/
if ( fbcon->ypos < ( fbcon->character.height - 1 ) ) {
fbcon->ypos++;
return;
}
/* Sanity check */
assert ( fbcon->ypos == fbcon->character.height );
/* Otherwise, scroll up character array */
/* Scroll up character array */
row_len = ( fbcon->character.width * sizeof ( struct fbcon_text_cell ));
memmove_user ( fbcon->text.start, 0, fbcon->text.start, row_len,
( row_len * ( 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 cy = ( params[0] - 1 );
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = cx;
if ( fbcon->xpos >= fbcon->character.width )
fbcon->xpos = ( fbcon->character.width - 1 );
fbcon->ypos = cy;
if ( fbcon->ypos >= fbcon->character.height )
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 */
fbcon->xpos = 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 */
static struct ansiesc_handler fbcon_ansiesc_handlers[] = {
{ ANSIESC_CUP, fbcon_handle_cup },
{ ANSIESC_ED, fbcon_handle_ed },
{ ANSIESC_SGR, fbcon_handle_sgr },
{ ANSIESC_DECTCEM_SET, fbcon_handle_dectcem_set },
{ ANSIESC_DECTCEM_RESET, fbcon_handle_dectcem_reset },
{ 0, NULL }
};
@ -462,35 +520,46 @@ void fbcon_putchar ( struct fbcon *fbcon, int character ) {
/* Handle control characters */
switch ( character ) {
case '\r':
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = 0;
return;
break;
case '\n':
fbcon_draw_cursor ( fbcon, 0 );
fbcon->xpos = 0;
fbcon_scroll ( fbcon );
return;
fbcon->ypos++;
break;
case '\b':
fbcon_draw_cursor ( fbcon, 0 );
if ( fbcon->xpos ) {
fbcon->xpos--;
} else if ( fbcon->ypos ) {
fbcon->xpos = ( fbcon->character.width - 1 );
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 */
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;
/* Scroll screen if necessary */
if ( fbcon->ypos >= fbcon->character.height )
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->font = font;
fbcon->ctx.handlers = fbcon_ansiesc_handlers;
fbcon->show_cursor = 1;
/* Derive overall length */
fbcon->len = ( pixel->height * pixel->stride );

View File

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