Skip to content

Commit 486ceab

Browse files
authored
Merge pull request #234 from flagarde/resizing
Resizing
2 parents 3ff2369 + 2f82636 commit 486ceab

File tree

16 files changed

+267
-115
lines changed

16 files changed

+267
-115
lines changed

cpp-terminal/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ configure_file(version.hpp.in version.hpp)
44
add_subdirectory(platforms)
55

66
# create and configure library target
7-
8-
add_library(cpp-terminal base.cpp prompt.cpp window.cpp input.cpp terminal.cpp color.cpp key.cpp event.cpp options.cpp)
7+
add_library(cpp-terminal base.cpp prompt.cpp window.cpp input.cpp terminal.cpp color.cpp key.cpp event.cpp screen.cpp options.cpp)
98
target_link_libraries(cpp-terminal PRIVATE Warnings::Warnings cpp-terminal::cpp-terminal-platforms)
109
target_compile_options(cpp-terminal PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
1110
target_include_directories(cpp-terminal PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}> $<INSTALL_INTERFACE:include>)

cpp-terminal/event.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@ bool Term::Event::empty()
77
return false;
88
}
99

10+
Term::Event::operator std::string()
11+
{
12+
if(m_Type == Type::CopyPaste) return m_str;
13+
else
14+
return std::string();
15+
}
16+
17+
Term::Event::operator Term::Screen()
18+
{
19+
if(m_Type == Type::Screen) return m_Screen;
20+
else
21+
return Term::Screen();
22+
}
23+
24+
Term::Event::Event(const Term::Screen& screen) : m_Type(Type::Screen), m_Screen(screen) {}
25+
1026
Term::Event::Event(const Term::Key& key) : m_Type(Type::Key), m_Key(key) {}
1127

1228
Term::Event::Type Term::Event::type() { return m_Type; }
@@ -19,9 +35,11 @@ void Term::Event::parse()
1935
{
2036
m_Type = Type::Key;
2137
m_Key = static_cast<Term::Key::Value>(m_str[0]);
38+
/* Backspace return 127 CTRL+backspace return 8 */
39+
if(m_Key == Term::Key::Value::DEL) m_Key = Term::Key::Value::BACKSPACE;
2240
m_str.clear();
2341
}
24-
else if(m_str.size() <= 5)
42+
else if(m_str.size() <= 10)
2543
{
2644
//https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
2745
// CSI = ESC[ SS3 = ESCO
@@ -156,8 +174,11 @@ void Term::Event::parse()
156174
m_Key = Term::Key::Value::F19;
157175
else if(m_str == "\033[34~")
158176
m_Key = Term::Key::Value::F20;
159-
if(!m_Key.empty()) m_Type = Type::Key;
160-
m_str.clear();
177+
if(!m_Key.empty())
178+
{
179+
m_Type = Type::Key;
180+
m_str.clear();
181+
}
161182
}
162183
else { m_Type = Type::CopyPaste; }
163184
}

cpp-terminal/event.hpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "cpp-terminal/key.hpp"
4+
#include "cpp-terminal/screen.hpp"
45

56
#include <cstdint>
67
#include <string>
@@ -15,22 +16,26 @@ class Event
1516
{
1617
Empty,
1718
Key,
19+
Screen,
1820
CopyPaste,
1921
};
2022
Event() = default;
2123
Event(const std::string&);
2224
Event(const Term::Key&);
25+
Event(const Term::Screen& screen);
2326
bool empty();
2427
Type type();
2528

26-
operator Term::Key();
27-
Key getKey() { return m_Key; }
29+
operator Term::Key();
30+
operator Term::Screen();
31+
operator std::string();
2832

2933
private:
30-
void parse();
31-
std::string m_str;
32-
Key m_Key{Key::Value::NO_KEY};
33-
Type m_Type{Type::Empty};
34+
void parse();
35+
Type m_Type{Type::Empty};
36+
std::string m_str;
37+
Key m_Key{Key::Value::NO_KEY};
38+
Term::Screen m_Screen;
3439
};
3540

3641
} // namespace Term

cpp-terminal/input.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@
88
#include "cpp-terminal/event.hpp"
99

1010
#include <chrono>
11-
#include <iostream>
1211
#include <thread>
1312
#include <type_traits>
1413

15-
std::int32_t Term::read_key()
14+
Term::Event Term::read_event()
1615
{
17-
Term::Key key;
18-
while((key = Platform::read_raw()).empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
19-
return key;
16+
Term::Event event;
17+
while((event = Platform::read_raw()).empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }
18+
return event;
2019
}
2120

2221
// returns the whole input from STDIN as string

cpp-terminal/input.hpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,8 @@ Term::Event read_raw();
1616
char read_raw_stdin();
1717
} // namespace Platform
1818

19-
// Waits for a key press, translates escape codes
20-
// if Term:Terminal is not enabling the keyboard it'll loop for infinity
21-
std::int32_t read_key();
22-
23-
// If there was a key press, returns the translated key from escape codes,
24-
// otherwise returns 0. If the escape code is not supported it returns a
25-
// negative number.
26-
// if Term::Terminal is not enabling the keyboard it'll always return 0
27-
std::int32_t read_key0();
19+
// Waits for an event (key press, screen resizing ...)
20+
Term::Event read_event();
2821

2922
// returns the stdin as a string
3023
// waits until the EOT signal is send

cpp-terminal/key.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ bool Term::Key::is_extended_ASCII()
2121
bool Term::Key::is_CTRL()
2222
{
2323
// Need to suppress the TAB etc...
24-
if(m_value > 0 && m_value <= 31 && m_value != Key::BACKSPACE && m_value != Key::TAB && m_value != ESC && /* the two mapped to ENTER */ m_value != Key::LF && m_value != ENTER) return true;
24+
if(m_value > 0 && m_value <= 31 && m_value != Key::BACKSPACE && m_value != Key::TAB && m_value != ESC && /* the two mapped to ENTER */ m_value != ENTER) return true;
2525
else
2626
return false;
2727
}

cpp-terminal/key.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Key
2222
CTRL_G = 7,
2323
BACKSPACE = 8,
2424
TAB = 9,
25-
LF = 10,
25+
CTRL_J = 10,
2626
CTRL_K = 11,
2727
CTRL_L = 12,
2828
ENTER = 13, // Mapped to ENTER

cpp-terminal/platforms/input.cpp

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <windows.h>
33
#else
44
#include <cerrno>
5+
#include <csignal>
6+
#include <fcntl.h>
57
#include <sys/ioctl.h>
68
#include <unistd.h>
79
#endif
@@ -13,6 +15,18 @@
1315
#include <string>
1416
#include <vector>
1517

18+
#if !defined(_WIN32)
19+
namespace
20+
{
21+
volatile std::sig_atomic_t gSignalStatus;
22+
}
23+
24+
static void sigwinchHandler(int sig)
25+
{
26+
if(sig == SIGWINCH) gSignalStatus = 1;
27+
}
28+
#endif
29+
1630
char Term::Platform::read_raw_stdin()
1731
{
1832
char c = getchar();
@@ -102,20 +116,55 @@ Term::Event Term::Platform::read_raw()
102116
case MENU_EVENT:
103117
case MOUSE_EVENT:
104118
case WINDOW_BUFFER_SIZE_EVENT:
105-
default: return Event();
119+
{
120+
COORD coord{buf[i].Event.WindowBufferSizeEvent.dwSize};
121+
return Event(Screen(coord.Y, coord.X));
122+
}
123+
default: continue;
106124
}
107125
}
108126
return Event(ret.c_str());
109127
}
110128
else
111129
return Event();
112130
#else
113-
std::string ret(4096, '\0'); // Max for cin
114-
errno = 0;
115-
::ssize_t nread{::read(0, &ret[0], ret.size())};
116-
if(nread == -1 && errno != EAGAIN) { throw Term::Exception("read() failed"); }
117-
if(nread >= 1) return Event(ret.c_str());
131+
static bool activated{false};
132+
if(!activated)
133+
{
134+
struct sigaction sa;
135+
sigemptyset(&sa.sa_mask);
136+
sa.sa_flags = 0;
137+
sa.sa_handler = sigwinchHandler;
138+
if(sigaction(SIGWINCH, &sa, NULL) == -1) throw Term::Exception("signal() failed");
139+
else
140+
activated = true;
141+
}
142+
143+
if(gSignalStatus == 1)
144+
{
145+
struct winsize ws
146+
{
147+
};
148+
ws.ws_row = 0;
149+
ws.ws_col = 0;
150+
ws.ws_xpixel = 0;
151+
ws.ws_ypixel = 0;
152+
int fd{open("/dev/tty", O_RDWR, O_NOCTTY)};
153+
ioctl(fd, TIOCGWINSZ, &ws);
154+
close(fd);
155+
gSignalStatus = 0;
156+
if(ws.ws_row != 0 && ws.ws_col != 0) return Event(Screen(ws.ws_row, ws.ws_col));
157+
}
118158
else
119-
return Event();
159+
{
160+
std::string ret(4096, '\0'); // Max for cin
161+
errno = 0;
162+
::ssize_t nread{::read(0, &ret[0], ret.size())};
163+
if(nread == -1 && errno != EAGAIN) { throw Term::Exception("read() failed"); }
164+
if(nread >= 1) return Event(ret.c_str());
165+
else
166+
return Event();
167+
}
168+
return Event();
120169
#endif
121170
}

cpp-terminal/prompt.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ Term::Result Term::prompt(const std::string& message, const std::string& first_o
1919
return Result::ERROR;
2020
}
2121

22-
int key;
22+
Term::Key key;
2323

2424
if(immediate)
2525
{
2626
while(true)
2727
{
28-
key = Term::read_key();
28+
key = Term::read_event();
29+
if(key == Term::Key::NO_KEY) continue;
2930
if(key == 'y' || key == 'Y')
3031
{
3132
std::cout << '\n' << std::flush;
@@ -59,7 +60,8 @@ Term::Result Term::prompt(const std::string& message, const std::string& first_o
5960
unsigned short int length = 0;
6061
while(true)
6162
{
62-
key = Term::read_key();
63+
key = Term::read_event();
64+
if(key == Term::Key::NO_KEY) continue;
6365
if(key >= 'a' && key <= 'z')
6466
{
6567
std::cout << (char)key << std::flush;
@@ -111,6 +113,7 @@ Term::Result Term::prompt(const std::string& message, const std::string& first_o
111113
}
112114
}
113115
}
116+
return Result::INVALID;
114117
}
115118

116119
Term::Result_simple Term::prompt_simple(const std::string& message)
@@ -221,7 +224,8 @@ std::string Term::prompt_multiline(const std::string& prompt_string, std::vector
221224
bool not_complete = true;
222225
while(not_complete)
223226
{
224-
key = static_cast<Key::Value>(Term::read_key());
227+
key = Term::read_event();
228+
if(key == Term::Key::NO_KEY) continue;
225229
if((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key.is_extended_ASCII() && !iscntrl(key)))
226230
{
227231
std::string before = m.lines[m.cursor_row - 1].substr(0, m.cursor_col - 1);

cpp-terminal/screen.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "cpp-terminal/screen.hpp"
2+
3+
std::size_t Term::Screen::rows() { return m_size.first; }
4+
5+
std::size_t Term::Screen::columns() { return m_size.second; }
6+
7+
bool Term::Screen::empty()
8+
{
9+
if(m_size.second == 0 && m_size.first == 0) return true;
10+
else
11+
return false;
12+
}
13+
14+
std::pair<std::size_t, std::size_t> Term::Screen::size() { return m_size; }

0 commit comments

Comments
 (0)