Skip to content

Commit

Permalink
Replace strategy for SIGINT and refactor a few names
Browse files Browse the repository at this point in the history
  • Loading branch information
a-n-t-h-o-n-y committed Jan 24, 2024
1 parent 2d26cf9 commit d7b684c
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 67 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ Note that not all terminals implement these features in the same way.

- Does not work with: aterm, eterm

- Some terminal emulators(Konsole) mouse input is always in `Mouse_mode::Drag`.
- Some terminal emulators(Konsole) mouse input is always in `MouseMode::Drag`.
18 changes: 13 additions & 5 deletions include/esc/detail/signals.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#ifndef ESC_DETAIL_SIGNALS
#define ESC_DETAIL_SIGNALS
#pragma once

#include <atomic>

namespace esc {

/// This is set to true when SIGINT is received. This should be periodically
/// checked by your event loop.
extern std::atomic<bool> sigint_flag;

} // namespace esc

namespace esc::detail {

/// Notifies read() and next_state(Initial) that the window has been resized.
/** Used by SIGWINCH handler and accessed in esc/io.cpp. */
extern bool window_resize_sig;
extern std::atomic<bool> window_resize_sig;

/// Install signal handlers for SIGWINCH and SIGINT, if sigint is true.
void register_signals(bool sigint);

} // namespace esc::detail
#endif // ESC_DETAIL_SIGNALS
} // namespace esc::detail
2 changes: 1 addition & 1 deletion include/esc/event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct KeyPress {
};

/// Key Release Event
/** Only used with Key_mode::Alternate set. */
/** Only used with KeyMode::Alternate set. */
struct KeyRelease {
Key key;
};
Expand Down
2 changes: 1 addition & 1 deletion include/esc/key.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ enum class Key : char32_t {
utf8 = 160,

// Unicode planes 4-13 are unassigned
// Below are only used in Key_mode::Raw
// Below are only used in KeyMode::Raw
LCtrl = 0x40000,
RCtrl,
LShift,
Expand Down
13 changes: 6 additions & 7 deletions include/esc/mouse.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef ESC_MOUSE_HPP
#define ESC_MOUSE_HPP
#pragma once

#include <cstdint>
#include <string>

Expand Down Expand Up @@ -43,15 +43,14 @@ struct Mouse {
[[nodiscard]] auto to_string(Mouse::Button b) -> std::string;

/// Defines all input modes for the Mouse.
enum class Mouse_mode {
enum class MouseMode {
Off, // No Mouse Events are generated, this is the default.
Basic, // Mouse Press & Release Events for all Buttons and Scroll Wheel.
Drag, // Basic, plus Move Events while a Button is pressed.
Move // Basic, plus Move Events sent with or without a Button pressed.
};

/// Return a string display of the given Mouse_mode enum.
[[nodiscard]] auto to_string(Mouse_mode mm) -> std::string;
/// Return a string display of the given MouseMode enum.
[[nodiscard]] auto to_string(MouseMode mm) -> std::string;

} // namespace esc
#endif // ESC_MOUSE_HPP
} // namespace esc
26 changes: 13 additions & 13 deletions include/esc/terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ void set(Screen_buffer);
/** Raw mode makes the read() call more complex, only enable if needed. All keys
* returned in Raw mode are lower-case. Has only been tested on a single laptop
* keyboard. */
enum class Key_mode : bool { Normal, Raw };
enum class KeyMode : bool { Normal, Raw };

/// Enable the given Key_mode value.
/// Enable the given KeyMode value.
/** Calls on ioctl internally. */
void set(Key_mode);
void set(KeyMode);

// CURSOR ----------------------------------------------------------------------

Expand All @@ -71,7 +71,7 @@ void set(Cursor);

/// Set the mouse input mode; determines which Events are generated for mouse.
/** Calls on write internally, but does not call flush(). */
void set(Mouse_mode);
void set(MouseMode);

// CONVENIENCE -----------------------------------------------------------------

Expand All @@ -82,8 +82,8 @@ bool constexpr is_setable = detail::is_any_of<T,
Signals,
Screen_buffer,
Cursor,
Mouse_mode,
Key_mode>;
MouseMode,
KeyMode>;

/// Convenience function to set multiple properties at once.
template <typename... Args>
Expand All @@ -109,7 +109,7 @@ void set(Args... args)
* Alternate buffer in order to restore the terminal screen to
* how it was before the application started.
*
* Mouse_mode - - Off: Generates no Mouse Events.
* MouseMode - - - Off: Generates no Mouse Events.
* Basic: Generate Mouse Press and Release Events for all
* buttons and the scroll wheel.
* Drag: Basic, plus Mouse Move Events while a button is
Expand All @@ -133,7 +133,7 @@ void set(Args... args)
* Off: Signals will not be generated on ctrl-[key] presses,
* sending the byte value of the ctrl character instead.
*
* Key_mode - - - Normal: KeyPress Events generated and auto-repeated if key
* KeyMode - - - - Normal: KeyPress Events generated and auto-repeated if key
* is held down.
* Raw: KeyPress and KeyRelease Events are generated, the
* shift key is not applied with other keys, each key
Expand All @@ -144,12 +144,12 @@ void set(Args... args)
* keyboard.
*/
void initialize_terminal(Screen_buffer,
Mouse_mode,
MouseMode,
Cursor,
Echo,
Input_buffer,
Signals,
Key_mode,
KeyMode,
bool sigint_uninit = true);

/// Initialize the terminal with 'normal' settings.
Expand All @@ -160,9 +160,9 @@ void initialize_normal_terminal();
/// Initialize the terminal with 'interactive' settings.
/** This is for typical console full-screen applications, the alternate screen
* buffer is set, key press echo is off, and the input buffer is immediate. */
void initialize_interactive_terminal(Mouse_mode mouse_mode = Mouse_mode::Basic,
Key_mode key_mode = Key_mode::Normal,
Signals signals = Signals::On);
void initialize_interactive_terminal(MouseMode mouse_mode = MouseMode::Basic,
KeyMode key_mode = KeyMode::Normal,
Signals signals = Signals::On);

// UNINITIALIZE ----------------------------------------------------------------

Expand Down
31 changes: 24 additions & 7 deletions src/detail/signals.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <esc/detail/signals.hpp>

#include <atomic>
#include <csignal>
#include <cstdlib>
#include <stdexcept>
Expand All @@ -10,32 +11,48 @@ namespace {

extern "C" auto sigint_handler(int sig) -> void
{
if (sig == SIGINT)
std::exit(EXIT_SUCCESS);
if (sig == SIGINT) {
if (esc::sigint_flag) {
// If this is second time ctrl + c is pressed, force exit.
std::quick_exit(1);
}
else {
esc::sigint_flag = true;
}
}
}

/// Set the window_resize_sig flag to true on SIGWINCH signals.
extern "C" void resize_handler(int sig)
{
if (sig == SIGWINCH)
if (sig == SIGWINCH) {
esc::detail::window_resize_sig = true;
}
}

} // namespace

namespace esc {

std::atomic<bool> sigint_flag = false;

} // namespace esc

namespace esc::detail {

bool window_resize_sig = false;
std::atomic<bool> window_resize_sig = false;

void register_signals(bool sigint)
{
std::atexit(esc::uninitialize_terminal);
std::at_quick_exit(::esc::uninitialize_terminal);

if (std::signal(SIGWINCH, &resize_handler) == SIG_ERR)
if (std::signal(SIGWINCH, &resize_handler) == SIG_ERR) {
throw std::runtime_error{"register_SIGWINCH(): std::signal call"};
}

if (sigint && std::signal(SIGINT, &sigint_handler) == SIG_ERR)
if (sigint && std::signal(SIGINT, &sigint_handler) == SIG_ERR) {
throw std::runtime_error{"register_SIGINT(): std::signal call"};
}
}

} // namespace esc::detail
12 changes: 6 additions & 6 deletions src/mouse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ auto to_string(Mouse::Button b) -> std::string
std::to_string(static_cast<std::uint16_t>(b))};
}

auto to_string(Mouse_mode mm) -> std::string
auto to_string(MouseMode mm) -> std::string
{
switch (mm) {
case Mouse_mode::Off: return "Mouse_mode::Off";
case Mouse_mode::Basic: return "Mouse_mode::Basic";
case Mouse_mode::Drag: return "Mouse_mode::Drag";
case Mouse_mode::Move: return "Mouse_mode::Move";
case MouseMode::Off: return "MouseMode::Off";
case MouseMode::Basic: return "MouseMode::Basic";
case MouseMode::Drag: return "MouseMode::Drag";
case MouseMode::Move: return "MouseMode::Move";
}
throw std::logic_error{"to_string(Mouse_mode): Bad Enum Value."};
throw std::logic_error{"to_string(MouseMode): Bad Enum Value."};
}

} // namespace esc
30 changes: 15 additions & 15 deletions src/terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,21 @@ void set(Screen_buffer sb)
}
}

void set(Key_mode km)
void set(KeyMode km)
{
// TODO implementation is messy, depends on call order.

// from linux/kd.h
constexpr auto k_xlate = 0x01;
constexpr auto k_raw = 0x00;
switch (km) {
case Key_mode::Normal:
case KeyMode::Normal:
if (detail::tty_file_descriptor.has_value()) {
detail::set_keyboard_mode(*detail::tty_file_descriptor,
k_xlate);
}
break;
case Key_mode::Raw:
case KeyMode::Raw:
detail::tty_file_descriptor = detail::open_console_file();
detail::set_keyboard_mode(*detail::tty_file_descriptor, k_raw);
break;
Expand All @@ -144,24 +144,24 @@ void set(Cursor c)
}
}

void set(Mouse_mode mm)
void set(MouseMode mm)
{
auto const ext_mode = detail::is_urxvt(TERM_var()) ? "1015" : "1006";

auto result = std::string{};
switch (mm) {
case Mouse_mode::Off:
case MouseMode::Off:
result.append("\033[?1000;1002;1003;").append(ext_mode).append("l");
break;
case Mouse_mode::Basic:
case MouseMode::Basic:
result.append("\033[?1002;1003l"); // Off
result.append("\033[?1000;").append(ext_mode).append("h");
break;
case Mouse_mode::Drag:
case MouseMode::Drag:
result.append("\033[?1000;1003l"); // Off
result.append("\033[?1002;").append(ext_mode).append("h");
break;
case Mouse_mode::Move:
case MouseMode::Move:
result.append("\033[?1000;1002l"); // Off
result.append("\033[?1003;").append(ext_mode).append("h");
break;
Expand All @@ -170,12 +170,12 @@ void set(Mouse_mode mm)
}

void initialize_terminal(Screen_buffer screen_buffer,
Mouse_mode mouse_mode,
MouseMode mouse_mode,
Cursor cursor,
Echo echo,
Input_buffer input_buffer,
Signals signals,
Key_mode key_mode,
KeyMode key_mode,
bool sigint_uninit)
{
auto constexpr stdout_buf_size = 4'096;
Expand Down Expand Up @@ -207,13 +207,13 @@ void initialize_terminal(Screen_buffer screen_buffer,

void initialize_normal_terminal()
{
initialize_terminal(Screen_buffer::Normal, Mouse_mode::Off, Cursor::Show,
initialize_terminal(Screen_buffer::Normal, MouseMode::Off, Cursor::Show,
Echo::On, Input_buffer::Canonical, Signals::On,
Key_mode::Normal);
KeyMode::Normal);
}

void initialize_interactive_terminal(Mouse_mode mouse_mode,
Key_mode key_mode,
void initialize_interactive_terminal(MouseMode mouse_mode,
KeyMode key_mode,
Signals signals)
{
initialize_terminal(Screen_buffer::Alternate, mouse_mode, Cursor::Hide,
Expand All @@ -225,7 +225,7 @@ void uninitialize_terminal()
// TODO take settings parameter and use that to reset the terminal to
// settings before.
write(turn_on_auto_wrap());
set(Screen_buffer::Normal, Mouse_mode::Off, Cursor::Show, Key_mode::Normal);
set(Screen_buffer::Normal, MouseMode::Off, Cursor::Show, KeyMode::Normal);
flush();
if (std::setlocale(LC_ALL, original_clocale.c_str()) == nullptr)
throw std::runtime_error{"uninitialize_terminal: set_locale() failed."};
Expand Down
22 changes: 11 additions & 11 deletions tools/termcaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,16 @@ class Change_mouse_mode {
public:
Change_mouse_mode(Point offset) : offset_{offset}
{
set(Mouse_mode::Basic);
this->update(Mouse_mode::Basic);
set(MouseMode::Basic);
this->update(MouseMode::Basic);
}

public:
auto row() const -> int { return offset_.y; }

auto current_mode() const -> Mouse_mode { return current_; }
auto current_mode() const -> MouseMode { return current_; }

void update(Mouse_mode mm)
void update(MouseMode mm)
{
set(mm);
current_ = mm;
Expand All @@ -258,7 +258,7 @@ class Change_mouse_mode {

private:
Point offset_;
Mouse_mode current_;
MouseMode current_;
};

auto constexpr column_two = 44;
Expand Down Expand Up @@ -356,14 +356,14 @@ struct Termcaps_app {
Color_palette_display color_palette_display{{column_two, 5}};
};

/// Returns the next mouse mode, skipping Mouse_mode::Off
auto next_mouse_mode(Mouse_mode mm) -> Mouse_mode
/// Returns the next mouse mode, skipping MouseMode::Off
auto next_mouse_mode(MouseMode mm) -> MouseMode
{
switch (mm) {
case Mouse_mode::Move:
case Mouse_mode::Off: return Mouse_mode::Basic;
case Mouse_mode::Basic: return Mouse_mode::Drag;
case Mouse_mode::Drag: return Mouse_mode::Move;
case MouseMode::Move:
case MouseMode::Off: return MouseMode::Basic;
case MouseMode::Basic: return MouseMode::Drag;
case MouseMode::Drag: return MouseMode::Move;
}
throw std::logic_error{"next_mouse_mode(): Bad enum value for mm."};
}
Expand Down

0 comments on commit d7b684c

Please sign in to comment.