mirror of
https://gitlab.os-k.eu/os-k-team/os-k.git
synced 2023-08-25 14:03:10 +02:00
209 lines
5.9 KiB
C
209 lines
5.9 KiB
C
//----------------------------------------------------------------------------//
|
|
// GNU GPL OS/K //
|
|
// //
|
|
// Desc: VGA terminal functions //
|
|
// //
|
|
// //
|
|
// Copyright © 2018-2020 The OS/K Team //
|
|
// //
|
|
// This file is part of OS/K. //
|
|
// //
|
|
// OS/K 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 //
|
|
// any later version. //
|
|
// //
|
|
// OS/K 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. //
|
|
// //
|
|
// You should have received a copy of the GNU General Public License //
|
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
#include <libbuf.h>
|
|
#include <init/boot.h>
|
|
#include <io/cursor.h>
|
|
#include <io/vga.h>
|
|
|
|
const char *RtlColorNames[VGA_COLOR_WHITE+1] =
|
|
{
|
|
"Black", "Blue", "Green", "Cyan", "Red",
|
|
"Magenta", "Brown", "Light Grey", "Dark Grey",
|
|
"Light Blue", "Light Green", "Light Cyan",
|
|
"Light Red", "Light Magenta", "Light Brown", "White",
|
|
};
|
|
|
|
//
|
|
// VGA-related macros
|
|
//
|
|
#define VGA_ComputeColorCode(fg, bg) ((fg) | (bg) << 4)
|
|
#define VGA_ComputeOffset(term, x, y) ((y) * (term)->width + (x))
|
|
#define VGA_ComputeEntry(ch, cl) (((ushort)(ch)) | (ushort)(cl) << 8)
|
|
|
|
static uint bscroll = 0;
|
|
static int bfg = VGA_COLOR_LIGHT_GREY;
|
|
static int bbg = VGA_COLOR_BLACK;
|
|
|
|
static int cursorOffset = 0;
|
|
|
|
//
|
|
// VGA Buffer Flusher
|
|
//
|
|
error_t bvgaflusher(Buffer_t *buf)
|
|
{
|
|
ushort *fbp = BtVideoInfo.framebufferAddr;
|
|
uint color = VGA_ComputeColorCode(bfg, bbg), cols = 0;
|
|
uint oldfg = bfg, skip, rem = BStdOut->lineLen;
|
|
|
|
uchar *currentLine = buf->wp - buf->lastLF;
|
|
uchar *bufStart = (uchar *)lmax((size_t)buf->buf,
|
|
(size_t)currentLine
|
|
- (buf->nLines - 1 + bscroll) * buf->lineLen);
|
|
|
|
uchar *ptr = bufStart;
|
|
|
|
for (skip = 0; ptr < buf->wp ; ptr++) {
|
|
// Handle color codes
|
|
if (*ptr >= RtlColorToChar(VGA_COLOR_BLACK)
|
|
&& *ptr <= RtlColorToChar(VGA_COLOR_WHITE)) {
|
|
skip++; cols++; // 'cols' (colors) is for scrolling
|
|
bfg = RtlCharToColor(*ptr);
|
|
}
|
|
|
|
// Write regular characters
|
|
else {
|
|
color = VGA_ComputeColorCode(bfg, bbg);
|
|
*fbp++ = VGA_ComputeEntry(*ptr, color);
|
|
}
|
|
|
|
// End of line?
|
|
if (--rem == 0) {
|
|
rem = BStdOut->lineLen;
|
|
cols = 0;
|
|
while (skip > 0) {
|
|
skip--;
|
|
*fbp++ = VGA_ComputeEntry(' ', color);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the cursor
|
|
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
|
|
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
|
|
|
|
IoUpdateCursor(max(min(curX + cursorOffset, buf->lineLen), 0), curY);
|
|
|
|
// Empty the rest of the buffer
|
|
|
|
const size_t bufSize = buf->nLines * buf->lineLen;
|
|
ushort *fbe = BtVideoInfo.framebufferAddr
|
|
+ (bufSize * sizeof(ushort));
|
|
|
|
if (fbp < fbe) {
|
|
const ushort filler = VGA_ComputeEntry(' ', color);
|
|
while (fbp < fbe) *fbp++ = filler;
|
|
}
|
|
|
|
bfg = oldfg;
|
|
|
|
return EOK;
|
|
}
|
|
|
|
int IoGetCursorOffset(void) {
|
|
return cursorOffset;
|
|
}
|
|
|
|
void IoSetCursorOffset(int ins) {
|
|
cursorOffset = ins;
|
|
}
|
|
|
|
uint IoGetScroll(void)
|
|
{
|
|
return bscroll;
|
|
}
|
|
|
|
void IoSetScroll(uint value)
|
|
{
|
|
bscroll = 0;
|
|
}
|
|
|
|
void IoScrollDown(void)
|
|
{
|
|
BLockBuf(BStdOut);
|
|
if (bscroll > 0)
|
|
bscroll--;
|
|
bvgaflusher(BStdOut);
|
|
BUnlockBuf(BStdOut);
|
|
}
|
|
|
|
|
|
void IoScrollUp(void)
|
|
{
|
|
BLockBuf(BStdOut);
|
|
|
|
uchar *currentLine = BStdOut->wp - BStdOut->lastLF;
|
|
|
|
// Scrollable lines
|
|
uint scrabble = max(0, (currentLine-BStdOut->buf)/BStdOut->lineLen
|
|
- BStdOut->nLines + 1);
|
|
|
|
if (bscroll < scrabble)
|
|
bscroll++;
|
|
|
|
bvgaflusher(BStdOut);
|
|
BUnlockBuf(BStdOut);
|
|
}
|
|
|
|
void IoChangeTermColor(int fg, int bg)
|
|
{
|
|
if (fg < 0) fg = bfg;
|
|
if (bg < 0) bg = bbg;
|
|
|
|
assert(fg <= VGA_COLOR_WHITE);
|
|
assert(bg <= VGA_COLOR_WHITE);
|
|
|
|
bfg = fg;
|
|
bbg = bg;
|
|
}
|
|
|
|
//
|
|
// Initialize VGA buffer
|
|
//
|
|
error_t IoInitVGABuffer(void)
|
|
{
|
|
static char bvgabufsrc[1 * MB];
|
|
static Buffer_t bvgabufstruct;
|
|
|
|
static char bdbgbufsrc[1 * MB];
|
|
static Buffer_t bdbgbufstruct;
|
|
|
|
BStdOut = &bvgabufstruct;
|
|
|
|
BOpenTermBufEx(&BStdOut,
|
|
bvgabufsrc, BS_WRONLY,
|
|
BtVideoInfo.framebufferWidth,
|
|
BtVideoInfo.framebufferHeight,
|
|
10, bvgaflusher);
|
|
|
|
BEnableAutoScroll(BStdOut);
|
|
|
|
#ifndef NDEBUG
|
|
BStdDbg = &bdbgbufstruct;
|
|
|
|
BOpenTermBufEx(&BStdDbg,
|
|
bdbgbufsrc, BS_WRONLY,
|
|
BtVideoInfo.framebufferWidth,
|
|
BtVideoInfo.framebufferHeight,
|
|
10, NULL);
|
|
|
|
BEnableAutoScroll(BStdDbg);
|
|
#else
|
|
BStdDbg = NULL;
|
|
#endif
|
|
|
|
return EOK;
|
|
}
|
|
|