From 7bfd9f2c864d8a060169f96fe36ba41c76206ac6 Mon Sep 17 00:00:00 2001 From: Benny Baumann <BenBE@geshi.org> Date: Sat, 9 Nov 2019 17:27:32 +0100 Subject: [PATCH] add: Intermediate rework of nccpp --- src/lib/nccpp/Color.hpp | 24 ++ src/lib/nccpp/Ncurses.cpp | 333 ++++++++++++++++++++++++++++ src/lib/nccpp/Ncurses.hpp | 119 ++++++++++ src/lib/nccpp/Subwindow.cpp | 53 +++++ src/lib/nccpp/Subwindow.hpp | 37 ++++ src/lib/nccpp/Window.cpp | 269 ++++++++++++++++++++++ src/lib/nccpp/Window.hpp | 201 +++++++++++++++++ src/lib/nccpp/Window_appearance.cpp | 61 +++++ src/lib/nccpp/Window_attributes.cpp | 74 +++++++ src/lib/nccpp/Window_input.cpp | 130 +++++++++++ src/lib/nccpp/Window_misc.cpp | 111 ++++++++++ src/lib/nccpp/Window_options.cpp | 43 ++++ src/lib/nccpp/Window_output.cpp | 154 +++++++++++++ src/lib/nccpp/constants.hpp | 261 ++++++++++++++++++++++ src/lib/nccpp/errors.hpp | 82 +++++++ src/lib/nccpp/ncursescpp.hpp | 8 + 16 files changed, 1960 insertions(+) create mode 100644 src/lib/nccpp/Color.hpp create mode 100644 src/lib/nccpp/Ncurses.cpp create mode 100644 src/lib/nccpp/Ncurses.hpp create mode 100644 src/lib/nccpp/Subwindow.cpp create mode 100644 src/lib/nccpp/Subwindow.hpp create mode 100644 src/lib/nccpp/Window.cpp create mode 100644 src/lib/nccpp/Window.hpp create mode 100644 src/lib/nccpp/Window_appearance.cpp create mode 100644 src/lib/nccpp/Window_attributes.cpp create mode 100644 src/lib/nccpp/Window_input.cpp create mode 100644 src/lib/nccpp/Window_misc.cpp create mode 100644 src/lib/nccpp/Window_options.cpp create mode 100644 src/lib/nccpp/Window_output.cpp create mode 100644 src/lib/nccpp/constants.hpp create mode 100644 src/lib/nccpp/errors.hpp create mode 100644 src/lib/nccpp/ncursescpp.hpp diff --git a/src/lib/nccpp/Color.hpp b/src/lib/nccpp/Color.hpp new file mode 100644 index 0000000..a8d44d6 --- /dev/null +++ b/src/lib/nccpp/Color.hpp @@ -0,0 +1,24 @@ +#pragma once + +namespace nccpp { + +/** + * \brief Class representing a ncurses color pair. + */ +struct Color { + Color() : Color{-1, -1} {} + Color(short f, short b) : foreground{f}, background{b} {} + + short foreground; ///< Foreground color. + short background; ///< Background color. +}; + +inline bool operator==(nccpp::Color const &lhs, nccpp::Color const &rhs) { + return (lhs.foreground == rhs.foreground) && (lhs.background == rhs.background); +} + +inline bool operator!=(nccpp::Color const &lhs, nccpp::Color const &rhs) { + return !(lhs == rhs); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Ncurses.cpp b/src/lib/nccpp/Ncurses.cpp new file mode 100644 index 0000000..59eab32 --- /dev/null +++ b/src/lib/nccpp/Ncurses.cpp @@ -0,0 +1,333 @@ +#include "lib/nccpp/Ncurses.hpp" + +#include <algorithm> +#include <cassert> + +#include "lib/nccpp/errors.hpp" + +namespace nccpp { + +inline Ncurses::Ncurses() : Window{initscr()}, registered_colors_{}, +#ifndef NDEBUG + windows_ {}, is_exit_ {false}, +#endif + colors_initialized_ {false} +{ + if (!win_) { + throw errors::NcursesInit{}; + } +} + +inline Ncurses::~Ncurses() { + endwin(); + win_ = nullptr; +#ifdef NO_LEAKS + _nc_freeall(); +#endif +} + +#ifndef NDEBUG +inline void Ncurses::register_window_(Window &new_win, Window::Key /*dummy*/) { + windows_.push_back(&new_win); +} + +inline void Ncurses::unregister_window_(Window &win, Window::Key /*dummy*/) { + auto it = std::find(std::begin(windows_), std::end(windows_), &win); + + assert(it != std::end(windows_)); + + windows_.erase(it); +} +#endif + +inline void Ncurses::exit_ncurses_mode() { + assert(!is_exit_ && "Ncurses mode is already off"); + +#ifndef NDEBUG + + for (auto elem : windows_) { + elem->invalidate_for_exit_(Window::Key{}); + } + + invalidate_for_exit_(Key{}); + is_exit_ = true; + +#endif + + endwin(); +} + +inline void Ncurses::resume_ncurses_mode() { + assert(is_exit_ && "Ncurses mode is already on"); + +#ifndef NDEBUG + + for (auto elem : windows_) { + elem->validate_for_resume_(Window::Key{}); + } + + validate_for_resume_(Key{}); + is_exit_ = false; + +#endif + + doupdate(); +} + +// Input options + +inline int Ncurses::cbreak(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return on ? ::cbreak() : nocbreak(); +} + +inline int Ncurses::echo(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return on ? ::echo() : noecho(); +} + +inline int Ncurses::halfdelay(int delay) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::halfdelay(delay); +} + +inline int Ncurses::intrflush(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::intrflush(win_, on); +} + +inline int Ncurses::meta(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::meta(win_, on); +} + +inline int Ncurses::raw(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return on ? ::raw() : noraw(); +} + +inline void Ncurses::qiflush(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + on ? ::qiflush() : noqiflush(); +} + +inline int Ncurses::typeahead(int fd) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::typeahead(fd); +} + +// Output options + +inline int Ncurses::clearok(bool on, bool use_cs) { + assert(!is_exit_ && "Ncurses mode is off"); + + return::clearok(use_cs ? curscr : win_, on); +} + +inline int Ncurses::idlok(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::idlok(win_, on); +} + +inline void Ncurses::idcok(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + ::idcok(win_, on); +} + +inline void Ncurses::immedok(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + ::immedok(win_, on); +} + +inline int Ncurses::leaveok(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::leaveok(win_, on); +} + +inline int Ncurses::scrollok(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::scrollok(win_, on); +} + +inline int Ncurses::nl(bool on) { + assert(!is_exit_ && "Ncurses mode is off"); + + return on ? ::nl() : nonl(); +} + +// Input functions + +inline int Ncurses::ungetch(int ch) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::ungetch(ch); +} + +inline int Ncurses::has_key(int ch) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::has_key(ch); +} + +// Misc + +inline int Ncurses::doupdate() { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::doupdate(); +} + +inline int Ncurses::line_count() { + assert(!is_exit_ && "Ncurses mode is off"); + + return LINES; +} + +inline int Ncurses::column_count() { + assert(!is_exit_ && "Ncurses mode is off"); + + return COLS; +} + +// Mouse + +inline bool Ncurses::has_mouse() { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::has_mouse(); +} + +inline int Ncurses::getmouse(MEVENT &event) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::getmouse(&event); +} + +inline int Ncurses::ungetmouse(MEVENT &event) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::ungetmouse(&event); +} + +inline mmask_t Ncurses::mousemask(mmask_t newmask, mmask_t* oldmask) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::mousemask(newmask, oldmask); +} + +inline int Ncurses::mouseinterval(int erval) { + assert(!is_exit_ && "Ncurses mode is off"); + + return ::mouseinterval(erval); +} + +// Window + +inline WINDOW* Ncurses::newwin_(int nlines, int ncols, int begin_y, int begin_x, Window::Key /*dummy*/) { + assert(!is_exit_ && "Ncurses mode is off"); + + return newwin(nlines, ncols, begin_y, begin_x); +} + +// Color + +inline void Ncurses::start_color() { + assert(!is_exit_ && "Ncurses mode is off"); + + if (colors_initialized_) { + return; + } + + if (::start_color() == ERR) { + throw errors::ColorInit{}; + } + + colors_initialized_ = true; +} + +inline int Ncurses::use_default_colors() { + assert(!is_exit_ && "Ncurses mode is off"); + + start_color(); + + return ::use_default_colors(); +} + +inline short Ncurses::color_to_pair_number(Color const &color) { + assert(!is_exit_ && "Ncurses mode is off"); + + auto it = std::find_if( + std::begin(registered_colors_), + std::end(registered_colors_), + [color](Color const & elem) { + return color == elem; + }); + + if (it != std::end(registered_colors_)) { + return static_cast<short>(it - std::begin(registered_colors_) + 1); + } + + start_color(); + + // Ensure push_back will not throw + registered_colors_.reserve(registered_colors_.size() + 1); + auto res = init_pair(static_cast<short>(registered_colors_.size() + 1), color.foreground, color.background); + + if (res == ERR) { + throw errors::TooMuchColors{color}; + } + + registered_colors_.push_back(color); + + return static_cast<short>(registered_colors_.size()); +} + +inline attr_t Ncurses::color_to_attr(Color const &color) { + assert(!is_exit_ && "Ncurses mode is off"); + + return static_cast<attr_t>(COLOR_PAIR(color_to_pair_number(color))); +} + +inline Color Ncurses::pair_number_to_color(short pair_n) { + assert(!is_exit_ && "Ncurses mode is off"); + assert(static_cast<std::size_t>(pair_n) <= registered_colors_.size() && "No such color"); + + return registered_colors_[static_cast<std::size_t>(pair_n - 1)]; +} + +inline Color Ncurses::attr_to_color(attr_t a) { + assert(!is_exit_ && "Ncurses mode is off"); + + return pair_number_to_color(static_cast<short>(PAIR_NUMBER(static_cast<int>(a)))); +} + +inline int Ncurses::init_color(short color, short r, short g, short b) { + assert(!is_exit_ && "Ncurses mode is off"); + + start_color(); + + return ::init_color(color, r, g, b); +} + +inline void Ncurses::assign(WINDOW*) { + assert(false && "Can't call nccpp::Ncurses::assign"); +} + +inline void Ncurses::destroy() { + assert(false && "Can't call nccpp::Ncurses::destroy"); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Ncurses.hpp b/src/lib/nccpp/Ncurses.hpp new file mode 100644 index 0000000..e31f0f9 --- /dev/null +++ b/src/lib/nccpp/Ncurses.hpp @@ -0,0 +1,119 @@ +#pragma once + +#include <vector> + +#include "lib/ncurses/ncurses.hpp" + +#include "lib/nccpp/Color.hpp" + +namespace nccpp { + class Ncurses; +} + +#include "lib/nccpp/Window.hpp" + +namespace nccpp{ + +class Ncurses : public Window{ + friend Ncurses &ncurses(); +public: + Ncurses(const Ncurses &) = delete; + Ncurses(Ncurses &&) = delete; + Ncurses &operator=(const Ncurses &) = delete; + Ncurses &operator=(Ncurses &&) = delete; + ~Ncurses(); + + void exit_ncurses_mode(); + void resume_ncurses_mode(); + + // Input options + + int cbreak(bool); + int echo(bool); + int halfdelay(int); + int intrflush(bool); + int meta(bool); + int raw(bool); + void qiflush(bool); + int typeahead(int); + + // Output options + + int clearok(bool, bool = false); + int idlok(bool); + void idcok(bool); + void immedok(bool); + int leaveok(bool); + int scrollok(bool); + int nl(bool); + + // Input functions + + int ungetch(int); + int has_key(int); + + // Misc + + int doupdate(); + int line_count(); + int column_count(); + + // Mouse + + bool has_mouse(); + int getmouse(MEVENT &); + int ungetmouse(MEVENT &); + mmask_t mousemask(mmask_t, mmask_t* = nullptr); + int mouseinterval(int); + + // Window + + /// \cond NODOC + WINDOW* newwin_(int, int, int, int, Window::Key); + +#ifndef NDEBUG + void register_window_(Window &, Window::Key); + void unregister_window_(Window &, Window::Key); +#endif + + // Color + + void start_color(); + int use_default_colors(); + + short color_to_pair_number(Color const &); + attr_t color_to_attr(Color const &); + Color pair_number_to_color(short); + Color attr_to_color(attr_t); + + int init_color(short, short, short, short); + +private: + Ncurses(); + + std::vector<Color> registered_colors_; + +#ifndef NDEBUG + std::vector<Window*> windows_; + bool is_exit_; +#endif + + bool colors_initialized_; + + void assign(WINDOW*) override; + void destroy() override; +}; + +/** + * Access the Ncurses singleton. + * + * \exception errors::NcursesInit Thrown when ncurses can't be initialized. + * \return A reference to the singleton. + */ +inline Ncurses &ncurses() +{ + static Ncurses nc{}; + return nc; +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Subwindow.cpp b/src/lib/nccpp/Subwindow.cpp new file mode 100644 index 0000000..36c2379 --- /dev/null +++ b/src/lib/nccpp/Subwindow.cpp @@ -0,0 +1,53 @@ +#include "lib/nccpp/Subwindow.hpp" + +#include <cassert> + +#include "lib/nccpp/Window.hpp" + +namespace nccpp { + +inline Window &Subwindow::get_parent() { + assert(win_ && "Invalid subwindow"); + + return parent_; +} + +inline int Subwindow::mvderwin(int y, int x) { + assert(win_ && "Invalid subwindow"); + + return ::mvderwin(win_, y, x); +} + +inline void Subwindow::syncup() { + assert(win_ && "Invalid subwindow"); + + wsyncup(win_); +} + +inline int Subwindow::syncok(bool on) { + assert(win_ && "Invalid subwindow"); + + return ::syncok(win_, on); +} + +inline void Subwindow::cursyncup() { + assert(win_ && "Invalid subwindow"); + + wcursyncup(win_); +} + +inline void Subwindow::syncdown() { + assert(win_ && "Invalid subwindow"); + + wsyncdown(win_); +} + +inline void Subwindow::assign(WINDOW*) { + assert(false && "Can't call nccpp::Subwindow::assign"); +} + +inline void Subwindow::destroy() { + assert(false && "Can't call nccpp::Subwindow::destroy"); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Subwindow.hpp b/src/lib/nccpp/Subwindow.hpp new file mode 100644 index 0000000..0d0a59a --- /dev/null +++ b/src/lib/nccpp/Subwindow.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "lib/nccpp/Ncurses.hpp" +#include "lib/nccpp/Window.hpp" + +namespace nccpp { + +class Subwindow : public Window { +public: + Subwindow(Window &parent, WINDOW* subwin, Window::Key /*dummy*/) + : Window{subwin}, parent_{parent} + {} + + Subwindow(const Subwindow &) = delete; + Subwindow(Subwindow &&) = default; + Subwindow &operator=(const Subwindow &) = delete; + Subwindow &operator=(Subwindow &&) = default; + + ~Subwindow() = default; + + Window &get_parent(); + + int mvderwin(int, int); + + void syncup(); + int syncok(bool); + void cursyncup(); + void syncdown(); + +private: + Window &parent_; + + void assign(WINDOW*) override; + void destroy() override; +}; + +} // namespace nccpp diff --git a/src/lib/nccpp/Window.cpp b/src/lib/nccpp/Window.cpp new file mode 100644 index 0000000..b5b39a3 --- /dev/null +++ b/src/lib/nccpp/Window.cpp @@ -0,0 +1,269 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +#include "lib/nccpp/errors.hpp" +#include "lib/nccpp/Ncurses.hpp" +#include "lib/nccpp/Subwindow.hpp" + +namespace nccpp{ + +inline Window::Window(WINDOW* win) : + win_{win}, +#ifndef NDEBUG + win_save_ {nullptr}, +#endif + subwindows_ {} +{ +#ifndef NDEBUG + + if (win_ != stdscr) { + ncurses().register_window_(*this, Key{}); + } + +#endif +} + +inline Window::Window(int nlines, int ncols, int begin_y, int begin_x) : + win_{ncurses().newwin_(nlines, ncols, begin_y, begin_x, Key{})}, +#ifndef NDEBUG + win_save_ {nullptr}, +#endif + subwindows_ {} +{ + if (!win_) { + throw errors::WindowInit{}; + } + +#ifndef NDEBUG + + try { + ncurses().register_window_(*this, Key{}); + } + catch (...) { + delwin(win_); + throw; + } + +#endif +} + +inline Window::Window(Window const &cp) : + win_{nullptr}, +#ifndef NDEBUG + win_save_ {nullptr}, +#endif + subwindows_ {} +{ + assert(!cp.win_save_ && "Can't duplicate windows while ncurses mode is off"); + subwindows_.reserve(cp.subwindows_.size()); + + if (cp.win_ && !(win_ = dupwin(cp.win_))) { + throw errors::WindowInit{}; + } + +#ifndef NDEBUG + + try { + ncurses().register_window_(*this, Key{}); + } + catch (...) { + delwin(win_); + throw; + } + +#endif +} + +inline Window &Window::operator=(Window const &cp){ + if (this != &cp) { + Window tmp{cp}; + *this = std::move(tmp); + } + + return *this; +} + +inline Window::Window(Window &&mv) +#ifdef NDEBUG +noexcept +#endif + : + win_ {mv.win_}, +#ifndef NDEBUG + win_save_ {mv.win_save_}, +#endif + subwindows_ {std::move(mv.subwindows_)} +{ + mv.win_ = nullptr; +#ifndef NDEBUG + mv.win_save_ = nullptr; + ncurses().register_window_(*this, Key{}); +#endif +} + +inline Window &Window::operator=(Window &&mv) noexcept { + if (this != &mv) { + destroy(); + win_ = mv.win_; + mv.win_ = nullptr; + +#ifndef NDEBUG + win_save_ = mv.win_save_; + mv.win_save_ = nullptr; +#endif + + subwindows_ = std::move(mv.subwindows_); + } + + return *this; +} + +inline Window::~Window() { +#ifndef NDEBUG + + if (this != &ncurses()) { + ncurses().unregister_window_(*this, Key{}); + } + +#endif + + destroy(); +} + +inline void Window::assign(WINDOW* new_win) { + assert(!win_save_ && "Can't modify window while ncurses mode is off"); + + if (win_) { + destroy(); + } + + win_ = new_win; +} + +inline void Window::destroy() { + if (win_) { + subwindows_.clear(); + delwin(win_); + win_ = nullptr; + } + +#ifndef NDEBUG + else if (win_save_) { + subwindows_.clear(); + delwin(win_save_); + win_save_ = nullptr; + } + +#endif +} + +inline WINDOW* Window::get_handle() { + assert(win_ && "Window doesn't manage any object"); + + return win_; +} + +inline WINDOW const* Window::get_handle() const { + assert(win_ && "Window doesn't manage any object"); + return win_; +} + +inline std::size_t Window::add_subwindow(int lines, int cols, int beg_y, int beg_x) { + assert(win_ && "Window doesn't manage any object"); + +#ifndef NDEBUG + int posx = 0, posy = 0, maxx = 0, maxy = 0; + get_begyx(posy, posx); + get_maxyx(maxy, maxx); + maxy += posy; + maxx += posx; +#endif + + assert(posy <= beg_y && posx <= beg_x && maxy >= beg_y + lines && maxx >= beg_x + cols && + "Invalid subwindow coordinates"); + + auto new_subw = subwin(win_, lines, cols, beg_y, beg_x); + + if (!new_subw) { + throw errors::WindowInit{}; + } + + try { + subwindows_.emplace_back(*this, new_subw, Window::Key{}); + } + catch (...) { + delwin(new_subw); + throw; + } + + return subwindows_.size() - 1; +} + +inline Subwindow &Window::get_subwindow(std::size_t index) { + assert(win_ && "Window doesn't manage any object"); + assert(index < subwindows_.size() && subwindows_[index].win_ && "Invalid subwindow"); + + return subwindows_[index]; +} + +inline void Window::delete_subwindow(std::size_t index) { + assert(win_ && "Window doesn't manage any object"); + assert(index < subwindows_.size() && subwindows_[index].win_ && "Invalid subwindow"); + + subwindows_[index].~Subwindow(); + new (&subwindows_[index]) Subwindow{*this, nullptr, Key{}}; +} + +#ifndef NDEBUG +inline void Window::invalidate_for_exit_(Window::Key /*dummy*/) { + for (auto &elem : subwindows_) { + elem.invalidate_for_exit_(Key{}); + } + + win_save_ = win_; + win_ = nullptr; +} + +inline void Window::validate_for_resume_(Window::Key /*dummy*/) { + for (auto &elem : subwindows_) { + elem.validate_for_resume_(Key{}); + } + + win_ = win_save_; + win_save_ = nullptr; +} +#endif + +inline int overlay(Window const &src, Window &dst) { + return ::overlay(src.get_handle(), dst.get_handle()); +} + +inline int overwrite(Window const &src, Window &dst) { + return ::overwrite(src.get_handle(), dst.get_handle()); +} + +inline int copywin( + Window const &src, + Window &dst, + int sminrow, + int smincol, + int dminrow, + int dmincol, + int dmaxrow, + int dmaxcol, + bool overlay +) { + return ::copywin( + src.get_handle(), + dst.get_handle(), + sminrow, + smincol, + dminrow, + dmincol, + dmaxrow, + dmaxcol, + overlay); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window.hpp b/src/lib/nccpp/Window.hpp new file mode 100644 index 0000000..9a98f06 --- /dev/null +++ b/src/lib/nccpp/Window.hpp @@ -0,0 +1,201 @@ +#pragma once + +#include <cstddef> +#include <string> +#include <vector> + +#include "lib/ncurses/ncurses.hpp" + +#include "lib/nccpp/Color.hpp" + +namespace nccpp { + +/** \brief Alias used for input functions. */ +using String = std::basic_string<chtype>; + +class Ncurses; +class Subwindow; + +class Window { +public: + explicit Window(WINDOW*); + Window(int, int, int, int); + + Window(Window const &); + Window &operator=(Window const &); + + Window(Window &&) +#ifdef NDEBUG + noexcept +#endif + ; + + Window &operator=(Window &&) noexcept; + + Window(const Ncurses &) = delete; + Window(Ncurses &&) = delete; + Window &operator=(const Ncurses &) = delete; + Window &operator=(Ncurses &&) = delete; + + Window(const Subwindow &) = delete; + Window(Subwindow &&) = delete; + Window &operator=(const Subwindow &) = delete; + Window &operator=(Subwindow &&) = delete; + + ~Window(); + + virtual void assign(WINDOW*); + virtual void destroy(); + WINDOW* get_handle(); + WINDOW const* get_handle() const; + + std::size_t add_subwindow(int, int, int, int); + Subwindow &get_subwindow(std::size_t); + void delete_subwindow(std::size_t); + + // Input options + + int keypad(bool); + int nodelay(bool); + int notimeout(bool); + void timeout(int); + + // Output options + + int clearok(bool); + int setscrreg(int, int); + + // Input functions + + int getch(); + int mvgetch(int, int); + + int scanw(char const*, ...); + int mvscanw(int, int, char const*, ...); + + int getstr(std::string &); + int getnstr(std::string &, std::size_t); + int mvgetstr(int, int, std::string &); + int mvgetnstr(int, int, std::string &, std::size_t); + + chtype inch(); + chtype mvinch(int, int); + + int instr(std::string &); + int innstr(std::string &, std::size_t); + int mvinstr(int, int, std::string &); + int mvinnstr(int, int, std::string &, std::size_t); + + int inchstr(String &); + int inchnstr(String &, std::size_t); + int mvinchstr(int, int, String &); + int mvinchnstr(int, int, String &, std::size_t); + + // Output functions + + int addch(chtype const); + int mvaddch(int, int, chtype const); + int echochar(chtype const); + + int printw(char const*, ...); + int mvprintw(int, int, char const*, ...); + + int addstr(std::string const &); + int addnstr(std::string const &, std::size_t); + int mvaddstr(int, int, std::string const &); + int mvaddnstr(int, int, std::string const &, std::size_t); + + int addchstr(String const &); + int addchnstr(String const &, std::size_t); + int mvaddchstr(int, int, String const &); + int mvaddchnstr(int, int, String const &, std::size_t); + + int insch(chtype); + int mvinsch(int y, int x, chtype); + + int insstr(std::string const &); + int insnstr(std::string const &, std::size_t); + int mvinsstr(int, int, std::string const &); + int mvinsnstr(int, int, std::string const &, std::size_t); + + // Deletion functions + + int delch(); + int mvdelch(int, int); + + int insdelln(int); + + // Border + + int border(chtype, chtype, chtype, chtype, chtype, chtype, chtype, chtype); + int box(chtype, chtype); + + int hline(chtype, int); + int vline(chtype, int); + int mvhline(int, int, chtype, int); + int mvvline(int, int, chtype, int); + + // Background + + void bkgdset(int); + int bkgd(int); + chtype getbkgd(); + + // Attributes + + int attroff(int); + int attron(int); + int attrset(int); + + int attr_get(attr_t &); + int color_get(Color &); + + int attr_color_get(attr_t &, Color &); + + int chgat(int, attr_t, Color); + int mvchgat(int, int, int, attr_t, Color); + + // Misc + + int move(int, int); + int mvwin(int, int); + + int erase(); + int clear(); + int clrtobot(); + int clrtoeol(); + + int refresh(); + int outrefresh(); + int redraw(); + int redrawln(int, int); + + int scroll(int = 1); + + void get_yx(int &, int &); + void get_begyx(int &, int &); + void get_maxyx(int &, int &); + + int touchln(int, int, bool); + + bool enclose(int, int); + bool coord_trafo(int &, int &, bool); + +protected: + struct Key {}; + + WINDOW* win_; + +#ifndef NDEBUG + WINDOW* win_save_; + +public: + void invalidate_for_exit_(Key); + void validate_for_resume_(Key); +#endif + +private: + std::vector<Subwindow> subwindows_; +}; + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_appearance.cpp b/src/lib/nccpp/Window_appearance.cpp new file mode 100644 index 0000000..80ac2fe --- /dev/null +++ b/src/lib/nccpp/Window_appearance.cpp @@ -0,0 +1,61 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +namespace nccpp { + +inline int Window::border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br) { + assert(win_ && "Window doesn't manage any object"); + + return wborder(win_, ls, rs, ts, bs, tl, tr, bl, br); +} + +inline int Window::box(chtype vch, chtype hch) { + assert(win_ && "Window doesn't manage any object"); + + return ::box(win_, vch, hch); +} + +inline int Window::hline(chtype ch, int n) { + assert(win_ && "Window doesn't manage any object"); + + return whline(win_, ch, n); +} + +inline int Window::vline(chtype ch, int n) { + assert(win_ && "Window doesn't manage any object"); + + return wvline(win_, ch, n); +} + +inline int Window::mvhline(int y, int x, chtype ch, int n) { + assert(win_ && "Window doesn't manage any object"); + + return (this->move)(y, x) == ERR ? ERR : (this->hline)(ch, n); +} + +inline int Window::mvvline(int y, int x, chtype ch, int n) { + assert(win_ && "Window doesn't manage any object"); + + return (this->move)(y, x) == ERR ? ERR : (this->vline)(ch, n); +} + +inline void Window::bkgdset(int ch) { + assert(win_ && "Window doesn't manage any object"); + + wbkgdset(win_, static_cast<chtype>(ch)); +} + +inline int Window::bkgd(int ch) { + assert(win_ && "Window doesn't manage any object"); + + return wbkgd(win_, static_cast<chtype>(ch)); +} + +inline chtype Window::getbkgd() { + assert(win_ && "Window doesn't manage any object"); + + return (::getbkgd)(win_); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_attributes.cpp b/src/lib/nccpp/Window_attributes.cpp new file mode 100644 index 0000000..a845d03 --- /dev/null +++ b/src/lib/nccpp/Window_attributes.cpp @@ -0,0 +1,74 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +#include "lib/nccpp/Color.hpp" +#include "lib/nccpp/Ncurses.hpp" + +namespace nccpp { + +inline int Window::attroff(int a) { + assert(win_ && "Window doesn't manage any object"); + + return wattroff(win_, a); +} + +inline int Window::attron(int a) { + assert(win_ && "Window doesn't manage any object"); + + return wattron(win_, a); +} + +inline int Window::attrset(int a) { + assert(win_ && "Window doesn't manage any object"); + + return wattrset(win_, a); +} + +inline int Window::attr_get(attr_t &a) { + assert(win_ && "Window doesn't manage any object"); + + return wattr_get(win_, &a, nullptr, nullptr); +} + +inline int Window::color_get(Color &c) { + assert(win_ && "Window doesn't manage any object"); + + short pair_n{0}; + + if (wattr_get(win_, nullptr, &pair_n, nullptr) == ERR) { + return ERR; + } + + c = nccpp::ncurses().pair_number_to_color(pair_n); + + return OK; +} + +inline int Window::attr_color_get(attr_t &a, Color &c) { + assert(win_ && "Window doesn't manage any object"); + + short pair_n{0}; + + if (wattr_get(win_, &a, &pair_n, nullptr) == ERR) { + return ERR; + } + + c = nccpp::ncurses().pair_number_to_color(pair_n); + + return OK; +} + +inline int Window::chgat(int n, attr_t a, Color c) { + assert(win_ && "Window doesn't manage any object"); + + return ::wchgat(win_, n, a, nccpp::ncurses().color_to_pair_number(c), nullptr); +} + +inline int Window::mvchgat(int y, int x, int n, attr_t a, Color c) { + assert(win_ && "Window doesn't manage any object"); + + return (this->move)(y, x) == ERR ? ERR : (this->chgat)(n, a, c); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_input.cpp b/src/lib/nccpp/Window_input.cpp new file mode 100644 index 0000000..26b15ae --- /dev/null +++ b/src/lib/nccpp/Window_input.cpp @@ -0,0 +1,130 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> +#include <string> + +namespace nccpp { + +// getch + +inline int Window::getch() { + assert(win_ && "Window doesn't manage any object"); + + return wgetch(win_); +} + +inline int Window::mvgetch(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return mvwgetch(win_, y, x); +} + +// scanw + +inline int Window::scanw(char const* fmt, ...) { + assert(win_ && "Window doesn't manage any object"); + + va_list args; + va_start(args, fmt); + auto ret = vw_scanw(win_, const_cast<char*>(fmt), args); + va_end(args); + + return ret; +} + +inline int Window::mvscanw(int y, int x, char const* fmt, ...) { + assert(win_ && "Window doesn't manage any object"); + + if ((this->move)(y, x) == ERR) { + return ERR; + } + + va_list args; + va_start(args, fmt); + auto ret = vw_scanw(win_, const_cast<char*>(fmt), args); + va_end(args); + + return ret; +} + +// getstr + +inline int Window::getstr(std::string &str) { + return (this->getnstr)(str, str.size()); +} + +inline int Window::getnstr(std::string &str, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + + str.resize(n); + + return wgetnstr(win_, &str[0], static_cast<int>(n)); +} + +inline int Window::mvgetstr(int y, int x, std::string &str) { + return (this->mvgetnstr)(y, x, str, str.size()); +} + +inline int Window::mvgetnstr(int y, int x, std::string &str, std::size_t n) { + return (this->move)(y, x) == ERR ? ERR : (this->getnstr)(str, n); +} + +// inch + +inline chtype Window::inch() { + assert(win_ && "Window doesn't manage any object"); + + return winch(win_); +} + +inline chtype Window::mvinch(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return mvwinch(win_, y, x); +} + +// instr + +inline int Window::instr(std::string &str) { + return (this->innstr)(str, str.size()); +} + +inline int Window::innstr(std::string &str, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + + str.resize(n); + + return winnstr(win_, &str[0], static_cast<int>(n)); +} + +inline int Window::mvinstr(int y, int x, std::string &str) { + return (this->mvinnstr)(y, x, str, str.size()); +} + +inline int Window::mvinnstr(int y, int x, std::string &str, std::size_t n) { + return (this->move)(y, x) == ERR ? ERR : (this->innstr)(str, n); +} + +// inchstr + +inline int Window::inchstr(String &str) { + return (this->inchnstr)(str, str.size()); +} + +inline int Window::inchnstr(String &str, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + + str.resize(n); + + return winchnstr(win_, &str[0], static_cast<int>(n)); +} + +inline int Window::mvinchstr(int y, int x, String &str) { + return (this->mvinchnstr)(y, x, str, str.size()); +} + +inline int Window::mvinchnstr(int y, int x, String &str, std::size_t n) { + return (this->move)(y, x) == ERR ? ERR : (this->inchnstr)(str, n); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_misc.cpp b/src/lib/nccpp/Window_misc.cpp new file mode 100644 index 0000000..7f017a9 --- /dev/null +++ b/src/lib/nccpp/Window_misc.cpp @@ -0,0 +1,111 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +#include "lib/ncurses/ncurses.hpp" + +namespace nccpp { + +inline int Window::move(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return wmove(win_, y, x); +} + +inline int Window::mvwin(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return ::mvwin(win_, y, x); +} + +inline int Window::erase() { + assert(win_ && "Window doesn't manage any object"); + + return werase(win_); +} + +inline int Window::clear() { + assert(win_ && "Window doesn't manage any object"); + + return wclear(win_); +} + +inline int Window::clrtobot() { + assert(win_ && "Window doesn't manage any object"); + + return wclrtobot(win_); +} + +inline int Window::clrtoeol() { + assert(win_ && "Window doesn't manage any object"); + + return wclrtoeol(win_); +} + +inline int Window::refresh() { + assert(win_ && "Window doesn't manage any object"); + + return wrefresh(win_); +} + +inline int Window::outrefresh() { + assert(win_ && "Window doesn't manage any object"); + + return wnoutrefresh(win_); +} + +inline int Window::redraw() { + assert(win_ && "Window doesn't manage any object"); + + return redrawwin(win_); +} + +inline int Window::redrawln(int beg, int num) { + assert(win_ && "Window doesn't manage any object"); + + return wredrawln(win_, beg, num); +} + +inline int Window::scroll(int n) { + assert(win_ && "Window doesn't manage any object"); + + return wscrl(win_, n); +} + +inline void Window::get_yx(int &y, int &x) { + assert(win_ && "Window doesn't manage any object"); + + getyx(win_, y, x); +} + +inline void Window::get_begyx(int &y, int &x) { + assert(win_ && "Window doesn't manage any object"); + + getbegyx(win_, y, x); +} + +inline void Window::get_maxyx(int &y, int &x) { + assert(win_ && "Window doesn't manage any object"); + + getmaxyx(win_, y, x); +} + +inline int Window::touchln(int start, int count, bool changed) { + assert(win_ && "Window doesn't manage any object"); + + return wtouchln(win_, start, count, changed); +} + +inline bool Window::enclose(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return wenclose(win_, y, x); +} + +inline bool Window::coord_trafo(int &y, int &x, bool to_screen) { + assert(win_ && "Window doesn't manage any object"); + + return wmouse_trafo(win_, &y, &x, to_screen); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_options.cpp b/src/lib/nccpp/Window_options.cpp new file mode 100644 index 0000000..a284df5 --- /dev/null +++ b/src/lib/nccpp/Window_options.cpp @@ -0,0 +1,43 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +namespace nccpp { + +inline int Window::keypad(bool on) { + assert(win_ && "Window doesn't manage any object"); + + return ::keypad(win_, on); +} + +inline int Window::nodelay(bool on) { + assert(win_ && "Window doesn't manage any object"); + + return ::nodelay(win_, on); +} + +inline int Window::notimeout(bool on) { + assert(win_ && "Window doesn't manage any object"); + + return ::notimeout(win_, on); +} + +inline void Window::timeout(int delay) { + assert(win_ && "Window doesn't manage any object"); + + wtimeout(win_, delay); +} + +inline int Window::clearok(bool on) { + assert(win_ && "Window doesn't manage any object"); + + return ::clearok(win_, on); +} + +inline int Window::setscrreg(int top, int bot) { + assert(win_ && "Window doesn't manage any object"); + + return wsetscrreg(win_, top, bot); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/Window_output.cpp b/src/lib/nccpp/Window_output.cpp new file mode 100644 index 0000000..3cd5cfb --- /dev/null +++ b/src/lib/nccpp/Window_output.cpp @@ -0,0 +1,154 @@ +#include "lib/nccpp/Window.hpp" + +#include <cassert> + +namespace nccpp { + +// addch + +inline int Window::addch(chtype const ch) { + assert(win_ && "Window doesn't manage any object"); + + return waddch(win_, ch); +} + +inline int Window::mvaddch(int y, int x, chtype const ch) { + assert(win_ && "Window doesn't manage any object"); + + return mvwaddch(win_, y, x, ch); +} + +inline int Window::echochar(chtype const ch) { + assert(win_ && "Window doesn't manage any object"); + + return wechochar(win_, ch); +} + +// printw + +inline int Window::printw(char const* fmt, ...) { + assert(win_ && "Window doesn't manage any object"); + + va_list args; + va_start(args, fmt); + auto ret = vw_printw(win_, fmt, args); + va_end(args); + + return ret; +} + +inline int Window::mvprintw(int y, int x, char const* fmt, ...) { + assert(win_ && "Window doesn't manage any object"); + + if ((this->move)(y, x) == ERR) { + return ERR; + } + + va_list args; + va_start(args, fmt); + auto ret = vw_printw(win_, fmt, args); + va_end(args); + + return ret; +} + +// addstr + +inline int Window::addstr(std::string const &str) { + return (this->addnstr)(str, str.size()); +} + +inline int Window::addnstr(std::string const &str, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + assert(n <= str.size()); + + return waddnstr(win_, str.c_str(), static_cast<int>(n)); +} + +inline int Window::mvaddstr(int y, int x, std::string const &str) { + return (this->mvaddnstr)(y, x, str, str.size()); +} + +inline int Window::mvaddnstr(int y, int x, std::string const &str, std::size_t n) { + return (this->move)(y, x) == ERR ? ERR : (this->addnstr)(str, n); +} + +// addchstr + +inline int Window::addchstr(String const &chstr) { + return (this->addchnstr)(chstr, chstr.size()); +} + +inline int Window::addchnstr(String const &chstr, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + assert(n <= chstr.size()); + + return waddchnstr(win_, chstr.c_str(), static_cast<int>(n)); +} + +inline int Window::mvaddchstr(int y, int x, String const &chstr) { + return (this->mvaddchnstr)(y, x, chstr.c_str(), chstr.size()); +} + +inline int Window::mvaddchnstr(int y, int x, String const &chstr, std::size_t n) { + return (this->move)(y, x) ? ERR : (this->addchnstr)(chstr, n); +} + +// insch + +inline int Window::insch(chtype ch) { + assert(win_ && "Window doesn't manage any object"); + + return winsch(win_, ch); +} + +inline int Window::mvinsch(int y, int x, chtype ch) { + assert(win_ && "Window doesn't manage any object"); + + return mvwinsch(win_, y, x, ch); +} + +// insstr + +inline int Window::insstr(std::string const &str) { + return (this->insnstr)(str, str.size()); +} + +inline int Window::insnstr(std::string const &str, std::size_t n) { + assert(win_ && "Window doesn't manage any object"); + assert(n <= str.size()); + + return winsnstr(win_, str.c_str(), static_cast<int>(n)); +} + +inline int Window::mvinsstr(int y, int x, std::string const &str) { + return (this->mvinsnstr)(y, x, str, str.size()); +} + +inline int Window::mvinsnstr(int y, int x, std::string const &str, std::size_t n) { + return (this->move)(y, x) == ERR ? ERR : (this->insnstr)(str, n); +} + +// delch + +inline int Window::delch() { + assert(win_ && "Window doesn't manage any object"); + + return wdelch(win_); +} + +inline int Window::mvdelch(int y, int x) { + assert(win_ && "Window doesn't manage any object"); + + return mvwdelch(win_, y, x); +} + +// deleteln + +inline int Window::insdelln(int n) { + assert(win_ && "Window doesn't manage any object"); + + return winsdelln(win_, n); +} + +} // namespace nccpp diff --git a/src/lib/nccpp/constants.hpp b/src/lib/nccpp/constants.hpp new file mode 100644 index 0000000..be16a34 --- /dev/null +++ b/src/lib/nccpp/constants.hpp @@ -0,0 +1,261 @@ +#pragma once + +#include <cassert> + +#include "lib/nccpp/Ncurses.hpp" + +namespace nccpp { + +namespace attributes { + +int constexpr normal{A_NORMAL}; +int constexpr standout{A_STANDOUT}; +int constexpr underline{A_UNDERLINE}; +int constexpr reverse{A_REVERSE}; +int constexpr blink{A_BLINK}; +int constexpr dim{A_DIM}; +int constexpr bold{A_BOLD}; +int constexpr protect{A_PROTECT}; +int constexpr invis{A_INVIS}; +int constexpr altcharset{A_ALTCHARSET}; +int constexpr chartext{A_CHARTEXT}; + +} // namespace attributes + +namespace internal { + +struct DefaultColor { + operator short() const { + static bool init_done{false}; + + if (!init_done) { + ncurses().use_default_colors(); + init_done = true; + } + + return -1; + } +}; + +} // namespace internal + +/** + * \brief Colors constants + */ +namespace colors { + +static internal::DefaultColor const def{}; +short constexpr black{COLOR_BLACK}; +short constexpr red{COLOR_RED}; +short constexpr green{COLOR_GREEN}; +short constexpr yellow{COLOR_YELLOW}; +short constexpr blue{COLOR_BLUE}; +short constexpr magenta{COLOR_MAGENTA}; +short constexpr cyan{COLOR_CYAN}; +short constexpr white{COLOR_WHITE}; + +} // namespace colors + +namespace internal { + +struct FunctionKeys { + int operator()(int n) const { + assert(n < 64 && "Function key doesn't exists"); + return KEY_F0 + n; + } +}; + +} + +/** + * \brief Keys constants + */ +namespace keys { + +int constexpr break_k{KEY_BREAK}; +int constexpr sreset{KEY_SRESET}; +int constexpr reset{KEY_RESET}; +int constexpr down{KEY_DOWN}; +int constexpr up{KEY_UP}; +int constexpr left{KEY_LEFT}; +int constexpr right{KEY_RIGHT}; +int constexpr home{KEY_HOME}; +int constexpr backspace{KEY_BACKSPACE}; +static internal::FunctionKeys const f{}; +int constexpr dl{KEY_DL}; +int constexpr il{KEY_IL}; +int constexpr dc{KEY_DC}; +int constexpr ic{KEY_IC}; +int constexpr eic{KEY_EIC}; +int constexpr clear{KEY_CLEAR}; +int constexpr eos{KEY_EOS}; +int constexpr eol{KEY_EOL}; +int constexpr sf{KEY_SF}; +int constexpr sr{KEY_SR}; +int constexpr npage{KEY_NPAGE}; +int constexpr ppage{KEY_PPAGE}; +int constexpr stab{KEY_STAB}; +int constexpr ctab{KEY_CTAB}; +int constexpr catab{KEY_CATAB}; +int constexpr enter{KEY_ENTER}; +int constexpr print{KEY_PRINT}; +int constexpr ll{KEY_LL}; +int constexpr a1{KEY_A1}; +int constexpr a3{KEY_A3}; +int constexpr b2{KEY_B2}; +int constexpr c1{KEY_C1}; +int constexpr c3{KEY_C3}; +int constexpr btab{KEY_BTAB}; +int constexpr beg{KEY_BEG}; +int constexpr cancel{KEY_CANCEL}; +int constexpr close{KEY_CLOSE}; +int constexpr command{KEY_COMMAND}; +int constexpr copy{KEY_COPY}; +int constexpr create{KEY_CREATE}; +int constexpr end{KEY_END}; +int constexpr exit{KEY_EXIT}; +int constexpr find{KEY_FIND}; +int constexpr help{KEY_HELP}; +int constexpr mark{KEY_MARK}; +int constexpr message{KEY_MESSAGE}; +int constexpr move{KEY_MOVE}; +int constexpr next{KEY_NEXT}; +int constexpr open{KEY_OPEN}; +int constexpr options{KEY_OPTIONS}; +int constexpr previous{KEY_PREVIOUS}; +int constexpr redo{KEY_REDO}; +int constexpr reference{KEY_REFERENCE}; +int constexpr refresh{KEY_REFRESH}; +int constexpr replace{KEY_REPLACE}; +int constexpr restart{KEY_RESTART}; +int constexpr resume{KEY_RESUME}; +int constexpr save{KEY_SAVE}; +int constexpr sbeg{KEY_SBEG}; +int constexpr scancel{KEY_SCANCEL}; +int constexpr scommand{KEY_SCOMMAND}; +int constexpr scopy{KEY_SCOPY}; +int constexpr screate{KEY_SCREATE}; +int constexpr sdc{KEY_SDC}; +int constexpr sdl{KEY_SDL}; +int constexpr select{KEY_SELECT}; +int constexpr send{KEY_SEND}; +int constexpr seol{KEY_SEOL}; +int constexpr sexit{KEY_SEXIT}; +int constexpr sfind{KEY_SFIND}; +int constexpr shelp{KEY_SHELP}; +int constexpr shome{KEY_SHOME}; +int constexpr sic{KEY_SIC}; +int constexpr sleft{KEY_SLEFT}; +int constexpr smessage{KEY_SMESSAGE}; +int constexpr smove{KEY_SMOVE}; +int constexpr snext{KEY_SNEXT}; +int constexpr soptions{KEY_SOPTIONS}; +int constexpr sprevious{KEY_SPREVIOUS}; +int constexpr sprint{KEY_SPRINT}; +int constexpr sredo{KEY_SREDO}; +int constexpr sreplace{KEY_SREPLACE}; +int constexpr sright{KEY_SRIGHT}; +int constexpr srsume{KEY_SRSUME}; +int constexpr ssave{KEY_SSAVE}; +int constexpr ssuspend{KEY_SSUSPEND}; +int constexpr sundo{KEY_SUNDO}; +int constexpr suspend{KEY_SUSPEND}; +int constexpr undo{KEY_UNDO}; +int constexpr mouse{KEY_MOUSE}; +int constexpr resize{KEY_RESIZE}; +int constexpr event{KEY_EVENT}; + +} // namespace keys + +namespace internal { + +struct ButtonRelease { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_RELEASE(event, button); + } +}; + +struct ButtonPress { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_PRESS(event, button); + } +}; + +struct ButtonClick { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_CLICK(event, button); + } +}; + +struct ButtonDoubleClick { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_DOUBLE_CLICK(event, button); + } +}; + +struct ButtonTripleClick { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_TRIPLE_CLICK(event, button); + } +}; + +struct ButtonReserved { + mmask_t operator()(mmask_t event, unsigned char button) const { + return BUTTON_RESERVED_EVENT(event, button); + } +}; + +} + +namespace mouse { + +int constexpr button1_pressed{BUTTON1_PRESSED}; +int constexpr button1_released{BUTTON1_RELEASED}; +int constexpr button1_clicked{BUTTON1_CLICKED}; +int constexpr button1_double_clicked{BUTTON1_DOUBLE_CLICKED}; +int constexpr button1_triple_clicked{BUTTON1_TRIPLE_CLICKED}; +int constexpr button2_pressed{BUTTON2_PRESSED}; +int constexpr button2_released{BUTTON2_RELEASED}; +int constexpr button2_clicked{BUTTON2_CLICKED}; +int constexpr button2_double_clicked{BUTTON2_DOUBLE_CLICKED}; +int constexpr button2_triple_clicked{BUTTON2_TRIPLE_CLICKED}; +int constexpr button3_pressed{BUTTON3_PRESSED}; +int constexpr button3_released{BUTTON3_RELEASED}; +int constexpr button3_clicked{BUTTON3_CLICKED}; +int constexpr button3_double_clicked{BUTTON3_DOUBLE_CLICKED}; +int constexpr button3_triple_clicked{BUTTON3_TRIPLE_CLICKED}; +int constexpr button4_pressed{BUTTON4_PRESSED}; +int constexpr button4_released{BUTTON4_RELEASED}; +int constexpr button4_clicked{BUTTON4_CLICKED}; +int constexpr button4_double_clicked{BUTTON4_DOUBLE_CLICKED}; +int constexpr button4_triple_clicked{BUTTON4_TRIPLE_CLICKED}; + +#if NCURSES_MOUSE_VERSION > 1 +int constexpr button5_pressed {BUTTON5_PRESSED}; +int constexpr button5_released {BUTTON5_RELEASED}; +int constexpr button5_clicked {BUTTON5_CLICKED}; +int constexpr button5_double_clicked {BUTTON5_DOUBLE_CLICKED}; +int constexpr button5_triple_clicked {BUTTON5_TRIPLE_CLICKED}; +#else +int constexpr button1_reserved_event {BUTTON1_RESERVED_EVENT}; +int constexpr button2_reserved_event {BUTTON2_RESERVED_EVENT}; +int constexpr button3_reserved_event {BUTTON3_RESERVED_EVENT}; +int constexpr button4_reserved_event {BUTTON4_RESERVED_EVENT}; +#endif + +int constexpr button_ctrl {BUTTON_CTRL}; +int constexpr button_shift{BUTTON_SHIFT}; +int constexpr button_alt{BUTTON_ALT}; +int constexpr report_mouse_position{REPORT_MOUSE_POSITION}; +int constexpr all{ALL_MOUSE_EVENTS}; + +static internal::ButtonRelease const release{}; +static internal::ButtonPress const press{}; +static internal::ButtonClick const click{}; +static internal::ButtonDoubleClick const double_click{}; +static internal::ButtonTripleClick const triple_click{}; +static internal::ButtonReserved const reserved_event{}; + +} + +} // namespace nccpp diff --git a/src/lib/nccpp/errors.hpp b/src/lib/nccpp/errors.hpp new file mode 100644 index 0000000..1178429 --- /dev/null +++ b/src/lib/nccpp/errors.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include <exception> + +#include "lib/nccpp/Color.hpp" + +namespace nccpp { + +namespace errors { + +class Base : public std::exception { +public: + Base() noexcept = default; + + Base(const Base &) noexcept = default; + Base &operator=(const Base &) noexcept = default; + + virtual ~Base() = default; + + char const* what() const noexcept override { + return "nccpp::errors::Base"; + } +}; + +class NcursesInit : public Base { +public: + NcursesInit() noexcept = default; + NcursesInit(const NcursesInit &) noexcept = default; + NcursesInit &operator=(const NcursesInit &) noexcept = default; + + virtual ~NcursesInit() = default; + + char const* what() const noexcept override { + return "nccpp::errors::NcursesInit : Can't initialize ncuses, initscr() failed"; + } +}; + +class WindowInit : public Base { +public: + WindowInit() noexcept = default; + WindowInit(const WindowInit &) noexcept = default; + WindowInit &operator=(const WindowInit &) noexcept = default; + + virtual ~WindowInit() = default; + + char const* what() const noexcept override { + return "nccpp::errors::WindowInit : Can't create new window, newwin() failed"; + } +}; + +class ColorInit : public Base { +public: + ColorInit() noexcept = default; + ColorInit(const ColorInit &) noexcept = default; + ColorInit &operator=(const ColorInit &) noexcept = default; + + virtual ~ColorInit() = default; + + char const* what() const noexcept override { + return "nccpp::errors::ColorInit : Can't initialize colors, start_color() failed"; + } +}; + +class TooMuchColors : public Base { +public: + TooMuchColors(const Color &c) noexcept : color {c} {} + + TooMuchColors(const TooMuchColors &) noexcept = default; + TooMuchColors &operator=(const TooMuchColors &) noexcept = default; + + virtual ~TooMuchColors() = default; + + char const* what() const noexcept override { + return "nccpp::errors::TooMuchColors : Can't initialize new colors, init_pair failed"; + } + + const Color color; ///< The color that caused the error. +}; + +} // namespace errors + +} // namespace nccpp diff --git a/src/lib/nccpp/ncursescpp.hpp b/src/lib/nccpp/ncursescpp.hpp new file mode 100644 index 0000000..bdd999c --- /dev/null +++ b/src/lib/nccpp/ncursescpp.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "lib/nccpp/Ncurses.hpp" +#include "lib/nccpp/Window.hpp" +#include "lib/nccpp/Subwindow.hpp" +#include "lib/nccpp/Color.hpp" +#include "lib/nccpp/constants.hpp" +#include "lib/nccpp/errors.hpp" -- GitLab