Browse Source

[fbcon] Add support for displaying a cursor

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 10 years ago
parent
commit
a2638a8edd
2 changed files with 97 additions and 25 deletions
  1. 95
    25
      src/core/fbcon.c
  2. 2
    0
      src/include/ipxe/fbcon.h

+ 95
- 25
src/core/fbcon.c View File

@@ -288,7 +288,7 @@ static void fbcon_redraw ( struct fbcon *fbcon ) {
288 288
  */
289 289
 static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
290 290
 	struct fbcon_text_cell cell = {
291
-		.foreground = 0,
291
+		.foreground = fbcon->foreground,
292 292
 		.background = fbcon->background,
293 293
 		.character = ' ',
294 294
 	};
@@ -317,19 +317,40 @@ static void fbcon_clear ( struct fbcon *fbcon, unsigned int ypos ) {
317 317
 static void fbcon_scroll ( struct fbcon *fbcon ) {
318 318
 	size_t row_len;
319 319
 
320
-	/* If we are not yet at the bottom of the screen, just update
321
-	 * the cursor position.
322
-	 */
323
-	if ( fbcon->ypos < ( fbcon->character.height - 1 ) ) {
324
-		fbcon->ypos++;
325
-		return;
326
-	}
320
+	/* Sanity check */
321
+	assert ( fbcon->ypos == fbcon->character.height );
327 322
 
328
-	/* Otherwise, scroll up character array */
323
+	/* Scroll up character array */
329 324
 	row_len = ( fbcon->character.width * sizeof ( struct fbcon_text_cell ));
330 325
 	memmove_user ( fbcon->text.start, 0, fbcon->text.start, row_len,
331 326
 		       ( row_len * ( fbcon->character.height - 1 ) ) );
332 327
 	fbcon_clear ( fbcon, ( fbcon->character.height - 1 ) );
328
+
329
+	/* Update cursor position */
330
+	fbcon->ypos--;
331
+}
332
+
333
+/**
334
+ * Draw character at cursor position
335
+ *
336
+ * @v fbcon		Frame buffer console
337
+ * @v show_cursor	Show cursor
338
+ */
339
+static void fbcon_draw_cursor ( struct fbcon *fbcon, int show_cursor ) {
340
+	struct fbcon_text_cell cell;
341
+	size_t offset;
342
+	uint32_t background;
343
+
344
+	offset = ( ( ( fbcon->ypos * fbcon->character.width ) + fbcon->xpos ) *
345
+		   sizeof ( cell ) );
346
+	copy_from_user ( &cell, fbcon->text.start, offset, sizeof ( cell ) );
347
+	if ( show_cursor ) {
348
+		background = cell.background;
349
+		cell.background = cell.foreground;
350
+		cell.foreground = ( ( background == FBCON_TRANSPARENT ) ?
351
+				    0 : background );
352
+	}
353
+	fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
333 354
 }
334 355
 
335 356
 /**
@@ -346,12 +367,14 @@ static void fbcon_handle_cup ( struct ansiesc_context *ctx,
346 367
 	int cx = ( params[1] - 1 );
347 368
 	int cy = ( params[0] - 1 );
348 369
 
370
+	fbcon_draw_cursor ( fbcon, 0 );
349 371
 	fbcon->xpos = cx;
350 372
 	if ( fbcon->xpos >= fbcon->character.width )
351 373
 		fbcon->xpos = ( fbcon->character.width - 1 );
352 374
 	fbcon->ypos = cy;
353 375
 	if ( fbcon->ypos >= fbcon->character.height )
354 376
 		fbcon->ypos = ( fbcon->character.height - 1 );
377
+	fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
355 378
 }
356 379
 
357 380
 /**
@@ -375,6 +398,7 @@ static void fbcon_handle_ed ( struct ansiesc_context *ctx,
375 398
 	/* Reset cursor position */
376 399
 	fbcon->xpos = 0;
377 400
 	fbcon->ypos = 0;
401
+	fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
378 402
 }
379 403
 
380 404
 /**
@@ -437,11 +461,45 @@ static void fbcon_handle_sgr ( struct ansiesc_context *ctx, unsigned int count,
437 461
 	}
438 462
 }
439 463
 
464
+/**
465
+ * Handle ANSI DECTCEM set (show cursor)
466
+ *
467
+ * @v ctx		ANSI escape sequence context
468
+ * @v count		Parameter count
469
+ * @v params		List of graphic rendition aspects
470
+ */
471
+static void fbcon_handle_dectcem_set ( struct ansiesc_context *ctx,
472
+				       unsigned int count __unused,
473
+				       int params[] __unused ) {
474
+	struct fbcon *fbcon = container_of ( ctx, struct fbcon, ctx );
475
+
476
+	fbcon->show_cursor = 1;
477
+	fbcon_draw_cursor ( fbcon, 1 );
478
+}
479
+
480
+/**
481
+ * Handle ANSI DECTCEM reset (hide cursor)
482
+ *
483
+ * @v ctx		ANSI escape sequence context
484
+ * @v count		Parameter count
485
+ * @v params		List of graphic rendition aspects
486
+ */
487
+static void fbcon_handle_dectcem_reset ( struct ansiesc_context *ctx,
488
+					 unsigned int count __unused,
489
+					 int params[] __unused ) {
490
+	struct fbcon *fbcon = container_of ( ctx, struct fbcon, ctx );
491
+
492
+	fbcon->show_cursor = 0;
493
+	fbcon_draw_cursor ( fbcon, 0 );
494
+}
495
+
440 496
 /** ANSI escape sequence handlers */
441 497
 static struct ansiesc_handler fbcon_ansiesc_handlers[] = {
442 498
 	{ ANSIESC_CUP, fbcon_handle_cup },
443 499
 	{ ANSIESC_ED, fbcon_handle_ed },
444 500
 	{ ANSIESC_SGR, fbcon_handle_sgr },
501
+	{ ANSIESC_DECTCEM_SET, fbcon_handle_dectcem_set },
502
+	{ ANSIESC_DECTCEM_RESET, fbcon_handle_dectcem_reset },
445 503
 	{ 0, NULL }
446 504
 };
447 505
 
@@ -462,35 +520,46 @@ void fbcon_putchar ( struct fbcon *fbcon, int character ) {
462 520
 	/* Handle control characters */
463 521
 	switch ( character ) {
464 522
 	case '\r':
523
+		fbcon_draw_cursor ( fbcon, 0 );
465 524
 		fbcon->xpos = 0;
466
-		return;
525
+		break;
467 526
 	case '\n':
527
+		fbcon_draw_cursor ( fbcon, 0 );
468 528
 		fbcon->xpos = 0;
469
-		fbcon_scroll ( fbcon );
470
-		return;
529
+		fbcon->ypos++;
530
+		break;
471 531
 	case '\b':
532
+		fbcon_draw_cursor ( fbcon, 0 );
472 533
 		if ( fbcon->xpos ) {
473 534
 			fbcon->xpos--;
474 535
 		} else if ( fbcon->ypos ) {
475 536
 			fbcon->xpos = ( fbcon->character.width - 1 );
476 537
 			fbcon->ypos--;
477 538
 		}
478
-		return;
539
+		break;
540
+	default:
541
+		/* Print character at current cursor position */
542
+		cell.foreground = ( fbcon->foreground | fbcon->bold );
543
+		cell.background = fbcon->background;
544
+		cell.character = character;
545
+		fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos);
546
+		fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
547
+
548
+		/* Advance cursor */
549
+		fbcon->xpos++;
550
+		if ( fbcon->xpos >= fbcon->character.width ) {
551
+			fbcon->xpos = 0;
552
+			fbcon->ypos++;
553
+		}
554
+		break;
479 555
 	}
480 556
 
481
-	/* Print character at current cursor position */
482
-	cell.foreground = ( fbcon->foreground | fbcon->bold );
483
-	cell.background = fbcon->background;
484
-	cell.character = character;
485
-	fbcon_store_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
486
-	fbcon_draw_character ( fbcon, &cell, fbcon->xpos, fbcon->ypos );
487
-
488
-	/* Advance cursor */
489
-	fbcon->xpos++;
490
-	if ( fbcon->xpos >= fbcon->character.width ) {
491
-		fbcon->xpos = 0;
557
+	/* Scroll screen if necessary */
558
+	if ( fbcon->ypos >= fbcon->character.height )
492 559
 		fbcon_scroll ( fbcon );
493
-	}
560
+
561
+	/* Show cursor */
562
+	fbcon_draw_cursor ( fbcon, fbcon->show_cursor );
494 563
 }
495 564
 
496 565
 /**
@@ -673,6 +742,7 @@ int fbcon_init ( struct fbcon *fbcon, userptr_t start,
673 742
 	fbcon->map = map;
674 743
 	fbcon->font = font;
675 744
 	fbcon->ctx.handlers = fbcon_ansiesc_handlers;
745
+	fbcon->show_cursor = 1;
676 746
 
677 747
 	/* Derive overall length */
678 748
 	fbcon->len = ( pixel->height * pixel->stride );

+ 2
- 0
src/include/ipxe/fbcon.h View File

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

Loading…
Cancel
Save