1
0
Fork 0
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:
Jonas 'Sortie' Termansen 2015-10-04 18:55:06 +02:00
parent 9297ff2a20
commit 8f233b4a10
9 changed files with 111 additions and 140 deletions

View file

@ -35,6 +35,10 @@
namespace Sortix { 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 struct TextPos
{ {
TextPos() { } TextPos() { }
@ -47,16 +51,20 @@ struct TextCharPOD
{ {
wchar_t c; wchar_t c;
uint8_t vgacolor; // Format of <sortix/vga.h> uint8_t vgacolor; // Format of <sortix/vga.h>
uint16_t attr;
}; };
struct TextChar struct TextChar
{ {
TextChar() { } TextChar() { }
TextChar(const TextCharPOD& o) : c(o.c), vgacolor(o.vgacolor) { } TextChar(const TextCharPOD& o) :
TextChar(wchar_t c, uint8_t vgacolor) : c(c), vgacolor(vgacolor) { } c(o.c), vgacolor(o.vgacolor), attr(o.attr) { }
operator TextCharPOD() { return TextCharPOD{c, vgacolor}; } 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; wchar_t c;
uint8_t vgacolor; // Format of <sortix/vga.h> uint8_t vgacolor; // Format of <sortix/vga.h>
uint16_t attr;
}; };
static inline bool IsTextPosBeforeTextPos(const TextPos& a, const TextPos& b) static inline bool IsTextPosBeforeTextPos(const TextPos& a, const TextPos& b)
@ -77,12 +85,9 @@ public:
virtual size_t Height() const = 0; virtual size_t Height() const = 0;
virtual TextChar GetChar(TextPos pos) const = 0; virtual TextChar GetChar(TextPos pos) const = 0;
virtual void SetChar(TextPos pos, TextChar c) = 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 Scroll(ssize_t off, TextChar fillwith) = 0;
virtual void Move(TextPos to, TextPos from, size_t numchars) = 0; virtual void Move(TextPos to, TextPos from, size_t numchars) = 0;
virtual void Fill(TextPos from, TextPos to, TextChar fillwith, virtual void Fill(TextPos from, TextPos to, TextChar fillwith) = 0;
uint16_t fillattr) = 0;
virtual bool GetCursorEnabled() const = 0; virtual bool GetCursorEnabled() const = 0;
virtual void SetCursorEnabled(bool enablecursor) = 0; virtual void SetCursorEnabled(bool enablecursor) = 0;
virtual TextPos GetCursorPos() const = 0; virtual TextPos GetCursorPos() const = 0;

View file

@ -63,7 +63,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
uint8_t* backbuf; uint8_t* backbuf;
uint8_t* font; uint8_t* font;
TextChar* chars; TextChar* chars;
uint16_t* attrs;
TextBufferCmd* queue; TextBufferCmd* queue;
LFBTextBuffer* ret; LFBTextBuffer* ret;
@ -75,10 +74,8 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
goto cleanup_backbuf; goto cleanup_backbuf;
if ( !(chars = new TextChar[columns * rows]) ) if ( !(chars = new TextChar[columns * rows]) )
goto cleanup_font; goto cleanup_font;
if ( !(attrs = new uint16_t[columns * rows]) )
goto cleanup_chars;
if ( !(queue = new TextBufferCmd[QUEUE_LENGTH]) ) if ( !(queue = new TextBufferCmd[QUEUE_LENGTH]) )
goto cleanup_attrs; goto cleanup_chars;
if ( !(ret = new LFBTextBuffer) ) if ( !(ret = new LFBTextBuffer) )
goto cleanup_queue; goto cleanup_queue;
@ -108,8 +105,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
ret->font = font; ret->font = font;
memset(chars, 0, sizeof(chars[0]) * columns * rows); memset(chars, 0, sizeof(chars[0]) * columns * rows);
ret->chars = chars; ret->chars = chars;
memset(attrs, 0, sizeof(attrs[0]) * columns * rows);
ret->attrs = attrs;
for ( size_t i = 0; i < 16UL; i++ ) for ( size_t i = 0; i < 16UL; i++ )
{ {
uint8_t r = i & 0b0100 ? (i & 0b1000 ? 255 : 191) : (i & 0b1000 ? 63 : 0); 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: cleanup_queue:
delete[] queue; delete[] queue;
cleanup_attrs:
delete[] attrs;
cleanup_chars: cleanup_chars:
delete[] chars; delete[] chars;
cleanup_font: cleanup_font:
@ -176,7 +169,6 @@ LFBTextBuffer::~LFBTextBuffer()
delete[] backbuf; delete[] backbuf;
delete[] font; delete[] font;
delete[] chars; delete[] chars;
delete[] attrs;
delete[] queue; delete[] queue;
} }
@ -220,6 +212,8 @@ void LFBTextBuffer::RenderChar(TextChar textchar, size_t posx, size_t posy)
return; return;
bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y; bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y;
uint8_t fgcoloridx = textchar.vgacolor >> 0 & 0x0F; uint8_t fgcoloridx = textchar.vgacolor >> 0 & 0x0F;
if ( textchar.attr & ATTR_BOLD )
fgcoloridx |= 0x08;
uint8_t bgcoloridx = textchar.vgacolor >> 4 & 0x0F; uint8_t bgcoloridx = textchar.vgacolor >> 4 & 0x0F;
uint32_t fgcolor = colors[fgcoloridx]; uint32_t fgcolor = colors[fgcoloridx];
uint32_t bgcolor = colors[bgcoloridx]; 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; 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; size_t pixely = posy * VGA_FONT_HEIGHT + y;
for ( size_t x = 0; x < VGA_FONT_WIDTH+1; x++ ) for ( size_t x = 0; x < VGA_FONT_WIDTH+1; x++ )
@ -378,7 +373,7 @@ TextChar LFBTextBuffer::GetChar(TextPos pos) const
((LFBTextBuffer*) this)->ResumeRendering(); ((LFBTextBuffer*) this)->ResumeRendering();
return ret; return ret;
} }
return {0, 0}; return {0, 0, 0};
} }
void LFBTextBuffer::SetChar(TextPos pos, TextChar c) void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
@ -393,30 +388,6 @@ void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
IssueCommand(&cmd); 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 bool LFBTextBuffer::GetCursorEnabled() const
{ {
((LFBTextBuffer*) this)->StopRendering(); ((LFBTextBuffer*) this)->StopRendering();
@ -485,8 +456,7 @@ void LFBTextBuffer::Move(TextPos to, TextPos from, size_t numchars)
IssueCommand(&cmd); IssueCommand(&cmd);
} }
void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith, void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith)
uint16_t fillattr)
{ {
from = CropPosition(from); from = CropPosition(from);
to = CropPosition(to); to = CropPosition(to);
@ -497,7 +467,6 @@ void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
cmd.to_x = to.x; cmd.to_x = to.x;
cmd.to_y = to.y; cmd.to_y = to.y;
cmd.c = fillwith; cmd.c = fillwith;
cmd.attr = fillattr;
IssueCommand(&cmd); 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}; TextPos fillto = neg ? TextPos{columns-1, rows-1} : TextPos{columns-1, absoff-1};
size_t scrollchars = columns * (rows-absoff); size_t scrollchars = columns * (rows-absoff);
DoMove(scrollto, scrollfrom, scrollchars); DoMove(scrollto, scrollfrom, scrollchars);
DoFill(fillfrom, fillto, entry, 0); DoFill(fillfrom, fillto, entry);
} }
void LFBTextBuffer::DoMove(TextPos to, TextPos from, size_t numchars) 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); size_t src = OffsetOfPos(from);
if ( dest < src ) if ( dest < src )
for ( size_t i = 0; i < numchars; i++ ) for ( size_t i = 0; i < numchars; i++ )
chars[dest + i] = chars[src + i], chars[dest + i] = chars[src + i];
attrs[dest + i] = attrs[src + i];
else if ( src < dest ) else if ( src < dest )
for ( size_t i = 0; i < numchars; i++ ) for ( size_t i = 0; i < numchars; i++ )
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i], chars[dest + numchars-1 - i] = chars[src + numchars-1 - i];
attrs[dest + numchars-1 - i] = attrs[src + numchars-1 - i];
} }
void LFBTextBuffer::DoFill(TextPos from, TextPos to, TextChar fillwith, void LFBTextBuffer::DoFill(TextPos from, TextPos to, TextChar fillwith)
uint16_t fillattr)
{ {
size_t start = OffsetOfPos(from); size_t start = OffsetOfPos(from);
size_t end = OffsetOfPos(to); size_t end = OffsetOfPos(to);
for ( size_t i = start; i <= end; i++ ) for ( size_t i = start; i <= end; i++ )
chars[i] = fillwith, chars[i] = fillwith;
attrs[i] = fillattr;
} }
bool LFBTextBuffer::IsCommandIdempotent(const TextBufferCmd* cmd) const 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_SYNC: return true;
case TEXTBUFCMD_PAUSE: return true; case TEXTBUFCMD_PAUSE: return true;
case TEXTBUFCMD_CHAR: return true; case TEXTBUFCMD_CHAR: return true;
case TEXTBUFCMD_ATTR: return true;
case TEXTBUFCMD_CURSOR_SET_ENABLED: return true; case TEXTBUFCMD_CURSOR_SET_ENABLED: return true;
case TEXTBUFCMD_CURSOR_MOVE: return true; case TEXTBUFCMD_CURSOR_MOVE: return true;
case TEXTBUFCMD_MOVE: return false; case TEXTBUFCMD_MOVE: return false;
@ -586,11 +550,6 @@ void LFBTextBuffer::ExecuteCommand(TextBufferCmd* cmd,
if ( IsTextPosAfterTextPos(pos, render_to) ) if ( IsTextPosAfterTextPos(pos, render_to) )
render_to = pos; render_to = pos;
} break; } break;
case TEXTBUFCMD_ATTR:
{
TextPos pos(cmd->x, cmd->y);
attrs[pos.y * columns + pos.x] = cmd->attr;
} break;
case TEXTBUFCMD_CURSOR_SET_ENABLED: case TEXTBUFCMD_CURSOR_SET_ENABLED:
if ( cmd->b != cursorenabled ) if ( cmd->b != cursorenabled )
{ {
@ -633,7 +592,7 @@ void LFBTextBuffer::ExecuteCommand(TextBufferCmd* cmd,
{ {
TextPos from(cmd->from_x, cmd->from_y); TextPos from(cmd->from_x, cmd->from_y);
TextPos to(cmd->to_x, cmd->to_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) ) if ( IsTextPosBeforeTextPos(from, render_from) )
render_from = from; render_from = from;
if ( IsTextPosAfterTextPos(to, render_to) ) if ( IsTextPosAfterTextPos(to, render_to) )
@ -778,7 +737,7 @@ void LFBTextBuffer::EmergencyReset()
{ {
// TODO: Reset everything here! // 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}); SetCursorPos(TextPos{0, 0});
} }

View file

@ -36,7 +36,6 @@ enum TextBufferCmdType
TEXTBUFCMD_SYNC, TEXTBUFCMD_SYNC,
TEXTBUFCMD_PAUSE, TEXTBUFCMD_PAUSE,
TEXTBUFCMD_CHAR, TEXTBUFCMD_CHAR,
TEXTBUFCMD_ATTR,
TEXTBUFCMD_CURSOR_SET_ENABLED, TEXTBUFCMD_CURSOR_SET_ENABLED,
TEXTBUFCMD_CURSOR_MOVE, TEXTBUFCMD_CURSOR_MOVE,
TEXTBUFCMD_MOVE, TEXTBUFCMD_MOVE,
@ -55,7 +54,7 @@ struct TextBufferCmd
union union
{ {
bool b; bool b;
struct { TextCharPOD c; uint16_t attr; }; TextCharPOD c;
size_t val; size_t val;
}; };
}; };
@ -74,12 +73,9 @@ public:
virtual size_t Height() const; virtual size_t Height() const;
virtual TextChar GetChar(TextPos pos) const; virtual TextChar GetChar(TextPos pos) const;
virtual void SetChar(TextPos pos, TextChar c); 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 Scroll(ssize_t off, TextChar fillwith);
virtual void Move(TextPos to, TextPos from, size_t numchars); virtual void Move(TextPos to, TextPos from, size_t numchars);
virtual void Fill(TextPos from, TextPos to, TextChar fillwith, virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
uint16_t fillattr);
virtual bool GetCursorEnabled() const; virtual bool GetCursorEnabled() const;
virtual void SetCursorEnabled(bool enablecursor); virtual void SetCursorEnabled(bool enablecursor);
virtual TextPos GetCursorPos() const; virtual TextPos GetCursorPos() const;
@ -104,7 +100,7 @@ private:
TextPos AddToPosition(TextPos pos, size_t count); TextPos AddToPosition(TextPos pos, size_t count);
void DoScroll(ssize_t off, TextChar entry); void DoScroll(ssize_t off, TextChar entry);
void DoMove(TextPos to, TextPos from, size_t numchars); 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 IssueCommand(TextBufferCmd* cmd);
void StopRendering(); void StopRendering();
void ResumeRendering(); void ResumeRendering();
@ -135,7 +131,6 @@ private:
uint8_t* backbuf; uint8_t* backbuf;
uint8_t* font; uint8_t* font;
TextChar* chars; TextChar* chars;
uint16_t* attrs;
size_t columns; size_t columns;
size_t rows; size_t rows;
size_t pixelsx; size_t pixelsx;

View file

@ -176,12 +176,10 @@ void Init(multiboot_info_t* bootinfo)
uint16_t* const VGAFB = (uint16_t*) 0xB8000; uint16_t* const VGAFB = (uint16_t*) 0xB8000;
const size_t VGA_WIDTH = 80; const size_t VGA_WIDTH = 80;
const size_t VGA_HEIGHT = 25; 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]; TextChar* vga_chars_buffer = new TextChar[VGA_WIDTH * VGA_HEIGHT];
if ( !vga_attr_buffer || !vga_chars_buffer ) if ( !vga_chars_buffer )
Panic(oom_msg); Panic(oom_msg);
textbuf = new VGATextBuffer(VGAFB, vga_chars_buffer, vga_attr_buffer, textbuf = new VGATextBuffer(VGAFB, vga_chars_buffer, VGA_WIDTH, VGA_HEIGHT);
VGA_WIDTH, VGA_HEIGHT);
if ( !textbuf ) if ( !textbuf )
Panic(oom_msg); Panic(oom_msg);
} }

View file

@ -228,7 +228,7 @@ void LogTerminal::ProcessKeystroke(int kbkey)
(!wasuni || termmode & TERMMODE_UNICODE) && (!wasuni || termmode & TERMMODE_UNICODE) &&
termmode & TERMMODE_ECHO && termmode & TERMMODE_ECHO &&
wasuni ) wasuni )
Log::Print("\b"); Log::Print("\b \b");
goto c_w_delete_more; goto c_w_delete_more;
} }
@ -243,7 +243,7 @@ void LogTerminal::ProcessKeystroke(int kbkey)
(!wasuni || termmode & TERMMODE_UNICODE) && (!wasuni || termmode & TERMMODE_UNICODE) &&
termmode & TERMMODE_ECHO && termmode & TERMMODE_ECHO &&
wasuni ) wasuni )
Log::Print("\b"); Log::Print("\b \b");
} }
return; return;
} }
@ -289,7 +289,7 @@ void LogTerminal::QueueUnicode(uint32_t unicode)
if ( waskbkey && !kbkeymode ) { continue; } if ( waskbkey && !kbkeymode ) { continue; }
if ( wasuni && !unicodemode ) { continue; } if ( wasuni && !unicodemode ) { continue; }
if ( !echomode ) { return; } if ( !echomode ) { return; }
if ( wasuni ) { Log::Print("\b"); } if ( wasuni ) { Log::Print("\b \b"); }
return; return;
} }
@ -308,7 +308,10 @@ void LogTerminal::QueueUnicode(uint32_t unicode)
memset(&ps, 0, sizeof(ps)); memset(&ps, 0, sizeof(ps));
char utf8buf[MB_CUR_MAX]; char utf8buf[MB_CUR_MAX];
size_t num_bytes = wcrtomb(utf8buf, (wchar_t) unicode, &ps); size_t num_bytes = wcrtomb(utf8buf, (wchar_t) unicode, &ps);
Log::PrintData(utf8buf, num_bytes); if ( num_bytes == 1 && utf8buf[0] == '\b' )
Log::PrintData("\b \b", 3);
else
Log::PrintData(utf8buf, num_bytes);
} }
bool commit = !linemode || wasenter; bool commit = !linemode || wasenter;

View file

@ -36,8 +36,7 @@
namespace Sortix { namespace Sortix {
const uint16_t DEFAULT_COLOR = COLOR8_LIGHT_GREY << 0U | COLOR8_BLACK << 4U; static const uint16_t DEFAULT_COLOR = COLOR8_LIGHT_GREY | COLOR8_BLACK << 4;
const uint16_t ATTR_CHAR = 1U << 0U;
TextTerminal::TextTerminal(TextBufferHandle* textbufhandle) TextTerminal::TextTerminal(TextBufferHandle* textbufhandle)
{ {
@ -53,6 +52,7 @@ TextTerminal::~TextTerminal()
void TextTerminal::Reset() void TextTerminal::Reset()
{ {
next_attr = 0;
vgacolor = DEFAULT_COLOR; vgacolor = DEFAULT_COLOR;
column = line = 0; column = line = 0;
ansisavedposx = ansisavedposy = 0; ansisavedposx = ansisavedposy = 0;
@ -60,8 +60,8 @@ void TextTerminal::Reset()
TextBuffer* textbuf = textbufhandle->Acquire(); TextBuffer* textbuf = textbufhandle->Acquire();
TextPos fillfrom(0, 0); TextPos fillfrom(0, 0);
TextPos fillto(textbuf->Width()-1, textbuf->Height()-1); TextPos fillto(textbuf->Width()-1, textbuf->Height()-1);
TextChar fillwith(' ', vgacolor); TextChar fillwith(' ', vgacolor, 0);
textbuf->Fill(fillfrom, fillto, fillwith, 0); textbuf->Fill(fillfrom, fillto, fillwith);
textbuf->SetCursorEnabled(true); textbuf->SetCursorEnabled(true);
UpdateCursor(textbuf); UpdateCursor(textbuf);
textbufhandle->Release(textbuf); textbufhandle->Release(textbuf);
@ -278,9 +278,9 @@ void TextTerminal::PutChar(TextBuffer* textbuf, char c)
if ( textbuf->Width() <= column ) if ( textbuf->Width() <= column )
Newline(textbuf); Newline(textbuf);
TextPos pos(column++, line); TextPos pos(column++, line);
TextChar tc(wc, vgacolor); TextChar tc(wc, vgacolor, ATTR_CHAR | next_attr);
textbuf->SetChar(pos, tc); textbuf->SetChar(pos, tc);
textbuf->SetCharAttr(pos, ATTR_CHAR); next_attr = 0;
} }
void TextTerminal::UpdateCursor(TextBuffer* textbuf) void TextTerminal::UpdateCursor(TextBuffer* textbuf)
@ -290,13 +290,21 @@ void TextTerminal::UpdateCursor(TextBuffer* textbuf)
void TextTerminal::Newline(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; column = 0;
if ( line < textbuf->Height()-1 ) if ( line < textbuf->Height()-1 )
line++; line++;
else else
textbuf->Scroll(1, TextChar(' ', vgacolor)), {
textbuf->Scroll(1, TextChar(' ', vgacolor, 0));
line = textbuf->Height()-1; line = textbuf->Height()-1;
}
} }
static TextPos DecrementTextPos(TextBuffer* textbuf, TextPos pos) static TextPos DecrementTextPos(TextBuffer* textbuf, TextPos pos)
@ -314,10 +322,16 @@ void TextTerminal::Backspace(TextBuffer* textbuf)
while ( pos.x || pos.y ) while ( pos.x || pos.y )
{ {
pos = DecrementTextPos(textbuf, pos); pos = DecrementTextPos(textbuf, pos);
uint16_t attr = textbuf->GetCharAttr(pos); TextChar tc = textbuf->GetChar(pos);
textbuf->SetChar(pos, TextChar(' ', vgacolor)); next_attr = tc.attr & (ATTR_BOLD | ATTR_UNDERLINE);
textbuf->SetCharAttr(pos, attr & ~ATTR_CHAR); if ( tc.c == L'_' )
if ( attr & ATTR_CHAR ) 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; break;
} }
column = pos.x; column = pos.x;
@ -328,17 +342,21 @@ void TextTerminal::Tab(TextBuffer* textbuf)
{ {
if ( column == textbuf->Width() ) if ( column == textbuf->Width() )
Newline(textbuf); Newline(textbuf);
// TODO: This does not work correctly if the text buffer width is not a unsigned int count = 8 - (column % 8);
// multiple of four and the column is near the edge. for ( unsigned int i = 0; i < count; i++ )
unsigned until = 8 - (column % 8); {
textbuf->SetCharAttr(TextPos(column, line), ATTR_CHAR); if ( column == textbuf->Width() )
while ( (until--) != 0 ) break;
textbuf->SetChar(TextPos(column++, line), TextChar(' ', vgacolor)); 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. // TODO: This implementation of the 'Ansi Escape Codes' is incomplete and hacky.
void TextTerminal::AnsiReset() void TextTerminal::AnsiReset()
{ {
next_attr = 0;
ansiusedparams = 0; ansiusedparams = 0;
currentparamindex = 0; currentparamindex = 0;
ansiparams[0] = 0; ansiparams[0] = 0;
@ -501,7 +519,7 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
from = TextPos{0, 0}, from = TextPos{0, 0},
to = TextPos{width-1, height-1}; to = TextPos{width-1, height-1};
textbuf->Fill(from, to, TextChar(' ', vgacolor), 0); textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
} break; } break;
case 'K': // Erase parts of the current line. case 'K': // Erase parts of the current line.
{ {
@ -521,16 +539,16 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
from = TextPos{0, line}, from = TextPos{0, line},
to = TextPos{width-1, line}; to = TextPos{width-1, line};
textbuf->Fill(from, to, TextChar(' ', vgacolor), 0); textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
} break; } break;
case 'S': // Scroll a line up and place a new line at the buttom. 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; line = height-1;
} break; } break;
case 'T': // Scroll a line up and place a new line at the top. 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; line = 0;
} break; } break;
case 'm': // Change how the text is rendered. case 'm': // Change how the text is rendered.

View file

@ -69,6 +69,7 @@ private:
mbstate_t ps; mbstate_t ps;
mutable TextBufferHandle* textbufhandle; mutable TextBufferHandle* textbufhandle;
mutable kthread_mutex_t termlock; mutable kthread_mutex_t termlock;
uint16_t next_attr;
uint8_t vgacolor; uint8_t vgacolor;
unsigned column; unsigned column;
unsigned line; unsigned line;

View file

@ -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. This file is part of Sortix.
@ -34,12 +34,11 @@
namespace Sortix { 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) size_t width, size_t height)
{ {
this->vga = vga; this->vga = vga;
this->chars = chars; this->chars = chars;
this->attr = attr;
this->width = width; this->width = width;
this->height = height; this->height = height;
cursorpos = {0, 0}; cursorpos = {0, 0};
@ -56,6 +55,8 @@ static uint16_t CharToTextEntry(TextChar c)
int remap = VGA::MapWideToVGAFont(c.c); int remap = VGA::MapWideToVGAFont(c.c);
if ( remap < 0 ) if ( remap < 0 )
remap = 0 /* replacement character */; remap = 0 /* replacement character */;
if ( c.attr & ATTR_BOLD )
c.vgacolor |= 0x08;
return (uint16_t) remap | (uint16_t) c.vgacolor << 8U; return (uint16_t) remap | (uint16_t) c.vgacolor << 8U;
} }
@ -92,27 +93,16 @@ TextChar VGATextBuffer::GetChar(TextPos pos) const
{ {
if ( UsablePosition(pos) ) if ( UsablePosition(pos) )
return chars[OffsetOfPos(pos)]; return chars[OffsetOfPos(pos)];
return {0, 0}; return {0, 0, 0};
} }
void VGATextBuffer::SetChar(TextPos pos, TextChar c) void VGATextBuffer::SetChar(TextPos pos, TextChar c)
{ {
if ( UsablePosition(pos) ) if ( UsablePosition(pos) )
chars[OffsetOfPos(pos)] = c, {
chars[OffsetOfPos(pos)] = c;
vga[OffsetOfPos(pos)] = CharToTextEntry(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) 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}; TextPos fillto = neg ? TextPos{width-1, height-1} : TextPos{width-1, absoff-1};
size_t scrollchars = width * (height-absoff); size_t scrollchars = width * (height-absoff);
Move(scrollto, scrollfrom, scrollchars); Move(scrollto, scrollfrom, scrollchars);
Fill(fillfrom, fillto, fillwith, 0); Fill(fillfrom, fillto, fillwith);
} }
void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars) 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 dest = OffsetOfPos(CropPosition(to));
size_t src = OffsetOfPos(CropPosition(from)); size_t src = OffsetOfPos(CropPosition(from));
if ( dest < src ) if ( dest < src )
{
for ( size_t i = 0; i < numchars; i++ ) for ( size_t i = 0; i < numchars; i++ )
chars[dest + i] = chars[src + i], {
vga[dest + i] = CharToTextEntry(chars[dest + i]), chars[dest + i] = chars[src + i];
attr[dest + i] = attr[src + i]; vga[dest + i] = CharToTextEntry(chars[dest + i]);
}
}
else if ( src < dest ) else if ( src < dest )
{
for ( size_t i = 0; i < numchars; i++ ) 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]), chars[dest + numchars-1 - i] = chars[src + numchars-1 - i];
attr[dest + numchars-1 - i] = attr[src + numchars-1 - i]; vga[dest + numchars-1 - i] = CharToTextEntry(chars[dest + numchars-1 - i]);
}
}
} }
void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith, void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith)
uint16_t fillattr)
{ {
from = CropPosition(from); from = CropPosition(from);
to = CropPosition(to); to = CropPosition(to);
size_t start = OffsetOfPos(from); size_t start = OffsetOfPos(from);
size_t end = OffsetOfPos(to); size_t end = OffsetOfPos(to);
size_t entry = CharToTextEntry(fillwith); uint16_t entry = CharToTextEntry(fillwith);
for ( size_t i = start; i <= end; i++ ) for ( size_t i = start; i <= end; i++ )
chars[i] = fillwith, {
vga[i] = entry, chars[i] = fillwith;
attr[i] = fillattr; vga[i] = entry;
}
} }
bool VGATextBuffer::GetCursorEnabled() const bool VGATextBuffer::GetCursorEnabled() const
@ -212,7 +208,7 @@ bool VGATextBuffer::EmergencyRecoup()
void VGATextBuffer::EmergencyReset() 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}); SetCursorPos(TextPos{0, 0});
} }

View file

@ -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. This file is part of Sortix.
@ -32,18 +32,15 @@ namespace Sortix {
class VGATextBuffer : public TextBuffer class VGATextBuffer : public TextBuffer
{ {
public: 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 ~VGATextBuffer();
virtual size_t Width() const; virtual size_t Width() const;
virtual size_t Height() const; virtual size_t Height() const;
virtual TextChar GetChar(TextPos pos) const; virtual TextChar GetChar(TextPos pos) const;
virtual void SetChar(TextPos pos, TextChar c); 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 Scroll(ssize_t off, TextChar fillwith);
virtual void Move(TextPos to, TextPos from, size_t numchars); virtual void Move(TextPos to, TextPos from, size_t numchars);
virtual void Fill(TextPos from, TextPos to, TextChar fillwith, virtual void Fill(TextPos from, TextPos to, TextChar fillwith);
uint16_t fillattr);
virtual bool GetCursorEnabled() const; virtual bool GetCursorEnabled() const;
virtual void SetCursorEnabled(bool enablecursor); virtual void SetCursorEnabled(bool enablecursor);
virtual TextPos GetCursorPos() const; virtual TextPos GetCursorPos() const;
@ -63,7 +60,6 @@ private:
private: private:
uint16_t* vga; uint16_t* vga;
TextChar* chars; TextChar* chars;
uint16_t* attr;
size_t width; size_t width;
size_t height; size_t height;
TextPos cursorpos; TextPos cursorpos;