mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add console backspace bold and underline support.
Combine textbuffer char and attr concepts while here.
This commit is contained in:
parent
9297ff2a20
commit
8f233b4a10
9 changed files with 111 additions and 140 deletions
|
@ -35,6 +35,10 @@
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
static const uint16_t ATTR_CHAR = 1 << 0;
|
||||
static const uint16_t ATTR_BOLD = 1 << 1;
|
||||
static const uint16_t ATTR_UNDERLINE = 1 << 2;
|
||||
|
||||
struct TextPos
|
||||
{
|
||||
TextPos() { }
|
||||
|
@ -47,16 +51,20 @@ struct TextCharPOD
|
|||
{
|
||||
wchar_t c;
|
||||
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||
uint16_t attr;
|
||||
};
|
||||
|
||||
struct TextChar
|
||||
{
|
||||
TextChar() { }
|
||||
TextChar(const TextCharPOD& o) : c(o.c), vgacolor(o.vgacolor) { }
|
||||
TextChar(wchar_t c, uint8_t vgacolor) : c(c), vgacolor(vgacolor) { }
|
||||
operator TextCharPOD() { return TextCharPOD{c, vgacolor}; }
|
||||
TextChar(const TextCharPOD& o) :
|
||||
c(o.c), vgacolor(o.vgacolor), attr(o.attr) { }
|
||||
TextChar(wchar_t c, uint8_t vgacolor, uint16_t attr) :
|
||||
c(c), vgacolor(vgacolor), attr(attr) { }
|
||||
operator TextCharPOD() { return TextCharPOD{c, vgacolor, attr}; }
|
||||
wchar_t c;
|
||||
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||
uint16_t attr;
|
||||
};
|
||||
|
||||
static inline bool IsTextPosBeforeTextPos(const TextPos& a, const TextPos& b)
|
||||
|
@ -77,12 +85,9 @@ public:
|
|||
virtual size_t Height() const = 0;
|
||||
virtual TextChar GetChar(TextPos pos) const = 0;
|
||||
virtual void SetChar(TextPos pos, TextChar c) = 0;
|
||||
virtual uint16_t GetCharAttr(TextPos pos) const = 0;
|
||||
virtual void SetCharAttr(TextPos pos, uint16_t attr) = 0;
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith) = 0;
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars) = 0;
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr) = 0;
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith) = 0;
|
||||
virtual bool GetCursorEnabled() const = 0;
|
||||
virtual void SetCursorEnabled(bool enablecursor) = 0;
|
||||
virtual TextPos GetCursorPos() const = 0;
|
||||
|
|
|
@ -63,7 +63,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
uint8_t* backbuf;
|
||||
uint8_t* font;
|
||||
TextChar* chars;
|
||||
uint16_t* attrs;
|
||||
TextBufferCmd* queue;
|
||||
LFBTextBuffer* ret;
|
||||
|
||||
|
@ -75,10 +74,8 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
goto cleanup_backbuf;
|
||||
if ( !(chars = new TextChar[columns * rows]) )
|
||||
goto cleanup_font;
|
||||
if ( !(attrs = new uint16_t[columns * rows]) )
|
||||
goto cleanup_chars;
|
||||
if ( !(queue = new TextBufferCmd[QUEUE_LENGTH]) )
|
||||
goto cleanup_attrs;
|
||||
goto cleanup_chars;
|
||||
if ( !(ret = new LFBTextBuffer) )
|
||||
goto cleanup_queue;
|
||||
|
||||
|
@ -108,8 +105,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
ret->font = font;
|
||||
memset(chars, 0, sizeof(chars[0]) * columns * rows);
|
||||
ret->chars = chars;
|
||||
memset(attrs, 0, sizeof(attrs[0]) * columns * rows);
|
||||
ret->attrs = attrs;
|
||||
for ( size_t i = 0; i < 16UL; i++ )
|
||||
{
|
||||
uint8_t r = i & 0b0100 ? (i & 0b1000 ? 255 : 191) : (i & 0b1000 ? 63 : 0);
|
||||
|
@ -135,8 +130,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
|
||||
cleanup_queue:
|
||||
delete[] queue;
|
||||
cleanup_attrs:
|
||||
delete[] attrs;
|
||||
cleanup_chars:
|
||||
delete[] chars;
|
||||
cleanup_font:
|
||||
|
@ -176,7 +169,6 @@ LFBTextBuffer::~LFBTextBuffer()
|
|||
delete[] backbuf;
|
||||
delete[] font;
|
||||
delete[] chars;
|
||||
delete[] attrs;
|
||||
delete[] queue;
|
||||
}
|
||||
|
||||
|
@ -220,6 +212,8 @@ void LFBTextBuffer::RenderChar(TextChar textchar, size_t posx, size_t posy)
|
|||
return;
|
||||
bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y;
|
||||
uint8_t fgcoloridx = textchar.vgacolor >> 0 & 0x0F;
|
||||
if ( textchar.attr & ATTR_BOLD )
|
||||
fgcoloridx |= 0x08;
|
||||
uint8_t bgcoloridx = textchar.vgacolor >> 4 & 0x0F;
|
||||
uint32_t fgcolor = colors[fgcoloridx];
|
||||
uint32_t bgcolor = colors[bgcoloridx];
|
||||
|
@ -259,9 +253,10 @@ void LFBTextBuffer::RenderChar(TextChar textchar, size_t posx, size_t posy)
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( likely(!drawcursor) )
|
||||
if ( likely(!drawcursor) && !(textchar.attr & ATTR_UNDERLINE) )
|
||||
return;
|
||||
for ( size_t y = VGA_FONT_HEIGHT - 2; y < VGA_FONT_HEIGHT; y++ )
|
||||
size_t underlines = VGA_FONT_HEIGHT - (!drawcursor ? 1 : 0);
|
||||
for ( size_t y = VGA_FONT_HEIGHT - 2; y < underlines; y++ )
|
||||
{
|
||||
size_t pixely = posy * VGA_FONT_HEIGHT + y;
|
||||
for ( size_t x = 0; x < VGA_FONT_WIDTH+1; x++ )
|
||||
|
@ -378,7 +373,7 @@ TextChar LFBTextBuffer::GetChar(TextPos pos) const
|
|||
((LFBTextBuffer*) this)->ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
return {0, 0};
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
|
||||
|
@ -393,30 +388,6 @@ void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
|
|||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
uint16_t LFBTextBuffer::GetCharAttr(TextPos pos) const
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
{
|
||||
((LFBTextBuffer*) this)->StopRendering();
|
||||
uint16_t ret = attrs[pos.y * columns + pos.x];
|
||||
((LFBTextBuffer*) this)->ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LFBTextBuffer::SetCharAttr(TextPos pos, uint16_t attrval)
|
||||
{
|
||||
if ( !UsablePosition(pos) )
|
||||
return;
|
||||
TextBufferCmd cmd;
|
||||
cmd.type = TEXTBUFCMD_ATTR;
|
||||
cmd.x = pos.x;
|
||||
cmd.y = pos.y;
|
||||
cmd.attr = attrval;
|
||||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
bool LFBTextBuffer::GetCursorEnabled() const
|
||||
{
|
||||
((LFBTextBuffer*) this)->StopRendering();
|
||||
|
@ -485,8 +456,7 @@ void LFBTextBuffer::Move(TextPos to, TextPos from, size_t numchars)
|
|||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr)
|
||||
void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith)
|
||||
{
|
||||
from = CropPosition(from);
|
||||
to = CropPosition(to);
|
||||
|
@ -497,7 +467,6 @@ void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
|||
cmd.to_x = to.x;
|
||||
cmd.to_y = to.y;
|
||||
cmd.c = fillwith;
|
||||
cmd.attr = fillattr;
|
||||
IssueCommand(&cmd);
|
||||
}
|
||||
|
||||
|
@ -513,7 +482,7 @@ void LFBTextBuffer::DoScroll(ssize_t off, TextChar entry)
|
|||
TextPos fillto = neg ? TextPos{columns-1, rows-1} : TextPos{columns-1, absoff-1};
|
||||
size_t scrollchars = columns * (rows-absoff);
|
||||
DoMove(scrollto, scrollfrom, scrollchars);
|
||||
DoFill(fillfrom, fillto, entry, 0);
|
||||
DoFill(fillfrom, fillto, entry);
|
||||
}
|
||||
|
||||
void LFBTextBuffer::DoMove(TextPos to, TextPos from, size_t numchars)
|
||||
|
@ -522,22 +491,18 @@ void LFBTextBuffer::DoMove(TextPos to, TextPos from, size_t numchars)
|
|||
size_t src = OffsetOfPos(from);
|
||||
if ( dest < src )
|
||||
for ( size_t i = 0; i < numchars; i++ )
|
||||
chars[dest + i] = chars[src + i],
|
||||
attrs[dest + i] = attrs[src + i];
|
||||
chars[dest + i] = chars[src + i];
|
||||
else if ( src < dest )
|
||||
for ( size_t i = 0; i < numchars; i++ )
|
||||
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i],
|
||||
attrs[dest + numchars-1 - i] = attrs[src + numchars-1 - i];
|
||||
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i];
|
||||
}
|
||||
|
||||
void LFBTextBuffer::DoFill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr)
|
||||
void LFBTextBuffer::DoFill(TextPos from, TextPos to, TextChar fillwith)
|
||||
{
|
||||
size_t start = OffsetOfPos(from);
|
||||
size_t end = OffsetOfPos(to);
|
||||
for ( size_t i = start; i <= end; i++ )
|
||||
chars[i] = fillwith,
|
||||
attrs[i] = fillattr;
|
||||
chars[i] = fillwith;
|
||||
}
|
||||
|
||||
bool LFBTextBuffer::IsCommandIdempotent(const TextBufferCmd* cmd) const
|
||||
|
@ -548,7 +513,6 @@ bool LFBTextBuffer::IsCommandIdempotent(const TextBufferCmd* cmd) const
|
|||
case TEXTBUFCMD_SYNC: return true;
|
||||
case TEXTBUFCMD_PAUSE: return true;
|
||||
case TEXTBUFCMD_CHAR: return true;
|
||||
case TEXTBUFCMD_ATTR: return true;
|
||||
case TEXTBUFCMD_CURSOR_SET_ENABLED: return true;
|
||||
case TEXTBUFCMD_CURSOR_MOVE: return true;
|
||||
case TEXTBUFCMD_MOVE: return false;
|
||||
|
@ -586,11 +550,6 @@ void LFBTextBuffer::ExecuteCommand(TextBufferCmd* cmd,
|
|||
if ( IsTextPosAfterTextPos(pos, render_to) )
|
||||
render_to = pos;
|
||||
} break;
|
||||
case TEXTBUFCMD_ATTR:
|
||||
{
|
||||
TextPos pos(cmd->x, cmd->y);
|
||||
attrs[pos.y * columns + pos.x] = cmd->attr;
|
||||
} break;
|
||||
case TEXTBUFCMD_CURSOR_SET_ENABLED:
|
||||
if ( cmd->b != cursorenabled )
|
||||
{
|
||||
|
@ -633,7 +592,7 @@ void LFBTextBuffer::ExecuteCommand(TextBufferCmd* cmd,
|
|||
{
|
||||
TextPos from(cmd->from_x, cmd->from_y);
|
||||
TextPos to(cmd->to_x, cmd->to_y);
|
||||
DoFill(from, to, cmd->c, cmd->attr);
|
||||
DoFill(from, to, cmd->c);
|
||||
if ( IsTextPosBeforeTextPos(from, render_from) )
|
||||
render_from = from;
|
||||
if ( IsTextPosAfterTextPos(to, render_to) )
|
||||
|
@ -778,7 +737,7 @@ void LFBTextBuffer::EmergencyReset()
|
|||
{
|
||||
// TODO: Reset everything here!
|
||||
|
||||
Fill(TextPos{0, 0}, TextPos{columns-1, rows-1}, TextChar{0, 0}, 0);
|
||||
Fill(TextPos{0, 0}, TextPos{columns-1, rows-1}, TextChar{0, 0, 0});
|
||||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ enum TextBufferCmdType
|
|||
TEXTBUFCMD_SYNC,
|
||||
TEXTBUFCMD_PAUSE,
|
||||
TEXTBUFCMD_CHAR,
|
||||
TEXTBUFCMD_ATTR,
|
||||
TEXTBUFCMD_CURSOR_SET_ENABLED,
|
||||
TEXTBUFCMD_CURSOR_MOVE,
|
||||
TEXTBUFCMD_MOVE,
|
||||
|
@ -55,7 +54,7 @@ struct TextBufferCmd
|
|||
union
|
||||
{
|
||||
bool b;
|
||||
struct { TextCharPOD c; uint16_t attr; };
|
||||
TextCharPOD c;
|
||||
size_t val;
|
||||
};
|
||||
};
|
||||
|
@ -74,12 +73,9 @@ public:
|
|||
virtual size_t Height() const;
|
||||
virtual TextChar GetChar(TextPos pos) const;
|
||||
virtual void SetChar(TextPos pos, TextChar c);
|
||||
virtual uint16_t GetCharAttr(TextPos pos) const;
|
||||
virtual void SetCharAttr(TextPos pos, uint16_t attrval);
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith);
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
|
||||
virtual bool GetCursorEnabled() const;
|
||||
virtual void SetCursorEnabled(bool enablecursor);
|
||||
virtual TextPos GetCursorPos() const;
|
||||
|
@ -104,7 +100,7 @@ private:
|
|||
TextPos AddToPosition(TextPos pos, size_t count);
|
||||
void DoScroll(ssize_t off, TextChar entry);
|
||||
void DoMove(TextPos to, TextPos from, size_t numchars);
|
||||
void DoFill(TextPos from, TextPos to, TextChar fillwith, uint16_t fillattr);
|
||||
void DoFill(TextPos from, TextPos to, TextChar fillwith);
|
||||
void IssueCommand(TextBufferCmd* cmd);
|
||||
void StopRendering();
|
||||
void ResumeRendering();
|
||||
|
@ -135,7 +131,6 @@ private:
|
|||
uint8_t* backbuf;
|
||||
uint8_t* font;
|
||||
TextChar* chars;
|
||||
uint16_t* attrs;
|
||||
size_t columns;
|
||||
size_t rows;
|
||||
size_t pixelsx;
|
||||
|
|
|
@ -176,12 +176,10 @@ void Init(multiboot_info_t* bootinfo)
|
|||
uint16_t* const VGAFB = (uint16_t*) 0xB8000;
|
||||
const size_t VGA_WIDTH = 80;
|
||||
const size_t VGA_HEIGHT = 25;
|
||||
uint16_t* vga_attr_buffer = new uint16_t[VGA_WIDTH * VGA_HEIGHT];
|
||||
TextChar* vga_chars_buffer = new TextChar[VGA_WIDTH * VGA_HEIGHT];
|
||||
if ( !vga_attr_buffer || !vga_chars_buffer )
|
||||
if ( !vga_chars_buffer )
|
||||
Panic(oom_msg);
|
||||
textbuf = new VGATextBuffer(VGAFB, vga_chars_buffer, vga_attr_buffer,
|
||||
VGA_WIDTH, VGA_HEIGHT);
|
||||
textbuf = new VGATextBuffer(VGAFB, vga_chars_buffer, VGA_WIDTH, VGA_HEIGHT);
|
||||
if ( !textbuf )
|
||||
Panic(oom_msg);
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ void LogTerminal::ProcessKeystroke(int kbkey)
|
|||
(!wasuni || termmode & TERMMODE_UNICODE) &&
|
||||
termmode & TERMMODE_ECHO &&
|
||||
wasuni )
|
||||
Log::Print("\b");
|
||||
Log::Print("\b \b");
|
||||
goto c_w_delete_more;
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ void LogTerminal::ProcessKeystroke(int kbkey)
|
|||
(!wasuni || termmode & TERMMODE_UNICODE) &&
|
||||
termmode & TERMMODE_ECHO &&
|
||||
wasuni )
|
||||
Log::Print("\b");
|
||||
Log::Print("\b \b");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ void LogTerminal::QueueUnicode(uint32_t unicode)
|
|||
if ( waskbkey && !kbkeymode ) { continue; }
|
||||
if ( wasuni && !unicodemode ) { continue; }
|
||||
if ( !echomode ) { return; }
|
||||
if ( wasuni ) { Log::Print("\b"); }
|
||||
if ( wasuni ) { Log::Print("\b \b"); }
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -308,6 +308,9 @@ void LogTerminal::QueueUnicode(uint32_t unicode)
|
|||
memset(&ps, 0, sizeof(ps));
|
||||
char utf8buf[MB_CUR_MAX];
|
||||
size_t num_bytes = wcrtomb(utf8buf, (wchar_t) unicode, &ps);
|
||||
if ( num_bytes == 1 && utf8buf[0] == '\b' )
|
||||
Log::PrintData("\b \b", 3);
|
||||
else
|
||||
Log::PrintData(utf8buf, num_bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,7 @@
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
const uint16_t DEFAULT_COLOR = COLOR8_LIGHT_GREY << 0U | COLOR8_BLACK << 4U;
|
||||
const uint16_t ATTR_CHAR = 1U << 0U;
|
||||
static const uint16_t DEFAULT_COLOR = COLOR8_LIGHT_GREY | COLOR8_BLACK << 4;
|
||||
|
||||
TextTerminal::TextTerminal(TextBufferHandle* textbufhandle)
|
||||
{
|
||||
|
@ -53,6 +52,7 @@ TextTerminal::~TextTerminal()
|
|||
|
||||
void TextTerminal::Reset()
|
||||
{
|
||||
next_attr = 0;
|
||||
vgacolor = DEFAULT_COLOR;
|
||||
column = line = 0;
|
||||
ansisavedposx = ansisavedposy = 0;
|
||||
|
@ -60,8 +60,8 @@ void TextTerminal::Reset()
|
|||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
TextPos fillfrom(0, 0);
|
||||
TextPos fillto(textbuf->Width()-1, textbuf->Height()-1);
|
||||
TextChar fillwith(' ', vgacolor);
|
||||
textbuf->Fill(fillfrom, fillto, fillwith, 0);
|
||||
TextChar fillwith(' ', vgacolor, 0);
|
||||
textbuf->Fill(fillfrom, fillto, fillwith);
|
||||
textbuf->SetCursorEnabled(true);
|
||||
UpdateCursor(textbuf);
|
||||
textbufhandle->Release(textbuf);
|
||||
|
@ -278,9 +278,9 @@ void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
|||
if ( textbuf->Width() <= column )
|
||||
Newline(textbuf);
|
||||
TextPos pos(column++, line);
|
||||
TextChar tc(wc, vgacolor);
|
||||
TextChar tc(wc, vgacolor, ATTR_CHAR | next_attr);
|
||||
textbuf->SetChar(pos, tc);
|
||||
textbuf->SetCharAttr(pos, ATTR_CHAR);
|
||||
next_attr = 0;
|
||||
}
|
||||
|
||||
void TextTerminal::UpdateCursor(TextBuffer* textbuf)
|
||||
|
@ -290,13 +290,21 @@ void TextTerminal::UpdateCursor(TextBuffer* textbuf)
|
|||
|
||||
void TextTerminal::Newline(TextBuffer* textbuf)
|
||||
{
|
||||
textbuf->SetCharAttr(TextPos(column, line), ATTR_CHAR);
|
||||
TextPos pos(column, line);
|
||||
TextChar tc = textbuf->GetChar(pos);
|
||||
if ( !(tc.attr & ATTR_CHAR) )
|
||||
{
|
||||
tc.attr |= ATTR_CHAR;
|
||||
textbuf->SetChar(pos, tc);
|
||||
}
|
||||
column = 0;
|
||||
if ( line < textbuf->Height()-1 )
|
||||
line++;
|
||||
else
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor)),
|
||||
{
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0));
|
||||
line = textbuf->Height()-1;
|
||||
}
|
||||
}
|
||||
|
||||
static TextPos DecrementTextPos(TextBuffer* textbuf, TextPos pos)
|
||||
|
@ -314,10 +322,16 @@ void TextTerminal::Backspace(TextBuffer* textbuf)
|
|||
while ( pos.x || pos.y )
|
||||
{
|
||||
pos = DecrementTextPos(textbuf, pos);
|
||||
uint16_t attr = textbuf->GetCharAttr(pos);
|
||||
textbuf->SetChar(pos, TextChar(' ', vgacolor));
|
||||
textbuf->SetCharAttr(pos, attr & ~ATTR_CHAR);
|
||||
if ( attr & ATTR_CHAR )
|
||||
TextChar tc = textbuf->GetChar(pos);
|
||||
next_attr = tc.attr & (ATTR_BOLD | ATTR_UNDERLINE);
|
||||
if ( tc.c == L'_' )
|
||||
next_attr |= ATTR_UNDERLINE;
|
||||
else if ( tc.c == L' ' )
|
||||
next_attr &= ~(ATTR_BOLD | ATTR_CHAR);
|
||||
else
|
||||
next_attr |= ATTR_BOLD;
|
||||
textbuf->SetChar(pos, TextChar(' ', vgacolor, 0));
|
||||
if ( tc.attr & ATTR_CHAR )
|
||||
break;
|
||||
}
|
||||
column = pos.x;
|
||||
|
@ -328,17 +342,21 @@ void TextTerminal::Tab(TextBuffer* textbuf)
|
|||
{
|
||||
if ( column == textbuf->Width() )
|
||||
Newline(textbuf);
|
||||
// TODO: This does not work correctly if the text buffer width is not a
|
||||
// multiple of four and the column is near the edge.
|
||||
unsigned until = 8 - (column % 8);
|
||||
textbuf->SetCharAttr(TextPos(column, line), ATTR_CHAR);
|
||||
while ( (until--) != 0 )
|
||||
textbuf->SetChar(TextPos(column++, line), TextChar(' ', vgacolor));
|
||||
unsigned int count = 8 - (column % 8);
|
||||
for ( unsigned int i = 0; i < count; i++ )
|
||||
{
|
||||
if ( column == textbuf->Width() )
|
||||
break;
|
||||
TextPos pos(column++, line);
|
||||
TextChar tc(' ', vgacolor, i == 0 ? ATTR_CHAR : 0);
|
||||
textbuf->SetChar(pos, tc);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This implementation of the 'Ansi Escape Codes' is incomplete and hacky.
|
||||
void TextTerminal::AnsiReset()
|
||||
{
|
||||
next_attr = 0;
|
||||
ansiusedparams = 0;
|
||||
currentparamindex = 0;
|
||||
ansiparams[0] = 0;
|
||||
|
@ -501,7 +519,7 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
from = TextPos{0, 0},
|
||||
to = TextPos{width-1, height-1};
|
||||
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor), 0);
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
|
||||
} break;
|
||||
case 'K': // Erase parts of the current line.
|
||||
{
|
||||
|
@ -521,16 +539,16 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
from = TextPos{0, line},
|
||||
to = TextPos{width-1, line};
|
||||
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor), 0);
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
|
||||
} break;
|
||||
case 'S': // Scroll a line up and place a new line at the buttom.
|
||||
{
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor));
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0));
|
||||
line = height-1;
|
||||
} break;
|
||||
case 'T': // Scroll a line up and place a new line at the top.
|
||||
{
|
||||
textbuf->Scroll(-1, TextChar(' ', vgacolor));
|
||||
textbuf->Scroll(-1, TextChar(' ', vgacolor, 0));
|
||||
line = 0;
|
||||
} break;
|
||||
case 'm': // Change how the text is rendered.
|
||||
|
|
|
@ -69,6 +69,7 @@ private:
|
|||
mbstate_t ps;
|
||||
mutable TextBufferHandle* textbufhandle;
|
||||
mutable kthread_mutex_t termlock;
|
||||
uint16_t next_attr;
|
||||
uint8_t vgacolor;
|
||||
unsigned column;
|
||||
unsigned line;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -34,12 +34,11 @@
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
VGATextBuffer::VGATextBuffer(uint16_t* vga, TextChar* chars, uint16_t* attr,
|
||||
VGATextBuffer::VGATextBuffer(uint16_t* vga, TextChar* chars,
|
||||
size_t width, size_t height)
|
||||
{
|
||||
this->vga = vga;
|
||||
this->chars = chars;
|
||||
this->attr = attr;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
cursorpos = {0, 0};
|
||||
|
@ -56,6 +55,8 @@ static uint16_t CharToTextEntry(TextChar c)
|
|||
int remap = VGA::MapWideToVGAFont(c.c);
|
||||
if ( remap < 0 )
|
||||
remap = 0 /* replacement character */;
|
||||
if ( c.attr & ATTR_BOLD )
|
||||
c.vgacolor |= 0x08;
|
||||
return (uint16_t) remap | (uint16_t) c.vgacolor << 8U;
|
||||
}
|
||||
|
||||
|
@ -92,27 +93,16 @@ TextChar VGATextBuffer::GetChar(TextPos pos) const
|
|||
{
|
||||
if ( UsablePosition(pos) )
|
||||
return chars[OffsetOfPos(pos)];
|
||||
return {0, 0};
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
void VGATextBuffer::SetChar(TextPos pos, TextChar c)
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
chars[OffsetOfPos(pos)] = c,
|
||||
{
|
||||
chars[OffsetOfPos(pos)] = c;
|
||||
vga[OffsetOfPos(pos)] = CharToTextEntry(c);
|
||||
}
|
||||
|
||||
uint16_t VGATextBuffer::GetCharAttr(TextPos pos) const
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
return attr[OffsetOfPos(pos)];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VGATextBuffer::SetCharAttr(TextPos pos, uint16_t attrval)
|
||||
{
|
||||
if ( UsablePosition(pos) )
|
||||
attr[OffsetOfPos(pos)] = attrval;
|
||||
}
|
||||
}
|
||||
|
||||
void VGATextBuffer::Scroll(ssize_t off, TextChar fillwith)
|
||||
|
@ -129,7 +119,7 @@ void VGATextBuffer::Scroll(ssize_t off, TextChar fillwith)
|
|||
TextPos fillto = neg ? TextPos{width-1, height-1} : TextPos{width-1, absoff-1};
|
||||
size_t scrollchars = width * (height-absoff);
|
||||
Move(scrollto, scrollfrom, scrollchars);
|
||||
Fill(fillfrom, fillto, fillwith, 0);
|
||||
Fill(fillfrom, fillto, fillwith);
|
||||
}
|
||||
|
||||
void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars)
|
||||
|
@ -137,29 +127,35 @@ void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars)
|
|||
size_t dest = OffsetOfPos(CropPosition(to));
|
||||
size_t src = OffsetOfPos(CropPosition(from));
|
||||
if ( dest < src )
|
||||
{
|
||||
for ( size_t i = 0; i < numchars; i++ )
|
||||
chars[dest + i] = chars[src + i],
|
||||
vga[dest + i] = CharToTextEntry(chars[dest + i]),
|
||||
attr[dest + i] = attr[src + i];
|
||||
{
|
||||
chars[dest + i] = chars[src + i];
|
||||
vga[dest + i] = CharToTextEntry(chars[dest + i]);
|
||||
}
|
||||
}
|
||||
else if ( src < dest )
|
||||
{
|
||||
for ( size_t i = 0; i < numchars; i++ )
|
||||
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i],
|
||||
vga[dest + numchars-1 - i] = CharToTextEntry(chars[dest + numchars-1 - i]),
|
||||
attr[dest + numchars-1 - i] = attr[src + numchars-1 - i];
|
||||
{
|
||||
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i];
|
||||
vga[dest + numchars-1 - i] = CharToTextEntry(chars[dest + numchars-1 - i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr)
|
||||
void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith)
|
||||
{
|
||||
from = CropPosition(from);
|
||||
to = CropPosition(to);
|
||||
size_t start = OffsetOfPos(from);
|
||||
size_t end = OffsetOfPos(to);
|
||||
size_t entry = CharToTextEntry(fillwith);
|
||||
uint16_t entry = CharToTextEntry(fillwith);
|
||||
for ( size_t i = start; i <= end; i++ )
|
||||
chars[i] = fillwith,
|
||||
vga[i] = entry,
|
||||
attr[i] = fillattr;
|
||||
{
|
||||
chars[i] = fillwith;
|
||||
vga[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
bool VGATextBuffer::GetCursorEnabled() const
|
||||
|
@ -212,7 +208,7 @@ bool VGATextBuffer::EmergencyRecoup()
|
|||
|
||||
void VGATextBuffer::EmergencyReset()
|
||||
{
|
||||
Fill(TextPos{0, 0}, TextPos{width-1, height-1}, TextChar{0, 0}, 0);
|
||||
Fill(TextPos{0, 0}, TextPos{width-1, height-1}, TextChar{0, 0, 0});
|
||||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
|
@ -32,18 +32,15 @@ namespace Sortix {
|
|||
class VGATextBuffer : public TextBuffer
|
||||
{
|
||||
public:
|
||||
VGATextBuffer(uint16_t* vga, TextChar* chars, uint16_t* attr, size_t width, size_t height);
|
||||
VGATextBuffer(uint16_t* vga, TextChar* chars, size_t width, size_t height);
|
||||
virtual ~VGATextBuffer();
|
||||
virtual size_t Width() const;
|
||||
virtual size_t Height() const;
|
||||
virtual TextChar GetChar(TextPos pos) const;
|
||||
virtual void SetChar(TextPos pos, TextChar c);
|
||||
virtual uint16_t GetCharAttr(TextPos pos) const ;
|
||||
virtual void SetCharAttr(TextPos pos, uint16_t attrval);
|
||||
virtual void Scroll(ssize_t off, TextChar fillwith);
|
||||
virtual void Move(TextPos to, TextPos from, size_t numchars);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||
uint16_t fillattr);
|
||||
virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
|
||||
virtual bool GetCursorEnabled() const;
|
||||
virtual void SetCursorEnabled(bool enablecursor);
|
||||
virtual TextPos GetCursorPos() const;
|
||||
|
@ -63,7 +60,6 @@ private:
|
|||
private:
|
||||
uint16_t* vga;
|
||||
TextChar* chars;
|
||||
uint16_t* attr;
|
||||
size_t width;
|
||||
size_t height;
|
||||
TextPos cursorpos;
|
||||
|
|
Loading…
Reference in a new issue