Home > Back-end >  Cursor in kernel terminal
Cursor in kernel terminal

Time:11-27

I'm trying to edit this kernel. c, it doesn't support cursor. I wrote over 25 lines, and it doesn't show more than 25 and I can't go up or down to see the rest. here is the whole code, except the main function.

uint8_t make_color(enum vga_color fg, enum vga_color bg) {
    return fg | bg << 4;}
    static const size_t VGA_WIDTH = 80;
    static const size_t VGA_HEIGHT = 25;

    uint16_t make_vgaentry(char c, uint8_t color) {
    uint16_t c16 = c;
    uint16_t color16 = color;
    return c16 | color16 << 8;}

    size_t strlen(const char* str) {
    size_t ret = 0;

    while ( str[ret] != 0 )
            ret  ;
    return ret;}
    static const size_t VGA_WIDTH = 80;
    static const size_t VGA_HEIGHT = 25;

    size_t terminal_row;
    size_t terminal_column;
    uint8_t terminal_color;
    uint16_t* terminal_buffer;
    void terminal_initialize() {
    terminal_row = 0;
    terminal_column = 0;
    terminal_color = make_color(COLOR_LIGHT_GREY, COLOR_BLACK);
    terminal_buffer = (uint16_t*) 0xB8000;

    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;
                    terminal_buffer[index] = make_vgaentry(' ',
                                    terminal_color);
            }}}
void terminal_setcolor(uint8_t color) {
    terminal_color = color;
 }

 void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) 
  {
    const size_t index = y * VGA_WIDTH   x;
    if(y>VGA_HEIGHT){
            size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH;
            for(size_t x = 0; x < VGA_WIDTH;   x)
    {
   terminal_buffer[index   x] = vga_entry(' ', terminal_color);
   }
    }
    else
    terminal_buffer[index] = make_vgaentry(c, color);}
    void terminal_putchar(char c) {
    terminal_putentryat(c, terminal_color, terminal_column, 
                   terminal_row);
    if (  terminal_column == VGA_WIDTH) {
            terminal_column = 0;
            if (  terminal_row == VGA_HEIGHT)
               terminal_row = 0;}
            else if (c == '\n')
    {
        terminal_row = terminal_row   1;
        terminal_column = 0;
    }
    }
void terminal_writestring(const char* data) {
    size_t datalen = strlen(data);
    for (size_t i = 0; i < datalen; i  )
            terminal_putchar(data[i]);}

i need to have scrolling like the one in the terminal, line by line.

CodePudding user response:

void terminal_scrollUp(void)
{
    for (size_t y = 1; y < VGA_HEIGHT; y  ) 
    {
        for (size_t x = 0; x < VGA_WIDTH; x  ) 
        {
            const size_t index = y * VGA_WIDTH   x;
            terminal_buffer[index - VGA_WIDTH] = terminal_buffer[index];
        }
    }
    for(size_t col = 0; col < VGA_WIDTH; col  )
    {
        terminal_putentryat(' ', terminal_color, col, VGA_HEIGHT - 1);
    }
}

void terminal_putchar(char c) 
{
    terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
    if (  terminal_column == VGA_WIDTH || c == '\n') 
    {
        terminal_column = 0;
        if(terminal_row == VGA_HEIGHT - 1)
        {
            terminal_scrollUp();
        }
        else
        {
            terminal_row  ;
        }
    }
}

CodePudding user response:

The text displayed on the screen is taken directly from the memory. If you move the contents of that memory it will look like the text moved.

So if you move from the second to the last "line" one line up (to the beginning of the display memory are) while setting the last "line" to all zeroes, then it will look like it scrolled.

Something like:

char *ptr_to_first_line = terminal_buffer;
char *ptr_to_second_line = terminal_buffer   VGA_WIDTH * 2;  // *2 because of the attribute byte
char *ptr_to_last_line = terminal_buffer   (VGA_WIDTH * 2) * (VGA_HEIGHT - 1); // -1 to get the beginning of the last line
char *ptr_to_end = terminal_buffer   VGA_WIDTH * 2 * VGA_HEIGHT;

// Move (copy, overlapping memory okay) the memory, making appear as it's scrolling
// This copies from the second line to the first line, the third line to the second line, etc.
memmove(ptr_to_first_line, ptr_to_second_line, ptr_to_end - ptr_to_second_line);

// Clear the last line so it appears empty
memset(ptr_to_last_line, 0, VGA_WIDTH * 2);

All you have to do after this is to place the cursor at the beginning of the last line.

  • Related