diff --git a/kernel/screen/include/cursor.h b/kernel/screen/include/cursor.h index 556f9d7..627b1e5 100644 --- a/kernel/screen/include/cursor.h +++ b/kernel/screen/include/cursor.h @@ -15,14 +15,14 @@ /* * _screen_move_cursor: - * Moves the cursor of the framebuffer to a give position calculated using - * @x and @y coordinates. + * Moves the cursor of the framebuffer to a given position calculated using + * the arguments. * - * @param x - horizontal position - * @param y - vertical position + * @param column - Vertical position + * @param row - Horizontal position * */ -void _screen_move_cursor(uint8_t x, uint8_t y); +void _screen_move_cursor(uint8_t column, uint8_t row); #endif diff --git a/kernel/screen/include/screen_internals.h b/kernel/screen/include/screen_internals.h index 4a4b89c..c6097b0 100644 --- a/kernel/screen/include/screen_internals.h +++ b/kernel/screen/include/screen_internals.h @@ -17,14 +17,14 @@ size_t screen_color; * Put character at a specified position or put character at the next position * available in framebuffer acording to state variables. * - * @param c - Char to be displayed - * @param color - Color attributes of @c - * @param x - Vertical position - * @param y - Horizontal position + * @param c - Char to be displayed + * @param color - Color attributes of @c + * @param column - Vertical position + * @param row - Horizontal position * */ -void _screen_putchar_at(char c, uint16_t color, size_t x, size_t y); +void _screen_putchar_at(char c, uint16_t color, size_t column, size_t row); void _screen_putchar(char c); /* @@ -35,4 +35,37 @@ void _screen_putchar(char c); void _screen_scroll_up(void); +/* + * _screen_delete_at: + * Deletes a character at a given position. + * + * @param column - Vertical position + * @param row - Horizontal position + * + */ + +void _screen_delete_at(size_t column, size_t row); + +/* + * _find_last_nonwhite_column: + * + * + * @return - the column with the last nonwhite character on the previous + * line. + */ + +size_t _find_last_nonwhite_column(void); + +/* + * _is_whitespace: + * + * @param column - Vertical position + * @param row - Horizontal poistion + * @return - 1 if it is whitespace + * 0 else + * + */ + +int _is_whitespace(size_t column, size_t row); + #endif diff --git a/kernel/screen/src/cursor.c b/kernel/screen/src/cursor.c index c641545..adba617 100644 --- a/kernel/screen/src/cursor.c +++ b/kernel/screen/src/cursor.c @@ -16,9 +16,9 @@ * */ -void _screen_move_cursor(uint8_t x, uint8_t y) { +void _screen_move_cursor(uint8_t column, uint8_t row) { - uint16_t sindex = y * VGA_WIDTH + x; + uint16_t sindex = row * VGA_WIDTH + column; outb(CURSOR_COMMAND_PORT, CURSOR_HIGH_BYTE_COMMAND); outb(CURSOR_DATA_PORT, ((sindex >> 8)) & 0x00FF); diff --git a/kernel/screen/src/screen.c b/kernel/screen/src/screen.c index 8f048db..f3aa7e5 100644 --- a/kernel/screen/src/screen.c +++ b/kernel/screen/src/screen.c @@ -2,6 +2,7 @@ #include "framebuffer.h" #include "screen_internals.h" +#include "cursor.h" #include "lib/vga.h" @@ -25,14 +26,9 @@ void screen_init(void) { fbuffer = (uint16_t *) FBUFFER_START_ADDR; - for (size_t y = 0; y < VGA_HEIGHT; y++) { - for (size_t x = 0; x < VGA_WIDTH; x++) { - - const size_t index = y * VGA_WIDTH + x; - fbuffer[index] = vga_entry(' ', screen_color); - - } - } + for (size_t row = 0; row < VGA_HEIGHT; row++) + for (size_t column = 0; column < VGA_WIDTH; column++) + _screen_delete_at(column, row); } @@ -54,3 +50,35 @@ size_t screen_write(char *buf, size_t len) { return i; } +/* + * screen_delete: + * -------------- + * + * Deletes the current character and updates the cursor. If current position + * is (0, 0) then do nothing. If current position is at the beginning of a + * line then find the last nonwhite element on the last line and move the + * cursor there. Else just delete the current element. + * + * Side effects: + * cursor position will be affected too. + * + */ + +void screen_delete(void) { + + if (!screen_column && !screen_row) + return; + + if (!screen_column && screen_row) { + + screen_column = _find_last_nonwhite_column(); + screen_row--; + + } else + screen_column--; + + _screen_delete_at(screen_column, screen_row); + _screen_move_cursor(screen_column, screen_row); + +} + diff --git a/kernel/screen/src/screen_internals.c b/kernel/screen/src/screen_internals.c index 4251ec8..a585b3b 100644 --- a/kernel/screen/src/screen_internals.c +++ b/kernel/screen/src/screen_internals.c @@ -6,6 +6,21 @@ #include #include +/* + * _screen_delete_at: + * ------------------ + * + * Replaces the character at (row, column) with a whitespace. + * + */ + +void _screen_delete_at(size_t column, size_t row) { + + const size_t index = row * VGA_WIDTH + column; + fbuffer[index] = vga_entry(' ', screen_color); + +} + /* * _screen_putchar_at: * ------------------ @@ -15,9 +30,9 @@ * */ -void _screen_putchar_at(char c, uint16_t color, size_t x, size_t y) { +void _screen_putchar_at(char c, uint16_t color, size_t column, size_t row) { - const size_t index = y * VGA_WIDTH + x; + const size_t index = row * VGA_WIDTH + column; fbuffer[index] = vga_entry(c, color); } @@ -38,7 +53,7 @@ void _screen_scroll_up(void) { fbuffer[i] = fbuffer[i + 80]; for (i = 0; i < VGA_WIDTH; i++) - fbuffer[(VGA_HEIGHT - 1) * VGA_WIDTH + i] = vga_entry(' ', screen_color); + _screen_delete_at(i, VGA_HEIGHT - 1); } @@ -75,7 +90,44 @@ void _screen_putchar(char c) { } - _screen_putchar_at(c, screen_color, screen_column++, screen_row); + _screen_putchar_at(c, screen_color, screen_column, screen_row); + screen_column++; _screen_move_cursor(screen_column, screen_row); } + +/* + * _is_whitespace: + * --------------- + * + */ + +int _is_whitespace(size_t column, size_t row) { + + int index = row * VGA_WIDTH + column; + return fbuffer[index] == vga_entry(' ', screen_color); + +} + +/* + * _find_last_nonwhite_column: + * --------------------------- + * + * Goes on the last line and returns the first column that has a nonwhite + * char. The traversal is from the end of the line to the beginning. + * It will return 0 if there is no nonwhite character. + * + */ + +size_t _find_last_nonwhite_column(void) { + + int row = screen_row - 1; + int y = VGA_WIDTH; + + for (; y > 0; y--) + if (!_is_whitespace(y, row)) + break; + + return y; + +}