eterm code refactor.

This commit is contained in:
Martín Lucas Golini
2022-07-03 19:41:58 -03:00
parent 8c6035a0bb
commit 3eb9d75fa4
35 changed files with 240 additions and 143 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
#include "terminal/terminaldisplay.hpp"
#include <eepp/ee.hpp>
#include <eterm/terminal/terminaldisplay.hpp>
EE::Window::Window* win = NULL;
std::shared_ptr<TerminalDisplay> terminal = nullptr;
-94
View File
@@ -1,94 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include "autohandle.hpp"
#ifndef _WIN32
#include <unistd.h>
#else
#include <windows.h>
#endif
EE::AutoHandle::AutoHandle() : mHandle( invalid_value() ) {}
EE::AutoHandle::AutoHandle( AutoHandle&& other ) : mHandle( other.mHandle ) {
other.mHandle = invalid_value();
}
EE::AutoHandle::~AutoHandle() {
release();
}
EE::AutoHandle& EE::AutoHandle::operator=( AutoHandle&& other ) {
if ( mHandle == other.mHandle )
return *this;
release();
mHandle = other.mHandle;
other.mHandle = invalid_value();
return *this;
}
#ifdef _WIN32
EE::AutoHandle::AutoHandle( HANDLE handle ) : mHandle( handle ) {}
void EE::AutoHandle::release() const {
if ( mHandle != INVALID_HANDLE_VALUE ) {
CloseHandle( mHandle );
mHandle = INVALID_HANDLE_VALUE;
}
}
#else
EE::AutoHandle::AutoHandle( int fd ) : mHandle( fd ) {}
void EE::AutoHandle::release() const {
if ( mHandle != -1 ) {
close( mHandle );
}
}
#endif
EE::AutoHandle::operator bool() const noexcept {
return mHandle != invalid_value();
}
EE::AutoHandle::type* EE::AutoHandle::get() {
return &mHandle;
}
const EE::AutoHandle::type* EE::AutoHandle::get() const {
return &mHandle;
}
EE::AutoHandle::operator EE::AutoHandle::type() const noexcept {
return mHandle;
}
#ifdef _WIN32
// On Windows we deal with the Windows API, which means HANDLE is used as the handle to files
// and pipes
constexpr EE::AutoHandle::type EE::AutoHandle::invalid_value() {
return nullptr;
}
#else
// On non-Windows OS'es we deal with file descriptors
constexpr EE::AutoHandle::type EE::AutoHandle::invalid_value() {
return -1;
}
#endif
-71
View File
@@ -1,71 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
namespace EE {
// This class is designed to automatically free a resource handle when destructed
class AutoHandle final {
public:
#ifdef _WIN32
// On Windows we deal with the Windows API, which means HANDLE is used as the handle to files
// and pipes
using type = void*;
static constexpr type invalid_value();
#else
// On non-Windows OS'es we deal with file descriptors
using type = int;
static constexpr type invalid_value();
#endif
explicit AutoHandle( type handle );
AutoHandle();
AutoHandle( AutoHandle&& other );
~AutoHandle();
AutoHandle& operator=( AutoHandle&& other );
AutoHandle( const AutoHandle& ) = delete;
AutoHandle& operator=( const AutoHandle& ) = delete;
explicit operator type() const noexcept;
operator bool() const noexcept;
type* get();
const type* get() const;
type handle() const {
return mHandle;
}
void release() const;
private:
mutable type mHandle;
};
} // namespace EE
-50
View File
@@ -1,50 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include <stdint.h>
#include <stdlib.h>
namespace EE { namespace System {
class IPipe {
public:
IPipe() = default;
IPipe( IPipe&& ) = delete;
IPipe( const IPipe& ) = delete;
IPipe& operator=( IPipe&& ) = delete;
IPipe& operator=( const IPipe& ) = delete;
virtual ~IPipe() = default;
virtual bool isTTY() const = 0;
virtual int write( const char* s, size_t n ) = 0;
virtual int read( char* buf, size_t n, bool block = false ) = 0;
};
}} // namespace EE::System
-53
View File
@@ -1,53 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
namespace EE { namespace System {
enum class ProcessStatus { RUNNING = 0, EXITED };
class IProcess {
public:
IProcess() = default;
virtual ~IProcess() = default;
IProcess( const IProcess& ) = delete;
IProcess( IProcess&& ) = delete;
IProcess& operator=( const IProcess& ) = delete;
IProcess& operator=( IProcess&& ) = delete;
virtual void checkExitStatus() = 0;
virtual bool hasExited() const = 0;
virtual int getExitCode() const = 0;
virtual void terminate() = 0;
virtual void waitForExit() = 0;
};
}} // namespace EE::System
@@ -1,61 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "../terminal/ipseudoterminal.hpp"
#include "iprocess.hpp"
#include <memory>
#include <string>
#include <vector>
using namespace EE::Terminal;
namespace EE { namespace System {
class IProcessFactory {
public:
IProcessFactory() = default;
virtual ~IProcessFactory() = default;
IProcessFactory( const IProcessFactory& ) = delete;
IProcessFactory( IProcessFactory&& ) = delete;
IProcessFactory& operator=( const IProcessFactory& ) = delete;
IProcessFactory& operator=( IProcessFactory&& ) = delete;
virtual std::unique_ptr<IProcess> createWithStdioPipe( const std::string& program,
const std::vector<std::string>& args,
const std::string& workingDirectory,
std::unique_ptr<IPipe>& outPipe,
bool withStderr = true ) = 0;
virtual std::unique_ptr<IProcess>
createWithPseudoTerminal( const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory, int numColumns, int numRows,
std::unique_ptr<IPseudoTerminal>& outPseudoTerminal ) = 0;
};
}} // namespace EE::System
-52
View File
@@ -1,52 +0,0 @@
#ifdef _WIN32
#include "pipe.hpp"
#include "../terminal/windowserrors.hpp"
#include <windows.h>
using namespace EE::System;
Pipe::Pipe( AutoHandle&& readHandle, AutoHandle&& writeHandle ) :
mInputHandle( std::move( readHandle ) ), mOutputHandle( std::move( writeHandle ) ) {}
bool Pipe::isTTY() const {
return false;
}
int Pipe::write( const char* s, size_t n ) {
constexpr size_t lim = 256;
DWORD c = (DWORD)n;
DWORD r = 0;
while ( n > 0 ) {
if ( !WriteFile( (HANDLE)mOutputHandle, s, (DWORD)( n > lim ? lim : n ), &r, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
s += r;
n -= r;
}
return (int)c;
}
int Pipe::read( char* buf, size_t n, bool block ) {
DWORD available;
DWORD read;
if ( !block ) {
if ( !PeekNamedPipe( mInputHandle.handle(), nullptr, 0, nullptr, &available, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
if ( available == 0 )
return 0;
}
if ( !ReadFile( mInputHandle.handle(), buf, (DWORD)n, &read, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
return (int)read;
}
#endif
-66
View File
@@ -1,66 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "../system/ipipe.hpp"
#include "autohandle.hpp"
#include <memory>
namespace EE { namespace System {
class Process;
class Pipe : public IPipe {
public:
Pipe( Pipe&& ) = delete;
Pipe( const Pipe& ) = delete;
Pipe& operator=( Pipe&& ) = delete;
Pipe& operator=( const Pipe& ) = delete;
virtual ~Pipe() = default;
virtual bool isTTY() const override;
virtual int write( const char* s, size_t n ) override;
virtual int read( char* buf, size_t n, bool block = false ) override;
static bool CreatePipePair( std::unique_ptr<Pipe>& outPipeA, std::unique_ptr<Pipe>& outPipeB );
private:
friend class Process;
#ifdef _WIN32
AutoHandle mInputHandle;
AutoHandle mOutputHandle;
Pipe( AutoHandle&& readHandle, AutoHandle&& writeHandle );
#else
AutoHandle mHandle;
Pipe( AutoHandle&& handle );
#endif
};
}} // namespace EE::System
-452
View File
@@ -1,452 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef _WIN32
#include "process.hpp"
#include <eepp/system/filesystem.hpp>
#include <poll.h>
#include <pwd.h>
#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#if defined( __linux )
#include <pty.h>
#elif defined( __OpenBSD__ ) || defined( __NetBSD__ ) || defined( __APPLE__ )
#include <sys/errno.h>
#include <util.h>
#elif defined( __FreeBSD__ ) || defined( __DragonFly__ )
#include <libutil.h>
#include <sys/errno.h>
#endif
using namespace EE::System;
Process::~Process() {
if ( mPID != -1 ) {
kill( mPID, SIGHUP );
}
}
void Process::checkExitStatus() {
if ( mStatus == ProcessStatus::EXITED ) {
return;
}
int status = 0;
int p = waitpid( mPID, &status, WNOHANG );
if ( p < 0 ) {
perror( "Process::checkExitStatus(waitpid)" );
}
if ( p == 0 ) {
return;
}
mStatus = ProcessStatus::EXITED;
mExitCode = WEXITSTATUS( status );
}
void Process::terminate() {
if ( mStatus == ProcessStatus::EXITED ) {
return;
}
if ( mPID != -1 ) {
kill( mPID, SIGHUP );
mExitCode = 1;
mStatus = ProcessStatus::EXITED;
}
}
void Process::waitForExit() {
if ( mStatus == ProcessStatus::EXITED ) {
return;
}
int status = 0;
int p = waitpid( mPID, &status, 0 );
if ( p < 0 ) {
perror( "Process::waitForExit(waitpid)" );
return;
}
mStatus = ProcessStatus::EXITED;
mExitCode = WEXITSTATUS( status );
}
bool Process::hasExited() const {
return mStatus == EE::System::ProcessStatus::EXITED;
}
int Process::getExitCode() const {
return mStatus == ProcessStatus::EXITED ? mExitCode : 255;
}
Process::Process( int pid ) : mPID( pid ) {}
static void execshell( const char* cmd, const char* const* args, std::string workingDirectory ) {
const struct passwd* pw;
const char* sh;
errno = 0;
if ( ( pw = getpwuid( getuid() ) ) == NULL ) {
if ( errno ) {
fprintf( stderr, "getpwuid: %s\n", strerror( errno ) );
_exit( 1 );
} else {
fprintf( stderr, "who are you?\n" );
_exit( 1 );
}
}
if ( ( sh = getenv( "SHELL" ) ) == NULL )
sh = ( pw->pw_shell[0] ) ? pw->pw_shell : cmd;
if ( workingDirectory.empty() )
workingDirectory = pw->pw_dir;
FileSystem::changeWorkingDirectory( workingDirectory );
unsetenv( "COLUMNS" );
unsetenv( "LINES" );
unsetenv( "TERMCAP" );
setenv( "LOGNAME", pw->pw_name, 1 );
setenv( "USER", pw->pw_name, 1 );
setenv( "SHELL", sh, 1 );
setenv( "HOME", pw->pw_dir, 1 );
setenv( "TERM", "st-256color", 1 );
signal( SIGCHLD, SIG_DFL );
signal( SIGHUP, SIG_DFL );
signal( SIGINT, SIG_DFL );
signal( SIGQUIT, SIG_DFL );
signal( SIGTERM, SIG_DFL );
signal( SIGALRM, SIG_DFL );
execvp( cmd, (char* const*)args );
_exit( 1 );
}
std::unique_ptr<Process> Process::createWithPipe( const std::string& /*program*/,
const std::vector<std::string>& /*args*/,
const std::string& /*workingDirectory*/,
std::unique_ptr<IPipe>& outPipe,
bool /*withStderr*/ ) {
outPipe = nullptr;
return nullptr;
}
std::unique_ptr<Process>
Process::createWithPseudoTerminal( const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory,
Terminal::PseudoTerminal& pseudoTerminal ) {
int pid = fork();
if ( pid == -1 ) {
fprintf( stderr, "Failed to fork process\n" );
return nullptr;
} else if ( pid == 0 ) {
setsid();
dup2( (int)pseudoTerminal.mSlave, 0 );
dup2( (int)pseudoTerminal.mSlave, 1 );
dup2( (int)pseudoTerminal.mSlave, 2 );
if ( ioctl( (int)pseudoTerminal.mSlave, TIOCSCTTY, NULL ) < 0 ) {
fprintf( stderr, "ioctl TIOCSCTTY failed: %s", strerror( errno ) );
exit( 1 );
}
// Make sure all non stdio file descriptors are closed before exec
int fdlimit = (int)sysconf( _SC_OPEN_MAX );
for ( int i = 3; i < fdlimit; i++ )
close( i );
#ifdef __OpenBSD__
if ( pledge( "stdio getpw proc exec", NULL ) == -1 ) {
fprintf( stderr, "pledge\n" );
exit( 1 );
}
#endif
std::vector<const char*> argsV;
argsV.push_back( program.c_str() );
for ( auto& a : args ) {
argsV.push_back( a.c_str() );
}
argsV.push_back( nullptr );
execshell( program.c_str(), argsV.data(), workingDirectory );
} else {
pseudoTerminal.mSlave.release();
return std::unique_ptr<Process>( new Process( pid ) );
}
return nullptr;
}
#else
#include "../terminal/windowserrors.hpp"
#include "pipe.hpp"
#include "process.hpp"
#include <assert.h>
#include <iomanip>
#include <sstream>
#define NTDDI_VERSION NTDDI_WIN10_RS5
#include <windows.h>
using namespace EE::System;
using namespace EE;
static std::wstring stringToWideString( const std::string& str ) {
if ( str.empty() )
return std::wstring();
int size_needed = MultiByteToWideChar( CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0 );
std::wstring wstrTo( size_needed, 0 );
MultiByteToWideChar( CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed );
return wstrTo;
}
#define HANDLE_WIN_ERR( err ) HRESULT_FROM_WIN32( err ), PrintWinApiError( err )
static HRESULT InitializeStartupInfoAttachedToPseudoConsole( STARTUPINFOEXW* pStartupInfo,
HPCON hPC ) {
HRESULT hr{ E_UNEXPECTED };
if ( pStartupInfo ) {
SIZE_T attrListSize{};
pStartupInfo->StartupInfo.cb = sizeof( STARTUPINFOEXW );
// pStartupInfo->StartupInfo.dwFlags = STARTF_USESTDHANDLES;
// Get the size of the thread attribute list.
InitializeProcThreadAttributeList( NULL, 1, 0, &attrListSize );
// Allocate a thread attribute list of the correct size
pStartupInfo->lpAttributeList = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(
HeapAlloc( GetProcessHeap(), 0, attrListSize ) );
// Initialize thread attribute list
if ( pStartupInfo->lpAttributeList &&
InitializeProcThreadAttributeList( pStartupInfo->lpAttributeList, 1, 0,
&attrListSize ) ) {
// Set Pseudo Console attribute
hr = UpdateProcThreadAttribute( pStartupInfo->lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof( hPC ),
NULL, NULL )
? S_OK
: HANDLE_WIN_ERR( GetLastError() );
printf( "errrr1: %ld", hr );
} else {
hr = HANDLE_WIN_ERR( GetLastError() );
}
}
return hr;
}
Process::Process( AutoHandle&& hProcess, void* lpAttributeList ) :
mStatus( ProcessStatus::RUNNING ),
mLeaveRunning( false ),
mExitCode( 1 ),
mProcessHandle( std::move( hProcess ) ),
mLpAttributeList( lpAttributeList ) {}
Process::~Process() {
if ( mLpAttributeList ) {
DeleteProcThreadAttributeList( (LPPROC_THREAD_ATTRIBUTE_LIST)mLpAttributeList );
HeapFree( GetProcessHeap(), 0, mLpAttributeList );
}
if ( !mLeaveRunning ) {
terminate();
}
}
void Process::checkExitStatus() {
if ( mStatus == ProcessStatus::RUNNING ) {
DWORD exitCode;
if ( GetExitCodeProcess( (HANDLE)mProcessHandle, &exitCode ) && exitCode != STILL_ACTIVE ) {
mStatus = ProcessStatus::EXITED;
mExitCode = (int)exitCode;
}
}
}
bool Process::hasExited() const {
return mStatus == ProcessStatus::EXITED;
}
int Process::getExitCode() const {
return mStatus == ProcessStatus::EXITED ? mExitCode : STILL_ACTIVE;
}
void Process::terminate() {
if ( mStatus == ProcessStatus::RUNNING ) {
TerminateProcess( (HANDLE)mProcessHandle, EXIT_FAILURE );
mExitCode = EXIT_FAILURE;
mStatus = ProcessStatus::EXITED;
mProcessHandle.release();
}
}
void Process::waitForExit() {
checkExitStatus();
if ( mStatus == ProcessStatus::RUNNING ) {
WaitForSingleObject( (HANDLE)mProcessHandle, INFINITE );
}
}
std::unique_ptr<Process> Process::createWithPipe( const std::string& program,
const std::vector<std::string>& args,
const std::string& workingDirectory,
std::unique_ptr<IPipe>& outPipe,
bool withStderr ) {
outPipe = nullptr;
SECURITY_ATTRIBUTES saAttr;
ZeroMemory( &saAttr, sizeof( saAttr ) );
saAttr.nLength = sizeof( saAttr );
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
AutoHandle g_hChildStd_IN_Rd{};
AutoHandle g_hChildStd_IN_Wr{};
AutoHandle g_hChildStd_OUT_Rd{};
AutoHandle g_hChildStd_OUT_Wr{};
if ( !CreatePipe( g_hChildStd_OUT_Rd.get(), g_hChildStd_OUT_Wr.get(), &saAttr, 0 ) ) {
fprintf( stderr, "Failed to create pipe (Stdout)\n" );
return nullptr;
}
if ( !SetHandleInformation( (HANDLE)g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ) ) {
fprintf( stderr, "Failed to set handle information (Stdout)\n" );
return nullptr;
}
if ( !CreatePipe( g_hChildStd_IN_Rd.get(), g_hChildStd_IN_Wr.get(), &saAttr, 0 ) ) {
fprintf( stderr, "Failed to create pipe (Stdin)\n" );
return nullptr;
}
if ( !SetHandleInformation( (HANDLE)g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0 ) ) {
fprintf( stderr, "Failed to set handle information (Stdin)\n" );
return nullptr;
}
PROCESS_INFORMATION piProcInfo;
STARTUPINFOW siStartInfo;
ZeroMemory( &piProcInfo, sizeof( PROCESS_INFORMATION ) );
ZeroMemory( &siStartInfo, sizeof( STARTUPINFOW ) );
siStartInfo.cb = sizeof( STARTUPINFOW );
siStartInfo.hStdError = withStderr ? (HANDLE)g_hChildStd_OUT_Wr : INVALID_HANDLE_VALUE;
siStartInfo.hStdOutput = (HANDLE)g_hChildStd_OUT_Wr;
siStartInfo.hStdInput = (HANDLE)g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
std::ostringstream oss;
oss << std::quoted( program );
for ( auto& arg : args ) {
oss << ' ' << arg;
}
std::wstring commandLine = stringToWideString( oss.str() );
// TODO: If workingDirectory is relative, make it absolute (relative to the
// current process working directory)
std::wstring workingDir = stringToWideString( workingDirectory );
if ( CreateProcessW( NULL, (LPWSTR)commandLine.c_str(), NULL, NULL, TRUE, 0, NULL,
workingDir.empty() ? NULL : workingDir.c_str(), &siStartInfo,
&piProcInfo ) ) {
std::unique_ptr<Pipe> pipe = std::unique_ptr<Pipe>(
new Pipe( std::move( g_hChildStd_OUT_Rd ), std::move( g_hChildStd_IN_Wr ) ) );
outPipe = std::move( pipe );
AutoHandle hProcess{ piProcInfo.hProcess };
AutoHandle hThread{ piProcInfo.hThread };
return std::unique_ptr<Process>( new Process( std::move( hProcess ), NULL ) );
}
// PrintWinApiError( GetLastError() );
return nullptr;
}
std::unique_ptr<Process>
Process::createWithPseudoTerminal( const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory,
Terminal::PseudoTerminal& pseudoTerminal ) {
SetEnvironmentVariableA( "WSLENV", "TERM/u" );
SetEnvironmentVariableA( "TERM", "st-256color" );
HRESULT hr{ E_UNEXPECTED };
AutoHandle hProcess{};
AutoHandle hThread{};
STARTUPINFOEXW startupInfo{};
PROCESS_INFORMATION piClient{};
std::ostringstream oss;
oss << std::quoted( program );
for ( auto& arg : args ) {
oss << ' ' << arg;
}
std::wstring commandLine = stringToWideString( oss.str() );
// TODO: If workingDirectory is relative, make it absolute (relative to the
// current process working directory)
std::wstring workingDir = stringToWideString( workingDirectory );
if ( ( hr = InitializeStartupInfoAttachedToPseudoConsole( &startupInfo,
pseudoTerminal.mPHPC ) ) != S_OK ) {
printf( "InitializeStartupInfoAttachedToPseudoConsole failed\n" );
PrintErrorResult( hr );
goto fail;
}
hr = CreateProcessW( NULL, // No module name - use Command Line
(wchar_t*)commandLine.c_str(), // Command Line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Inherit handles
EXTENDED_STARTUPINFO_PRESENT, // Creation flags
NULL, // Use parent's environment block
workingDir.empty() ? NULL
: workingDir.c_str(), // Use parent's starting directory
&startupInfo.StartupInfo, // Pointer to STARTUPINFO
&piClient ) // Pointer to PROCESS_INFORMATION
? S_OK
: HANDLE_WIN_ERR( GetLastError() );
if ( hr != S_OK ) {
printf( "CreateProcessW failed\n" );
goto fail;
}
hProcess = AutoHandle( piClient.hProcess );
hThread = AutoHandle( piClient.hThread );
pseudoTerminal.mAttached = true;
return std::unique_ptr<Process>(
new Process( std::move( hProcess ), startupInfo.lpAttributeList ) );
fail:
return std::unique_ptr<Process>();
}
#endif
-82
View File
@@ -1,82 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "../terminal/pseudoterminal.hpp"
#include "iprocess.hpp"
namespace EE { namespace System {
class Process final : public IProcess {
public:
~Process();
Process( const Process& ) = delete;
Process( Process&& ) = delete;
Process& operator=( const Process& ) = delete;
Process& operator=( Process&& ) = delete;
virtual void checkExitStatus() override;
virtual bool hasExited() const override;
virtual int getExitCode() const override;
virtual void terminate() override;
virtual void waitForExit() override;
static std::unique_ptr<Process> createWithPipe( const std::string& program,
const std::vector<std::string>& args,
const std::string& workingDirectory,
std::unique_ptr<IPipe>& outPipe,
bool withStderr = true );
static std::unique_ptr<Process>
createWithPseudoTerminal( const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory,
Terminal::PseudoTerminal& pseudoTerminal );
private:
ProcessStatus mStatus{ ProcessStatus::RUNNING };
int mExitCode{ 1 };
#ifdef _WIN32
bool mLeaveRunning{ false };
AutoHandle mProcessHandle;
void* mLpAttributeList;
Process( AutoHandle&& processHandle, void* lpAttributeList );
#else
int mPID;
Process( int pid );
#endif
};
}} // namespace EE::System
-37
View File
@@ -1,37 +0,0 @@
#include "../system/processfactory.hpp"
#include "../system/process.hpp"
#include "../terminal/pseudoterminal.hpp"
using namespace EE::System;
std::unique_ptr<IProcess> ProcessFactory::createWithStdioPipe( const std::string& program,
const std::vector<std::string>& args,
const std::string& workingDirectory,
std::unique_ptr<IPipe>& outPipe,
bool withStderr ) {
return Process::createWithPipe( program, args, workingDirectory, outPipe, withStderr );
}
std::unique_ptr<IProcess> ProcessFactory::createWithPseudoTerminal(
const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory, int numColumns, int numRows,
std::unique_ptr<IPseudoTerminal>& outPseudoTerminal ) {
outPseudoTerminal = nullptr;
auto pseudoTerminal = Terminal::PseudoTerminal::create( numColumns, numRows );
if ( !pseudoTerminal ) {
fprintf( stderr,
"ProcessFactory::createWithPseudoTerminal: Failed to create pseudo terminal\n" );
return nullptr;
}
auto process = System::Process::createWithPseudoTerminal( program, args, workingDirectory,
*pseudoTerminal );
if ( !process ) {
fprintf( stderr, "ProcessFactory::createWithPseudoTerminal: Failed to spawn process\n" );
return nullptr;
}
outPseudoTerminal = std::move( pseudoTerminal );
return process;
}
-56
View File
@@ -1,56 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "iprocessfactory.hpp"
using namespace EE::Terminal;
namespace EE { namespace System {
class ProcessFactory : public IProcessFactory {
public:
ProcessFactory() = default;
virtual ~ProcessFactory() = default;
ProcessFactory( const ProcessFactory& ) = delete;
ProcessFactory( ProcessFactory&& ) = delete;
ProcessFactory& operator=( const ProcessFactory& ) = delete;
ProcessFactory& operator=( ProcessFactory&& ) = delete;
virtual std::unique_ptr<IProcess> createWithStdioPipe( const std::string& program,
const std::vector<std::string>& args,
const std::string& workingDirectory,
std::unique_ptr<IPipe>& outPipe,
bool withStderr = true ) override;
virtual std::unique_ptr<IProcess>
createWithPseudoTerminal( const std::string& program, const std::vector<std::string>& args,
const std::string& workingDirectory, int numColumns, int numRows,
std::unique_ptr<IPseudoTerminal>& outPseudoTerminal ) override;
};
}} // namespace EE::System
-267
View File
@@ -1,267 +0,0 @@
/*
* Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
* MIT/X Consortium License
*/
/*
* U+25XX codepoints data
*
* References:
* http://www.unicode.org/charts/PDF/U2500.pdf
* http://www.unicode.org/charts/PDF/U2580.pdf
*
* Test page:
* https://github.com/GNOME/vte/blob/master/doc/boxes.txt
*/
/*
* Copyright 2018 Avi Halachmi (:avih) avihpit@yahoo.com https://github.com/avih
* MIT/X Consortium License
*/
/* Each shape is encoded as 16-bits. Higher bits are category, lower are data */
/* Categories (mutually exclusive except BDB): */
/* For convenience, BDL/BDA/BBS/BDB are 1 bit each, the rest are enums */
#define BDL ( 1 << 8 ) /* Box Draw Lines (light/double/heavy) */
#define BDA ( 1 << 9 ) /* Box Draw Arc (light) */
#define BBD ( 1 << 10 ) /* Box Block Down (lower) X/8 */
#define BBL ( 2 << 10 ) /* Box Block Left X/8 */
#define BBU ( 3 << 10 ) /* Box Block Upper X/8 */
#define BBR ( 4 << 10 ) /* Box Block Right X/8 */
#define BBQ ( 5 << 10 ) /* Box Block Quadrants */
#define BRL ( 6 << 10 ) /* Box Braille (data is lower byte of U28XX) */
#define BBS ( 1 << 14 ) /* Box Block Shades */
#define BDB ( 1 << 15 ) /* Box Draw is Bold */
/* (BDL/BDA) Light/Double/Heavy x Left/Up/Right/Down/Horizontal/Vertical */
/* Heavy is light+double (literally drawing light+double align to form heavy) */
#define LL ( 1 << 0 )
#define LU ( 1 << 1 )
#define LR ( 1 << 2 )
#define LD ( 1 << 3 )
#define LH ( LL + LR )
#define LV ( LU + LD )
#define DL ( 1 << 4 )
#define DU ( 1 << 5 )
#define DR ( 1 << 6 )
#define DD ( 1 << 7 )
#define DH ( DL + DR )
#define DV ( DU + DD )
#define HL ( LL + DL )
#define HU ( LU + DU )
#define HR ( LR + DR )
#define HD ( LD + DD )
#define HH ( HL + HR )
#define HV ( HU + HD )
/* (BBQ) Quadrants Top/Bottom x Left/Right */
#define TL ( 1 << 0 )
#define TR ( 1 << 1 )
#define BL ( 1 << 2 )
#define BR ( 1 << 3 )
/* Data for U+2500 - U+259F except dashes/diagonals */
static const unsigned short boxdata[256] = {
BDL + LH,
BDL + HH,
BDL + LV,
BDL + HV,
0,
0,
0,
0,
0,
0,
0,
0,
BDL + LD + LR,
BDL + HR + LD,
BDL + HD + LR,
BDL + HD + HR,
BDL + LD + LL,
BDL + HL + LD,
BDL + HD + LL,
BDL + HD + HL,
BDL + LU + LR,
BDL + HR + LU,
BDL + HU + LR,
BDL + HU + HR,
BDL + LU + LL,
BDL + HL + LU,
BDL + HU + LL,
BDL + HU + HL,
BDL + LV + LR,
BDL + HR + LV,
BDL + HU + LD + LR,
BDL + HD + LR + LU,
BDL + HV + LR,
BDL + HU + HR + LD,
BDL + HD + HR + LU,
BDL + HV + HR,
BDL + LV + LL,
BDL + HL + LV,
BDL + HU + LD + LL,
BDL + HD + LU + LL,
BDL + HV + LL,
BDL + HU + HL + LD,
BDL + HD + HL + LU,
BDL + HV + HL,
BDL + LH + LD,
BDL + HL + LD + LR,
BDL + HR + LL + LD,
BDL + HH + LD,
BDL + HD + LH,
BDL + HD + HL + LR,
BDL + HR + HD + LL,
BDL + HH + HD,
BDL + LH + LU,
BDL + HL + LU + LR,
BDL + HR + LU + LL,
BDL + HH + LU,
BDL + HU + LH,
BDL + HU + HL + LR,
BDL + HU + HR + LL,
BDL + HH + HU,
BDL + LV + LH,
BDL + HL + LV + LR,
BDL + HR + LV + LL,
BDL + HH + LV,
BDL + HU + LH + LD,
BDL + HD + LH + LU,
BDL + HV + LH,
BDL + HU + HL + LD + LR,
BDL + HU + HR + LD + LL,
BDL + HD + HL + LU + LR,
BDL + HD + HR + LU + LL,
BDL + HH + HU + LD,
BDL + HH + HD + LU,
BDL + HV + HL + LR,
BDL + HV + HR + LL,
BDL + HV + HH,
0,
0,
0,
0,
BDL + DH,
BDL + DV,
BDL + DR + LD,
BDL + DD + LR,
BDL + DR + DD,
BDL + DL + LD,
BDL + DD + LL,
BDL + DL + DD,
BDL + DR + LU,
BDL + DU + LR,
BDL + DU + DR,
BDL + DL + LU,
BDL + DU + LL,
BDL + DL + DU,
BDL + DR + LV,
BDL + DV + LR,
BDL + DV + DR,
BDL + DL + LV,
BDL + DV + LL,
BDL + DV + DL,
BDL + DH + LD,
BDL + DD + LH,
BDL + DD + DH,
BDL + DH + LU,
BDL + DU + LH,
BDL + DH + DU,
BDL + DH + LV,
BDL + DV + LH,
BDL + DH + DV,
BDA + LD + LR,
BDA + LD + LL,
BDA + LU + LL,
BDA + LU + LR,
0,
0,
0,
BDL + LL,
BDL + LU,
BDL + LR,
BDL + LD,
BDL + HL,
BDL + HU,
BDL + HR,
BDL + HD,
BDL + HR + LL,
BDL + HD + LU,
BDL + HL + LR,
BDL + HU + LD,
BBU + 4,
BBD + 7,
BBD + 6,
BBD + 5,
BBD + 4,
BBD + 3,
BBD + 2,
BBD + 1,
BBD + 0,
BBL + 7,
BBL + 6,
BBL + 5,
BBL + 4,
BBL + 3,
BBL + 2,
BBL + 1,
BBR + 4,
BBS + 1,
BBS + 2,
BBS + 3,
BBU + 1,
BBR + 7,
BBQ + BL,
BBQ + BR,
BBQ + TL,
BBQ + TL + BL + BR,
BBQ + TL + BR,
BBQ + TL + TR + BL,
BBQ + TL + TR + BR,
BBQ + TR,
BBQ + BL + TR,
BBQ + BL + TR + BR,
};
@@ -1,50 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "../system/ipipe.hpp"
#include <stdint.h>
namespace EE { namespace Terminal {
class IPseudoTerminal : public EE::System::IPipe {
public:
IPseudoTerminal() = default;
IPseudoTerminal( IPseudoTerminal&& ) = delete;
IPseudoTerminal( const IPseudoTerminal& ) = delete;
IPseudoTerminal& operator=( IPseudoTerminal&& ) = delete;
IPseudoTerminal& operator=( const IPseudoTerminal& ) = delete;
virtual ~IPseudoTerminal() = default;
virtual int getNumColumns() const = 0;
virtual int getNumRows() const = 0;
virtual bool resize( int columns, int rows ) = 0;
};
}} // namespace EE::Terminal
@@ -1,77 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#include "../terminal/iterminaldisplay.hpp"
#include "../terminal/terminalemulator.hpp"
#include <assert.h>
#define MODBIT( x, set, bit ) ( ( set ) ? ( ( x ) |= ( bit ) ) : ( ( x ) &= ~( bit ) ) )
using namespace EE::Terminal;
ITerminalDisplay::ITerminalDisplay() :
mMode( MODE_VISIBLE ), mCursorMode( SteadyBar ), mEmulator( nullptr ) {}
void ITerminalDisplay::attach( TerminalEmulator* terminal ) {
assert( mEmulator == nullptr );
mEmulator = terminal;
}
void ITerminalDisplay::detach( TerminalEmulator* terminal ) {
assert( mEmulator == terminal );
mEmulator = nullptr;
}
void ITerminalDisplay::bell() {}
void ITerminalDisplay::resetColors() {}
int ITerminalDisplay::resetColor( Uint32 /*index*/, const char* /*name*/ ) {
return 0;
}
void ITerminalDisplay::setMode( TerminalWinMode mode, int set ) {
int m = mMode;
MODBIT( ( (int&)mMode ), set, mode );
if ( ( mMode & MODE_REVERSE ) != ( m & MODE_REVERSE ) && mEmulator ) {
mEmulator->redraw();
}
}
void ITerminalDisplay::setCursorMode( TerminalCursorMode cursor ) {
mCursorMode = cursor;
}
TerminalCursorMode ITerminalDisplay::getCursorMode() const {
return mCursorMode;
}
void ITerminalDisplay::setTitle( const char* ) {}
void ITerminalDisplay::setIconTitle( const char* ) {}
void ITerminalDisplay::setClipboard( const char* ) {}
const char* ITerminalDisplay::getClipboard() const {
return "";
}
void ITerminalDisplay::onProcessExit( int /*exitCode*/ ) {}
@@ -1,90 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "types.hpp"
#include <eepp/config.hpp>
namespace EE { namespace Terminal {
class TerminalEmulator;
class ITerminalDisplay {
public:
ITerminalDisplay();
virtual ~ITerminalDisplay() = default;
ITerminalDisplay( const ITerminalDisplay& ) = delete;
ITerminalDisplay( ITerminalDisplay&& ) = delete;
ITerminalDisplay& operator=( const ITerminalDisplay& ) = delete;
ITerminalDisplay& operator=( ITerminalDisplay&& ) = delete;
virtual void attach( TerminalEmulator* terminal );
virtual void detach( TerminalEmulator* terminal );
virtual void bell();
virtual void resetColors();
virtual int resetColor( Uint32 index, const char* name );
virtual void setMode( TerminalWinMode mode, int set );
inline bool getMode( TerminalWinMode mode ) const { return mMode & mode; }
virtual void setCursorMode( TerminalCursorMode cursor );
virtual TerminalCursorMode getCursorMode() const;
virtual void setTitle( const char* title );
virtual void setIconTitle( const char* title );
virtual void setClipboard( const char* text );
virtual const char* getClipboard() const;
virtual bool drawBegin( int columns, int rows ) = 0;
virtual void drawLine( Line line, int x1, int y, int x2 ) = 0;
virtual void drawCursor( int cx, int cy, TerminalGlyph g, int ox, int oy,
TerminalGlyph og ) = 0;
virtual void drawEnd() = 0;
protected:
friend class TerminalEmulator;
int mMode;
TerminalCursorMode mCursorMode;
TerminalEmulator* mEmulator;
virtual void onProcessExit( int exitCode );
};
}} // namespace EE::Terminal
-70
View File
@@ -1,70 +0,0 @@
16, 16, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 16, 32, 16, 16, 16, 33, 34,
35, 36, 37, 38, 39, 16, 16, 40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 41, 42, 16, 16, 43,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 16, 45,
46, 47, 48, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 49, 16, 16, 50, 51, 16, 52, 16, 16, 16, 16, 16, 16, 16,
16, 53, 16, 16, 16, 16, 16, 54, 55, 16, 16, 16, 16, 56, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 57, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 58, 59, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 248, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255,
255, 255, 191, 182, 0, 0, 0, 0, 0, 0, 0, 31, 0, 255, 7, 0, 0, 0, 0, 0, 248, 255, 255, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 191, 159, 61, 0, 0, 0, 128, 2, 0, 0, 0, 255, 255, 255, 7,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 255, 1, 0, 0, 0, 0, 0, 0, 248, 15, 0, 0, 0, 192, 251, 239,
62, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 255, 127, 7, 0,
0, 0, 0, 0, 0, 20, 254, 33, 254, 0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 16, 30, 32, 0, 0, 12, 0,
0, 0, 6, 0, 0, 0, 0, 0, 0, 16, 134, 57, 2, 0, 0, 0, 35, 0, 6, 0, 0, 0, 0, 0, 0, 16, 190, 33, 0,
0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 144, 30, 32, 64, 0, 12, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1,
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 193, 61, 96, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 144, 64, 48, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 32, 0, 0, 12, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 4, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 242, 7, 128, 127, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 242, 27, 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 160, 2, 0, 0, 0, 0, 0, 0,
254, 127, 223, 224, 255, 254, 255, 255, 255, 31, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224,
253, 102, 0, 0, 0, 195, 1, 0, 30, 0, 100, 32, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 28, 0, 0, 0, 28, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 176, 63, 64, 254, 15, 32, 0,
0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 135, 1, 4, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 128, 1, 0, 0, 0, 0, 0, 0, 64, 127, 229, 31, 248, 159, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 208, 23, 4, 0, 0, 0, 0, 248, 15, 0, 3, 0, 0, 0, 60,
11, 0, 0, 0, 0, 0, 0, 64, 163, 3, 0, 0, 0, 0, 0, 0, 240, 207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 247, 255, 253, 33, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 127, 0, 0, 240, 0, 248, 0, 0, 0, 124, 0, 0, 0, 0,
0, 0, 31, 252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0,
0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 247, 63, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
68, 8, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 255, 255,
3, 0, 0, 0, 0, 0, 192, 63, 0, 0, 128, 255, 3, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 200, 19, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 102, 0, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 193,
2, 0, 0, 0, 0, 48, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 110, 240, 0, 0, 0, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 255, 127, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 120, 38, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 128, 239, 31, 0, 0, 0, 0, 0, 0,
0, 0, 0, 3, 0, 0, 0, 0, 0, 192, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 128, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 128, 3, 248, 255, 231, 15, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-303
View File
@@ -1,303 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#ifndef _WIN32
// Windows has its own source file
#include "pseudoterminal.hpp"
#include <cstdio>
#include <poll.h>
#if defined( __linux )
#include <pty.h>
#elif defined( __OpenBSD__ ) || defined( __NetBSD__ ) || defined( __APPLE__ )
#include <util.h>
#elif defined( __FreeBSD__ ) || defined( __DragonFly__ )
#include <libutil.h>
#elif EE_PLATFORM == EE_PLATFORM_HAIKU
#define _DEFAULT_SOURCE
#include <bsd/pty.h>
#endif
#include <eepp/system/log.hpp>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <unistd.h>
using namespace EE::System;
#if EE_PLATFORM == EE_PLATFORM_ANDROID
#include <fcntl.h>
int openpty( int* amaster, int* aslave, char* name, struct termios* termp, struct winsize* winp ) {
int master, slave;
char* name_slave;
master = open( "/dev/ptmx", O_RDWR | O_NONBLOCK );
if ( master == -1 ) {
Log::error( "openpty: Fail to open master" );
return -1;
}
if ( grantpt( master ) ) {
Log::error( "openpty: grantpt failed" );
goto fail;
}
if ( unlockpt( master ) ) {
Log::error( "openpty: unlockpt failed" );
goto fail;
}
name_slave = ptsname( master );
slave = open( name_slave, O_RDWR | O_NOCTTY );
if ( slave == -1 ) {
Log::error( "openpty: failed to open slave name %s", name_slave );
goto fail;
}
if ( termp )
tcsetattr( slave, TCSAFLUSH, termp );
if ( winp )
ioctl( slave, TIOCSWINSZ, winp );
*amaster = master;
*aslave = slave;
if ( name != NULL )
strcpy( name, name_slave );
return 0;
fail:
close( master );
return -1;
}
#endif
using namespace EE::Terminal;
PseudoTerminal::~PseudoTerminal() {}
PseudoTerminal::PseudoTerminal( int columns, int rows, AutoHandle&& master, AutoHandle&& slave ) :
mColumns( columns ),
mRows( rows ),
mMaster( std::move( master ) ),
mSlave( std::move( slave ) ) {}
bool PseudoTerminal::isTTY() const {
return true;
}
bool PseudoTerminal::resize( int columns, int rows ) {
struct winsize w;
w.ws_row = rows;
w.ws_col = columns;
w.ws_xpixel = 0;
w.ws_ypixel = 0;
if ( ioctl( (int)mMaster, TIOCSWINSZ, &w ) < 0 ) {
perror( "PseudoTerminal::Resize" );
return false;
}
return true;
}
int PseudoTerminal::getNumColumns() const {
return mColumns;
}
int PseudoTerminal::getNumRows() const {
return mRows;
}
int PseudoTerminal::write( const char* s, size_t n ) {
size_t c = n;
while ( n > 0 ) {
ssize_t r = ::write( (int)mMaster, s, n );
if ( r < 0 ) {
return -1;
}
n -= r;
s += r;
}
return c;
}
int PseudoTerminal::read( char* s, size_t n, bool block ) {
struct pollfd pfd;
pfd.fd = (int)mMaster;
pfd.events = POLLIN;
pfd.revents = 0;
if ( !block ) {
auto i = poll( &pfd, 1, 0 );
if ( i == 0 || !( pfd.revents & POLLIN ) ) {
return 0;
}
if ( i < 0 ) {
perror( "PseudoTerminal::Reader(poll)" );
return -1;
}
}
ssize_t r = ::read( (int)mMaster, s, n );
return (int)r;
}
std::unique_ptr<PseudoTerminal> PseudoTerminal::create( int columns, int rows ) {
AutoHandle master;
AutoHandle slave;
struct winsize win;
memset( &win, 0, sizeof( win ) );
win.ws_col = columns;
win.ws_row = rows;
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
return nullptr;
#else
if ( openpty( master.get(), slave.get(), nullptr, NULL, &win ) != 0 ) {
perror( "PseudoTerminal::create(openpty)" );
Log::error( "PseudoTerminal::create(openpty)" );
return nullptr;
}
return std::unique_ptr<PseudoTerminal>(
new PseudoTerminal( columns, rows, std::move( master ), std::move( slave ) ) );
#endif
}
#else
#include "pseudoterminal.hpp"
#include "windowserrors.hpp"
#include <assert.h>
#define NTDDI_VERSION NTDDI_WIN10_RS5
#include <windows.h>
using namespace EE::Terminal;
PseudoTerminal::~PseudoTerminal() {
ClosePseudoConsole( mPHPC );
}
PseudoTerminal::PseudoTerminal( int columns, int rows, AutoHandle&& hInput, AutoHandle&& hOutput,
void* hPC ) :
mInputHandle( std::move( hInput ) ),
mOutputHandle( std::move( hOutput ) ),
mPHPC( hPC ),
mAttached( false ) {
mSize.x = (SHORT)columns;
mSize.y = (SHORT)rows;
}
bool PseudoTerminal::isTTY() const {
return true;
}
bool PseudoTerminal::resize( int columns, int rows ) {
HRESULT hr = ResizePseudoConsole( mPHPC, { (SHORT)columns, (SHORT)rows } );
if ( hr != S_OK ) {
PrintErrorResult( hr );
return false;
}
mSize.x = (SHORT)columns;
mSize.y = (SHORT)rows;
return true;
}
int PseudoTerminal::write( const char* s, size_t n ) {
constexpr size_t lim = 256;
DWORD c = (DWORD)n;
DWORD r = 0;
while ( n > 0 ) {
if ( !WriteFile( (HANDLE)mOutputHandle, s, (DWORD)( n > lim ? lim : n ), &r, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
s += r;
n -= r;
}
return (int)c;
}
int PseudoTerminal::read( char* buf, size_t n, bool block ) {
DWORD available = 0;
DWORD read;
if ( !block ) {
if ( !PeekNamedPipe( mInputHandle.handle(), nullptr, 0, nullptr, &available, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
if ( available == 0 )
return 0;
}
if ( !ReadFile( mInputHandle.handle(), buf, available, &read, nullptr ) ) {
PrintLastWinApiError();
return -1;
}
return (int)read;
}
int PseudoTerminal::getNumColumns() const {
return mSize.x;
}
int PseudoTerminal::getNumRows() const {
return mSize.y;
}
std::unique_ptr<PseudoTerminal> PseudoTerminal::create( int columns, int rows ) {
using Pointer = std::unique_ptr<PseudoTerminal>;
HRESULT hr{ E_UNEXPECTED };
void* hPC{ INVALID_HANDLE_VALUE };
AutoHandle hPipeIn{};
AutoHandle hPipeOut{};
AutoHandle hPipePTYIn{};
AutoHandle hPipePTYOut{};
if ( CreatePipe( hPipePTYIn.get(), hPipeOut.get(), NULL, 0 ) &&
CreatePipe( hPipeIn.get(), hPipePTYOut.get(), NULL, 0 ) ) {
COORD ptySize;
ptySize.X = (SHORT)columns;
ptySize.Y = (SHORT)rows;
assert( ptySize.X > 0 );
assert( ptySize.Y > 0 );
hr = CreatePseudoConsole( ptySize, hPipePTYIn.handle(), hPipePTYOut.handle(), 0, &hPC );
}
if ( hr != S_OK ) {
PrintErrorResult( hr );
return Pointer();
}
return Pointer(
new PseudoTerminal( columns, rows, std::move( hPipeIn ), std::move( hPipeOut ), hPC ) );
}
#endif
@@ -1,83 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "../system/autohandle.hpp"
#include "ipseudoterminal.hpp"
#include <eepp/math/vector2.hpp>
#include <memory>
using namespace EE::Math;
namespace EE {
namespace System {
class Process;
}
namespace Terminal {
class PseudoTerminal final : public IPseudoTerminal {
public:
virtual ~PseudoTerminal();
PseudoTerminal( PseudoTerminal&& ) = delete;
PseudoTerminal( const PseudoTerminal& ) = delete;
PseudoTerminal& operator=( PseudoTerminal&& ) = delete;
PseudoTerminal& operator=( const PseudoTerminal& ) = delete;
virtual bool isTTY() const override;
virtual int getNumColumns() const override;
virtual int getNumRows() const override;
virtual bool resize( int columns, int rows ) override;
virtual int write( const char* s, size_t n ) override;
virtual int read( char* buf, size_t n, bool block = false ) override;
static std::unique_ptr<PseudoTerminal> create( int columns, int rows );
private:
friend class ::EE::System::Process;
#ifdef _WIN32
Vector2i mSize;
AutoHandle mInputHandle;
AutoHandle mOutputHandle;
void* mPHPC;
bool mAttached;
PseudoTerminal( int columns, int rows, AutoHandle&& hInput, AutoHandle&& hOutput, void* hPC );
#else
int mColumns;
int mRows;
AutoHandle mMaster;
AutoHandle mSlave;
PseudoTerminal( int columns, int rows, AutoHandle&& master, AutoHandle&& slave );
#endif
};
} // namespace Terminal
} // namespace EE
File diff suppressed because it is too large Load Diff
@@ -1,289 +0,0 @@
#ifndef ETERMINALDISPLAY_HPP
#define ETERMINALDISPLAY_HPP
#include "../system/iprocessfactory.hpp"
#include "iterminaldisplay.hpp"
#include "terminalemulator.hpp"
#include <eepp/config.hpp>
#include <eepp/graphics/font.hpp>
#include <eepp/graphics/framebuffer.hpp>
#include <eepp/system/clock.hpp>
#include <eepp/window/inputevent.hpp>
#include <eepp/window/keycodes.hpp>
#include <eepp/window/window.hpp>
#include <atomic>
#include <memory>
#include <unordered_map>
#include <vector>
using namespace EE;
using namespace EE::Terminal;
using namespace EE::Window;
using namespace EE::System;
enum class TerminalShortcutAction {
PASTE,
COPY,
SCROLLUP_ROW,
SCROLLDOWN_ROW,
SCROLLUP_SCREEN,
SCROLLDOWN_SCREEN,
SCROLLUP_HISTORY,
SCROLLDOWN_HISTORY,
FONTSIZE_GROW,
FONTSIZE_SHRINK
};
struct TerminalKey {
Keycode keysym;
Uint32 mask;
const char* string;
int appkey;
int appcursor;
};
struct TerminalScancode {
Scancode scancode;
Uint32 mask;
std::string string;
int appkey;
int appcursor;
};
struct TerminalShortcut {
Keycode keysym;
Uint32 mask;
TerminalShortcutAction action;
int appkey;
int appcursor;
int altscrn{ 0 }; /* 0: don't care, -1: not alt screen, 1: alt screen */
};
struct TerminalMouseShortcut {
MouseButtonsMask button;
Uint32 mask;
TerminalShortcutAction action;
int appkey;
int appcursor;
int altscrn{ 0 }; /* 0: don't care, -1: not alt screen, 1: alt screen */
};
struct TerminalKeyMapEntry {
Uint32 mask;
std::string string;
int appkey;
int appcursor;
};
struct TerminalKeyMapShortcut {
Uint32 mask;
TerminalShortcutAction action;
int appkey;
int appcursor;
int altscrn{ 0 }; /* 0: don't care, -1: not alt screen, 1: alt screen */
};
class TerminalKeyMap {
private:
std::unordered_map<Keycode, std::vector<TerminalKeyMapEntry>> mKeyMap;
std::unordered_map<Scancode, std::vector<TerminalKeyMapEntry>> mPlatformKeyMap;
std::unordered_map<Keycode, std::vector<TerminalKeyMapShortcut>> mShortcuts;
std::unordered_map<Uint32, std::vector<TerminalKeyMapShortcut>> mMouseShortcuts;
public:
TerminalKeyMap( const TerminalKey keys[], size_t keysLen, const TerminalScancode platformKeys[],
size_t platformKeysLen, const TerminalShortcut shortcuts[], size_t shortcutsLen,
const TerminalMouseShortcut mouseShortcuts[], size_t mouseShortcutsLen );
inline const std::unordered_map<Keycode, std::vector<TerminalKeyMapEntry>>& KeyMap() const {
return mKeyMap;
}
inline const std::unordered_map<Scancode, std::vector<TerminalKeyMapEntry>>&
PlatformKeyMap() const {
return mPlatformKeyMap;
}
inline const std::unordered_map<Keycode, std::vector<TerminalKeyMapShortcut>>&
Shortcuts() const {
return mShortcuts;
}
inline const std::unordered_map<Uint32, std::vector<TerminalKeyMapShortcut>>&
MouseShortcuts() const {
return mMouseShortcuts;
}
};
constexpr int TerminalKeyModFlags_Any = 0xFFFFFFFF;
extern TerminalKeyMap terminalKeyMap;
static const Scancode asciiScancodeTable[] = {
SCANCODE_A, SCANCODE_B, SCANCODE_C, SCANCODE_D, SCANCODE_E, SCANCODE_F,
SCANCODE_G, SCANCODE_H, SCANCODE_I, SCANCODE_J, SCANCODE_K, SCANCODE_L,
SCANCODE_M, SCANCODE_N, SCANCODE_O, SCANCODE_P, SCANCODE_Q, SCANCODE_R,
SCANCODE_S, SCANCODE_T, SCANCODE_U, SCANCODE_V, SCANCODE_W, SCANCODE_X,
SCANCODE_Y, SCANCODE_Z, SCANCODE_LEFTBRACKET, SCANCODE_SLASH, SCANCODE_RIGHTBRACKET };
class TerminalDisplay : public ITerminalDisplay {
public:
enum class EventType { TITLE, ICON_TITLE, UNKNOWN };
struct Event {
EventType type{ EventType::UNKNOWN };
std::string eventData;
};
typedef std::function<void( const TerminalDisplay::Event& event )> EventFunc;
static std::shared_ptr<TerminalDisplay>
create( EE::Window::Window* window, Font* font, const Float& fontSize, const Sizef& pixelsSize,
std::shared_ptr<TerminalEmulator>&& terminalEmulator,
const bool& useFrameBuffer = false );
static std::shared_ptr<TerminalDisplay>
create( EE::Window::Window* window, Font* font, const Float& fontSize, const Sizef& pixelsSize,
std::string program = "", const std::vector<std::string>& args = {},
const std::string& workingDir = "", const size_t& historySize = 10000,
IProcessFactory* processFactory = nullptr, const bool& useFrameBuffer = false );
virtual ~TerminalDisplay();
virtual void resetColors();
virtual int resetColor( Uint32 index, const char* name );
virtual void setTitle( const char* title );
virtual void setIconTitle( const char* title );
virtual void setClipboard( const char* text );
virtual const char* getClipboard() const;
virtual bool drawBegin( int columns, int rows );
virtual void drawLine( Line line, int x1, int y, int x2 );
virtual void drawCursor( int cx, int cy, TerminalGlyph g, int ox, int oy, TerminalGlyph og );
virtual void drawEnd();
virtual void update();
void action( TerminalShortcutAction action );
bool hasTerminated() const;
void draw();
virtual void onMouseDoubleClick( const Vector2i& pos, const Uint32& flags );
virtual void onMouseMotion( const Vector2i& pos, const Uint32& flags );
virtual void onMouseDown( const Vector2i& pos, const Uint32& flags );
virtual void onMouseUp( const Vector2i& pos, const Uint32& flags );
virtual void onTextInput( const Uint32& chr );
virtual void onKeyDown( const Keycode& keyCode, const Uint32& chr, const Uint32& mod,
const Scancode& scancode );
Float getFontSize() const;
void setFontSize( const Float& FontSize );
const Vector2f& getPosition() const;
void setPosition( const Vector2f& position );
const Sizef& getSize() const;
void setSize( const Sizef& size );
bool isDirty() const { return mDirty; }
void invalidate();
void invalidateCursor();
void invalidateLine( const int& line );
void invalidateLines();
bool hasFocus() const { return mFocus; }
void setFocus( bool focus );
bool isBlinkingCursor();
const Sizef& getPadding() const;
void setPadding( const Sizef& padding );
const std::shared_ptr<TerminalEmulator>& getTerminal() const;
virtual void attach( TerminalEmulator* terminal );
int scrollSize() const;
int rowCount() const;
Uint32 pushEventCallback( const EventFunc& func );
void popEventCallback( const Uint32& id );
protected:
EE::Window::Window* mWindow;
std::vector<TerminalGlyph> mBuffer;
std::vector<std::pair<Color, std::string>> mColors;
std::shared_ptr<TerminalEmulator> mTerminal;
mutable std::string mClipboard;
Uint32 mNumCallBacks;
std::map<Uint32, EventFunc> mCallbacks;
Font* mFont{ nullptr };
Float mFontSize{ 12 };
Sizef mPadding;
Vector2f mPosition;
Sizef mSize;
std::vector<bool> mDirtyLines;
bool mDirty{ true };
bool mDirtyCursor{ true };
bool mDrawing{ false };
Vector2i mCursor;
TerminalGlyph mCursorGlyph;
bool mUseColorEmoji{ true };
bool mPasteNewlineFix{ true };
bool mFocus{ true };
bool mUseFrameBuffer{ true };
Clock mClock;
Clock mLastDoubleClick;
int mColumns{ 0 };
int mRows{ 0 };
FrameBuffer* mFrameBuffer{ nullptr };
std::string mProgram;
std::vector<std::string> mArgs;
std::string mWorkingDir;
TerminalDisplay( EE::Window::Window* window, Font* font, const Float& fontSize,
const Sizef& pixelsSize, const bool& useFrameBuffer );
void draw( const Vector2f& pos );
void drawGrid( const Vector2f& pos );
Vector2i positionToGrid( const Vector2i& pos );
void onSizeChange();
virtual void onProcessExit( int exitCode );
void sendEvent( const TerminalDisplay::Event& event );
Sizei getFrameBufferSize();
void createFrameBuffer();
void drawFrameBuffer();
};
#endif // ETERMINALDISPLAY_HPP
File diff suppressed because it is too large Load Diff
@@ -1,327 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Copyright (c) 2014 - 2020 Hiltjo Posthuma<hiltjo at codemadness dot org>
// Copyright (c) 2018 Devin J.Pohly<djpohly at gmail dot com>
// Copyright (c) 2014 - 2017 Quentin Rameau<quinq at fifth dot space>
// Copyright (c) 2009 - 2012 Aurélien APTEL<aurelien dot aptel at gmail dot com>
// Copyright (c) 2008 - 2017 Anselm R Garbe<garbeam at gmail dot com>
// Copyright (c) 2012 - 2017 Roberto E.Vargas Caballero<k0ga at shike2 dot com>
// Copyright (c) 2012 - 2016 Christoph Lohmann<20h at r - 36 dot net>
// Copyright (c) 2013 Eon S.Jeon<esjeon at hyunmu dot am>
// Copyright (c) 2013 Alexander Sedov<alex0player at gmail dot com>
// Copyright (c) 2013 Mark Edgar<medgar123 at gmail dot com>
// Copyright (c) 2013 - 2014 Eric Pruitt<eric.pruitt at gmail dot com>
// Copyright (c) 2013 Michael Forney<mforney at mforney dot org>
// Copyright (c) 2013 - 2014 Markus Teich<markus dot teich at stusta dot mhn dot de>
// Copyright (c) 2014 - 2015 Laslo Hunhold<dev at frign dot de>
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include "../system/iprocess.hpp"
#include "ipseudoterminal.hpp"
#include "iterminaldisplay.hpp"
#include "types.hpp"
#include <eepp/math/vector2.hpp>
#include <eepp/window/keycodes.hpp>
#include <memory>
#include <stdint.h>
#include <sys/types.h>
using namespace EE;
using namespace EE::System;
using namespace EE::Math;
using namespace EE::Window;
namespace EE { namespace Terminal {
constexpr int ESC_BUF_SIZ = 512;
constexpr int ESC_ARG_SIZ = 16;
constexpr int STR_BUF_SIZ = ESC_BUF_SIZ;
constexpr int STR_ARG_SIZ = ESC_ARG_SIZ;
/* Internal representation of the screen */
struct Term {
int row{ 0 }; /* nb row */
int col{ 0 }; /* nb col */
Line* line{ nullptr }; /* screen */
Line* alt{ nullptr }; /* alternate screen */
std::vector<Line> hist; /* history buffer */
int histsize{ 0 }; /* history size */
int histi{ 0 }; /* history index */
int scr{ 0 }; /* scroll back */
int* dirty{ nullptr }; /* dirtyness of lines */
TerminalCursor c{}; /* cursor */
int ocx{ 0 }; /* old cursor col */
int ocy{ 0 }; /* old cursor row */
int top{ 0 }; /* top scroll limit */
int bot{ 0 }; /* bottom scroll limit */
int mode{ 0 }; /* terminal mode flags */
int esc{ 0 }; /* escape state flags */
char trantbl[4]{ 0, 0, 0, 0 }; /* charset table translation */
int charset{ 0 }; /* current charset */
int icharset{ 0 }; /* selected charset for sequence */
int* tabs{ nullptr };
Rune lastc{ 0 }; /* last printed char outside of sequence, 0 if control */
};
/* CSI Escape sequence structs */
/* ESC '[' [[ [<priv>] <arg> [;]] <mode> [<mode>]] */
struct CSIEscape {
char buf[ESC_BUF_SIZ]; /* raw string */
size_t len; /* raw string length */
char priv;
int arg[ESC_ARG_SIZ];
int narg; /* nb of args */
char mode[2];
};
/* STR Escape sequence structs */
/* ESC type [[ [<priv>] <arg> [;]] <mode>] ESC '\' */
struct STREscape {
char type; /* ESC type ... */
char* buf; /* allocated raw string */
size_t siz; /* allocation size */
size_t len; /* raw string length */
char* args[STR_ARG_SIZ];
int narg; /* nb of args */
};
enum class TerminalMouseEventType { MouseMotion, MouseButtonDown, MouseButtonRelease };
class TerminalEmulator final {
public:
using DpyPtr = std::weak_ptr<ITerminalDisplay>;
using PtyPtr = std::unique_ptr<IPseudoTerminal>;
using ProcPtr = std::unique_ptr<System::IProcess>;
static ushort boxdrawindex( const TerminalGlyph* g );
~TerminalEmulator();
TerminalEmulator( const TerminalEmulator& ) = delete;
TerminalEmulator( TerminalEmulator&& ) = delete;
TerminalEmulator& operator=( const TerminalEmulator& ) = delete;
TerminalEmulator& operator=( TerminalEmulator&& ) = delete;
static std::unique_ptr<TerminalEmulator>
create( PtyPtr&& pty, ProcPtr&& process, const std::shared_ptr<ITerminalDisplay>& display,
const size_t& historySize = 1000 );
void resize( int columns, int rows );
void redraw();
void logError( const char* err );
void update();
void terminate();
bool hasExited() const;
int getExitCode() const;
inline bool isSelected( int column, int row ) { return selected( column, row ); }
inline uint32_t getDefaultForeground() const { return mDefaultFg; }
inline uint32_t getDefaultBackground() const { return mDefaultBg; }
inline uint32_t getDefaultCursorColor() const { return mDefaultCs; }
inline uint32_t getDefaultReverseCursorColor() const { return mDefaultrCs; }
inline int getNumColumns() const { return mTerm.col; }
inline int getNumRows() const { return mTerm.row; }
int write( const char* buf, size_t buflen );
void printscreen( const TerminalArg* );
void printsel( const TerminalArg* );
void sendbreak( const TerminalArg* );
void toggleprinter( const TerminalArg* );
TerminalSelectionMode getSelectionMode() const;
void selclear();
void selinit();
void selstart( int, int, int );
void selextend( int, int, int, int );
int selected( int, int );
char* getsel() const;
std::string getSelection() const;
void mousereport( const TerminalMouseEventType& type, const Vector2i& pos, const Uint32& flags,
const Uint32& mod );
const bool& isDirty() const { return mDirty; }
void setPtyAndProcess( PtyPtr&& pty, ProcPtr&& process );
void kscrolldown( const TerminalArg* a );
void kscrollup( const TerminalArg* a );
bool isScrolling() const;
void ttywrite( const char* s, size_t n, int may_echo );
int tisaltscr();
int scrollSize() const;
int rowCount() const;
void clearHistory();
private:
DpyPtr mDpy;
PtyPtr mPty;
ProcPtr mProcess;
bool mColorsLoaded;
bool mDirty{ true };
int mExitCode;
enum { STARTING = 0, RUNNING, TERMINATED } mStatus;
char mBuf[8192];
int mBuflen;
Term mTerm;
TerminalSelection mSel;
CSIEscape mCsiescseq;
STREscape mStrescseq;
uint32_t mDefaultFg;
uint32_t mDefaultBg;
uint32_t mDefaultCs;
uint32_t mDefaultrCs;
int mAllowAltScreen;
int mAllowWindowOps;
void resizeHistory();
void setClipboard( const char* str );
void loadColors();
int resetColor( int x, const char* name );
void onProcessExit( int exitCode );
void csidump();
void csihandle();
void csiparse();
void csireset();
int eschandle( uchar );
void strdump();
void strhandle();
void strparse();
void strreset();
void tprinter( const char*, size_t );
void tdumpsel();
void tdumpline( int );
void tdump();
void tclearregion( int, int, int, int );
void tcursor( int );
void tdeletechar( int );
void tdeleteline( int );
void tinsertblank( int );
void tinsertblankline( int );
int tlinelen( int ) const;
void tmoveto( int, int );
void tmoveato( int, int );
void tnewline( int );
void tputtab( int );
void tputc( Rune );
void treset();
void tscrollup( int, int, int );
void tscrolldown( int, int, int );
void tsetattr( int*, int );
void tsetchar( Rune, TerminalGlyph*, int, int );
void tsetdirt( int, int );
void tsetscroll( int, int );
void tswapscreen();
void tsetmode( int, int, int*, int );
int twrite( const char*, int, int );
void tfulldirt();
void tcontrolcode( uchar );
void tdectest( char );
void tdefutf8( char );
int32_t tdefcolor( int*, int*, int );
void tdeftran( char );
void tstrsequence( uchar );
void selnormalize();
void selscroll( int, int );
void selsnap( int*, int*, int );
void _die( const char*, ... );
void drawregion( ITerminalDisplay& dpy, int, int, int, int );
void draw();
int tattrset( int );
void tnew( int, int, size_t );
void tresize( int, int );
void tsetdirtattr( int );
void ttyhangup();
size_t ttyread();
void ttywriteraw( const char*, size_t );
void resettitle();
void xbell();
void xclipcopy();
int xsetcolorname( int, const char* );
void xseticontitle( char* );
void xsettitle( char* );
int xsetcursor( int );
void xsetmode( int, unsigned int );
bool xgetmode( const TerminalWinMode& );
void xsetpointermotion( int );
void xsetsel( char* );
void xximspot( int, int );
TerminalEmulator( PtyPtr&& pty, ProcPtr&& process,
const std::shared_ptr<ITerminalDisplay>& display,
const size_t& historySize = 1000 );
};
}} // namespace EE::Terminal
-175
View File
@@ -1,175 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#include <stdint.h>
#include <string.h>
namespace EE { namespace Terminal {
enum TerminalCursorMode {
BlinkingBlock = 0,
BlinkingBlockDefault = 1,
SteadyBlock = 2,
BlinkUnderline = 3,
SteadyUnderline = 4,
BlinkBar = 5,
SteadyBar = 6,
StExtension = 7,
MAX_CURSOR
};
enum TerminalWinMode {
MODE_VISIBLE = 1 << 0,
MODE_FOCUSED = 1 << 1,
MODE_APPKEYPAD = 1 << 2,
MODE_MOUSEBTN = 1 << 3,
MODE_MOUSEMOTION = 1 << 4,
MODE_REVERSE = 1 << 5,
MODE_KBDLOCK = 1 << 6,
MODE_HIDE = 1 << 7,
MODE_APPCURSOR = 1 << 8,
MODE_MOUSESGR = 1 << 9,
MODE_8BIT = 1 << 10,
MODE_BLINK = 1 << 11,
MODE_FBLINK = 1 << 12,
MODE_FOCUS = 1 << 13,
MODE_MOUSEX10 = 1 << 14,
MODE_MOUSEMANY = 1 << 15,
MODE_BRCKTPASTE = 1 << 16,
MODE_NUMLOCK = 1 << 17,
MODE_MOUSE = MODE_MOUSEBTN | MODE_MOUSEMOTION | MODE_MOUSEX10 | MODE_MOUSEMANY,
};
enum TerminalGlyphAttribute {
ATTR_NULL = 0,
ATTR_BOLD = 1 << 0,
ATTR_FAINT = 1 << 1,
ATTR_ITALIC = 1 << 2,
ATTR_UNDERLINE = 1 << 3,
ATTR_BLINK = 1 << 4,
ATTR_REVERSE = 1 << 5,
ATTR_INVISIBLE = 1 << 6,
ATTR_STRUCK = 1 << 7,
ATTR_WRAP = 1 << 8,
ATTR_WIDE = 1 << 9,
ATTR_WDUMMY = 1 << 10,
ATTR_BOXDRAW = 1 << 11,
ATTR_EMOJI = 1 << 12,
ATTR_BOLD_FAINT = ATTR_BOLD | ATTR_FAINT,
};
enum TerminalSelectionMode { SEL_IDLE = 0, SEL_EMPTY = 1, SEL_READY = 2 };
enum TerminalSelectionType { SEL_REGULAR = 1, SEL_RECTANGULAR = 2 };
enum TerminalSelectionSnap { SNAP_WORD = 1, SNAP_LINE = 2 };
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef uint_least32_t Rune;
struct TerminalGlyph {
Rune u{ 0 }; /* character code */
ushort mode{ 0 }; /* attribute flags */
uint32_t fg{ 0 }; /* foreground */
uint32_t bg{ 0 }; /* background */
bool operator==( const TerminalGlyph& r ) {
return u == r.u && mode == r.mode && fg == r.fg && bg == r.bg;
}
bool operator!=( const TerminalGlyph& r ) { return !( *this == r ); }
};
typedef TerminalGlyph* Line;
union TerminalArg {
int i;
uint ui;
float f;
const void* v;
const char* s;
TerminalArg() { memset( this, 0, sizeof( *this ) ); }
TerminalArg( int x ) { i = x; }
TerminalArg( uint x ) { ui = x; }
TerminalArg( float x ) { f = x; }
TerminalArg( const void* x ) { v = x; }
TerminalArg( const char* x ) { s = x; }
};
enum TermMode {
MODE_WRAP = 1 << 0,
MODE_INSERT = 1 << 1,
MODE_ALTSCREEN = 1 << 2,
MODE_CRLF = 1 << 3,
MODE_ECHO = 1 << 4,
MODE_PRINT = 1 << 5,
MODE_UTF8 = 1 << 6,
};
enum TerminalCursorMovement { CURSOR_SAVE, CURSOR_LOAD };
enum TerminalCursorState { CURSOR_DEFAULT = 0, CURSOR_WRAPNEXT = 1, CURSOR_ORIGIN = 2 };
enum TerminalCharset { CS_GRAPHIC0, CS_GRAPHIC1, CS_UK, CS_USA, CS_MULTI, CS_GER, CS_FIN };
enum TerminalEscapeState {
ESC_START = 1,
ESC_CSI = 2,
ESC_STR = 4, /* DCS, OSC, PM, APC */
ESC_ALTCHARSET = 8,
ESC_STR_END = 16, /* a final string was encountered */
ESC_TEST = 32, /* Enter in test mode */
ESC_UTF8 = 64,
};
struct TerminalCursor {
TerminalGlyph attr; /* current char attributes */
int x{ 0 };
int y{ 0 };
char state{ 0 };
};
struct TerminalSelection {
int mode;
int type;
int snap;
/*
* Selection variables:
* nb – normalized coordinates of the beginning of the selection
* ne – normalized coordinates of the end of the selection
* ob – original coordinates of the beginning of the selection
* oe – original coordinates of the end of the selection
*/
struct {
int x, y;
} nb, ne, ob, oe;
int alt;
};
}} // namespace EE::Terminal
-45
View File
@@ -1,45 +0,0 @@
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 21, 22,
23, 24, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 26, 16, 16, 16, 16,
27, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 28, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 16, 16, 16, 29, 30, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 31,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 248, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 252, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 251, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 15, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63, 0, 0,
0, 255, 15, 255, 255, 255, 255, 255, 255, 255, 127, 254, 255, 255, 255, 255, 255, 255, 255, 255,
255, 127, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 224, 255, 255, 255,
255, 63, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 255, 7,
255, 255, 255, 255, 15, 0, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 255, 0, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 31, 255, 255, 255, 255, 255, 255, 127, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 15, 0, 255, 255, 127, 248, 255, 255, 255, 255, 255, 15, 0, 0, 255, 3, 0, 0,
255, 255, 255, 255, 247, 255, 127, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 127, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 255, 255, 255, 255, 255, 7, 255, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -1,56 +0,0 @@
// The MIT License (MIT)
// Copyright (c) 2020 Fredrik A. Kristiansen
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#pragma once
#ifdef _WIN32
#define NTDDI_VERSION NTDDI_WIN10_RS5
#include <comdef.h>
#include <iostream>
#include <string>
#include <windows.h>
static void PrintErrorResult( HRESULT hr ) {
_com_error err( hr );
LPCTSTR errMsg = err.ErrorMessage();
std::cerr << "ERROR: " << errMsg << std::endl;
}
static void PrintWinApiError( DWORD error ) {
if ( error == 0 )
return;
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&messageBuffer, 0, NULL );
std::string message( messageBuffer, size );
// Free the buffer.
LocalFree( messageBuffer );
std::cerr << "ERROR WinAPI: " << message << std::endl;
}
static void PrintLastWinApiError( void ) {
PrintWinApiError( GetLastError() );
}
#endif