mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add unicode support to kernel terminal and console.
This commit is contained in:
parent
f41964fcab
commit
dc11b9f837
9 changed files with 312 additions and 77 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
|
@ -42,11 +43,19 @@ struct TextPos
|
||||||
size_t y;
|
size_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TextCharPOD
|
||||||
|
{
|
||||||
|
wchar_t c;
|
||||||
|
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||||
|
};
|
||||||
|
|
||||||
struct TextChar
|
struct TextChar
|
||||||
{
|
{
|
||||||
TextChar() { }
|
TextChar() { }
|
||||||
TextChar(char c, uint8_t vgacolor) : c(c), vgacolor(vgacolor) { }
|
TextChar(const TextCharPOD& o) : c(o.c), vgacolor(o.vgacolor) { }
|
||||||
char c;
|
TextChar(wchar_t c, uint8_t vgacolor) : c(c), vgacolor(vgacolor) { }
|
||||||
|
operator TextCharPOD() { return TextCharPOD{c, vgacolor}; }
|
||||||
|
wchar_t c;
|
||||||
uint8_t vgacolor; // Format of <sortix/vga.h>
|
uint8_t vgacolor; // Format of <sortix/vga.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
|
||||||
const size_t VGA_WIDTH = 80;
|
const size_t VGA_WIDTH = 80;
|
||||||
const size_t VGA_HEIGHT = 25;
|
const size_t VGA_HEIGHT = 25;
|
||||||
static uint16_t vga_attr_buffer[VGA_WIDTH*VGA_HEIGHT];
|
static uint16_t vga_attr_buffer[VGA_WIDTH*VGA_HEIGHT];
|
||||||
VGATextBuffer textbuf(VGAFB, vga_attr_buffer, VGA_WIDTH, VGA_HEIGHT);
|
static struct TextCharPOD vga_chars_pod_buffer[VGA_WIDTH*VGA_HEIGHT];
|
||||||
|
TextChar* vga_chars_buffer = (TextChar*) vga_chars_pod_buffer;
|
||||||
|
VGATextBuffer textbuf(VGAFB, vga_chars_buffer, vga_attr_buffer, VGA_WIDTH, VGA_HEIGHT);
|
||||||
TextBufferHandle textbufhandlestack(NULL, false, &textbuf, false);
|
TextBufferHandle textbufhandlestack(NULL, false, &textbuf, false);
|
||||||
textbufhandle = Ref<TextBufferHandle>(&textbufhandlestack);
|
textbufhandle = Ref<TextBufferHandle>(&textbufhandlestack);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
||||||
size_t fontsize = VGA_FONT_CHARSIZE * VGA_FONT_NUMCHARS;
|
size_t fontsize = VGA_FONT_CHARSIZE * VGA_FONT_NUMCHARS;
|
||||||
uint8_t* backbuf;
|
uint8_t* backbuf;
|
||||||
uint8_t* font;
|
uint8_t* font;
|
||||||
uint16_t* chars;
|
TextChar* chars;
|
||||||
uint16_t* attrs;
|
uint16_t* attrs;
|
||||||
TextBufferCmd* queue;
|
TextBufferCmd* queue;
|
||||||
LFBTextBuffer* ret;
|
LFBTextBuffer* ret;
|
||||||
|
@ -73,7 +73,7 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
||||||
goto cleanup_done;
|
goto cleanup_done;
|
||||||
if ( !(font = new uint8_t[fontsize]) )
|
if ( !(font = new uint8_t[fontsize]) )
|
||||||
goto cleanup_backbuf;
|
goto cleanup_backbuf;
|
||||||
if ( !(chars = new uint16_t[columns * rows]) )
|
if ( !(chars = new TextChar[columns * rows]) )
|
||||||
goto cleanup_font;
|
goto cleanup_font;
|
||||||
if ( !(attrs = new uint16_t[columns * rows]) )
|
if ( !(attrs = new uint16_t[columns * rows]) )
|
||||||
goto cleanup_chars;
|
goto cleanup_chars;
|
||||||
|
@ -106,9 +106,9 @@ LFBTextBuffer* CreateLFBTextBuffer(uint8_t* lfb, uint32_t lfbformat,
|
||||||
ret->columns = columns;
|
ret->columns = columns;
|
||||||
ret->rows = rows;
|
ret->rows = rows;
|
||||||
ret->font = font;
|
ret->font = font;
|
||||||
memset(chars, 0, sizeof(uint16_t) * columns * rows);
|
memset(chars, 0, sizeof(chars[0]) * columns * rows);
|
||||||
ret->chars = chars;
|
ret->chars = chars;
|
||||||
memset(attrs, 0, sizeof(uint16_t) * columns * rows);
|
memset(attrs, 0, sizeof(attrs[0]) * columns * rows);
|
||||||
ret->attrs = attrs;
|
ret->attrs = attrs;
|
||||||
for ( size_t i = 0; i < 16UL; i++ )
|
for ( size_t i = 0; i < 16UL; i++ )
|
||||||
{
|
{
|
||||||
|
@ -147,21 +147,6 @@ cleanup_done:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Those are also in vgatextbuffer.cpp. Move them to a shared location and
|
|
||||||
// give them better names.
|
|
||||||
static TextChar EntryToTextChar(uint16_t entry)
|
|
||||||
{
|
|
||||||
char c = entry & 0x00FF;
|
|
||||||
uint8_t vgacolor = entry >> 8U;
|
|
||||||
return TextChar{c, vgacolor};
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t CharToTextEntry(TextChar c)
|
|
||||||
{
|
|
||||||
unsigned char uc = c.c;
|
|
||||||
return (uint16_t) uc | (uint16_t) c.vgacolor << 8U;
|
|
||||||
}
|
|
||||||
|
|
||||||
LFBTextBuffer::LFBTextBuffer()
|
LFBTextBuffer::LFBTextBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -216,7 +201,7 @@ TextPos LFBTextBuffer::AddToPosition(TextPos pos, size_t count)
|
||||||
return CropPosition(ret);
|
return CropPosition(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LFBTextBuffer::RenderChar(uint16_t vgachar, size_t posx, size_t posy)
|
void LFBTextBuffer::RenderChar(TextChar textchar, size_t posx, size_t posy)
|
||||||
{
|
{
|
||||||
if ( columns <= posx || rows <= posy )
|
if ( columns <= posx || rows <= posy )
|
||||||
return;
|
return;
|
||||||
|
@ -224,15 +209,15 @@ void LFBTextBuffer::RenderChar(uint16_t vgachar, size_t posx, size_t posy)
|
||||||
if ( lfbformat != 32 || VGA_FONT_WIDTH != 8UL )
|
if ( lfbformat != 32 || VGA_FONT_WIDTH != 8UL )
|
||||||
return;
|
return;
|
||||||
bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y;
|
bool drawcursor = cursorenabled && posx == cursorpos.x && posy == cursorpos.y;
|
||||||
uint8_t c = vgachar >> 0 & 0xFF;
|
uint8_t fgcoloridx = textchar.vgacolor >> 0 & 0x0F;
|
||||||
uint8_t fgcoloridx = vgachar >> 8 & 0x0F;
|
uint8_t bgcoloridx = textchar.vgacolor >> 4 & 0x0F;
|
||||||
uint8_t bgcoloridx = vgachar >> 12 & 0x0F;
|
|
||||||
uint32_t fgcolor = colors[fgcoloridx];
|
uint32_t fgcolor = colors[fgcoloridx];
|
||||||
uint32_t bgcolor = colors[bgcoloridx];
|
uint32_t bgcolor = colors[bgcoloridx];
|
||||||
|
const uint8_t* charfont = VGA::GetCharacterFont(font, textchar.c);
|
||||||
for ( size_t y = 0; y < VGA_FONT_HEIGHT; y++ )
|
for ( size_t y = 0; y < VGA_FONT_HEIGHT; y++ )
|
||||||
{
|
{
|
||||||
size_t pixely = posy * VGA_FONT_HEIGHT + y;
|
size_t pixely = posy * VGA_FONT_HEIGHT + y;
|
||||||
uint8_t linebitmap = font[c * VGA_FONT_CHARSIZE + y];
|
uint8_t linebitmap = charfont[y];
|
||||||
for ( size_t x = 0; x < VGA_FONT_WIDTH+1; x++ )
|
for ( size_t x = 0; x < VGA_FONT_WIDTH+1; x++ )
|
||||||
{
|
{
|
||||||
uint32_t* line = (uint32_t*) (lfb + pixely * scansize);
|
uint32_t* line = (uint32_t*) (lfb + pixely * scansize);
|
||||||
|
@ -354,7 +339,7 @@ TextChar LFBTextBuffer::GetChar(TextPos pos) const
|
||||||
if ( UsablePosition(pos) )
|
if ( UsablePosition(pos) )
|
||||||
{
|
{
|
||||||
((LFBTextBuffer*) this)->StopRendering();
|
((LFBTextBuffer*) this)->StopRendering();
|
||||||
TextChar ret = EntryToTextChar(chars[pos.y * columns + pos.x]);
|
TextChar ret = chars[pos.y * columns + pos.x];
|
||||||
((LFBTextBuffer*) this)->ResumeRendering();
|
((LFBTextBuffer*) this)->ResumeRendering();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -365,12 +350,11 @@ void LFBTextBuffer::SetChar(TextPos pos, TextChar c)
|
||||||
{
|
{
|
||||||
if ( !UsablePosition(pos) )
|
if ( !UsablePosition(pos) )
|
||||||
return;
|
return;
|
||||||
uint16_t entry = CharToTextEntry(c);
|
|
||||||
TextBufferCmd cmd;
|
TextBufferCmd cmd;
|
||||||
cmd.type = TEXTBUFCMD_CHAR;
|
cmd.type = TEXTBUFCMD_CHAR;
|
||||||
cmd.x = pos.x;
|
cmd.x = pos.x;
|
||||||
cmd.y = pos.y;
|
cmd.y = pos.y;
|
||||||
cmd.c = entry;
|
cmd.c = c;
|
||||||
IssueCommand(&cmd);
|
IssueCommand(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,7 +427,7 @@ void LFBTextBuffer::Scroll(ssize_t off, TextChar fillwith)
|
||||||
TextBufferCmd cmd;
|
TextBufferCmd cmd;
|
||||||
cmd.type = TEXTBUFCMD_SCROLL;
|
cmd.type = TEXTBUFCMD_SCROLL;
|
||||||
cmd.scroll_offset = off;
|
cmd.scroll_offset = off;
|
||||||
cmd.c = CharToTextEntry(fillwith);
|
cmd.c = fillwith;
|
||||||
IssueCommand(&cmd);
|
IssueCommand(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,12 +456,12 @@ void LFBTextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||||
cmd.from_y = from.y;
|
cmd.from_y = from.y;
|
||||||
cmd.to_x = to.x;
|
cmd.to_x = to.x;
|
||||||
cmd.to_y = to.y;
|
cmd.to_y = to.y;
|
||||||
cmd.c = CharToTextEntry(fillwith);
|
cmd.c = fillwith;
|
||||||
cmd.attr = fillattr;
|
cmd.attr = fillattr;
|
||||||
IssueCommand(&cmd);
|
IssueCommand(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LFBTextBuffer::DoScroll(ssize_t off, uint16_t entry)
|
void LFBTextBuffer::DoScroll(ssize_t off, TextChar entry)
|
||||||
{
|
{
|
||||||
bool neg = 0 < off;
|
bool neg = 0 < off;
|
||||||
size_t absoff = off < 0 ? -off : off;
|
size_t absoff = off < 0 ? -off : off;
|
||||||
|
@ -506,7 +490,7 @@ void LFBTextBuffer::DoMove(TextPos to, TextPos from, size_t numchars)
|
||||||
attrs[dest + numchars-1 - i] = attrs[src + numchars-1 - i];
|
attrs[dest + numchars-1 - i] = attrs[src + numchars-1 - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void LFBTextBuffer::DoFill(TextPos from, TextPos to, uint16_t fillwith,
|
void LFBTextBuffer::DoFill(TextPos from, TextPos to, TextChar fillwith,
|
||||||
uint16_t fillattr)
|
uint16_t fillattr)
|
||||||
{
|
{
|
||||||
size_t start = OffsetOfPos(from);
|
size_t start = OffsetOfPos(from);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ struct TextBufferCmd
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
bool b;
|
bool b;
|
||||||
struct { uint16_t c; uint16_t attr; };
|
struct { TextCharPOD c; uint16_t attr; };
|
||||||
size_t val;
|
size_t val;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -91,7 +91,7 @@ public:
|
||||||
virtual void RenderThread();
|
virtual void RenderThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RenderChar(uint16_t vgachar, size_t posx, size_t posy);
|
void RenderChar(TextChar textchar, size_t posx, size_t posy);
|
||||||
void RenderCharAt(TextPos pos);
|
void RenderCharAt(TextPos pos);
|
||||||
void RenderRegion(size_t c1, size_t r1, size_t c2, size_t r2);
|
void RenderRegion(size_t c1, size_t r1, size_t c2, size_t r2);
|
||||||
void RenderRange(TextPos from, TextPos to);
|
void RenderRange(TextPos from, TextPos to);
|
||||||
|
@ -99,9 +99,9 @@ private:
|
||||||
size_t OffsetOfPos(TextPos pos) const;
|
size_t OffsetOfPos(TextPos pos) const;
|
||||||
TextPos CropPosition(TextPos pos) const;
|
TextPos CropPosition(TextPos pos) const;
|
||||||
TextPos AddToPosition(TextPos pos, size_t count);
|
TextPos AddToPosition(TextPos pos, size_t count);
|
||||||
void DoScroll(ssize_t off, uint16_t 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, uint16_t fillwith, uint16_t fillattr);
|
void DoFill(TextPos from, TextPos to, TextChar fillwith, uint16_t fillattr);
|
||||||
void IssueCommand(TextBufferCmd* cmd);
|
void IssueCommand(TextBufferCmd* cmd);
|
||||||
void StopRendering();
|
void StopRendering();
|
||||||
void ResumeRendering();
|
void ResumeRendering();
|
||||||
|
@ -131,7 +131,7 @@ private:
|
||||||
uint8_t* lfb;
|
uint8_t* lfb;
|
||||||
uint8_t* backbuf;
|
uint8_t* backbuf;
|
||||||
uint8_t* font;
|
uint8_t* font;
|
||||||
uint16_t* chars;
|
TextChar* chars;
|
||||||
uint16_t* attrs;
|
uint16_t* attrs;
|
||||||
size_t columns;
|
size_t columns;
|
||||||
size_t rows;
|
size_t rows;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include <sortix/vga.h>
|
#include <sortix/vga.h>
|
||||||
|
|
||||||
#include <sortix/kernel/kernel.h>
|
#include <sortix/kernel/kernel.h>
|
||||||
|
@ -37,6 +41,7 @@ const uint16_t ATTR_CHAR = 1U << 0U;
|
||||||
|
|
||||||
TextTerminal::TextTerminal(Ref<TextBufferHandle> textbufhandle)
|
TextTerminal::TextTerminal(Ref<TextBufferHandle> textbufhandle)
|
||||||
{
|
{
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
this->textbufhandle = textbufhandle;
|
this->textbufhandle = textbufhandle;
|
||||||
this->termlock = KTHREAD_MUTEX_INITIALIZER;
|
this->termlock = KTHREAD_MUTEX_INITIALIZER;
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -233,24 +238,39 @@ bool TextTerminal::EmergencySync()
|
||||||
void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
||||||
{
|
{
|
||||||
if ( ansimode )
|
if ( ansimode )
|
||||||
PutAnsiEscaped(textbuf, c);
|
return PutAnsiEscaped(textbuf, c);
|
||||||
else switch ( c )
|
|
||||||
|
if ( mbsinit(&ps) )
|
||||||
{
|
{
|
||||||
case '\n': Newline(textbuf); break;
|
switch ( c )
|
||||||
case '\r': column = 0; break;
|
{
|
||||||
case '\b': Backspace(textbuf); break;
|
case '\n': Newline(textbuf); return;
|
||||||
case '\t': Tab(textbuf); break;
|
case '\r': column = 0; return;
|
||||||
case '\e': AnsiReset(); break;
|
case '\b': Backspace(textbuf); return;
|
||||||
default:
|
case '\t': Tab(textbuf); return;
|
||||||
{
|
case '\e': AnsiReset(); return;
|
||||||
if ( textbuf->Width() <= column )
|
default: break;
|
||||||
Newline(textbuf);
|
}
|
||||||
TextPos pos(column++, line);
|
|
||||||
TextChar tc(c, vgacolor);
|
|
||||||
textbuf->SetChar(pos, tc);
|
|
||||||
textbuf->SetCharAttr(pos, ATTR_CHAR);
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wchar_t wc;
|
||||||
|
size_t result = mbrtowc(&wc, &c, 1, &ps);
|
||||||
|
if ( result == (size_t) -2 )
|
||||||
|
return;
|
||||||
|
if ( result == (size_t) -1 )
|
||||||
|
{
|
||||||
|
memset(&ps, 0, sizeof(ps));
|
||||||
|
wc = L'<EFBFBD>';
|
||||||
|
}
|
||||||
|
if ( result == (size_t) 0 )
|
||||||
|
wc = L' ';
|
||||||
|
|
||||||
|
if ( textbuf->Width() <= column )
|
||||||
|
Newline(textbuf);
|
||||||
|
TextPos pos(column++, line);
|
||||||
|
TextChar tc(wc, vgacolor);
|
||||||
|
textbuf->SetChar(pos, tc);
|
||||||
|
textbuf->SetCharAttr(pos, ATTR_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextTerminal::UpdateCursor(TextBuffer* textbuf)
|
void TextTerminal::UpdateCursor(TextBuffer* textbuf)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
#ifndef SORTIX_TEXTTERMINAL_H
|
#ifndef SORTIX_TEXTTERMINAL_H
|
||||||
#define SORTIX_TEXTTERMINAL_H
|
#define SORTIX_TEXTTERMINAL_H
|
||||||
|
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
#include <sortix/kernel/kthread.h>
|
#include <sortix/kernel/kthread.h>
|
||||||
#include <sortix/kernel/refcount.h>
|
#include <sortix/kernel/refcount.h>
|
||||||
|
|
||||||
|
@ -63,6 +65,7 @@ private:
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
mbstate_t ps;
|
||||||
mutable Ref<TextBufferHandle> textbufhandle;
|
mutable Ref<TextBufferHandle> textbufhandle;
|
||||||
mutable kthread_mutex_t termlock;
|
mutable kthread_mutex_t termlock;
|
||||||
uint8_t vgacolor;
|
uint8_t vgacolor;
|
||||||
|
|
218
kernel/vga.h
218
kernel/vga.h
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
#ifndef SORTIX_VGA_H
|
#ifndef SORTIX_VGA_H
|
||||||
#define SORTIX_VGA_H
|
#define SORTIX_VGA_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <sortix/kernel/refcount.h>
|
#include <sortix/kernel/refcount.h>
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
@ -38,6 +40,220 @@ const size_t VGA_FONT_CHARSIZE = VGA_FONT_WIDTH * VGA_FONT_HEIGHT / 8UL;
|
||||||
|
|
||||||
namespace VGA {
|
namespace VGA {
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Code_page_437
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline int MapWideToVGAFont(wchar_t c)
|
||||||
|
{
|
||||||
|
if ( 32 <= c && c < 127 )
|
||||||
|
return (int) c;
|
||||||
|
switch ( c )
|
||||||
|
{
|
||||||
|
case L'☺': return 1;
|
||||||
|
case L'☻': return 2;
|
||||||
|
case L'♥': return 3;
|
||||||
|
case L'♦': return 4;
|
||||||
|
case L'♣': return 5;
|
||||||
|
case L'♠': return 6;
|
||||||
|
case L'•': return 7;
|
||||||
|
case L'◘': return 8;
|
||||||
|
case L'○': return 9;
|
||||||
|
case L'◙': return 10;
|
||||||
|
case L'♂': return 11;
|
||||||
|
case L'♀': return 12;
|
||||||
|
case L'♪': return 13;
|
||||||
|
case L'♬': return 14;
|
||||||
|
case L'☼': return 15;
|
||||||
|
case L'►': return 16;
|
||||||
|
case L'◄': return 17;
|
||||||
|
case L'↕': return 18;
|
||||||
|
case L'‼': return 19;
|
||||||
|
case L'¶': return 20;
|
||||||
|
case L'§': return 21;
|
||||||
|
case L'▬': return 22;
|
||||||
|
case L'↨': return 23;
|
||||||
|
case L'↑': return 24;
|
||||||
|
case L'↓': return 25;
|
||||||
|
case L'→': return 26;
|
||||||
|
case L'←': return 27;
|
||||||
|
case L'∟': return 28;
|
||||||
|
case L'↔': return 29;
|
||||||
|
case L'▲': return 30;
|
||||||
|
case L'▼': return 31;
|
||||||
|
case L'⌂': return 127;
|
||||||
|
case L'Ç': return 128;
|
||||||
|
case L'ü': return 129;
|
||||||
|
case L'é': return 130;
|
||||||
|
case L'â': return 131;
|
||||||
|
case L'ä': return 132;
|
||||||
|
case L'à': return 133;
|
||||||
|
case L'å': return 134;
|
||||||
|
case L'ç': return 135;
|
||||||
|
case L'ê': return 136;
|
||||||
|
case L'ë': return 137;
|
||||||
|
case L'è': return 138;
|
||||||
|
case L'ï': return 139;
|
||||||
|
case L'î': return 140;
|
||||||
|
case L'ì': return 141;
|
||||||
|
case L'Ä': return 142;
|
||||||
|
case L'Å': return 143;
|
||||||
|
case L'É': return 144;
|
||||||
|
case L'æ': return 145;
|
||||||
|
case L'Æ': return 146;
|
||||||
|
case L'ô': return 147;
|
||||||
|
case L'ö': return 148;
|
||||||
|
case L'ò': return 149;
|
||||||
|
case L'û': return 150;
|
||||||
|
case L'ù': return 151;
|
||||||
|
case L'ÿ': return 152;
|
||||||
|
case L'Ö': return 153;
|
||||||
|
case L'Ü': return 154;
|
||||||
|
case L'¢': return 155;
|
||||||
|
case L'£': return 156;
|
||||||
|
case L'¥': return 157;
|
||||||
|
case L'₧': return 158;
|
||||||
|
case L'ƒ': return 159;
|
||||||
|
case L'á': return 160;
|
||||||
|
case L'í': return 161;
|
||||||
|
case L'ó': return 162;
|
||||||
|
case L'ú': return 163;
|
||||||
|
case L'ñ': return 164;
|
||||||
|
case L'Ñ': return 165;
|
||||||
|
case L'ª': return 166;
|
||||||
|
case L'º': return 167;
|
||||||
|
case L'¿': return 168;
|
||||||
|
case L'⌐': return 169;
|
||||||
|
case L'¬': return 170;
|
||||||
|
case L'½': return 171;
|
||||||
|
case L'¼': return 172;
|
||||||
|
case L'¡': return 173;
|
||||||
|
case L'«': return 174;
|
||||||
|
case L'»': return 175;
|
||||||
|
case L'░': return 176;
|
||||||
|
case L'▒': return 177;
|
||||||
|
case L'▓': return 178;
|
||||||
|
case L'│': return 179;
|
||||||
|
case L'┤': return 180;
|
||||||
|
case L'╡': return 181;
|
||||||
|
case L'╢': return 182;
|
||||||
|
case L'╖': return 183;
|
||||||
|
case L'╕': return 184;
|
||||||
|
case L'╣': return 185;
|
||||||
|
case L'║': return 186;
|
||||||
|
case L'╗': return 187;
|
||||||
|
case L'╝': return 188;
|
||||||
|
case L'╜': return 189;
|
||||||
|
case L'╛': return 190;
|
||||||
|
case L'┐': return 191;
|
||||||
|
case L'└': return 192;
|
||||||
|
case L'┴': return 193;
|
||||||
|
case L'┬': return 194;
|
||||||
|
case L'├': return 195;
|
||||||
|
case L'─': return 196;
|
||||||
|
case L'┼': return 197;
|
||||||
|
case L'╞': return 198;
|
||||||
|
case L'╟': return 199;
|
||||||
|
case L'╚': return 200;
|
||||||
|
case L'╔': return 201;
|
||||||
|
case L'╩': return 202;
|
||||||
|
case L'╦': return 203;
|
||||||
|
case L'╠': return 204;
|
||||||
|
case L'═': return 205;
|
||||||
|
case L'╬': return 206;
|
||||||
|
case L'╧': return 207;
|
||||||
|
case L'╨': return 208;
|
||||||
|
case L'╤': return 209;
|
||||||
|
case L'╥': return 210;
|
||||||
|
case L'╙': return 211;
|
||||||
|
case L'╘': return 212;
|
||||||
|
case L'╒': return 213;
|
||||||
|
case L'╓': return 214;
|
||||||
|
case L'╫': return 215;
|
||||||
|
case L'╪': return 216;
|
||||||
|
case L'┘': return 217;
|
||||||
|
case L'┌': return 218;
|
||||||
|
case L'█': return 219;
|
||||||
|
case L'▄': return 220;
|
||||||
|
case L'▌': return 221;
|
||||||
|
case L'▐': return 222;
|
||||||
|
case L'▀': return 223;
|
||||||
|
case L'α': return 224;
|
||||||
|
case L'ß': return 225; /* German sharp S U+00DF */
|
||||||
|
case L'β': return 225; /* Greek lowercase beta U+03B2 */
|
||||||
|
case L'Γ': return 226;
|
||||||
|
case L'π': return 227;
|
||||||
|
case L'Σ': return 228; /* Greek uppercase sigma U+03A3 */
|
||||||
|
case L'∑': return 228; /* n-ary summation sign U+2211 (replacement) */
|
||||||
|
case L'σ': return 229;
|
||||||
|
case L'µ': return 230;
|
||||||
|
case L'τ': return 231;
|
||||||
|
case L'Φ': return 232;
|
||||||
|
case L'Θ': return 233;
|
||||||
|
case L'Ω': return 234;
|
||||||
|
case L'δ': return 235; /* Greek lowercase delta U+03B4 */
|
||||||
|
case L'ð': return 235; /* Icelandic lowercase eth U+00F0 (replacement) */
|
||||||
|
case L'∂': return 235; /* Partial derivative sign U+2202 (replacement) */
|
||||||
|
case L'∞': return 236;
|
||||||
|
case L'φ': return 237; /* Greek lowercase phi U+03C6 */
|
||||||
|
case L'∅': return 237; /* Empty set sign U+2205 (replacement) */
|
||||||
|
case L'ϕ': return 237; /* Greek phi symbol in italics U+03D5 (replacement) */
|
||||||
|
case L'⌀': return 237; /* Diameter sign U+2300 (replacement) */
|
||||||
|
case L'ø': return 237; /* Latin lowercase O with stroke U+00F8 (replacement) */
|
||||||
|
case L'Ø': return 237; /* Latin uppercase O with stroke U+00D8 (replacement) */
|
||||||
|
case L'ε': return 238; /* Greek lowercase epsilon U+03B5 */
|
||||||
|
case L'∈': return 238; /* Element-of sign U+2208 */
|
||||||
|
case L'€': return 238; /* Euro sign U+20AC */
|
||||||
|
case L'∩': return 239;
|
||||||
|
case L'≡': return 240;
|
||||||
|
case L'±': return 241;
|
||||||
|
case L'≥': return 242;
|
||||||
|
case L'≤': return 243;
|
||||||
|
case L'⌠': return 244;
|
||||||
|
case L'⌡': return 245;
|
||||||
|
case L'÷': return 246;
|
||||||
|
case L'≈': return 247;
|
||||||
|
case L'°': return 248;
|
||||||
|
case L'∙': return 249;
|
||||||
|
case L'·': return 250;
|
||||||
|
case L'√': return 251;
|
||||||
|
case L'ⁿ': return 252;
|
||||||
|
case L'²': return 253;
|
||||||
|
case L'■': return 254;
|
||||||
|
default: return 0 <= c && c < 256 ? c : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static const uint8_t font_replacement_character[16] =
|
||||||
|
{
|
||||||
|
0b00000000,
|
||||||
|
0b00010000,
|
||||||
|
0b00111000,
|
||||||
|
0b01000100,
|
||||||
|
0b10111010,
|
||||||
|
0b10111010,
|
||||||
|
0b11110110,
|
||||||
|
0b11101110,
|
||||||
|
0b11101110,
|
||||||
|
0b11111110,
|
||||||
|
0b01101100,
|
||||||
|
0b00101000,
|
||||||
|
0b00010000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
0b00000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static inline const uint8_t* GetCharacterFont(const uint8_t* font, wchar_t wc)
|
||||||
|
{
|
||||||
|
if ( wc == L'<EFBFBD>' )
|
||||||
|
return font_replacement_character;
|
||||||
|
int remap = MapWideToVGAFont(wc);
|
||||||
|
if ( remap < 0 )
|
||||||
|
return font_replacement_character;
|
||||||
|
return font + 16 * remap;
|
||||||
|
}
|
||||||
|
|
||||||
void Init(const char* devpath, Ref<Descriptor> slashdev);
|
void Init(const char* devpath, Ref<Descriptor> slashdev);
|
||||||
void SetCursor(unsigned x, unsigned y);
|
void SetCursor(unsigned x, unsigned y);
|
||||||
const uint8_t* GetFont();
|
const uint8_t* GetFont();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -34,10 +34,11 @@
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
VGATextBuffer::VGATextBuffer(uint16_t* vga, uint16_t* attr,
|
VGATextBuffer::VGATextBuffer(uint16_t* vga, TextChar* chars, uint16_t* attr,
|
||||||
size_t width, size_t height)
|
size_t width, size_t height)
|
||||||
{
|
{
|
||||||
this->vga = vga;
|
this->vga = vga;
|
||||||
|
this->chars = chars;
|
||||||
this->attr = attr;
|
this->attr = attr;
|
||||||
this->width = width;
|
this->width = width;
|
||||||
this->height = height;
|
this->height = height;
|
||||||
|
@ -50,17 +51,12 @@ VGATextBuffer::~VGATextBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static TextChar EntryToTextChar(uint16_t entry)
|
|
||||||
{
|
|
||||||
char c = entry & 0x00FF;
|
|
||||||
uint8_t vgacolor = entry >> 8U;
|
|
||||||
return TextChar{c, vgacolor};
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t CharToTextEntry(TextChar c)
|
static uint16_t CharToTextEntry(TextChar c)
|
||||||
{
|
{
|
||||||
unsigned char uc = c.c;
|
int remap = VGA::MapWideToVGAFont(c.c);
|
||||||
return (uint16_t) uc | (uint16_t) c.vgacolor << 8U;
|
if ( remap < 0 )
|
||||||
|
return (uint16_t) '?' | (uint16_t) COLOR8_RED << 8U;
|
||||||
|
return (uint16_t) remap | (uint16_t) c.vgacolor << 8U;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VGATextBuffer::UsablePosition(TextPos pos) const
|
bool VGATextBuffer::UsablePosition(TextPos pos) const
|
||||||
|
@ -95,13 +91,14 @@ size_t VGATextBuffer::Height() const
|
||||||
TextChar VGATextBuffer::GetChar(TextPos pos) const
|
TextChar VGATextBuffer::GetChar(TextPos pos) const
|
||||||
{
|
{
|
||||||
if ( UsablePosition(pos) )
|
if ( UsablePosition(pos) )
|
||||||
return EntryToTextChar(vga[OffsetOfPos(pos)]);
|
return chars[OffsetOfPos(pos)];
|
||||||
return {0, 0};
|
return {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,
|
||||||
vga[OffsetOfPos(pos)] = CharToTextEntry(c);
|
vga[OffsetOfPos(pos)] = CharToTextEntry(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,11 +138,13 @@ void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars)
|
||||||
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++ )
|
||||||
vga[dest + i] = vga[src + i],
|
chars[dest + i] = chars[src + i],
|
||||||
|
vga[dest + i] = CharToTextEntry(chars[dest + i]),
|
||||||
attr[dest + i] = attr[src + i];
|
attr[dest + i] = attr[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++ )
|
||||||
vga[dest + numchars-1 - i] = vga[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]),
|
||||||
attr[dest + numchars-1 - i] = attr[src + numchars-1 - i];
|
attr[dest + numchars-1 - i] = attr[src + numchars-1 - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +157,7 @@ void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
||||||
size_t end = OffsetOfPos(to);
|
size_t end = OffsetOfPos(to);
|
||||||
size_t entry = CharToTextEntry(fillwith);
|
size_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,
|
vga[i] = entry,
|
||||||
attr[i] = fillattr;
|
attr[i] = fillattr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace Sortix {
|
||||||
class VGATextBuffer : public TextBuffer
|
class VGATextBuffer : public TextBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VGATextBuffer(uint16_t* vga, uint16_t* attr, size_t width, size_t height);
|
VGATextBuffer(uint16_t* vga, TextChar* chars, uint16_t* attr, 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;
|
||||||
|
@ -60,6 +60,7 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t* vga;
|
uint16_t* vga;
|
||||||
|
TextChar* chars;
|
||||||
uint16_t* attr;
|
uint16_t* attr;
|
||||||
size_t width;
|
size_t width;
|
||||||
size_t height;
|
size_t height;
|
||||||
|
|
Loading…
Add table
Reference in a new issue