Skip to content
Merged

Utf8 #261

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions ci/examples.ps1
Original file line number Diff line number Diff line change
@@ -1,9 +1,2 @@
echo "running example programs"
.\install\bin\examples\colors.exe

echo "testing read_stind"
if ((echo test | .\install\bin\examples\read_stdin.exe) -ne "Input from stdin: test")
{
echo "read_stdin gave wrong output"
exit 1
}
7 changes: 0 additions & 7 deletions ci/examples.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
set -ex

./install/bin/examples/colors
./install/bin/examples/read_stdin

echo "testing stdin example"
if [[ $(echo test | ./install/bin/examples/read_stdin) != "Input from stdin: test" ]]; then
echo "stdin example returned wrong input"
exit 1
fi

echo "Expected to succeed:"
./install/bin/examples/colors < ./install/bin/examples/colors
Expand Down
14 changes: 11 additions & 3 deletions cpp-terminal/event.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "cpp-terminal/event.hpp"

#include "cpp-terminal/platforms/conversion.hpp"

bool Term::Event::empty()
{
if(m_Type == Type::Empty) return true;
Expand Down Expand Up @@ -191,13 +193,19 @@ void Term::Event::parse()
m_Key = Key(Term::Key::Value::F20);
else if(m_str == "\033[G")
m_Key = Key(Term::Key::Value::NUMERIC_5);
if(!m_Key.empty())
else if(m_str.size() == 2 && ((m_str[0] & 0b11100000) == 0b11000000) && ((m_str[1] & 0b11000000) == 0b10000000)) { m_Key = Key(static_cast<Term::Key::Value>(Term::Private::utf8_to_utf32(m_str)[0])); }
else if(m_str.size() == 3 && ((m_str[0] & 0b11110000) == 0b11100000) && ((m_str[1] & 0b11000000) == 0b10000000) && ((m_str[2] & 0b11000000) == 0b10000000)) { m_Key = Key(static_cast<Term::Key::Value>(Term::Private::utf8_to_utf32(m_str)[0])); }
else if(m_str.size() == 4 && ((m_str[0] & 0b11111000) == 0b11110000) && ((m_str[1] & 0b11000000) == 0b10000000) && ((m_str[2] & 0b11000000) == 0b10000000) && ((m_str[2] & 0b11000000) == 0b10000000))
{
m_Type = Type::Key;
m_str.clear();
m_Key = Key(static_cast<Term::Key::Value>(Term::Private::utf8_to_utf32(m_str)[0]));
}
}
else { m_Type = Type::CopyPaste; }
if(!m_Key.empty())
{
m_Type = Type::Key;
m_str.clear();
}
}

Term::Event::operator Term::Key()
Expand Down
13 changes: 0 additions & 13 deletions cpp-terminal/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,3 @@ Term::Event Term::read_event()
while((event = Platform::read_raw()).empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
return event;
}

// returns the whole input from STDIN as string
std::string Term::read_stdin()
{
std::string file;
char c{'\0'};
while(true)
{
c = Platform::read_raw_stdin();
if(c == 0x04) return file;
else { file.push_back(c); }
}
}
2 changes: 0 additions & 2 deletions cpp-terminal/input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ namespace Platform
// Returns true if a character is read, otherwise immediately returns false
// This can't be made inline
Term::Event read_raw();

char read_raw_stdin();
} // namespace Platform

// Waits for an event (key press, screen resizing ...)
Expand Down
13 changes: 13 additions & 0 deletions cpp-terminal/key.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
#include "cpp-terminal/key.hpp"

#include "cpp-terminal/platforms/conversion.hpp"

std::string Term::Key::str()
{
std::string ret;
if(m_value >= 0x10FFFF) return std::string();
else
{
Term::Private::codepoint_to_utf8(ret, static_cast<char32_t>(m_value));
return ret;
}
}

Term::Key::Key(const Term::Key::Value& value) : m_value(value) {}

Term::Key::operator Term::Key::Value() { return m_value; }
Expand Down
4 changes: 3 additions & 1 deletion cpp-terminal/key.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <cstdint>
#include <string>

namespace Term
{
Expand Down Expand Up @@ -223,7 +224,8 @@ class Key
// Detect if Key is ALT+*
bool isALT();
bool empty();
char getChar();

std::string str();

private:
Value m_value{NO_KEY};
Expand Down
50 changes: 25 additions & 25 deletions cpp-terminal/platforms/input.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifdef _WIN32
#include <vector>
// clang-format off
#include <windows.h>
#include <stringapiset.h>
// clang-format on
#include <vector>
#else
#include <cerrno>
#include <csignal>
Expand All @@ -25,43 +28,31 @@ static void sigwinchHandler(int sig)
}
#endif

char Term::Platform::read_raw_stdin()
{
char c = getchar();
if(c >= 0) { return c; }
else if(c == EOF)
{
// In non-raw (blocking) mode this happens when the input file
// ends. In such a case, return the End of Transmission (EOT)
// character (Ctrl-D)
return 0x04;
}
else { throw Term::Exception("getchar() failed"); }
}

Term::Event Term::Platform::read_raw()
{
#ifdef _WIN32
DWORD nread{0};
GetNumberOfConsoleInputEvents(Private::std_cin.getHandler(), &nread);
if(nread >= 1)
{
std::string ret;
int processed{0};
DWORD nre{0};
std::vector<INPUT_RECORD> buf{nread};
if(!ReadConsoleInput(Private::std_cin.getHandler(), &buf[0], buf.size(), &nre)) { Term::Exception("ReadFile() failed"); }
std::string ret(nre, '\0');
int processed{0};
if(!ReadConsoleInputW(Private::std_cin.getHandler(), &buf[0], buf.size(), &nre)) { Term::Exception("ReadFile() failed"); }
for(std::size_t i = 0; i != nre; ++i)
{
switch(buf[i].EventType)
{
case KEY_EVENT:
{
WORD skip = buf[i].Event.KeyEvent.wVirtualKeyCode; //skip them for now
if(skip == VK_SHIFT || skip == VK_LWIN || skip == VK_RWIN || skip == VK_APPS || skip == VK_CONTROL || skip == VK_MENU || skip == VK_CAPITAL) break;
//if(buf[i].Event.KeyEvent.wVirtualKeyCode != 0) break; //skip them for now
if(buf[i].Event.KeyEvent.bKeyDown)
{
if(buf[i].Event.KeyEvent.uChar.AsciiChar != 0) ret[processed] = buf[i].Event.KeyEvent.uChar.AsciiChar;
std::size_t size_needed = WideCharToMultiByte(CP_UTF8, 0, &buf[i].Event.KeyEvent.uChar.UnicodeChar, -1, NULL, 0, NULL, NULL);
std::string strTo(size_needed, '\0');
WideCharToMultiByte(CP_UTF8, 0, &buf[i].Event.KeyEvent.uChar.UnicodeChar, 1, &strTo[0], size_needed, NULL, NULL);
ret += strTo.c_str();
++processed;
break;
/*else
Expand Down Expand Up @@ -109,17 +100,26 @@ Term::Event Term::Platform::read_raw()
break;
}
case FOCUS_EVENT:
{
break;
}
case MENU_EVENT:
{
break;
}
case MOUSE_EVENT:
{
break;
}
case WINDOW_BUFFER_SIZE_EVENT:
{
COORD coord{buf[i].Event.WindowBufferSizeEvent.dwSize};
return Event(Screen(coord.Y, coord.X));
return Event(Screen(buf[i].Event.WindowBufferSizeEvent.dwSize.Y, buf[i].Event.WindowBufferSizeEvent.dwSize.X));
}
default: continue;
}
}
return Event(ret.c_str());
if(processed >= 1) return Event(ret);
else
return Event();
}
else
return Event();
Expand Down
6 changes: 3 additions & 3 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ target_link_libraries(keys PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings
add_executable(colors colors.cpp)
target_link_libraries(colors PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(read_stdin read_stdin.cpp)
target_link_libraries(read_stdin PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
add_executable(events events.cpp)
target_link_libraries(events PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

if(CPPTERMINAL_ENABLE_INSTALL)
install(TARGETS cin minimal prompt_multiline prompt_immediate prompt_not_immediate prompt_simple kilo menu menu_window keys colors read_stdin RUNTIME DESTINATION bin/examples)
install(TARGETS cin minimal prompt_multiline prompt_immediate prompt_not_immediate prompt_simple kilo menu menu_window keys colors RUNTIME DESTINATION bin/examples)
endif()
62 changes: 62 additions & 0 deletions examples/events.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <cpp-terminal/event.hpp>
#include <cpp-terminal/input.hpp>
#include <cpp-terminal/key.hpp>
#include <cpp-terminal/terminal.hpp>

int main()
{
try
{
// set options for the console
Term::terminal.setOptions(Term::Option::NoClearScreen, Term::Option::NoSignalKeys, Term::Option::Cursor, Term::Option::Raw);
// initial render of the whole screen
Term::terminal << "CTRL + Q to end" << std::endl;
bool main_loop_continue = true;
while(main_loop_continue)
{
auto event = Term::read_event();
switch(event.type())
{
case Term::Event::Type::Empty:
{
Term::terminal << "Event: Empty" << std::endl;
break;
}
case Term::Event::Type::Key:
{
Term::Key keyEvent = event;
if(keyEvent.iscntrl()) Term::terminal << "Event: Key (control key)" << std::endl;
else
Term::terminal << "Event: Key (" << keyEvent.str() << ")" << std::endl;
if(keyEvent == Term::Key::CTRL_Q) main_loop_continue = false;
break;
}
case Term::Event::Type::Screen:
{
Term::terminal << "Event: Screen" << std::endl;
break;
}
case Term::Event::Type::Cursor:
{
Term::terminal << "Event: Cursor" << std::endl;
break;
}
case Term::Event::Type::CopyPaste:
{
Term::terminal << "Event: CopyPaste (" << static_cast<std::string>(event) << ")" << std::endl;
break;
}
default:
{
Term::terminal << "Event: Unknown" << std::endl;
break;
}
}
}
}
catch(...)
{
Term::terminal << "There was an exception!" << std::endl;
}
return 0;
}
11 changes: 0 additions & 11 deletions examples/read_stdin.cpp

This file was deleted.