/* * Copyright (c) 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 * 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. * * vgatextbuffer.cpp * An indexable text buffer with the VGA text mode framebuffer as backend. */ #include #include #include #include #include #include "vga.h" #include "vgatextbuffer.h" namespace Sortix { VGATextBuffer::VGATextBuffer(uint16_t* vga, TextChar* chars, size_t width, size_t height) { this->vga = vga; this->chars = chars; this->width = width; this->height = height; cursorpos = {0, 0}; cursorenabled = true; UpdateCursor(); } VGATextBuffer::~VGATextBuffer() { } static uint16_t CharToTextEntry(TextChar c) { int remap = VGA::MapWideToVGAFont(c.c); if ( remap < 0 ) remap = 0 /* replacement character */; if ( c.attr & ATTR_BOLD ) c.vgacolor |= 0x08; return (uint16_t) remap | (uint16_t) c.vgacolor << 8U; } 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() { return width; } size_t VGATextBuffer::Height() { return height; } TextChar VGATextBuffer::GetChar(TextPos pos) { if ( UsablePosition(pos) ) return chars[OffsetOfPos(pos)]; return {0, 0, 0, 0, 0}; } void VGATextBuffer::SetChar(TextPos pos, TextChar c) { if ( UsablePosition(pos) ) { chars[OffsetOfPos(pos)] = c; vga[OffsetOfPos(pos)] = CharToTextEntry(c); } } 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); } void VGATextBuffer::Move(TextPos to, TextPos from, size_t numchars) { size_t dest = OffsetOfPos(CropPosition(to)); size_t src = OffsetOfPos(CropPosition(from)); if ( dest < src ) { for ( size_t i = 0; i < numchars; i++ ) { chars[dest + i] = chars[src + i]; vga[dest + i] = CharToTextEntry(chars[dest + i]); } } else if ( src < dest ) { for ( size_t i = 0; i < numchars; i++ ) { chars[dest + numchars-1 - i] = chars[src + numchars-1 - i]; vga[dest + numchars-1 - i] = CharToTextEntry(chars[dest + numchars-1 - i]); } } } void VGATextBuffer::Fill(TextPos from, TextPos to, TextChar fillwith) { from = CropPosition(from); to = CropPosition(to); size_t start = OffsetOfPos(from); size_t end = OffsetOfPos(to); uint16_t entry = CharToTextEntry(fillwith); for ( size_t i = start; i <= end; i++ ) { chars[i] = fillwith; vga[i] = entry; } } bool VGATextBuffer::GetCursorEnabled() { return cursorenabled; } void VGATextBuffer::SetCursorEnabled(bool enablecursor) { cursorenabled = enablecursor; UpdateCursor(); } TextPos VGATextBuffer::GetCursorPos() { 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); } void VGATextBuffer::SpawnThreads() { } void VGATextBuffer::Invalidate() { } 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, 0, 0}); SetCursorPos(TextPos{0, 0}); } void VGATextBuffer::Resume() { UpdateCursor(); } void VGATextBuffer::Pause() { } } // namespace Sortix