mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
eterm code refactor.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user