diff --git a/Kernel/core/console.cpp b/Kernel/core/console.cpp index 89d99a98..789437dd 100644 --- a/Kernel/core/console.cpp +++ b/Kernel/core/console.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "../kernel.h" @@ -112,6 +113,38 @@ namespace KernelConsole FontRenderer Renderer; + ConsoleTerminal *Terminals[16] = {nullptr}; + std::atomic CurrentTerminal = nullptr; + + void paint_blinker(bool Enable) + { + if (CurrentTerminal == nullptr) + return; + + ConsoleTerminal *term = CurrentTerminal.load(); + ConsoleTerminal::Blinker *blinker = &term->Blink; + + TerminalCell *cell = term->Term->GetCell(Renderer.Cursor.X + Renderer.Cursor.Y * term->Term->GetWinsize()->ws_row); + + uint32_t bgColor = cell->attr.Bright ? TermBrightColors[cell->attr.Background] : TermColors[cell->attr.Background]; + + Renderer.Paint(Renderer.Cursor.X, Renderer.Cursor.Y, + term->Blink.Character, + Enable ? term->Blink.Color : bgColor, + bgColor); + } + + void paint_blinker_thread() + { + bool blink = false; + while (true) + { + paint_blinker(blink); + blink = !blink; + std::this_thread::sleep_for(std::chrono::milliseconds(CurrentTerminal.load()->Blink.Delay)); + } + } + void paint_callback(TerminalCell *cell, long x, long y) { if (cell->attr.Bright) @@ -123,11 +156,9 @@ namespace KernelConsole void cursor_callback(TerminalCursor *cur) { Renderer.Cursor = {cur->X, cur->Y}; + paint_blinker(false); } - VirtualTerminal *Terminals[16] = {nullptr}; - std::atomic CurrentTerminal = nullptr; - bool SetTheme(std::string Theme) { FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode); @@ -267,24 +298,15 @@ namespace KernelConsole size_t Rows = Display->GetWidth / Renderer.CurrentFont->GetInfo().Width; size_t Cols = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height; debug("Terminal size: %ux%u", Rows, Cols); - Terminals[0] = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback); - Terminals[0]->Clear(0, 0, Rows, Cols - 1); + Terminals[0] = new ConsoleTerminal; + Terminals[0]->Term = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback); + Terminals[0]->Term->Clear(0, 0, Rows, Cols - 1); CurrentTerminal.store(Terminals[0], std::memory_order_release); } - void LateInit() + void LoadConsoleConfig(std::string &Config) { - FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode); - if (rn == nullptr) - return; - - kstat st{}; - rn->Stat(&st); - - char *sh = new char[st.Size]; - rn->Read(sh, st.Size, 0); - - ini_t *ini = ini_load(sh, NULL); + ini_t *ini = ini_load(Config.c_str(), NULL); int general = ini_find_section(ini, "general", NULL); int cursor = ini_find_section(ini, "cursor", NULL); assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND); @@ -292,16 +314,22 @@ namespace KernelConsole int themeIndex = ini_find_property(ini, general, "theme", NULL); assert(themeIndex != INI_NOT_FOUND); - int cursorColor = ini_find_property(ini, cursor, "color", NULL); int cursorBlink = ini_find_property(ini, cursor, "blink", NULL); - assert(cursorColor != INI_NOT_FOUND && cursorBlink != INI_NOT_FOUND); + int cursorColor = ini_find_property(ini, cursor, "color", NULL); + int cursorChar = ini_find_property(ini, cursor, "char", NULL); + int cursorDelay = ini_find_property(ini, cursor, "delay", NULL); + assert(cursorBlink != INI_NOT_FOUND && cursorColor != INI_NOT_FOUND && cursorChar != INI_NOT_FOUND && cursorDelay != INI_NOT_FOUND); const char *colorThemeStr = ini_property_value(ini, general, themeIndex); const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor); const char *cursorBlinkStr = ini_property_value(ini, cursor, cursorBlink); + const char *cursorCharStr = ini_property_value(ini, cursor, cursorChar); + const char *cursorDelayStr = ini_property_value(ini, cursor, cursorDelay); debug("colorThemeStr=%s", colorThemeStr); - debug("cursorColorStr=%s", cursorColorStr); debug("cursorBlinkStr=%s", cursorBlinkStr); + debug("cursorColorStr=%s", cursorColorStr); + debug("cursorCharStr=%s", cursorCharStr); + debug("cursorDelayStr=%s", cursorDelayStr); auto getColorComponent = [](const char *str, int &index) -> int { @@ -335,11 +363,36 @@ namespace KernelConsole uint32_t blinkColor = 0xFFFFFF; if (cursorColorStr != 0) blinkColor = parseColor(cursorColorStr); - fixme("cursor blink with colors %X", blinkColor); + debug("cursor blink with colors %X and char '%s' and delay %s", blinkColor, cursorCharStr, cursorDelayStr); + Terminals[0]->Blink.Enabled = true; + Terminals[0]->Blink.Color = blinkColor; + Terminals[0]->Blink.Character = *cursorCharStr; + Terminals[0]->Blink.Delay = atoi(cursorDelayStr); } ini_destroy(ini); - delete[] sh; + } + + void LateInit() + { + FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode); + if (rn == nullptr) + return; + + { + kstat st; + rn->Stat(&st); + std::string cfg; + cfg.reserve(st.Size); + rn->Read(cfg.data(), st.Size, 0); + LoadConsoleConfig(cfg); + } + + if (Terminals[0]->Blink.Enabled) + { + std::thread t = std::thread(paint_blinker_thread); + t.detach(); + } #ifdef DEBUG // __test_themes(); diff --git a/Kernel/core/panic/handler.cpp b/Kernel/core/panic/handler.cpp index ecf4a7d3..744e2e7b 100644 --- a/Kernel/core/panic/handler.cpp +++ b/Kernel/core/panic/handler.cpp @@ -84,7 +84,7 @@ void paint_callback(TerminalCell *cell, long x, long y) nsa void __printfWrapper(char c, void *) { - KernelConsole::Terminals[15]->Process(c); + KernelConsole::Terminals[15]->Term->Process(c); } nsa void ExPrint(const char *Format, ...) @@ -162,7 +162,8 @@ nsa void InitFont() { size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width; size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height; - Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr); + Terminals[15] = new ConsoleTerminal; + Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr); } } @@ -372,7 +373,8 @@ nsa void BaseBufferStackError(bool Stack) { size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width; size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height; - Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr); + Terminals[15] = new ConsoleTerminal; + Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr); } ExceptionLock.store(true, std::memory_order_release); diff --git a/Kernel/drivers/misc/pty/pty.cpp b/Kernel/drivers/misc/pty/pty.cpp index 837826b7..b182c1b4 100644 --- a/Kernel/drivers/misc/pty/pty.cpp +++ b/Kernel/drivers/misc/pty/pty.cpp @@ -37,7 +37,7 @@ namespace Driver::TeleTypeDevices { dev_t min = Node->GetMinor(); if (min == ids.kcon) - return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode); + return KernelConsole::CurrentTerminal.load()->Term->Open(Flags, Mode); else if (min == ids.tty) { TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty; @@ -55,7 +55,7 @@ namespace Driver::TeleTypeDevices { dev_t min = Node->GetMinor(); if (min == ids.kcon) - return KernelConsole::CurrentTerminal.load()->Close(); + return KernelConsole::CurrentTerminal.load()->Term->Close(); else if (min == ids.tty) { TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty; @@ -73,7 +73,7 @@ namespace Driver::TeleTypeDevices { dev_t min = Node->GetMinor(); if (min == ids.kcon) - return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp); + return KernelConsole::CurrentTerminal.load()->Term->Ioctl(Request, Argp); else if (min == ids.tty) { TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty; @@ -91,7 +91,7 @@ namespace Driver::TeleTypeDevices { dev_t min = Node->GetMinor(); if (min == ids.kcon) - return KernelConsole::CurrentTerminal.load()->Read(Buffer, Size, Offset); + return KernelConsole::CurrentTerminal.load()->Term->Read(Buffer, Size, Offset); else if (min == ids.tty) { TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty; @@ -109,7 +109,7 @@ namespace Driver::TeleTypeDevices { dev_t min = Node->GetMinor(); if (min == ids.kcon) - return KernelConsole::CurrentTerminal.load()->Write(Buffer, Size, Offset); + return KernelConsole::CurrentTerminal.load()->Term->Write(Buffer, Size, Offset); else if (min == ids.tty) { TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty; diff --git a/Kernel/exec/spawn.cpp b/Kernel/exec/spawn.cpp index 98885985..9ffb3a43 100644 --- a/Kernel/exec/spawn.cpp +++ b/Kernel/exec/spawn.cpp @@ -170,7 +170,7 @@ namespace Execute fixme("remove workarounds for stdio and tty"); if (!Parent->tty) - Process->tty = KernelConsole::CurrentTerminal.load(); + Process->tty = KernelConsole::CurrentTerminal.load()->Term; if (!ForkStdio(Parent->stdin)) fdt->usr_open("/dev/console", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); diff --git a/Kernel/include/kcon.hpp b/Kernel/include/kcon.hpp index 2644f1fe..3fcda3a9 100644 --- a/Kernel/include/kcon.hpp +++ b/Kernel/include/kcon.hpp @@ -126,20 +126,34 @@ namespace KernelConsole void csi_cha(ANSIArgument *Args, int ArgsCount); void Process(char c); + TerminalCell *GetCell(size_t index) { return &Cells[index]; } + VirtualTerminal(unsigned short Rows, unsigned short Columns, unsigned short XPixels, unsigned short YPixels, PaintCallback Paint, CursorCallback Print); ~VirtualTerminal(); }; + struct ConsoleTerminal + { + VirtualTerminal *Term = nullptr; + struct Blinker + { + bool Enabled = false; + uint32_t Color = 0x000000; + char Character = '\0'; + int Delay = 500; + } Blink; + }; + /** * 0 - Default * 1...11 - User * ... * 15 - Panic */ - extern VirtualTerminal *Terminals[16]; - extern std::atomic CurrentTerminal; + extern ConsoleTerminal *Terminals[16]; + extern std::atomic CurrentTerminal; extern int TermColors[]; extern int TermBrightColors[]; diff --git a/Kernel/kernel.cpp b/Kernel/kernel.cpp index e8f14d63..982e7efd 100644 --- a/Kernel/kernel.cpp +++ b/Kernel/kernel.cpp @@ -62,7 +62,7 @@ UART::Driver uart; EXTERNC void putchar(char c) { - KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire); + KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire)->Term; if (vt != nullptr) vt->Process(c); else diff --git a/Kernel/kernel_thread.cpp b/Kernel/kernel_thread.cpp index 57454002..755a440d 100644 --- a/Kernel/kernel_thread.cpp +++ b/Kernel/kernel_thread.cpp @@ -152,8 +152,7 @@ void KernelMainThread() goto Exit; } - KPrint("Waiting for \x1b[32m%s\x1b[0m to start...", - Config.InitPath); + KPrint("Waiting for init program to start..."); thisThread->SetPriority(Tasking::Idle); initProc = TaskManager->GetProcessByID(tid); diff --git a/Kernel/tasking/process.cpp b/Kernel/tasking/process.cpp index 140642c6..d64d590b 100644 --- a/Kernel/tasking/process.cpp +++ b/Kernel/tasking/process.cpp @@ -282,7 +282,7 @@ namespace Tasking /* FIXME: DON'T DELETE THE TTY spawn.cpp is using this as workaround - tty == KernelConsole::CurrentTerminal.load(); + tty == KernelConsole::CurrentTerminal.load()->Term; */ /* If we own the pointer to the diff --git a/rootfs/sys/cfg/term b/rootfs/sys/cfg/term index f888959a..cc1e7be6 100644 --- a/rootfs/sys/cfg/term +++ b/rootfs/sys/cfg/term @@ -2,8 +2,10 @@ theme=vga [cursor] -color=255,255,255 blink=true +color=244,244,244 +char=_ +delay=250 [vga] color0=0,0,0:133,133,133