74 |
/* Forward declaration. */ |
/* Forward declaration. */ |
75 |
static struct display_ops vga_display_ops; |
static struct display_ops vga_display_ops; |
76 |
|
|
77 |
|
/* The current width and height the ncursesw driver is using. */ |
78 |
|
static int current_width; |
79 |
|
static int current_height; |
80 |
|
|
81 |
|
/* The cursor state to restore the state to. */ |
82 |
|
static int cursor_state; |
83 |
|
|
84 |
|
/* Is set to 1 if the cursor moved out of the physical screen and the |
85 |
|
cursor state should be hidden. */ |
86 |
|
static int cursor_hidden; |
87 |
|
|
88 |
struct refchr |
struct refchr |
89 |
{ |
{ |
328 |
} |
} |
329 |
|
|
330 |
|
|
331 |
/* Set the cursor's position on display HANDLE to column COL and row |
/* Set the cursor's state to STATE on display HANDLE. */ |
|
ROW. */ |
|
332 |
static error_t |
static error_t |
333 |
vga_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row) |
vga_display_set_cursor_status (void *handle, uint32_t state) |
334 |
{ |
{ |
335 |
struct vga_display *disp = handle; |
struct vga_display *disp = handle; |
|
unsigned int pos = row * disp->width + col; |
|
336 |
|
|
337 |
vga_set_cursor_pos (pos); |
/* Don't display the cursor if its location is not within the |
338 |
|
physical screen. */ |
339 |
|
if (!cursor_hidden) |
340 |
|
{ |
341 |
|
if (state != CONS_CURSOR_INVISIBLE) |
342 |
|
dynafont_set_cursor (disp->df, state == CONS_CURSOR_VERY_VISIBLE ? 1 : 0); |
343 |
|
|
344 |
|
vga_display_cursor (state == CONS_CURSOR_INVISIBLE ? 0 : 1); |
345 |
|
} |
346 |
|
|
347 |
|
cursor_state = state; |
348 |
|
|
349 |
return 0; |
return 0; |
350 |
} |
} |
351 |
|
|
352 |
|
|
353 |
/* Set the cursor's state to STATE on display HANDLE. */ |
/* Set the cursor's position on display HANDLE to column COL and row |
354 |
|
ROW. */ |
355 |
static error_t |
static error_t |
356 |
vga_display_set_cursor_status (void *handle, uint32_t state) |
vga_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row) |
357 |
{ |
{ |
358 |
struct vga_display *disp = handle; |
struct vga_display *disp = handle; |
359 |
|
unsigned int pos = row * disp->width + col; |
360 |
|
|
361 |
if (state != CONS_CURSOR_INVISIBLE) |
/* Make sure the cursor can only be moved to a position on te |
362 |
dynafont_set_cursor (disp->df, state == CONS_CURSOR_VERY_VISIBLE ? 1 : 0); |
physical screen. */ |
363 |
vga_display_cursor (state == CONS_CURSOR_INVISIBLE ? 0 : 1); |
if (col < disp->width && row < disp->height) |
364 |
|
{ |
365 |
|
vga_set_cursor_pos (pos); |
366 |
|
if (cursor_hidden) |
367 |
|
{ |
368 |
|
/* Restore the cursor. */ |
369 |
|
cursor_hidden = 0; |
370 |
|
vga_display_set_cursor_status (handle, cursor_state); |
371 |
|
} |
372 |
|
} |
373 |
|
else if (!cursor_hidden) |
374 |
|
{ |
375 |
|
/* Hide the cursor. */ |
376 |
|
cursor_hidden = 1; |
377 |
|
vga_display_cursor (CONS_CURSOR_INVISIBLE); |
378 |
|
} |
379 |
|
|
380 |
return 0; |
return 0; |
381 |
} |
} |
390 |
int count = abs(delta) * disp->width; |
int count = abs(delta) * disp->width; |
391 |
int i; |
int i; |
392 |
struct refchr *refpos; |
struct refchr *refpos; |
393 |
|
|
394 |
|
/* XXX: If the virtual console is bigger than the physical console it is |
395 |
|
impossible to scroll because the data to scroll is not in memory. */ |
396 |
|
if (current_height > disp->height) |
397 |
|
return ENOTSUP; |
398 |
|
|
399 |
if (delta > 0) |
if (delta > 0) |
400 |
{ |
{ |
401 |
memmove (vga_videomem, vga_videomem + 2 * count, |
memmove (vga_videomem, vga_videomem + 2 * count, |
525 |
vga_display_clear (void *handle, size_t length, uint32_t col, uint32_t row) |
vga_display_clear (void *handle, size_t length, uint32_t col, uint32_t row) |
526 |
{ |
{ |
527 |
struct vga_display *disp = handle; |
struct vga_display *disp = handle; |
528 |
struct refchr *refpos = &disp->refmatrix[row][col]; |
struct refchr *refpos = &disp->refmatrix[row][0]; |
529 |
|
int cols; |
530 |
|
|
531 |
|
/* The column can be outside the physical screen, in that case |
532 |
|
adjust the position. */ |
533 |
|
if (col >= disp->width) |
534 |
|
{ |
535 |
|
col = disp->width - col; |
536 |
|
row++; |
537 |
|
} |
538 |
|
refpos += col; |
539 |
|
|
540 |
|
/* The first row is not in the physical screen, nothing has to be |
541 |
|
done. */ |
542 |
|
if (row >= disp->height) |
543 |
|
return 0; |
544 |
|
|
545 |
|
/* The length cannot be used. Recalculate it to wrap the lines. */ |
546 |
|
cols = length / current_width; |
547 |
|
length = (length % current_width) + cols * disp->width ; |
548 |
|
|
549 |
|
/* Make sure the end of length is still in the physical screen. */ |
550 |
|
if (length > (disp->width * disp->height - (row * disp->width + col)) - col) |
551 |
|
length = disp->width * disp->height - (row * disp->width + col) - col; |
552 |
|
|
553 |
while (length > 0) |
while (length > 0) |
554 |
{ |
{ |
555 |
if (refpos->used) |
if (refpos->used) |
574 |
uint32_t col, uint32_t row) |
uint32_t col, uint32_t row) |
575 |
{ |
{ |
576 |
struct vga_display *disp = handle; |
struct vga_display *disp = handle; |
577 |
char *pos = vga_videomem + 2 * (row * disp->width + col); |
char *pos; |
578 |
struct refchr *refpos = &disp->refmatrix[row][col]; |
struct refchr *refpos = &disp->refmatrix[row][col]; |
579 |
|
|
580 |
|
/* The starting column is outside the physical screen. */ |
581 |
|
if (disp->width < current_width && col >= disp->width) |
582 |
|
{ |
583 |
|
size_t skip = current_width - disp->width; |
584 |
|
str += skip; |
585 |
|
length -= skip; |
586 |
|
col = 0; |
587 |
|
row++; |
588 |
|
} |
589 |
|
|
590 |
|
pos = vga_videomem + 2 * (row * disp->width + col); |
591 |
|
|
592 |
/* Although all references to the current fgcol or bgcol could have |
/* Although all references to the current fgcol or bgcol could have |
593 |
been released here, for example due to a scroll operation, we |
been released here, for example due to a scroll operation, we |
594 |
know that the color slots have not been reused yet, as no routine |
know that the color slots have not been reused yet, as no routine |
599 |
while (length--) |
while (length--) |
600 |
{ |
{ |
601 |
int charval = dynafont_lookup (disp->df, str); |
int charval = dynafont_lookup (disp->df, str); |
602 |
|
col++; |
603 |
|
|
604 |
|
/* The virtual console is smaller than the physical screen. */ |
605 |
|
if (col > current_width) |
606 |
|
{ |
607 |
|
size_t skip = disp->width - current_width; |
608 |
|
pos += skip * 2; |
609 |
|
refpos += skip; |
610 |
|
col = 1; |
611 |
|
row++; |
612 |
|
} |
613 |
|
/* The virtual console is bigger than the physical console. */ |
614 |
|
else if (disp->width < current_width && col == disp->width) |
615 |
|
{ |
616 |
|
size_t skip = current_width - disp->width; |
617 |
|
str += skip; |
618 |
|
length -= skip; |
619 |
|
col = 1; |
620 |
|
row++; |
621 |
|
} |
622 |
|
|
623 |
|
/* The screen is filled until the bottom of the screen. */ |
624 |
|
if (row >= disp->height) |
625 |
|
return 0; |
626 |
|
|
627 |
if (!disp->cur_conchar_attr_init |
if (!disp->cur_conchar_attr_init |
628 |
|| *(uint32_t *) &disp->cur_conchar_attr != *(uint32_t *) &str->attr) |
|| *(uint32_t *) &disp->cur_conchar_attr != *(uint32_t *) &str->attr) |
629 |
{ |
{ |
666 |
return 0; |
return 0; |
667 |
} |
} |
668 |
|
|
669 |
|
static error_t |
670 |
|
vga_set_dimension (void *handle, int width, int height) |
671 |
|
{ |
672 |
|
if (current_width && current_height) |
673 |
|
vga_display_clear (handle, current_width * current_height, 0, 0); |
674 |
|
|
675 |
|
current_width = width; |
676 |
|
current_height = height; |
677 |
|
|
678 |
|
/* FIXME: Should support greater dimensions by changing the video |
679 |
|
mode. */ |
680 |
|
|
681 |
|
return 0; |
682 |
|
} |
683 |
|
|
684 |
|
|
685 |
struct driver_ops driver_vga_ops = |
struct driver_ops driver_vga_ops = |
686 |
{ |
{ |
698 |
vga_display_write, |
vga_display_write, |
699 |
NULL, |
NULL, |
700 |
vga_display_flash, |
vga_display_flash, |
701 |
NULL |
NULL, |
702 |
|
vga_set_dimension |
703 |
}; |
}; |