tty: Fix kcon & tty implementation; Add stub ptmx

This commit is contained in:
EnderIce2
2024-10-13 13:00:22 +03:00
parent f48032658f
commit 396ad681ba
18 changed files with 895 additions and 404 deletions

View File

@ -17,7 +17,6 @@
#include <kcon.hpp>
#include <filesystem/ioctl.hpp>
#include <memory.hpp>
#include <stropts.h>
#include <string.h>
@ -27,100 +26,6 @@
namespace KernelConsole
{
int KConIoctl(struct Inode *Node, unsigned long Request, void *Argp)
{
fixme("KConIoctl");
switch (Request)
{
case TCGETS:
{
struct termios *t = (struct termios *)Argp;
// memcpy(t, &term, sizeof(struct termios));
return 0;
}
case TCSETS:
{
debug("TCSETS not supported");
return -EINVAL;
struct termios *t = (struct termios *)Argp;
// memcpy(&term, t, sizeof(struct termios));
return 0;
}
case TIOCGPGRP:
{
*((pid_t *)Argp) = 0;
return 0;
}
case TIOCSPGRP:
{
*((pid_t *)Argp) = 0;
return 0;
}
case TIOCGWINSZ:
{
struct winsize *ws = (struct winsize *)Argp;
// memcpy(ws, &termSize, sizeof(struct winsize));
return 0;
}
case TIOCSWINSZ:
{
debug("TIOCSWINSZ not supported");
return -EINVAL;
struct winsize *ws = (struct winsize *)Argp;
// memcpy(&termSize, ws, sizeof(struct winsize));
return 0;
}
case TCSETSW:
case TCSETSF:
case TCGETA:
case TCSETA:
case TCSETAW:
case TCSETAF:
case TCSBRK:
case TCXONC:
case TCFLSH:
case TIOCEXCL:
case TIOCNXCL:
case TIOCSCTTY:
case TIOCOUTQ:
case TIOCSTI:
case TIOCMGET:
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
{
fixme("ioctl %#lx not implemented", Request);
return -ENOSYS;
}
case TIOCGPTN:
case 0xffffffff80045430: /* FIXME: ???? */
{
fixme("stub ioctl %#lx", Request);
int *n = (int *)Argp;
*n = -1;
break;
}
case TIOCSPTLCK:
{
fixme("stub ioctl %#lx", Request);
int *n = (int *)Argp;
*n = 0;
break;
}
default:
{
debug("Unknown ioctl %#lx", Request);
return -EINVAL;
}
}
return 0;
}
int TermColors[] = {
[TerminalColor::BLACK] = 0x000000,
[TerminalColor::RED] = 0xAA0000,
@ -369,8 +274,6 @@ namespace KernelConsole
void LateInit()
{
new vfs::PTMXDevice;
FileNode *rn = fs->GetByPath("/etc/term", thisProcess->Info.RootNode);
if (rn == nullptr)
return;

View File

@ -20,6 +20,7 @@
#include <interface/driver.h>
#include <interface/input.h>
#include <memory.hpp>
#include <stropts.h>
#include <ints.hpp>
#include <task.hpp>
#include <printf.h>
@ -44,6 +45,8 @@ namespace Driver
* 4 - /dev/random
* 5 - /dev/mem
* 6 - /dev/kcon
* 7 - /dev/tty
* 8 - /dev/ptmx
*
* maj = 1
* min:
@ -52,9 +55,13 @@ namespace Driver
* ..- /dev/input/eventX
*/
TTY::PTMXDevice *ptmx = nullptr;
int __fs_Lookup(struct Inode *_Parent, const char *Name, struct Inode **Result)
{
auto Parent = (Manager::DeviceInode *)_Parent;
func("%#lx %s %#lx", _Parent, Name, Result);
assert(_Parent != nullptr);
const char *basename;
size_t length;
@ -65,9 +72,10 @@ namespace Driver
return -EINVAL;
}
auto Parent = (Manager::DeviceInode *)_Parent;
for (const auto &child : Parent->Children)
{
debug("Comparing %s with %s", child->Name.c_str(), basename);
debug("Comparing %s with %s", basename, child->Name.c_str());
if (strcmp(child->Name.c_str(), basename) != 0)
continue;
@ -81,6 +89,8 @@ namespace Driver
int __fs_Create(struct Inode *_Parent, const char *Name, mode_t Mode, struct Inode **Result)
{
func("%#lx %s %d", _Parent, Name, Mode);
assert(_Parent != nullptr);
/* We expect to be /dev or children of it */
@ -99,6 +109,7 @@ namespace Driver
ssize_t __fs_Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
func("%#lx %d %d", Node, Size, Offset);
switch (Node->GetMajor())
{
case 0:
@ -141,10 +152,11 @@ namespace Driver
return 0;
}
case 6: /* /dev/kcon */
{
stub;
return 0;
}
return KernelConsole::CurrentTerminal.load()->Read(Buffer, Size, Offset);
case 7: /* /dev/tty */
return ((TTY::TeletypeDriver *)thisProcess->tty)->Read(Buffer, Size, Offset);
case 8: /* /dev/ptmx */
return -ENOSYS;
default:
return -ENOENT;
};
@ -210,6 +222,8 @@ namespace Driver
ssize_t __fs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
func("%#lx %p %d %d", Node, Buffer, Size, Offset);
switch (Node->GetMajor())
{
case 0:
@ -234,13 +248,11 @@ namespace Driver
return 0;
}
case 6: /* /dev/kcon */
{
char *buf = (char *)Buffer;
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load();
for (size_t i = 0; i < Size; i++)
vt->Process(buf[i]);
return Size;
}
return KernelConsole::CurrentTerminal.load()->Write(Buffer, Size, Offset);
case 7: /* /dev/tty */
return ((TTY::TeletypeDriver *)thisProcess->tty)->Write(Buffer, Size, Offset);
case 8: /* /dev/ptmx */
return -ENOSYS;
default:
return -ENOENT;
};
@ -281,9 +293,180 @@ namespace Driver
}
}
int __fs_Open(struct Inode *Node, int Flags, mode_t Mode)
{
func("%#lx %d %d", Node, Flags, Mode);
switch (Node->GetMajor())
{
case 0:
{
switch (Node->GetMinor())
{
case 2: /* /dev/null */
case 3: /* /dev/zero */
case 4: /* /dev/random */
case 5: /* /dev/mem */
return -ENOSYS;
case 6: /* /dev/kcon */
return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode);
case 7: /* /dev/tty */
return ((TTY::TeletypeDriver *)thisProcess->tty)->Open(Flags, Mode);
case 8: /* /dev/ptmx */
return ptmx->Open();
default:
return -ENOENT;
};
}
case 1:
{
switch (Node->GetMinor())
{
case 0: /* /dev/input/keyboard */
case 1: /* /dev/input/mouse */
return -ENOTSUP;
default:
return -ENOENT;
};
}
default:
{
std::unordered_map<dev_t, Driver::DriverObject> &drivers =
DriverManager->GetDrivers();
const auto it = drivers.find(Node->GetMajor());
if (it == drivers.end())
ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor());
const Driver::DriverObject *drv = &it->second;
auto dop = drv->DeviceOperations;
auto dOps = dop->find(Node->GetMinor());
if (dOps == dop->end())
ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor());
AssertReturnError(dOps->second.Ops, -ENOTSUP);
AssertReturnError(dOps->second.Ops->Open, -ENOTSUP);
return dOps->second.Ops->Open(Node, Flags, Mode);
}
}
}
int __fs_Close(struct Inode *Node)
{
func("%#lx", Node);
switch (Node->GetMajor())
{
case 0:
{
switch (Node->GetMinor())
{
case 2: /* /dev/null */
case 3: /* /dev/zero */
case 4: /* /dev/random */
case 5: /* /dev/mem */
return -ENOSYS;
case 6: /* /dev/kcon */
return KernelConsole::CurrentTerminal.load()->Close();
case 7: /* /dev/tty */
return ((TTY::TeletypeDriver *)thisProcess->tty)->Close();
case 8: /* /dev/ptmx */
return ptmx->Close();
default:
return -ENOENT;
};
}
case 1:
{
switch (Node->GetMinor())
{
case 0: /* /dev/input/keyboard */
case 1: /* /dev/input/mouse */
return -ENOTSUP;
default:
return -ENOENT;
};
}
default:
{
std::unordered_map<dev_t, Driver::DriverObject> &drivers =
DriverManager->GetDrivers();
const auto it = drivers.find(Node->GetMajor());
if (it == drivers.end())
ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor());
const Driver::DriverObject *drv = &it->second;
auto dop = drv->DeviceOperations;
auto dOps = dop->find(Node->GetMinor());
if (dOps == dop->end())
ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor());
AssertReturnError(dOps->second.Ops, -ENOTSUP);
AssertReturnError(dOps->second.Ops->Close, -ENOTSUP);
return dOps->second.Ops->Close(Node);
}
}
}
int __fs_Ioctl(struct Inode *Node, unsigned long Request, void *Argp)
{
func("%#lx %lu %#lx", Node, Request, Argp);
switch (Node->GetMajor())
{
case 0:
{
switch (Node->GetMinor())
{
case 2: /* /dev/null */
case 3: /* /dev/zero */
case 4: /* /dev/random */
case 5: /* /dev/mem */
return -ENOSYS;
case 6: /* /dev/kcon */
return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp);
case 7: /* /dev/tty */
return ((TTY::TeletypeDriver *)thisProcess->tty)->Ioctl(Request, Argp);
case 8: /* /dev/ptmx */
return -ENOSYS;
default:
return -ENOENT;
};
break;
}
case 1:
{
switch (Node->GetMinor())
{
case 0: /* /dev/input/keyboard */
case 1: /* /dev/input/mouse */
return -ENOSYS;
default:
return -ENOENT;
};
}
default:
{
std::unordered_map<dev_t, Driver::DriverObject> &drivers =
DriverManager->GetDrivers();
const auto it = drivers.find(Node->GetMajor());
if (it == drivers.end())
ReturnLogError(-EINVAL, "Driver %d not found", Node->GetMajor());
const Driver::DriverObject *drv = &it->second;
auto dop = drv->DeviceOperations;
auto dOps = dop->find(Node->GetMinor());
if (dOps == dop->end())
ReturnLogError(-EINVAL, "Device %d not found", Node->GetMinor());
AssertReturnError(dOps->second.Ops, -ENOTSUP);
AssertReturnError(dOps->second.Ops->Ioctl, -ENOTSUP);
return dOps->second.Ops->Ioctl(Node, Request, Argp);
}
}
}
__no_sanitize("alignment")
ssize_t __fs_Readdir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
{
func("%#lx %#lx %d %d %d", _Node, Buffer, Size, Offset, Entries);
auto Node = (Manager::DeviceInode *)_Node;
off_t realOffset = Offset;
@ -545,6 +728,8 @@ namespace Driver
void Manager::InitializeDaemonFS()
{
ptmx = new TTY::PTMXDevice;
dev_t MinorID = 0;
DeviceInode *_dev = new DeviceInode;
_dev->Name = "dev";
@ -559,7 +744,7 @@ namespace Driver
dev->Flags = I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
FileSystemInfo *fsi = new FileSystemInfo;
fsi->Name = "Driver Manager";
fsi->Name = "Device Virtual File System";
fsi->RootName = "dev";
fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->SuperOps = {};
@ -567,6 +752,9 @@ namespace Driver
fsi->Ops.Create = __fs_Create;
fsi->Ops.Read = __fs_Read;
fsi->Ops.Write = __fs_Write;
fsi->Ops.Open = __fs_Open;
fsi->Ops.Close = __fs_Close;
fsi->Ops.Ioctl = __fs_Ioctl;
fsi->Ops.ReadDir = __fs_Readdir;
dev->Device = fs->RegisterFileSystem(fsi, dev);
@ -642,6 +830,20 @@ namespace Driver
S_IFCHR;
createDevice(_dev, devNode, "kcon", 0, MinorID++, mode);
/* c rw- rw- rw- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IRUSR | S_IWUSR |
S_IFCHR;
createDevice(_dev, devNode, "tty", 0, MinorID++, mode);
/* c rw- rw- rw- */
mode = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IRUSR | S_IWUSR |
S_IFCHR;
createDevice(_dev, devNode, "ptmx", 0, MinorID++, mode);
/* ------------------------------------------------------ */
MinorID = 0;

View File

@ -1,499 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel 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.
Fennix Kernel 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 Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <kcon.hpp>
#include <memory.hpp>
#include <stropts.h>
#include <string.h>
#include <uart.hpp>
#include "../kernel.h"
namespace KernelConsole
{
void VirtualTerminal::Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY)
{
assert(this->PaintCB != nullptr);
for (long i = StartX + StartY * this->termSize.ws_row; i < EndX + EndY * this->termSize.ws_row; i++)
{
TerminalCell *cell = &this->Cells[i];
cell->c = ' ';
cell->attr = {};
this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row);
}
}
void VirtualTerminal::Scroll(unsigned short Lines)
{
assert(this->PaintCB != nullptr);
if (Lines == 0)
return;
Lines = Lines > this->termSize.ws_col ? this->termSize.ws_col : Lines;
for (int i = 0; i < ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i++)
{
this->Cells[i] = this->Cells[i + (this->termSize.ws_row * Lines)];
this->PaintCB(&this->Cells[i], i % this->termSize.ws_row, i / this->termSize.ws_row);
}
for (int i = ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i < this->termSize.ws_row * this->termSize.ws_col; i++)
{
TerminalCell *cell = &this->Cells[i];
cell->attr = {};
cell->c = ' ';
this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row);
}
// Move the cursor up $lines
if (this->Cursor.Y > 0)
{
this->Cursor.Y -= Lines;
if (this->Cursor.Y < 0)
this->Cursor.Y = 0;
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
}
void VirtualTerminal::NewLine()
{
this->Cursor.X = 0;
this->Cursor.Y++;
if (this->Cursor.Y >= this->termSize.ws_col)
this->Scroll(1);
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
void VirtualTerminal::Append(char c)
{
if (c == '\n')
this->NewLine();
else if (c == '\r')
{
this->Cursor.X = 0;
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
else if (c == '\t')
{
int n = 8 - (this->Cursor.X % 8);
for (int i = 0; i < n; i++)
this->Append(' ');
}
else if (c == '\b')
{
if (this->Cursor.X > 0)
{
this->Cursor.X--;
}
else
{
this->Cursor.Y--;
this->Cursor.X = this->termSize.ws_row - 1;
}
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
else
{
if (this->Cursor.X >= this->termSize.ws_row)
this->NewLine();
TerminalCell *cell = &this->Cells[this->Cursor.X + this->Cursor.Y * this->termSize.ws_row];
cell->c = c;
cell->attr = this->Attribute;
assert(this->PaintCB != nullptr);
this->PaintCB(cell, this->Cursor.X, this->Cursor.Y);
this->Cursor.X++;
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
}
void VirtualTerminal::csi_cup(ANSIArgument *Args, int ArgsCount)
{
if (ArgsCount == 1 && Args[0].Empty)
{
this->Cursor.X = 0;
this->Cursor.Y = 0;
}
else if (ArgsCount == 2)
{
if (Args[0].Empty)
this->Cursor.Y = 0;
else
this->Cursor.Y = MIN(Args[0].Value - 1, this->termSize.ws_col - 1);
if (Args[1].Empty)
this->Cursor.Y = 0;
else
this->Cursor.X = MIN(Args[1].Value - 1, this->termSize.ws_row - 1);
}
if (this->CursorCB != nullptr)
this->CursorCB(&this->Cursor);
}
void VirtualTerminal::csi_ed(ANSIArgument *Args, int ArgsCount)
{
TerminalCursor cursor = this->Cursor;
if (Args[0].Empty)
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1);
else
{
int attr = Args[0].Value;
if (attr == 0)
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1);
else if (attr == 1)
this->Clear(0, 0, cursor.X, cursor.Y);
else if (attr == 2)
this->Clear(0, 0, this->termSize.ws_row, this->termSize.ws_col - 1);
}
}
void VirtualTerminal::csi_el(ANSIArgument *Args, int ArgsCount)
{
TerminalCursor cursor = this->Cursor;
if (Args[0].Empty)
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y);
else
{
int attr = Args[0].Value;
if (attr == 0)
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y);
else if (attr == 1)
this->Clear(0, cursor.Y, cursor.X, cursor.Y);
else if (attr == 2)
this->Clear(0, cursor.Y, this->termSize.ws_row, cursor.Y);
}
}
void VirtualTerminal::csi_sgr(ANSIArgument *Args, int ArgsCount)
{
for (int i = 0; i < ArgsCount; i++)
{
if (Args[i].Empty || Args[i].Value == 0)
this->Attribute = {};
else
{
int attr = Args[i].Value;
if (attr == 1)
this->Attribute.Bright = true;
else if (attr >= 30 && attr <= 37)
this->Attribute.Foreground = (TerminalColor)(attr - 30);
else if (attr >= 40 && attr <= 47)
this->Attribute.Background = (TerminalColor)(attr - 40);
}
}
}
void VirtualTerminal::csi_cuu(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.Y -= P1;
if (Cursor.Y < 0)
Cursor.Y = 0;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cud(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.Y += P1;
if (Cursor.Y >= this->termSize.ws_col)
Cursor.Y = this->termSize.ws_col - 1;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cuf(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.X += P1;
if (Cursor.X >= this->termSize.ws_row)
Cursor.X = this->termSize.ws_row - 1;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cub(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.X -= P1;
if (Cursor.X < 0)
Cursor.X = 0;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cnl(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.Y += P1;
if (Cursor.Y >= this->termSize.ws_col)
Cursor.Y = this->termSize.ws_col - 1;
Cursor.X = 0;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cpl(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.Y -= P1;
if (Cursor.Y < 0)
Cursor.Y = 0;
Cursor.X = 0;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::csi_cha(ANSIArgument *Args, int ArgsCount)
{
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
Cursor.X = P1 - 1;
if (Cursor.X >= this->termSize.ws_row)
Cursor.X = this->termSize.ws_row - 1;
if (CursorCB)
CursorCB(&Cursor);
}
void VirtualTerminal::Process(char c)
{
#ifdef DEBUG
static int once = 0;
static uint8_t com4 = 0xFF;
if (!once++)
{
com4 = inb(0x2E8);
debug("COM4 is available");
outb(s_cst(uint16_t, 0x2E8 + 1), 0x00);
outb(s_cst(uint16_t, 0x2E8 + 3), 0x80);
outb(s_cst(uint16_t, 0x2E8 + 0), 0x01);
outb(s_cst(uint16_t, 0x2E8 + 1), 0x00);
outb(s_cst(uint16_t, 0x2E8 + 3), 0x03);
outb(s_cst(uint16_t, 0x2E8 + 2), 0xC7);
outb(s_cst(uint16_t, 0x2E8 + 4), 0x0B);
outb(s_cst(uint16_t, 0x2E8 + 4), 0x0F);
}
if (com4 != 0xFF)
{
while ((inb(s_cst(uint16_t, 0x2E8 + 5)) & 0x20) == 0)
;
outb(0x2E8, c);
}
// while (true)
// {
// while ((inb(0x2E8 + 5) & 1) == 0)
// ;
// outb(0x2E8, inb(0x2E8));
// }
#endif
ANSIParser *parser = &this->Parser;
switch (parser->State)
{
case ANSIParser::ParserState::Escape:
{
if (c == '\x1b')
{
parser->State = ANSIParser::ParserState::Bracket;
parser->Index = 0;
parser->Stack[parser->Index].Value = 0;
parser->Stack[parser->Index].Empty = true;
}
else
{
parser->State = ANSIParser::ParserState::Escape;
this->Append(c);
}
break;
}
case ANSIParser::ParserState::Bracket:
{
if (c == '[')
parser->State = ANSIParser::ParserState::Attribute;
else
{
parser->State = ANSIParser::ParserState::Escape;
this->Append(c);
}
break;
}
case ANSIParser::ParserState::Attribute:
{
if (isdigit(c))
{
parser->Stack[parser->Index].Value *= 10;
parser->Stack[parser->Index].Value += c - '0';
parser->Stack[parser->Index].Empty = false;
}
else
{
if (parser->Index < 8)
parser->Index++;
parser->Stack[parser->Index].Value = 0;
parser->Stack[parser->Index].Empty = true;
parser->State = ANSIParser::ParserState::EndValue;
}
break;
}
case ANSIParser::ParserState::EndValue:
break;
default:
assert(!"Invalid parser state");
}
if (parser->State == ANSIParser::ParserState::EndValue)
{
if (c == ';')
parser->State = ANSIParser::ParserState::Attribute;
else
{
switch (c)
{
case 'A':
this->csi_cuu(parser->Stack, parser->Index);
break;
case 'B':
this->csi_cud(parser->Stack, parser->Index);
break;
case 'C':
this->csi_cuf(parser->Stack, parser->Index);
break;
case 'D':
this->csi_cub(parser->Stack, parser->Index);
break;
case 'E':
this->csi_cnl(parser->Stack, parser->Index);
break;
case 'F':
this->csi_cpl(parser->Stack, parser->Index);
break;
case 'G':
this->csi_cha(parser->Stack, parser->Index);
break;
case 'd':
fixme("move cursor left P1 columns");
break;
case 'H':
this->csi_cup(parser->Stack, parser->Index);
break;
case 'J':
this->csi_ed(parser->Stack, parser->Index);
break;
case 'K':
this->csi_el(parser->Stack, parser->Index);
break;
case 'm':
this->csi_sgr(parser->Stack, parser->Index);
break;
default:
break;
}
parser->State = ANSIParser::ParserState::Escape;
}
}
}
VirtualTerminal::VirtualTerminal(unsigned short Rows, unsigned short Columns,
unsigned short XPixels, unsigned short YPixels,
PaintCallback _Paint, CursorCallback _Print)
: PaintCB(_Paint), CursorCB(_Print)
{
this->termSize = {
.ws_row = Rows,
.ws_col = Columns,
.ws_xpixel = XPixels,
.ws_ypixel = YPixels,
};
/*
- ICRNL - Map Carriage Return to New Line
- IXON - Enable XON/XOFF flow control
- OPOST - Enable output processing
- ONLCR - Map New Line to Carriage Return - New Line
- CS8 - 8-bit characters
- CREAD - Enable receiver
- HUPCL - Hang up on last close
- ECHO - Echo input characters
- ICANON - Enable canonical input (enable line editing)
*/
this->term.c_iflag = /*ICRNL |*/ IXON;
this->term.c_oflag = OPOST | ONLCR;
this->term.c_cflag = CS8 | CREAD | HUPCL;
this->term.c_lflag = ECHO | ICANON;
this->term.c_cc[VINTR] = 0x03; /* ^C */
this->term.c_cc[VQUIT] = 0x1C; /* ^\ */
this->term.c_cc[VERASE] = 0x7F; /* DEL */
this->term.c_cc[VKILL] = 0x15; /* ^U */
this->term.c_cc[VEOF] = 0x04; /* ^D */
this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
this->term.c_cc[VSWTC] = 0; /* ^O */
this->term.c_cc[VSTART] = 0x11; /* ^Q */
this->term.c_cc[VSTOP] = 0x13; /* ^S */
this->term.c_cc[VSUSP] = 0x1A; /* ^Z */
this->term.c_cc[VEOL] = 0x00; /* NUL */
this->term.c_cc[VREPRINT] = 0x12; /* ^R */
this->term.c_cc[VDISCARD] = 0x14; /* ^T */
this->term.c_cc[VWERASE] = 0x17; /* ^W */
this->term.c_cc[VLNEXT] = 0x19; /* ^Y */
this->term.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */
this->Cells = new TerminalCell[Rows * Columns];
debug("Allocated %d bytes for terminal cells",
(Rows * Columns) * sizeof(TerminalCell));
}
VirtualTerminal::~VirtualTerminal()
{
delete[] this->Cells;
}
}