summaryrefslogtreecommitdiff
path: root/archived/projt-launcher/launcher/console/WindowsConsole.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'archived/projt-launcher/launcher/console/WindowsConsole.cpp')
-rw-r--r--archived/projt-launcher/launcher/console/WindowsConsole.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/archived/projt-launcher/launcher/console/WindowsConsole.cpp b/archived/projt-launcher/launcher/console/WindowsConsole.cpp
new file mode 100644
index 0000000000..ecc2b3b7d2
--- /dev/null
+++ b/archived/projt-launcher/launcher/console/WindowsConsole.cpp
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-3.0-only
+// SPDX-FileCopyrightText: 2026 Project Tick
+// SPDX-FileContributor: Project Tick Team
+/*
+ * ProjT Launcher - Minecraft Launcher
+ * Copyright (C) 2026 Project Tick
+ *
+ * This program 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, version 3.
+ *
+ * This program 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 this program. If not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "WindowsConsole.hpp"
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#include <fcntl.h>
+#include <io.h>
+#include <stdio.h>
+#include <iostream>
+
+namespace
+{
+ bool ShouldBindStdHandle(DWORD handleId)
+ {
+ HANDLE handle = GetStdHandle(handleId);
+ if (handle == INVALID_HANDLE_VALUE || handle == nullptr)
+ {
+ return true;
+ }
+ DWORD type = GetFileType(handle);
+ return type == FILE_TYPE_CHAR || type == FILE_TYPE_UNKNOWN;
+ }
+
+ void RedirectHandle(DWORD handleId, FILE* stream, const char* mode)
+ {
+ HANDLE stdHandle = GetStdHandle(handleId);
+ if (stdHandle == INVALID_HANDLE_VALUE || stdHandle == nullptr)
+ {
+ return;
+ }
+
+ int fileDescriptor = _open_osfhandle(reinterpret_cast<intptr_t>(stdHandle), _O_TEXT);
+ if (fileDescriptor == -1)
+ {
+ return;
+ }
+
+ FILE* file = _fdopen(fileDescriptor, mode);
+ if (file == nullptr)
+ {
+ return;
+ }
+
+ if (_dup2(_fileno(file), _fileno(stream)) == 0)
+ {
+ setvbuf(stream, nullptr, _IONBF, 0);
+ }
+ }
+
+ void ReopenToNull(FILE* stream, const char* mode)
+ {
+ FILE* dummyFile = nullptr;
+ freopen_s(&dummyFile, "nul", mode, stream);
+ }
+} // namespace
+
+namespace projt::console
+{
+ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
+ {
+ if (bindStdIn)
+ {
+ ReopenToNull(stdin, "r");
+ }
+ if (bindStdOut)
+ {
+ ReopenToNull(stdout, "w");
+ }
+ if (bindStdErr)
+ {
+ ReopenToNull(stderr, "w");
+ }
+
+ if (bindStdIn)
+ {
+ RedirectHandle(STD_INPUT_HANDLE, stdin, "r");
+ }
+ if (bindStdOut)
+ {
+ RedirectHandle(STD_OUTPUT_HANDLE, stdout, "w");
+ }
+ if (bindStdErr)
+ {
+ RedirectHandle(STD_ERROR_HANDLE, stderr, "w");
+ }
+ if (bindStdIn)
+ {
+ std::wcin.clear();
+ std::cin.clear();
+ }
+ if (bindStdOut)
+ {
+ std::wcout.clear();
+ std::cout.clear();
+ }
+ if (bindStdErr)
+ {
+ std::wcerr.clear();
+ std::cerr.clear();
+ }
+ }
+
+ bool AttachWindowsConsole()
+ {
+ bool bindStdIn = ShouldBindStdHandle(STD_INPUT_HANDLE);
+ bool bindStdOut = ShouldBindStdHandle(STD_OUTPUT_HANDLE);
+ bool bindStdErr = ShouldBindStdHandle(STD_ERROR_HANDLE);
+
+ if (AttachConsole(ATTACH_PARENT_PROCESS))
+ {
+ BindCrtHandlesToStdHandles(bindStdIn, bindStdOut, bindStdErr);
+ return true;
+ }
+
+ return false;
+ }
+
+ std::error_code EnableAnsiSupport()
+ {
+ HANDLE console_handle = CreateFileW(L"CONOUT$",
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (console_handle == INVALID_HANDLE_VALUE)
+ {
+ return std::error_code(GetLastError(), std::system_category());
+ }
+
+ DWORD console_mode;
+ if (0 == GetConsoleMode(console_handle, &console_mode))
+ {
+ auto error = std::error_code(GetLastError(), std::system_category());
+ CloseHandle(console_handle);
+ return error;
+ }
+
+ if ((console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0)
+ {
+ if (0 == SetConsoleMode(console_handle, console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
+ {
+ auto error = std::error_code(GetLastError(), std::system_category());
+ CloseHandle(console_handle);
+ return error;
+ }
+ }
+
+ CloseHandle(console_handle);
+ return {};
+ }
+} // namespace projt::console