|
@@ -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 );
|