2012-07-22 18:01:12 -04:00
|
|
|
/*******************************************************************************
|
|
|
|
|
2014-04-19 14:28:54 -04:00
|
|
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
2013-07-10 09:26:01 -04:00
|
|
|
This file is part of Sortix.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
2013-07-10 09:26:01 -04:00
|
|
|
Sortix is free software: you can redistribute it and/or modify it under the
|
|
|
|
terms of the GNU General Public License as published by the Free Software
|
|
|
|
Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
version.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
2013-07-10 09:26:01 -04:00
|
|
|
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
details.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
2013-07-10 09:26:01 -04:00
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
|
|
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
2013-07-10 09:26:01 -04:00
|
|
|
vgatextbuffer.cpp
|
|
|
|
An indexable text buffer with the VGA text mode framebuffer as backend.
|
2012-07-22 18:01:12 -04:00
|
|
|
|
|
|
|
*******************************************************************************/
|
|
|
|
|
2013-10-26 20:42:10 -04:00
|
|
|
#include <sortix/vga.h>
|
|
|
|
|
|
|
|
#include <sortix/kernel/kernel.h>
|
2012-07-22 18:01:12 -04:00
|
|
|
#include <sortix/kernel/kthread.h>
|
|
|
|
#include <sortix/kernel/refcount.h>
|
|
|
|
#include <sortix/kernel/textbuffer.h>
|
2013-10-26 20:42:10 -04:00
|
|
|
|
2012-07-22 18:01:12 -04:00
|
|
|
#include "vga.h"
|
|
|
|
#include "vgatextbuffer.h"
|
|
|
|
|
|
|
|
namespace Sortix {
|
|
|
|
|
2014-04-19 14:28:54 -04:00
|
|
|
VGATextBuffer::VGATextBuffer(uint16_t* vga, TextChar* chars, uint16_t* attr,
|
2012-07-22 18:01:12 -04:00
|
|
|
size_t width, size_t height)
|
|
|
|
{
|
|
|
|
this->vga = vga;
|
2014-04-19 14:28:54 -04:00
|
|
|
this->chars = chars;
|
2012-07-22 18:01:12 -04:00
|
|
|
this->attr = attr;
|
|
|
|
this->width = width;
|
|
|
|
this->height = height;
|
|
|
|
cursorpos = {0, 0};
|
|
|
|
cursorenabled = true;
|
|
|
|
UpdateCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
VGATextBuffer::~VGATextBuffer()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t CharToTextEntry(TextChar c)
|
|
|
|
{
|
2014-04-19 14:28:54 -04:00
|
|
|
int remap = VGA::MapWideToVGAFont(c.c);
|
|
|
|
if ( remap < 0 )
|
2014-12-28 14:18:25 -05:00
|
|
|
remap = 0 /* replacement character */;
|
2014-04-19 14:28:54 -04:00
|
|
|
return (uint16_t) remap | (uint16_t) c.vgacolor << 8U;
|
2012-07-22 18:01:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VGATextBuffer::UsablePosition(TextPos pos) const
|
|
|
|
{
|
|
|
|
return pos.x < width && pos.y < height;
|
|
|
|
}
|
|
|
|
|
|
|
|
TextPos VGATextBuffer::CropPosition(TextPos pos) const
|
|
|
|
{
|
|
|
|
if ( width <= pos.x )
|
|
|
|
pos.x = width - 1;
|
|
|
|
if ( height <= pos.y )
|
|
|
|
pos.y = height -1;
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t VGATextBuffer::OffsetOfPos(TextPos pos) const
|
|
|
|
{
|
|
|
|
return pos.y * width + pos.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t VGATextBuffer::Width() const
|
|
|
|
{
|
|
|
|
return width;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t VGATextBuffer::Height() const
|
|
|
|
{
|
|
|
|
return height;
|
|
|
|
}
|
|
|
|
|
|
|
|
TextChar VGATextBuffer::GetChar(TextPos pos) const
|
|
|
|
{
|
|
|
|
if ( UsablePosition(pos) )
|
2014-04-19 14:28:54 -04:00
|
|
|
return chars[OffsetOfPos(pos)];
|
2012-07-22 18:01:12 -04:00
|
|
|
return {0, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::SetChar(TextPos pos, TextChar c)
|
|
|
|
{
|
|
|
|
if ( UsablePosition(pos) )
|
2014-04-19 14:28:54 -04:00
|
|
|
chars[OffsetOfPos(pos)] = c,
|
2012-07-22 18:01:12 -04:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
if ( !off )
|
|
|
|
return;
|
|
|
|
bool neg = 0 < off;
|
|
|
|
size_t absoff = off < 0 ? -off : off;
|
|
|
|
if ( height < absoff )
|
|
|
|
absoff = height;
|
|
|
|
TextPos scrollfrom = neg ? TextPos{0, absoff} : TextPos{0, 0};
|
|
|
|
TextPos scrollto = neg ? TextPos{0, 0} : TextPos{0, absoff};
|
|
|
|
TextPos fillfrom = neg ? TextPos{0, height-absoff} : TextPos{0, 0};
|
|
|
|
TextPos fillto = neg ? TextPos{width-1, height-1} : TextPos{width-1, absoff-1};
|
|
|
|
size_t scrollchars = width * (height-absoff);
|
|
|
|
Move(scrollto, scrollfrom, scrollchars);
|
|
|
|
Fill(fillfrom, fillto, fillwith, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars)
|
|
|
|
{
|
|
|
|
size_t dest = OffsetOfPos(CropPosition(to));
|
|
|
|
size_t src = OffsetOfPos(CropPosition(from));
|
|
|
|
if ( dest < src )
|
|
|
|
for ( size_t i = 0; i < numchars; i++ )
|
2014-04-19 14:28:54 -04:00
|
|
|
chars[dest + i] = chars[src + i],
|
|
|
|
vga[dest + i] = CharToTextEntry(chars[dest + i]),
|
2012-07-22 18:01:12 -04:00
|
|
|
attr[dest + i] = attr[src + i];
|
|
|
|
else if ( src < dest )
|
|
|
|
for ( size_t i = 0; i < numchars; i++ )
|
2014-04-19 14:28:54 -04:00
|
|
|
chars[dest + numchars-1 - i] = chars[src + numchars-1 - i],
|
|
|
|
vga[dest + numchars-1 - i] = CharToTextEntry(chars[dest + numchars-1 - i]),
|
2012-07-22 18:01:12 -04:00
|
|
|
attr[dest + numchars-1 - i] = attr[src + numchars-1 - i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith,
|
|
|
|
uint16_t fillattr)
|
|
|
|
{
|
|
|
|
from = CropPosition(from);
|
|
|
|
to = CropPosition(to);
|
|
|
|
size_t start = OffsetOfPos(from);
|
|
|
|
size_t end = OffsetOfPos(to);
|
|
|
|
size_t entry = CharToTextEntry(fillwith);
|
|
|
|
for ( size_t i = start; i <= end; i++ )
|
2014-04-19 14:28:54 -04:00
|
|
|
chars[i] = fillwith,
|
2012-07-22 18:01:12 -04:00
|
|
|
vga[i] = entry,
|
|
|
|
attr[i] = fillattr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VGATextBuffer::GetCursorEnabled() const
|
|
|
|
{
|
|
|
|
return cursorenabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::SetCursorEnabled(bool enablecursor)
|
|
|
|
{
|
|
|
|
cursorenabled = enablecursor;
|
|
|
|
UpdateCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
TextPos VGATextBuffer::GetCursorPos() const
|
|
|
|
{
|
|
|
|
return cursorpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::SetCursorPos(TextPos cursorpos)
|
|
|
|
{
|
|
|
|
this->cursorpos = cursorpos;
|
|
|
|
UpdateCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::UpdateCursor()
|
|
|
|
{
|
|
|
|
if ( cursorenabled )
|
|
|
|
VGA::SetCursor(cursorpos.x, cursorpos.y);
|
|
|
|
else
|
|
|
|
VGA::SetCursor(width, height-1);
|
|
|
|
}
|
|
|
|
|
2013-11-11 16:21:56 -05:00
|
|
|
bool VGATextBuffer::EmergencyIsImpaired()
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VGATextBuffer::EmergencyRecoup()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VGATextBuffer::EmergencyReset()
|
|
|
|
{
|
|
|
|
Fill(TextPos{0, 0}, TextPos{width-1, height-1}, TextChar{0, 0}, 0);
|
|
|
|
SetCursorPos(TextPos{0, 0});
|
|
|
|
}
|
|
|
|
|
2012-07-22 18:01:12 -04:00
|
|
|
} // namespace Sortix
|