vxBoot/src/terminal/util.c

169 lines
3.9 KiB
C

#include "vxBoot/terminal.h"
#include <gint/display.h>
#include <string.h>
//---
// Update the internal buffer
//---
/* terminal_buffer_insert() : insert string anywhere in the output buffer */
void terminal_buffer_insert(char *buffer, size_t nb)
{
size_t dump;
void *start;
/* calculate the "real" number of byte to dump into the buffer */
dump = nb;
start = &buffer[0];
if (dump > terminal.buffer.size) {
dump -= terminal.buffer.size;
start = &buffer[nb - dump];
}
/* dump the buffer (be carful with the circular effect) */
if (terminal.buffer.cursor + dump > terminal.buffer.size) {
memcpy(
&terminal.buffer.data[terminal.buffer.cursor],
start,
terminal.buffer.size - terminal.buffer.cursor
);
dump -= terminal.buffer.size - terminal.buffer.cursor;
terminal.buffer.cursor = 0;
}
memcpy(&terminal.buffer.data[terminal.buffer.cursor], start, dump);
terminal.buffer.cursor += dump;
}
//---
// Display the internal buffer
//---
/* terminal_vertical_update() - Update vertical cursor */
static void terminal_vertical_update(void)
{
if (terminal.cursor.y + 1 < terminal.winsize.ws_col) {
terminal.cursor.y = terminal.cursor.y + 1;
return;
}
}
/* earlyterm_horizontal_update() - Update horizotal cursor */
static int terminal_horizontal_update(void)
{
terminal.cursor.x = terminal.cursor.x + 1;
if (terminal.cursor.x >= terminal.winsize.ws_col) {
terminal_vertical_update();
terminal.cursor.x = 0;
return (1);
}
return (0);
}
/* line_discipline() - Check "special" char */
static int terminal_line_discipline(char n)
{
int offset;
switch (n) {
case '\0':
return (1);
case '\n':
terminal.cursor.x = 0;
terminal_vertical_update();
return (1);
case '\b':
if (terminal.cursor.x > 0)
terminal.cursor.x = terminal.cursor.x - 1;
return (1);
case '\v':
terminal_vertical_update();
return (1);
case '\r':
terminal.cursor.x = 0;
return (1);
case '\t':
/* Check if we need a new line or not. */
offset = terminal.cursor.x - ((terminal.cursor.x / 5) * 5);
offset = 5 - offset;
while (--offset >= 0)
terminal_horizontal_update();
return (1);
default:
return (0);
}
}
/* terminal_buffer_write() : display the buffer on screen */
void terminal_buffer_display(void)
{
uint8_t *buffer;
uint16_t tmp;
int cursor;
int x;
int y;
int i;
/* Due to potential special char, we sould find the "real" starting
index for the internal buffer */
terminal.cursor.x = 0;
terminal.cursor.y = 0;
i = terminal.buffer.cursor - 1;
buffer = &terminal.buffer.data[0];
while (1) {
/* decrease the cursor and avoid circular effect */
if (--i < 0)
i = terminal.buffer.size - 1;
/* check loop condition */
if (i == (int)terminal.buffer.cursor)
break;
/* check EOL */
if (buffer[i] == '\0') {
break;
}
/* handle the character (only to force update cursors) */
if (terminal_line_discipline(buffer[i] & 0x7f) == 0)
terminal_horizontal_update();
if (terminal.cursor.y >= terminal.winsize.ws_row)
break;
}
/* Display character per character because we need to check special
behaviour (like cariege return, line feed, ...) */
terminal.cursor.x = 0;
terminal.cursor.y = 0;
while (1) {
/* update the index */
if (++i >= (int)terminal.buffer.size)
i = 0;
if (i == (int)terminal.buffer.cursor)
break;
/* get the cursor and remove the potential cursor marker */
cursor = ((buffer[i] & 0x80) != 0);
buffer[i] &= 0x7f;
/* display part (character + cursor if needed) */
x = terminal.cursor.x * terminal.winsize.ft_xpixel;
y = terminal.cursor.y * terminal.winsize.ft_ypixel;
if (terminal_line_discipline(buffer[i]) == 0) {
tmp = buffer[i] << 8;
dtext(x, y, terminal.private.color.fg, (void*)&tmp);
terminal_horizontal_update();
}
if (cursor != 0) {
dline(x,
y + terminal.winsize.ft_ypixel,
x + terminal.winsize.ft_xpixel - 2,
y + terminal.winsize.ft_ypixel,
terminal.private.color.fg);
}
}
}