mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Support 8-bit/24-bit color and more escape codes in the graphical console.
The console has gained these escape codes: - Set color to any of 256 entries in the palette. - Set color to any 24-bit RGB value. - Inverse mode. - Bold mode. - Underline mode. - Move cursor to line N. - \a is now ignored. The effectively unused ATTR_CHAR has been removed. Parsing of escape codes has been improved. The graphical palette has been changed to the tango colors, which makes Sortix look a bit differently. Some user-space programs have been changed to use different colors that look better under the new palette. Remove const from methods that weren't really const and remove mutable keyword workaround.
This commit is contained in:
parent
ce54be34da
commit
0bb608b09e
10 changed files with 560 additions and 99 deletions
|
@ -30,7 +30,7 @@
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
static const uint16_t ATTR_CHAR = 1 << 0;
|
||||
static const uint16_t ATTR_INVERSE = 1 << 0;
|
||||
static const uint16_t ATTR_BOLD = 1 << 1;
|
||||
static const uint16_t ATTR_UNDERLINE = 1 << 2;
|
||||
|
||||
|
@ -47,19 +47,23 @@ struct TextCharPOD
|
|||
wchar_t c;
|
||||
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||
uint16_t attr;
|
||||
uint32_t fg;
|
||||
uint32_t bg;
|
||||
};
|
||||
|
||||
struct TextChar
|
||||
{
|
||||
TextChar() { }
|
||||
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}; }
|
||||
c(o.c), vgacolor(o.vgacolor), attr(o.attr), fg(o.fg), bg(o.bg) { }
|
||||
TextChar(wchar_t c, uint8_t vgacolor, uint16_t attr, uint32_t fg, uint32_t bg) :
|
||||
c(c), vgacolor(vgacolor), attr(attr), fg(fg), bg(bg) { }
|
||||
operator TextCharPOD() { return TextCharPOD{c, vgacolor, attr, fg, bg}; }
|
||||
wchar_t c;
|
||||
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||
uint16_t attr;
|
||||
uint32_t fg; // 32-bit foreground color.
|
||||
uint32_t bg; // 32-bit background color.
|
||||
};
|
||||
|
||||
static inline bool IsTextPosBeforeTextPos(const TextPos& a, const TextPos& b)
|
||||
|
|
|
@ -33,8 +33,20 @@
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
static uint32_t ColorFromRGB(uint8_t r, uint8_t g, uint8_t b)
|
||||
static uint32_t boldify(uint32_t color)
|
||||
{
|
||||
int b = color >> 0 & 0xFF;
|
||||
int g = color >> 8 & 0xFF;
|
||||
int r = color >> 16 & 0xFF;
|
||||
b += 63;
|
||||
if ( 255 < b )
|
||||
b = 255;
|
||||
g += 63;
|
||||
if ( 255 < g )
|
||||
g = 255;
|
||||
r += 63;
|
||||
if ( 255 < r )
|
||||
r = 255;
|
||||
return (uint32_t) b << 0 | (uint32_t) g << 8 | (uint32_t) r << 16;
|
||||
}
|
||||
|
||||
|
@ -96,13 +108,6 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
|||
ret->font = font;
|
||||
memset(chars, 0, sizeof(chars[0]) * columns * rows);
|
||||
ret->chars = chars;
|
||||
for ( size_t i = 0; i < 16UL; i++ )
|
||||
{
|
||||
uint8_t r = i & 0b0100 ? (i & 0b1000 ? 255 : 191) : (i & 0b1000 ? 63 : 0);
|
||||
uint8_t g = i & 0b0010 ? (i & 0b1000 ? 255 : 191) : (i & 0b1000 ? 63 : 0);
|
||||
uint8_t b = i & 0b0001 ? (i & 0b1000 ? 255 : 191) : (i & 0b1000 ? 63 : 0);
|
||||
ret->colors[i] = ColorFromRGB(r, g, b);
|
||||
}
|
||||
ret->cursorenabled = true;
|
||||
ret->cursorpos = TextPos(0, 0);
|
||||
ret->emergency_state = false;
|
||||
|
@ -216,12 +221,10 @@ void LFBTextBuffer::RenderChar(TextChar textchar, size_t posx, size_t posy)
|
|||
if ( VGA_FONT_WIDTH != 8UL )
|
||||
return;
|
||||
bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y;
|
||||
uint8_t fgcoloridx = textchar.vgacolor >> 0 & 0x0F;
|
||||
uint32_t fgcolor = textchar.fg;
|
||||
uint32_t bgcolor = textchar.bg;
|
||||
if ( textchar.attr & ATTR_BOLD )
|
||||
fgcoloridx |= 0x08;
|
||||
uint8_t bgcoloridx = textchar.vgacolor >> 4 & 0x0F;
|
||||
uint32_t fgcolor = colors[fgcoloridx];
|
||||
uint32_t bgcolor = colors[bgcoloridx];
|
||||
fgcolor = boldify(fgcolor);
|
||||
int remap = VGA::MapWideToVGAFont(textchar.c);
|
||||
const uint8_t* charfont = VGA::GetCharacterFont(font, remap);
|
||||
size_t pixelyoff = rows * VGA_FONT_HEIGHT;
|
||||
|
@ -408,7 +411,7 @@ TextChar LFBTextBuffer::GetChar(TextPos pos)
|
|||
ResumeRendering();
|
||||
return ret;
|
||||
}
|
||||
return {0, 0, 0};
|
||||
return {0, 0, 0, 0, 0};
|
||||
}
|
||||
|
||||
void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
|
||||
|
@ -781,7 +784,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, 0, 0});
|
||||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,6 @@ private:
|
|||
size_t pixelsx;
|
||||
size_t pixelsy;
|
||||
size_t scansize;
|
||||
uint32_t colors[16UL];
|
||||
uint32_t lfbformat;
|
||||
size_t bytes_per_pixel;
|
||||
bool cursorenabled;
|
||||
|
|
283
kernel/palette.h
Normal file
283
kernel/palette.h
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* palette.h
|
||||
* Console color palette, matches the xterm palette with tango colors.
|
||||
*/
|
||||
|
||||
#ifndef PALETTE_H
|
||||
#define PALETTE_H
|
||||
|
||||
static const uint32_t palette[256] =
|
||||
{
|
||||
0x000000,
|
||||
0xcc0000,
|
||||
0x3e9a06,
|
||||
0xc4a000,
|
||||
0x3465a4,
|
||||
0x75507b,
|
||||
0x06989a,
|
||||
0xbfbfbf,
|
||||
0x555753,
|
||||
0xef2929,
|
||||
0x8ae234,
|
||||
0xfce94f,
|
||||
0x729fcf,
|
||||
0xad7fa8,
|
||||
0x34e2e2,
|
||||
0xffffff,
|
||||
0x000000,
|
||||
0x00005f,
|
||||
0x000087,
|
||||
0x0000af,
|
||||
0x0000d7,
|
||||
0x0000ff,
|
||||
0x005f00,
|
||||
0x005f5f,
|
||||
0x005f87,
|
||||
0x005faf,
|
||||
0x005fd7,
|
||||
0x005fff,
|
||||
0x008700,
|
||||
0x00875f,
|
||||
0x008787,
|
||||
0x0087af,
|
||||
0x0087d7,
|
||||
0x0087ff,
|
||||
0x00af00,
|
||||
0x00af5f,
|
||||
0x00af87,
|
||||
0x00afaf,
|
||||
0x00afd7,
|
||||
0x00afff,
|
||||
0x00d700,
|
||||
0x00d75f,
|
||||
0x00d787,
|
||||
0x00d7af,
|
||||
0x00d7d7,
|
||||
0x00d7ff,
|
||||
0x00ff00,
|
||||
0x00ff5f,
|
||||
0x00ff87,
|
||||
0x00ffaf,
|
||||
0x00ffd7,
|
||||
0x00ffff,
|
||||
0x5f0000,
|
||||
0x5f005f,
|
||||
0x5f0087,
|
||||
0x5f00af,
|
||||
0x5f00d7,
|
||||
0x5f00ff,
|
||||
0x5f5f00,
|
||||
0x5f5f5f,
|
||||
0x5f5f87,
|
||||
0x5f5faf,
|
||||
0x5f5fd7,
|
||||
0x5f5fff,
|
||||
0x5f8700,
|
||||
0x5f875f,
|
||||
0x5f8787,
|
||||
0x5f87af,
|
||||
0x5f87d7,
|
||||
0x5f87ff,
|
||||
0x5faf00,
|
||||
0x5faf5f,
|
||||
0x5faf87,
|
||||
0x5fafaf,
|
||||
0x5fafd7,
|
||||
0x5fafff,
|
||||
0x5fd700,
|
||||
0x5fd75f,
|
||||
0x5fd787,
|
||||
0x5fd7af,
|
||||
0x5fd7d7,
|
||||
0x5fd7ff,
|
||||
0x5fff00,
|
||||
0x5fff5f,
|
||||
0x5fff87,
|
||||
0x5fffaf,
|
||||
0x5fffd7,
|
||||
0x5fffff,
|
||||
0x870000,
|
||||
0x87005f,
|
||||
0x870087,
|
||||
0x8700af,
|
||||
0x8700d7,
|
||||
0x8700ff,
|
||||
0x875f00,
|
||||
0x875f5f,
|
||||
0x875f87,
|
||||
0x875faf,
|
||||
0x875fd7,
|
||||
0x875fff,
|
||||
0x878700,
|
||||
0x87875f,
|
||||
0x878787,
|
||||
0x8787af,
|
||||
0x8787d7,
|
||||
0x8787ff,
|
||||
0x87af00,
|
||||
0x87af5f,
|
||||
0x87af87,
|
||||
0x87afaf,
|
||||
0x87afd7,
|
||||
0x87afff,
|
||||
0x87d700,
|
||||
0x87d75f,
|
||||
0x87d787,
|
||||
0x87d7af,
|
||||
0x87d7d7,
|
||||
0x87d7ff,
|
||||
0x87ff00,
|
||||
0x87ff5f,
|
||||
0x87ff87,
|
||||
0x87ffaf,
|
||||
0x87ffd7,
|
||||
0x87ffff,
|
||||
0xaf0000,
|
||||
0xaf005f,
|
||||
0xaf0087,
|
||||
0xaf00af,
|
||||
0xaf00d7,
|
||||
0xaf00ff,
|
||||
0xaf5f00,
|
||||
0xaf5f5f,
|
||||
0xaf5f87,
|
||||
0xaf5faf,
|
||||
0xaf5fd7,
|
||||
0xaf5fff,
|
||||
0xaf8700,
|
||||
0xaf875f,
|
||||
0xaf8787,
|
||||
0xaf87af,
|
||||
0xaf87d7,
|
||||
0xaf87ff,
|
||||
0xafaf00,
|
||||
0xafaf5f,
|
||||
0xafaf87,
|
||||
0xafafaf,
|
||||
0xafafd7,
|
||||
0xafafff,
|
||||
0xafd700,
|
||||
0xafd75f,
|
||||
0xafd787,
|
||||
0xafd7af,
|
||||
0xafd7d7,
|
||||
0xafd7ff,
|
||||
0xafff00,
|
||||
0xafff5f,
|
||||
0xafff87,
|
||||
0xafffaf,
|
||||
0xafffd7,
|
||||
0xafffff,
|
||||
0xd70000,
|
||||
0xd7005f,
|
||||
0xd70087,
|
||||
0xd700af,
|
||||
0xd700d7,
|
||||
0xd700ff,
|
||||
0xd75f00,
|
||||
0xd75f5f,
|
||||
0xd75f87,
|
||||
0xd75faf,
|
||||
0xd75fd7,
|
||||
0xd75fff,
|
||||
0xd78700,
|
||||
0xd7875f,
|
||||
0xd78787,
|
||||
0xd787af,
|
||||
0xd787d7,
|
||||
0xd787ff,
|
||||
0xd7af00,
|
||||
0xd7af5f,
|
||||
0xd7af87,
|
||||
0xd7afaf,
|
||||
0xd7afd7,
|
||||
0xd7afff,
|
||||
0xd7d700,
|
||||
0xd7d75f,
|
||||
0xd7d787,
|
||||
0xd7d7af,
|
||||
0xd7d7d7,
|
||||
0xd7d7ff,
|
||||
0xd7ff00,
|
||||
0xd7ff5f,
|
||||
0xd7ff87,
|
||||
0xd7ffaf,
|
||||
0xd7ffd7,
|
||||
0xd7ffff,
|
||||
0xff0000,
|
||||
0xff005f,
|
||||
0xff0087,
|
||||
0xff00af,
|
||||
0xff00d7,
|
||||
0xff00ff,
|
||||
0xff5f00,
|
||||
0xff5f5f,
|
||||
0xff5f87,
|
||||
0xff5faf,
|
||||
0xff5fd7,
|
||||
0xff5fff,
|
||||
0xff8700,
|
||||
0xff875f,
|
||||
0xff8787,
|
||||
0xff87af,
|
||||
0xff87d7,
|
||||
0xff87ff,
|
||||
0xffaf00,
|
||||
0xffaf5f,
|
||||
0xffaf87,
|
||||
0xffafaf,
|
||||
0xffafd7,
|
||||
0xffafff,
|
||||
0xffd700,
|
||||
0xffd75f,
|
||||
0xffd787,
|
||||
0xffd7af,
|
||||
0xffd7d7,
|
||||
0xffd7ff,
|
||||
0xffff00,
|
||||
0xffff5f,
|
||||
0xffff87,
|
||||
0xffffaf,
|
||||
0xffffd7,
|
||||
0xffffff,
|
||||
0x080808,
|
||||
0x121212,
|
||||
0x1c1c1c,
|
||||
0x262626,
|
||||
0x303030,
|
||||
0x3a3a3a,
|
||||
0x444444,
|
||||
0x4e4e4e,
|
||||
0x585858,
|
||||
0x626262,
|
||||
0x6c6c6c,
|
||||
0x767676,
|
||||
0x808080,
|
||||
0x8a8a8a,
|
||||
0x949494,
|
||||
0x9e9e9e,
|
||||
0xa8a8a8,
|
||||
0xb2b2b2,
|
||||
0xbcbcbc,
|
||||
0xc6c6c6,
|
||||
0xd0d0d0,
|
||||
0xdadada,
|
||||
0xe4e4e4,
|
||||
0xeeeeee,
|
||||
};
|
||||
|
||||
#endif
|
|
@ -138,7 +138,7 @@ void TextBufferHandle::FinishReplace(TextBuffer* newtextbuf)
|
|||
size_t src_x = dst_x;
|
||||
TextPos src_pos{src_x, src_y};
|
||||
TextPos dst_pos{dst_x, dst_y};
|
||||
TextChar tc{0, 0, 0};
|
||||
TextChar tc{0, 0, 0, 0, 0};
|
||||
if ( src_x < src_width && src_y < src_height )
|
||||
tc = textbuf->GetChar(src_pos);
|
||||
else if ( src_width && src_height )
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -27,11 +27,19 @@
|
|||
#include <sortix/kernel/refcount.h>
|
||||
#include <sortix/kernel/textbuffer.h>
|
||||
|
||||
#include "palette.h"
|
||||
#include "textterminal.h"
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
static const uint16_t DEFAULT_COLOR = COLOR8_LIGHT_GREY | COLOR8_BLACK << 4;
|
||||
static const uint16_t DEFAULT_VGACOLOR = COLOR8_LIGHT_GREY | COLOR8_BLACK << 4;
|
||||
static const unsigned int DEFAULT_FOREGROUND = 7;
|
||||
static const unsigned int DEFAULT_BACKGROUND = 0;
|
||||
|
||||
static uint32_t ColorFromRGB(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return (uint32_t) b << 0 | (uint32_t) g << 8 | (uint32_t) r << 16;
|
||||
}
|
||||
|
||||
TextTerminal::TextTerminal(TextBufferHandle* textbufhandle)
|
||||
{
|
||||
|
@ -47,15 +55,18 @@ TextTerminal::~TextTerminal()
|
|||
|
||||
void TextTerminal::Reset()
|
||||
{
|
||||
attr = 0;
|
||||
next_attr = 0;
|
||||
vgacolor = DEFAULT_COLOR;
|
||||
vgacolor = DEFAULT_VGACOLOR;
|
||||
fgcolor = palette[DEFAULT_FOREGROUND];
|
||||
bgcolor = palette[DEFAULT_BACKGROUND];
|
||||
column = line = 0;
|
||||
ansisavedposx = ansisavedposy = 0;
|
||||
ansimode = NONE;
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
TextPos fillfrom(0, 0);
|
||||
TextPos fillto(textbuf->Width()-1, textbuf->Height()-1);
|
||||
TextChar fillwith(' ', vgacolor, 0);
|
||||
TextChar fillwith(' ', vgacolor, 0, fgcolor, bgcolor);
|
||||
textbuf->Fill(fillfrom, fillto, fillwith);
|
||||
textbuf->SetCursorEnabled(true);
|
||||
UpdateCursor(textbuf);
|
||||
|
@ -88,7 +99,7 @@ size_t TextTerminal::PrintRaw(const char* string, size_t stringlen)
|
|||
return stringlen;
|
||||
}
|
||||
|
||||
size_t TextTerminal::Width() const
|
||||
size_t TextTerminal::Width()
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
|
@ -97,7 +108,7 @@ size_t TextTerminal::Width() const
|
|||
return width;
|
||||
}
|
||||
|
||||
size_t TextTerminal::Height() const
|
||||
size_t TextTerminal::Height()
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
|
@ -106,7 +117,7 @@ size_t TextTerminal::Height() const
|
|||
return height;
|
||||
}
|
||||
|
||||
void TextTerminal::GetCursor(size_t* column, size_t* row) const
|
||||
void TextTerminal::GetCursor(size_t* column, size_t* row)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
*column = this->column;
|
||||
|
@ -253,7 +264,7 @@ size_t TextTerminal::EmergencyPrintRaw(const char* string, size_t stringlen)
|
|||
return stringlen;
|
||||
}
|
||||
|
||||
size_t TextTerminal::EmergencyWidth() const
|
||||
size_t TextTerminal::EmergencyWidth()
|
||||
{
|
||||
// This is during a kernel emergency where preemption has been disabled and
|
||||
// this is the only thread running. Another thread may have been interrupted
|
||||
|
@ -266,7 +277,7 @@ size_t TextTerminal::EmergencyWidth() const
|
|||
return width;
|
||||
}
|
||||
|
||||
size_t TextTerminal::EmergencyHeight() const
|
||||
size_t TextTerminal::EmergencyHeight()
|
||||
{
|
||||
// This is during a kernel emergency where preemption has been disabled and
|
||||
// this is the only thread running. Another thread may have been interrupted
|
||||
|
@ -279,7 +290,7 @@ size_t TextTerminal::EmergencyHeight() const
|
|||
return height;
|
||||
}
|
||||
|
||||
void TextTerminal::EmergencyGetCursor(size_t* column, size_t* row) const
|
||||
void TextTerminal::EmergencyGetCursor(size_t* column, size_t* row)
|
||||
{
|
||||
// This is during a kernel emergency where preemption has been disabled and
|
||||
// this is the only thread running. Another thread may have been interrupted
|
||||
|
@ -308,6 +319,7 @@ void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
|||
{
|
||||
switch ( c )
|
||||
{
|
||||
case '\a': return;
|
||||
case '\n': Newline(textbuf); return;
|
||||
case '\r': column = 0; return;
|
||||
case '\b': Backspace(textbuf); return;
|
||||
|
@ -336,7 +348,23 @@ void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
|||
Newline(textbuf);
|
||||
}
|
||||
TextPos pos(column++, line);
|
||||
TextChar tc(wc, vgacolor, ATTR_CHAR | next_attr);
|
||||
uint16_t tcvgacolor;
|
||||
uint16_t tcattr = attr | next_attr;
|
||||
uint32_t tcfgcolor;
|
||||
uint32_t tcbgcolor;
|
||||
if ( !(tcattr & ATTR_INVERSE) )
|
||||
{
|
||||
tcvgacolor = vgacolor;
|
||||
tcfgcolor = fgcolor;
|
||||
tcbgcolor = bgcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcvgacolor = (vgacolor >> 4 & 0xF) << 0 | (vgacolor >> 0 & 0xF) << 4;
|
||||
tcfgcolor = bgcolor;
|
||||
tcbgcolor = fgcolor;
|
||||
}
|
||||
TextChar tc(wc, tcvgacolor, tcattr, tcfgcolor, tcbgcolor);
|
||||
textbuf->SetChar(pos, tc);
|
||||
next_attr = 0;
|
||||
}
|
||||
|
@ -353,11 +381,14 @@ void TextTerminal::Newline(TextBuffer* textbuf)
|
|||
line++;
|
||||
else
|
||||
{
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0));
|
||||
uint32_t fillfg = attr & ATTR_INVERSE ? bgcolor : fgcolor;
|
||||
uint32_t fillbg = attr & ATTR_INVERSE ? fgcolor : bgcolor;
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0, fillfg, fillbg));
|
||||
line = textbuf->Height()-1;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static TextPos DecrementTextPos(TextBuffer* textbuf, TextPos pos)
|
||||
{
|
||||
if ( !pos.x && !pos.y )
|
||||
|
@ -366,27 +397,23 @@ static TextPos DecrementTextPos(TextBuffer* textbuf, TextPos pos)
|
|||
return TextPos(textbuf->Width(), pos.y-1);
|
||||
return TextPos(pos.x-1, pos.y);
|
||||
}
|
||||
#endif
|
||||
|
||||
void TextTerminal::Backspace(TextBuffer* textbuf)
|
||||
{
|
||||
TextPos pos(column, line);
|
||||
while ( pos.x || pos.y )
|
||||
if ( column )
|
||||
{
|
||||
pos = DecrementTextPos(textbuf, pos);
|
||||
column--;
|
||||
TextPos pos(column, line);
|
||||
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);
|
||||
next_attr &= ~ATTR_BOLD;
|
||||
else
|
||||
next_attr |= ATTR_BOLD;
|
||||
textbuf->SetChar(pos, TextChar(' ', vgacolor, 0));
|
||||
if ( tc.attr & ATTR_CHAR )
|
||||
break;
|
||||
}
|
||||
column = pos.x;
|
||||
line = pos.y;
|
||||
}
|
||||
|
||||
void TextTerminal::Tab(TextBuffer* textbuf)
|
||||
|
@ -396,15 +423,11 @@ void TextTerminal::Tab(TextBuffer* textbuf)
|
|||
column = 0;
|
||||
Newline(textbuf);
|
||||
}
|
||||
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);
|
||||
}
|
||||
column++;
|
||||
column = -(-column & ~0x7U);
|
||||
size_t width = textbuf->Width();
|
||||
if ( width <= column )
|
||||
column = width;
|
||||
}
|
||||
|
||||
// TODO: This implementation of the 'Ansi Escape Codes' is incomplete and hacky.
|
||||
|
@ -412,9 +435,7 @@ void TextTerminal::AnsiReset()
|
|||
{
|
||||
next_attr = 0;
|
||||
ansiusedparams = 0;
|
||||
currentparamindex = 0;
|
||||
ansiparams[0] = 0;
|
||||
paramundefined = true;
|
||||
ignoresequence = false;
|
||||
ansimode = CSI;
|
||||
}
|
||||
|
@ -424,32 +445,47 @@ void TextTerminal::PutAnsiEscaped(TextBuffer* textbuf, char c)
|
|||
// Check the proper prefixes are used.
|
||||
if ( ansimode == CSI )
|
||||
{
|
||||
if ( c != '[' ) { ansimode = NONE; return; }
|
||||
ansimode = COMMAND;
|
||||
if ( c == '[' )
|
||||
ansimode = COMMAND;
|
||||
else if ( c == '(' || c == ')' || c == '*' || c == '+' ||
|
||||
c == '-' || c == '.' || c == '/' )
|
||||
ansimode = CHARSET;
|
||||
// TODO: Enter and exit alternatve keypad mode.
|
||||
else if ( c == '=' || c == '>' )
|
||||
ansimode = NONE;
|
||||
else
|
||||
{
|
||||
ansimode = NONE;
|
||||
ansimode = NONE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ansimode == CHARSET )
|
||||
{
|
||||
ansimode = NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Read part of a parameter.
|
||||
if ( '0' <= c && c <= '9' )
|
||||
{
|
||||
if ( paramundefined )
|
||||
if ( ansiusedparams == 0 )
|
||||
ansiusedparams++;
|
||||
paramundefined = false;
|
||||
unsigned val = c - '0';
|
||||
ansiparams[currentparamindex] *= 10;
|
||||
ansiparams[currentparamindex] += val;
|
||||
ansiparams[ansiusedparams-1] *= 10;
|
||||
ansiparams[ansiusedparams-1] += val;
|
||||
}
|
||||
|
||||
// Parameter delimiter.
|
||||
else if ( c == ';' )
|
||||
{
|
||||
if ( currentparamindex == ANSI_NUM_PARAMS - 1 )
|
||||
if ( ansiusedparams == ANSI_NUM_PARAMS )
|
||||
{
|
||||
ansimode = NONE;
|
||||
return;
|
||||
}
|
||||
paramundefined = true;
|
||||
ansiparams[++currentparamindex] = 0;
|
||||
ansiparams[ansiusedparams++] = 0;
|
||||
}
|
||||
|
||||
// Left for future standardization, so discard this sequence.
|
||||
|
@ -458,11 +494,35 @@ void TextTerminal::PutAnsiEscaped(TextBuffer* textbuf, char c)
|
|||
ignoresequence = true;
|
||||
}
|
||||
|
||||
else if ( c == '>' )
|
||||
{
|
||||
ansimode = GREATERTHAN;
|
||||
}
|
||||
|
||||
// Run a command.
|
||||
else if ( 64 <= c && c <= 126 )
|
||||
{
|
||||
if ( !ignoresequence )
|
||||
RunAnsiCommand(textbuf, c);
|
||||
{
|
||||
if ( ansimode == COMMAND )
|
||||
RunAnsiCommand(textbuf, c);
|
||||
else if ( ansimode == GREATERTHAN )
|
||||
{
|
||||
// Send Device Attributes
|
||||
if ( c == 'c' )
|
||||
{
|
||||
// TODO: Send an appropriate response through the terminal.
|
||||
}
|
||||
else
|
||||
{
|
||||
ansimode = NONE;
|
||||
return;
|
||||
}
|
||||
ansimode = NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
ansimode = NONE;
|
||||
}
|
||||
|
||||
// Something I don't understand, and ignore intentionally.
|
||||
|
@ -573,7 +633,9 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
from = TextPos{0, 0},
|
||||
to = TextPos{width-1, height-1};
|
||||
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
|
||||
uint32_t fillfg = attr & ATTR_INVERSE ? bgcolor : fgcolor;
|
||||
uint32_t fillbg = attr & ATTR_INVERSE ? fgcolor : bgcolor;
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0, fillfg, fillbg));
|
||||
} break;
|
||||
case 'K': // Erase parts of the current line.
|
||||
{
|
||||
|
@ -593,18 +655,35 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
from = TextPos{0, line},
|
||||
to = TextPos{width-1, line};
|
||||
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0));
|
||||
uint32_t fillfg = attr & ATTR_INVERSE ? bgcolor : fgcolor;
|
||||
uint32_t fillbg = attr & ATTR_INVERSE ? fgcolor : bgcolor;
|
||||
textbuf->Fill(from, to, TextChar(' ', vgacolor, 0, fillfg, fillbg));
|
||||
} break;
|
||||
// TODO: CSI Ps M Delete Ps Line(s) (default = 1) (DL).
|
||||
// (delete those lines and move the rest of the lines upwards).
|
||||
// TODO: CSI Ps P Delete Ps Character(s) (default = 1) (DCH).
|
||||
// (delete those characters and move the rest of the line leftward).
|
||||
case 'S': // Scroll a line up and place a new line at the buttom.
|
||||
{
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0));
|
||||
uint32_t fillfg = attr & ATTR_INVERSE ? bgcolor : fgcolor;
|
||||
uint32_t fillbg = attr & ATTR_INVERSE ? fgcolor : bgcolor;
|
||||
textbuf->Scroll(1, TextChar(' ', vgacolor, 0, fillfg, fillbg));
|
||||
line = height-1;
|
||||
} break;
|
||||
case 'T': // Scroll a line up and place a new line at the top.
|
||||
{
|
||||
textbuf->Scroll(-1, TextChar(' ', vgacolor, 0));
|
||||
uint32_t fillfg = attr & ATTR_INVERSE ? bgcolor : fgcolor;
|
||||
uint32_t fillbg = attr & ATTR_INVERSE ? fgcolor : bgcolor;
|
||||
textbuf->Scroll(-1, TextChar(' ', vgacolor, 0, fillfg, fillbg));
|
||||
line = 0;
|
||||
} break;
|
||||
case 'd': // Move the cursor to line N.
|
||||
{
|
||||
unsigned posy = 0 < ansiusedparams ? ansiparams[0]-1 : 0;
|
||||
if ( height <= posy )
|
||||
posy = height-1;
|
||||
line = posy;
|
||||
} break;
|
||||
case 'm': // Change how the text is rendered.
|
||||
{
|
||||
if ( ansiusedparams == 0 )
|
||||
|
@ -616,8 +695,12 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
// Convert from the ANSI color scheme to the VGA color scheme.
|
||||
const unsigned conversion[8] =
|
||||
{
|
||||
#if 0
|
||||
0, 4, 2, 6, 1, 5, 3, 7
|
||||
#else
|
||||
COLOR8_BLACK, COLOR8_RED, COLOR8_GREEN, COLOR8_BROWN,
|
||||
COLOR8_BLUE, COLOR8_MAGENTA, COLOR8_CYAN, COLOR8_LIGHT_GREY,
|
||||
#endif
|
||||
};
|
||||
|
||||
for ( size_t i = 0; i < ansiusedparams; i++ )
|
||||
|
@ -626,20 +709,72 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
// Turn all attributes off.
|
||||
if ( cmd == 0 )
|
||||
{
|
||||
vgacolor = DEFAULT_COLOR;
|
||||
vgacolor = DEFAULT_VGACOLOR;
|
||||
attr = 0;
|
||||
fgcolor = palette[DEFAULT_FOREGROUND];
|
||||
bgcolor = palette[DEFAULT_BACKGROUND];
|
||||
}
|
||||
// Boldness.
|
||||
else if ( cmd == 1 )
|
||||
attr |= ATTR_BOLD;
|
||||
// TODO: 2, Faint
|
||||
// TODO: 3, Italicized
|
||||
// Underline.
|
||||
else if ( cmd == 4 )
|
||||
attr |= ATTR_UNDERLINE;
|
||||
// TODO: 5, Blink (appears as Bold)
|
||||
// Inverse.
|
||||
else if ( cmd == 7 )
|
||||
attr |= ATTR_INVERSE;
|
||||
// TODO: 8, Invisible
|
||||
// TODO: 9, Crossed-out
|
||||
// TODO: 21, Doubly-underlined
|
||||
// Normal (neither bold nor faint).
|
||||
else if ( cmd == 22 )
|
||||
attr &= ~ATTR_BOLD;
|
||||
// TODO: 23, Not italicized
|
||||
// Not underlined.
|
||||
else if ( cmd == 24 )
|
||||
attr &= ~ATTR_UNDERLINE;
|
||||
// TODO: 25, Steady (not blinking)
|
||||
// Positive (not inverse).
|
||||
else if ( cmd == 27 )
|
||||
attr &= ~ATTR_INVERSE;
|
||||
// TODO: 28, Visible (not hidden)
|
||||
// Set text color.
|
||||
else if ( 30 <= cmd && cmd <= 37 )
|
||||
{
|
||||
unsigned val = cmd - 30;
|
||||
vgacolor &= 0xF0;
|
||||
vgacolor |= conversion[val] << 0;
|
||||
fgcolor = palette[val];
|
||||
}
|
||||
// Set text color.
|
||||
else if ( cmd == 38 )
|
||||
{
|
||||
if ( 5 <= ansiusedparams - i && ansiparams[i+1] == 2 )
|
||||
{
|
||||
uint8_t r = ansiparams[i+2];
|
||||
uint8_t g = ansiparams[i+3];
|
||||
uint8_t b = ansiparams[i+4];
|
||||
i += 5 - 1;
|
||||
fgcolor = ColorFromRGB(r, g, b);
|
||||
// TODO: Approxpiate vgacolor.
|
||||
}
|
||||
else if ( 3 <= ansiusedparams - i && ansiparams[i+1] == 5 )
|
||||
{
|
||||
uint8_t index = ansiparams[i+2];
|
||||
i += 3 - 1;
|
||||
fgcolor = palette[index];
|
||||
// TODO: Approxpiate vgacolor.
|
||||
}
|
||||
}
|
||||
// Set default text color.
|
||||
else if ( cmd == 39 )
|
||||
{
|
||||
vgacolor &= 0xF0;
|
||||
vgacolor |= DEFAULT_COLOR & 0x0F;
|
||||
vgacolor |= DEFAULT_VGACOLOR & 0x0F;
|
||||
fgcolor = palette[DEFAULT_FOREGROUND];
|
||||
}
|
||||
// Set background color.
|
||||
else if ( 40 <= cmd && cmd <= 47 )
|
||||
|
@ -647,32 +782,60 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
unsigned val = cmd - 40;
|
||||
vgacolor &= 0x0F;
|
||||
vgacolor |= conversion[val] << 4;
|
||||
bgcolor = palette[val];
|
||||
}
|
||||
// Set background color.
|
||||
else if ( cmd == 48 )
|
||||
{
|
||||
if ( 5 <= ansiusedparams - i && ansiparams[i+1] == 2 )
|
||||
{
|
||||
uint8_t r = ansiparams[i+2];
|
||||
uint8_t g = ansiparams[i+3];
|
||||
uint8_t b = ansiparams[i+4];
|
||||
i += 5 - 1;
|
||||
bgcolor = ColorFromRGB(r, g, b);
|
||||
// TODO: Approxpiate vgacolor.
|
||||
}
|
||||
else if ( 3 <= ansiusedparams - i && ansiparams[i+1] == 5 )
|
||||
{
|
||||
uint8_t index = ansiparams[i+2];
|
||||
i += 3 - 1;
|
||||
bgcolor = palette[index];
|
||||
// TODO: Approxpiate vgacolor.
|
||||
}
|
||||
}
|
||||
// Set default background color.
|
||||
else if ( cmd == 49 )
|
||||
{
|
||||
vgacolor &= 0x0F;
|
||||
vgacolor |= DEFAULT_COLOR & 0xF0;
|
||||
vgacolor |= DEFAULT_VGACOLOR & 0xF0;
|
||||
bgcolor = palette[DEFAULT_BACKGROUND];
|
||||
}
|
||||
// Set text color.
|
||||
else if ( 90 <= cmd && cmd <= 97 )
|
||||
{
|
||||
unsigned val = cmd - 90;
|
||||
unsigned val = cmd - 90 + 8;
|
||||
vgacolor &= 0xF0;
|
||||
vgacolor |= (0x8 | conversion[val]) << 0;
|
||||
vgacolor |= (0x8 | conversion[val - 8]) << 0;
|
||||
fgcolor = palette[val];
|
||||
}
|
||||
// Set background color.
|
||||
else if ( 100 <= cmd && cmd <= 107 )
|
||||
{
|
||||
unsigned val = cmd - 100;
|
||||
unsigned val = cmd - 100 + 8;
|
||||
vgacolor &= 0x0F;
|
||||
vgacolor |= (0x8 | conversion[val]) << 4;
|
||||
vgacolor |= (0x8 | conversion[val - 8]) << 4;
|
||||
bgcolor = palette[val];
|
||||
}
|
||||
else
|
||||
{
|
||||
ansimode = NONE;
|
||||
}
|
||||
// TODO: There are many other things we don't support.
|
||||
}
|
||||
} break;
|
||||
case 'n': // Request special information from terminal.
|
||||
{
|
||||
ansimode = NONE;
|
||||
// TODO: Handle this code.
|
||||
} break;
|
||||
case 's': // Save cursor position.
|
||||
|
@ -694,13 +857,21 @@ void TextTerminal::RunAnsiCommand(TextBuffer* textbuf, char c)
|
|||
// TODO: This is somehow related to the special char '?'.
|
||||
if ( 0 < ansiusedparams && ansiparams[0] == 25 )
|
||||
textbuf->SetCursorEnabled(false);
|
||||
if ( 0 < ansiusedparams && ansiparams[0] == 1049 )
|
||||
{}; // TODO: Save scrollback.
|
||||
} break;
|
||||
case 'h': // Show cursor.
|
||||
{
|
||||
// TODO: This is somehow related to the special char '?'.
|
||||
if ( 0 < ansiusedparams && ansiparams[0] == 25 )
|
||||
textbuf->SetCursorEnabled(true);
|
||||
if ( 0 < ansiusedparams && ansiparams[0] == 1049 )
|
||||
{}; // TODO: Restore scrollback.
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
ansimode = NONE;
|
||||
}
|
||||
// TODO: Handle other cases.
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -36,9 +36,9 @@ public:
|
|||
~TextTerminal();
|
||||
size_t Print(const char* string, size_t stringlen);
|
||||
size_t PrintRaw(const char* string, size_t stringlen);
|
||||
size_t Width() const;
|
||||
size_t Height() const;
|
||||
void GetCursor(size_t* column, size_t* row) const;
|
||||
size_t Width();
|
||||
size_t Height();
|
||||
void GetCursor(size_t* column, size_t* row);
|
||||
bool Sync();
|
||||
bool Invalidate();
|
||||
void BeginReplace();
|
||||
|
@ -49,9 +49,9 @@ public:
|
|||
void EmergencyReset();
|
||||
size_t EmergencyPrint(const char* string, size_t stringlen);
|
||||
size_t EmergencyPrintRaw(const char* string, size_t stringlen);
|
||||
size_t EmergencyWidth() const;
|
||||
size_t EmergencyHeight() const;
|
||||
void EmergencyGetCursor(size_t* column, size_t* row) const;
|
||||
size_t EmergencyWidth();
|
||||
size_t EmergencyHeight();
|
||||
void EmergencyGetCursor(size_t* column, size_t* row);
|
||||
bool EmergencySync();
|
||||
|
||||
private:
|
||||
|
@ -67,20 +67,21 @@ private:
|
|||
|
||||
private:
|
||||
mbstate_t ps;
|
||||
mutable TextBufferHandle* textbufhandle;
|
||||
mutable kthread_mutex_t termlock;
|
||||
TextBufferHandle* textbufhandle;
|
||||
kthread_mutex_t termlock;
|
||||
uint16_t next_attr;
|
||||
uint32_t attr;
|
||||
uint32_t fgcolor;
|
||||
uint32_t bgcolor;
|
||||
uint8_t vgacolor;
|
||||
unsigned column;
|
||||
unsigned line;
|
||||
unsigned ansisavedposx;
|
||||
unsigned ansisavedposy;
|
||||
enum { NONE = 0, CSI, COMMAND, } ansimode;
|
||||
enum { NONE = 0, CSI, CHARSET, COMMAND, GREATERTHAN, } ansimode;
|
||||
static const size_t ANSI_NUM_PARAMS = 16;
|
||||
unsigned ansiusedparams;
|
||||
unsigned ansiparams[ANSI_NUM_PARAMS];
|
||||
unsigned currentparamindex;
|
||||
bool paramundefined;
|
||||
bool ignoresequence;
|
||||
|
||||
};
|
||||
|
|
|
@ -88,7 +88,7 @@ TextChar VGATextBuffer::GetChar(TextPos pos)
|
|||
{
|
||||
if ( UsablePosition(pos) )
|
||||
return chars[OffsetOfPos(pos)];
|
||||
return {0, 0, 0};
|
||||
return {0, 0, 0, 0, 0};
|
||||
}
|
||||
|
||||
void VGATextBuffer::SetChar(TextPos pos, TextChar c)
|
||||
|
@ -203,7 +203,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, 0, 0});
|
||||
SetCursorPos(TextPos{0, 0});
|
||||
}
|
||||
|
||||
|
|
2
sh/sh.c
2
sh/sh.c
|
@ -1833,7 +1833,7 @@ void read_command_interactive(struct sh_read_command* sh_read_command)
|
|||
}
|
||||
|
||||
char* ps1;
|
||||
asprintf(&ps1, "\e[32m%s@%s \e[36m%s%s %c\e[37m ",
|
||||
asprintf(&ps1, "\e[;1;32m%s@%s \e[1;34m%s%s %c\e[m ",
|
||||
print_username,
|
||||
print_hostname,
|
||||
print_dir_1,
|
||||
|
|
16
utils/ls.c
16
utils/ls.c
|
@ -298,7 +298,7 @@ static void color(const char** pre,
|
|||
|
||||
if ( failure )
|
||||
{
|
||||
*pre = "\e[31m";
|
||||
*pre = "\e[1;31m";
|
||||
*post = "\e[m";
|
||||
return;
|
||||
}
|
||||
|
@ -306,16 +306,16 @@ static void color(const char** pre,
|
|||
*post = "\e[m";
|
||||
switch ( mode_to_dt(st->st_mode) )
|
||||
{
|
||||
case DT_UNKNOWN: *pre = "\e[91m"; break;
|
||||
case DT_BLK: *pre = "\e[93m"; break;
|
||||
case DT_CHR: *pre = "\e[93m"; break;
|
||||
case DT_DIR: *pre = "\e[36m"; break;
|
||||
case DT_UNKNOWN: *pre = "\e[1;31m"; break;
|
||||
case DT_BLK: *pre = "\e[1;33m"; break;
|
||||
case DT_CHR: *pre = "\e[1;33m"; break;
|
||||
case DT_DIR: *pre = "\e[1;34m"; break;
|
||||
case DT_FIFO: *pre = "\e[33m"; break;
|
||||
case DT_LNK: *pre = "\e[96m"; break;
|
||||
case DT_SOCK: *pre = "\e[35m"; break;
|
||||
case DT_LNK: *pre = "\e[1;36m"; break;
|
||||
case DT_SOCK: *pre = "\e[1;35m"; break;
|
||||
case DT_REG:
|
||||
if ( st->st_mode & 0111 )
|
||||
*pre = "\e[32m";
|
||||
*pre = "\e[1;32m";
|
||||
else
|
||||
*post = "";
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue