mirror of
https://gitlab.os-k.eu/os-k-team/os-k.git
synced 2023-08-25 14:03:10 +02:00
237 lines
5.4 KiB
C
237 lines
5.4 KiB
C
|
//----------------------------------------------------------------------------//
|
||
|
// GNU GPL OS/K //
|
||
|
// //
|
||
|
// Authors: spectral` //
|
||
|
// NeoX //
|
||
|
// //
|
||
|
// Desc: Early terminal functions //
|
||
|
//----------------------------------------------------------------------------//
|
||
|
|
||
|
#include <kaleid.h>
|
||
|
|
||
|
static Terminal_t vgaTerm;
|
||
|
|
||
|
//
|
||
|
// Initialize standard output
|
||
|
//
|
||
|
void InitTerms(void)
|
||
|
{
|
||
|
KalAssert(!GetStdOut() && vgaTerm.initDone != INITOK);
|
||
|
|
||
|
vgaTerm.initDone = INITOK;
|
||
|
|
||
|
SetStdDbg(&vgaTerm);
|
||
|
SetStdOut(&vgaTerm);
|
||
|
|
||
|
ClearTerm(GetStdOut());
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill terminal with spaces
|
||
|
//
|
||
|
error_t ClearTerm(Terminal_t *term)
|
||
|
{
|
||
|
error_t retcode;
|
||
|
|
||
|
if (term == NULL) return EINVAL;
|
||
|
KalAssert(term->initDone == INITOK);
|
||
|
|
||
|
AquireLock(&term->lock);
|
||
|
retcode = term->ClearTermUnlocked(term);
|
||
|
ReleaseLock(&term->lock);
|
||
|
|
||
|
return retcode;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Change the color code
|
||
|
//
|
||
|
error_t ChTermColor(Terminal_t *term, TermColor_t fgColor, TermColor_t bgColor)
|
||
|
{
|
||
|
if (fgColor > KTERM_COLOR_WHITE || bgColor > KTERM_COLOR_WHITE)
|
||
|
return EINVAL;
|
||
|
|
||
|
if (term == NULL)
|
||
|
return EINVAL;
|
||
|
|
||
|
AquireLock(&term->lock);
|
||
|
|
||
|
term->fgColor = fgColor;
|
||
|
term->bgColor = bgColor;
|
||
|
|
||
|
ReleaseLock(&term->lock);
|
||
|
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write a single character on the terminal
|
||
|
//
|
||
|
error_t PutOnTerm(Terminal_t *term, char ch)
|
||
|
{
|
||
|
error_t retcode;
|
||
|
|
||
|
if (term == NULL) return EINVAL;
|
||
|
KalAssert(term->initDone == INITOK);
|
||
|
|
||
|
AquireLock(&term->lock);
|
||
|
retcode = term->PutOnTermUnlocked(term, ch);
|
||
|
ReleaseLock(&term->lock);
|
||
|
|
||
|
return retcode;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Print string on terminal
|
||
|
//
|
||
|
error_t PrintOnTerm(Terminal_t *term, const char *str)
|
||
|
{
|
||
|
error_t retcode = EOK;
|
||
|
|
||
|
if (term == NULL) return EINVAL;
|
||
|
KalAssert(term->initDone == INITOK);
|
||
|
|
||
|
AquireLock(&term->lock);
|
||
|
while (*str && retcode == EOK) {
|
||
|
retcode = term->PutOnTermUnlocked(term, *str++);
|
||
|
}
|
||
|
ReleaseLock(&term->lock);
|
||
|
|
||
|
return retcode;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------//
|
||
|
// Internal functions for VGA terminals //
|
||
|
// These DO NOT check input correctness //
|
||
|
//----------------------------------------------------------//
|
||
|
|
||
|
//
|
||
|
// 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)
|
||
|
|
||
|
//
|
||
|
// Fill terminal with '\0'
|
||
|
//
|
||
|
error_t VGA_ClearTermUnlocked(Terminal_t *term)
|
||
|
{
|
||
|
const uchar color = VGA_ComputeColorCode(term->fgColor, term->bgColor);
|
||
|
const ushort filler = VGA_ComputeEntry('\0', color);
|
||
|
const size_t bufsize = term->width * term->height;
|
||
|
|
||
|
// Fill the buffer
|
||
|
memsetw((ushort *)term->data, filler, bufsize);
|
||
|
|
||
|
// XXX update cursor too
|
||
|
term->currentX = term->currentY = 0;
|
||
|
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write a single character on the terminal
|
||
|
//
|
||
|
error_t VGA_PutOnTermUnlocked(Terminal_t *term, char ch)
|
||
|
{
|
||
|
uint i;
|
||
|
size_t prevY;
|
||
|
|
||
|
if (ch == '\r') {
|
||
|
term->currentX = 0;
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Line feed first takes us to the very end of the line
|
||
|
// Later in this function we actually do the line feed
|
||
|
//
|
||
|
else if (ch == '\n') {
|
||
|
term->currentY = term->width - 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Tabulations account for "term->tabSize" spaces
|
||
|
//
|
||
|
else if (ch == '\t') {
|
||
|
prevY = term->currentY;
|
||
|
for (i = 0; i < term->tabSize; i++) {
|
||
|
//
|
||
|
// Make sure tabulations can't spread over two lines
|
||
|
//
|
||
|
if (term->currentY == prevY) {
|
||
|
VGA_PutOnTermUnlocked(term, ' ');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
ushort *buffer = (ushort *)term->data;
|
||
|
const size_t offset = VGA_ComputeOffset(term, term->currentY, term->currentY);
|
||
|
buffer[offset] = VGA_ComputeEntry(ch, VGA_ComputeColorCode(term->fgColor, term->bgColor));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Did we reach the end of line?
|
||
|
//
|
||
|
if (++term->currentX == term->width) {
|
||
|
term->currentX = 0;
|
||
|
|
||
|
//
|
||
|
// Did we reach the buffer's end?
|
||
|
//
|
||
|
if (++term->currentY == term->height) {
|
||
|
//
|
||
|
// XXX scroll up
|
||
|
//
|
||
|
term->currentY = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Nothing can go wrong
|
||
|
//
|
||
|
return EOK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Print string on terminal
|
||
|
//
|
||
|
error_t VGA_PrintOnTermUnlocked(Terminal_t *term, const char *str)
|
||
|
{
|
||
|
error_t retcode = EOK;
|
||
|
|
||
|
while (*str && retcode == EOK) {
|
||
|
retcode = term->PutOnTermUnlocked(term, *str++);
|
||
|
}
|
||
|
|
||
|
return retcode;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// VGA output
|
||
|
//
|
||
|
static Terminal_t vgaTerm = {
|
||
|
.initDone = FALSE,
|
||
|
.lock = INITLOCK(KLOCK_MUTEX),
|
||
|
|
||
|
.name = "VGA Output Terminal",
|
||
|
.type = "VGA",
|
||
|
|
||
|
.data = (void *)0xB8000,
|
||
|
.width = 80,
|
||
|
.height = 25,
|
||
|
.currentX = 0,
|
||
|
.currentY = 0,
|
||
|
|
||
|
.tabSize = KTABSIZE,
|
||
|
.fgColor = KTERM_COLOR_LGREY,
|
||
|
.bgColor = KTERM_COLOR_BLACK,
|
||
|
|
||
|
.ClearTermUnlocked = VGA_ClearTermUnlocked,
|
||
|
.PutOnTermUnlocked = VGA_PutOnTermUnlocked,
|
||
|
.PrintOnTermUnlocked = VGA_PrintOnTermUnlocked,
|
||
|
};
|
||
|
|