diff --git a/CMakeLists.txt b/CMakeLists.txt index f96d6bac1..1a4b9669b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,13 +192,16 @@ target_compile_definitions(notcurses-static # libnotcurses++ set(NCPP_SOURCES + src/libcpp/FDPlane.cc src/libcpp/Menu.cc src/libcpp/MultiSelector.cc src/libcpp/NotCurses.cc src/libcpp/Plane.cc + src/libcpp/Plot.cc src/libcpp/Reel.cc src/libcpp/Root.cc src/libcpp/Selector.cc + src/libcpp/Subproc.cc src/libcpp/Tablet.cc src/libcpp/Visual.cc ) diff --git a/include/ncpp/FDPlane.hh b/include/ncpp/FDPlane.hh new file mode 100644 index 000000000..546090e82 --- /dev/null +++ b/include/ncpp/FDPlane.hh @@ -0,0 +1,69 @@ +#ifndef __NCPP_FDPLANE_HH +#define __NCPP_FDPLANE_HH + +#include + +#include "Root.hh" +#include "Plane.hh" + +namespace ncpp +{ + class NCPP_API_EXPORT FDPlane : public Root + { + public: + static ncfdplane_options default_options; + + public: + explicit FDPlane (Plane* n, int fd, ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + : FDPlane (n, fd, nullptr, cbfxn, donecbfxn) + {} + + explicit FDPlane (Plane* n, int fd, ncfdplane_options *opts = nullptr, ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + { + if (n == nullptr) + throw invalid_argument ("'n' must be a valid pointer"); + create_fdplane (*n, fd, opts, cbfxn, donecbfxn); + } + + explicit FDPlane (Plane& n, int fd, ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + : FDPlane (n, fd, nullptr, cbfxn, donecbfxn) + {} + + explicit FDPlane (Plane& n, int fd, ncfdplane_options *opts = nullptr, ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + { + create_fdplane (n, fd, opts, cbfxn, donecbfxn); + } + + ~FDPlane () + { + if (is_notcurses_stopped ()) + return; + + ncfdplane_destroy (fdplane); + } + + Plane* get_plane () const noexcept + { + return Plane::map_plane (ncfdplane_plane (fdplane)); + } + + private: + void create_fdplane (Plane& n, int fd, ncfdplane_options *opts, ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn) + { + fdplane = ncfdplane_create ( + n, + opts == nullptr ? &default_options : opts, + fd, + cbfxn, + donecbfxn + ); + + if (fdplane == nullptr) + throw init_error ("NotCurses failed to create an ncfdplane instance"); + } + + private: + ncfdplane *fdplane; + }; +} +#endif // __NCPP_FDPLANE_HH diff --git a/include/ncpp/NotCurses.hh b/include/ncpp/NotCurses.hh index 6c471cf70..0015014af 100644 --- a/include/ncpp/NotCurses.hh +++ b/include/ncpp/NotCurses.hh @@ -203,6 +203,11 @@ namespace ncpp return notcurses_at_yx (nc, yoff, xoff, attr, channels); } + int get_inputready_fd () const noexcept + { + return notcurses_inputready_fd (nc); + } + void drop_planes () const noexcept { notcurses_drop_planes (nc); diff --git a/include/ncpp/Plane.hh b/include/ncpp/Plane.hh index 4ad1206c6..c8d6d329f 100644 --- a/include/ncpp/Plane.hh +++ b/include/ncpp/Plane.hh @@ -1018,7 +1018,13 @@ namespace ncpp bool ret = ncblit_rgba (plane, placey, placex, linesize, data, begy, begx, leny, lenx) < 0; return error_guard_cond (ret, ret); } - + + int qrcode (int maxversion, const void *data, size_t len) const NOEXCEPT_MAYBE + { + int ret = ncplane_qrcode (plane, maxversion, data, len); + return error_guard_cond (ret, ret < 0); + } + protected: explicit Plane (ncplane *_plane, bool _is_stdplane) : plane (_plane), diff --git a/include/ncpp/Plot.hh b/include/ncpp/Plot.hh index 8b5ec688f..c2a3e2fa2 100644 --- a/include/ncpp/Plot.hh +++ b/include/ncpp/Plot.hh @@ -1,6 +1,8 @@ #ifndef __NCPP_PLOT_HH #define __NCPP_PLOT_HH +#include + #include #include "Root.hh" @@ -10,59 +12,144 @@ namespace ncpp { class Plane; - class NCPP_API_EXPORT Plot : public Root + template + class NCPP_API_EXPORT PlotBase : public Root { - public: - static ncplot_options default_options; + static constexpr bool is_double = std::is_same_v; + static constexpr bool is_uint64 = std::is_same_v; public: - explicit Plot (Plane *plane, const ncplot_options *opts = nullptr) - : Plot (reinterpret_cast(plane), opts) - {} + bool add_sample(TCoord x, TCoord y) const NOEXCEPT_MAYBE + { + int ret; - explicit Plot (Plane const* plane, const ncplot_options *opts = nullptr) - : Plot (const_cast(plane), opts) - {} + if constexpr (is_double) { + ret = ncdplot_add_sample (plot, x, y); + } else { + ret = nduplot_add_sample (plot, x, y); + } - explicit Plot (Plane &plane, const ncplot_options *opts = nullptr) - : Plot (reinterpret_cast(&plane), opts) - {} + return error_guard (ret, -1); + } - explicit Plot (Plane const& plane, const ncplot_options *opts = nullptr) - : Plot (const_cast(&plane), opts) - {} + bool set_sample(TCoord x, TCoord y) const NOEXCEPT_MAYBE + { + int ret; - explicit Plot (ncplane *plane, const ncplot_options *opts = nullptr, - uint64_t miny = 0, uint64_t maxy = 0) + if constexpr (is_double) { + ret = ncdplot_set_sample (plot, x, y); + } else { + ret = nduplot_set_sample (plot, x, y); + } + return error_guard (ret, -1); + } + + protected: + explicit PlotBase (ncplane *plane, const ncplot_options *opts, TCoord miny = 0, TCoord maxy = 0) { + static_assert (is_double || is_uint64, "PlotBase must be parameterized with either 'double' or 'uint64_t' types"); + if constexpr (is_double) { + static_assert (std::is_same_v, "ncdplot must be used for a plot using double coordinates"); + } else { + static_assert (std::is_same_v, "ncuplot must be used for a plot using uint64_t coordinates"); + } + if (plane == nullptr) throw invalid_argument ("'plane' must be a valid pointer"); - plot = ncuplot_create (plane, opts == nullptr ? &default_options : opts, miny, maxy); + if (opts == nullptr) + throw invalid_argument ("'opts' must be a valid pointer"); + + if constexpr (is_uint64) { + plot = ncuplot_create (plane, opts, miny, maxy); + } else { + plot = ncdplot_create (plane, opts, miny, maxy); + } + if (plot == nullptr) throw init_error ("notcurses failed to create a new plot"); } - ~Plot () + ~PlotBase () { - if (!is_notcurses_stopped ()) - ncuplot_destroy (plot); + if (!is_notcurses_stopped ()) { + if constexpr (is_double) { + ncdplot_destroy (plot); + } else { + ncuplot_destroy (plot); + } + } } - bool add_sample(uint64_t x, uint64_t y) const NOEXCEPT_MAYBE + TPlot *get_plot () const noexcept { - return error_guard (ncuplot_add_sample (plot, x, y), -1); + return plot; } - bool set_sample(uint64_t x, uint64_t y) const NOEXCEPT_MAYBE - { - return error_guard (ncuplot_set_sample (plot, x, y), -1); - } + private: + TPlot *plot; + }; + + class NCPP_API_EXPORT PlotU : public PlotBase + { + public: + static ncplot_options default_options; + + public: + explicit PlotU (Plane *plane, const ncplot_options *opts = nullptr) + : PlotU (reinterpret_cast(plane), opts) + {} + + explicit PlotU (Plane const* plane, const ncplot_options *opts = nullptr) + : PlotU (const_cast(plane), opts) + {} + + explicit PlotU (Plane &plane, const ncplot_options *opts = nullptr) + : PlotU (reinterpret_cast(&plane), opts) + {} + + explicit PlotU (Plane const& plane, const ncplot_options *opts = nullptr) + : PlotU (const_cast(&plane), opts) + {} + + explicit PlotU (ncplane *plane, const ncplot_options *opts = nullptr, + uint64_t miny = 0, uint64_t maxy = 0) + : PlotBase (plane, opts == nullptr ? &default_options : opts, miny, maxy) + {} Plane* get_plane () const noexcept; + }; - private: - ncuplot *plot; + class NCPP_API_EXPORT PlotD : public PlotBase + { + public: + static ncplot_options default_options; + + public: + explicit PlotD (Plane *plane, const ncplot_options *opts = nullptr) + : PlotD (reinterpret_cast(plane), opts) + {} + + explicit PlotD (Plane const* plane, const ncplot_options *opts = nullptr) + : PlotD (const_cast(plane), opts) + {} + + explicit PlotD (Plane &plane, const ncplot_options *opts = nullptr) + : PlotD (reinterpret_cast(&plane), opts) + {} + + explicit PlotD (Plane const& plane, const ncplot_options *opts = nullptr) + : PlotD (const_cast(&plane), opts) + {} + + explicit PlotD (ncplane *plane, const ncplot_options *opts = nullptr, + double miny = 0, double maxy = 0) + : PlotBase (plane, opts == nullptr ? &default_options : opts, miny, maxy) + {} + + Plane* get_plane () const noexcept; }; + + using Plot = PlotU; } #endif diff --git a/include/ncpp/Subproc.hh b/include/ncpp/Subproc.hh new file mode 100644 index 000000000..13d66046c --- /dev/null +++ b/include/ncpp/Subproc.hh @@ -0,0 +1,93 @@ +#ifndef __NCPP_SUBPROC_HH +#define __NCPP_SUBPROC_HH + +#include + +#include "Root.hh" +#include "Plane.hh" + +namespace ncpp +{ + class NCPP_API_EXPORT Subproc : public Root + { + public: + static ncsubproc_options default_options; + + public: + explicit Subproc (Plane* n, const char* bin, bool use_path = true, + char* const arg[] = nullptr, char* const env[] = nullptr, + ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + : Subproc (n, bin, nullptr, use_path, arg, env, cbfxn, donecbfxn) + {} + + explicit Subproc (Plane* n, const char* bin, const ncsubproc_options* opts, bool use_path = true, + char* const arg[] = nullptr, char* const env[] = nullptr, + ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + { + if (n == nullptr) + throw invalid_argument ("'n' must be a valid pointer"); + create_subproc (*n, bin, opts, use_path, arg, env, cbfxn, donecbfxn); + } + + explicit Subproc (Plane& n, const char* bin, bool use_path = true, + char* const arg[] = nullptr, char* const env[] = nullptr, + ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + : Subproc (n, bin, nullptr, use_path, arg, env, cbfxn, donecbfxn) + {} + + explicit Subproc (Plane& n, const char* bin, const ncsubproc_options* opts, bool use_path = true, + char* const arg[] = nullptr, char* const env[] = nullptr, + ncfdplane_callback cbfxn = nullptr, ncfdplane_done_cb donecbfxn = nullptr) + { + create_subproc (n, bin, opts, use_path, arg, env, cbfxn, donecbfxn); + } + + ~Subproc () + { + if (is_notcurses_stopped ()) + return; + + ncsubproc_destroy (subproc); + } + + Plane* get_plane () const noexcept + { + return Plane::map_plane (ncsubproc_plane (subproc)); + } + + private: + void create_subproc (Plane& n, const char* bin, const ncsubproc_options* opts, bool use_path, + char* const arg[], char* const env[], + ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn) + { + if (bin == nullptr) + throw invalid_argument ("'bin' must be a valid pointer"); + + if (opts == nullptr) + opts = &default_options; + + if (use_path) { + if (env != nullptr) { + subproc = ncsubproc_createvpe ( + n, opts, bin, arg, env, cbfxn, donecbfxn + ); + } else { + subproc = ncsubproc_createvp ( + n, opts, bin, arg, cbfxn, donecbfxn + ); + } + } else { + subproc = ncsubproc_createv ( + n, opts, bin, arg, cbfxn, donecbfxn + ); + } + + if (subproc == nullptr) + throw new init_error ("NotCurses failed to create ncsubproc instance"); + } + + private: + ncsubproc *subproc; + }; +} +#endif // __NCPP_SUBPROC_HH diff --git a/src/libcpp/FDPlane.cc b/src/libcpp/FDPlane.cc new file mode 100644 index 000000000..a1d5bf4bc --- /dev/null +++ b/src/libcpp/FDPlane.cc @@ -0,0 +1,8 @@ +#include + +using namespace ncpp; + +ncfdplane_options FDPlane::default_options = { + nullptr, // curry + false, // follow +}; diff --git a/src/libcpp/Plot.cc b/src/libcpp/Plot.cc index 8a5cfe32e..9c01bb029 100644 --- a/src/libcpp/Plot.cc +++ b/src/libcpp/Plot.cc @@ -3,19 +3,32 @@ using namespace ncpp; -ncplot_options Plot::default_options = { +ncplot_options PlotD::default_options = { 0, // maxchannel 0, // minchannel ncgridgeom_e::NCPLOT_1x1, // ncgridgeom_e 0, // rangex - 0, // miny - 0, // maxy false, // labelaxisd, - false, // exponentialy + false, // exponentially false, // verticalindep }; -Plane* Plot::get_plane () const noexcept +ncplot_options PlotU::default_options = { + 0, // maxchannel + 0, // minchannel + ncgridgeom_e::NCPLOT_1x1, // ncgridgeom_e + 0, // rangex + false, // labelaxisd, + false, // exponentially + false, // verticalindep +}; + +Plane* PlotD::get_plane () const noexcept +{ + return Plane::map_plane (ncdplot_plane (get_plot ())); +} + +Plane* PlotU::get_plane () const noexcept { - return Plane::map_plane (ncplot_plane (plot)); + return Plane::map_plane (ncuplot_plane (get_plot ())); } diff --git a/src/libcpp/Subproc.cc b/src/libcpp/Subproc.cc new file mode 100644 index 000000000..5efe8f8b3 --- /dev/null +++ b/src/libcpp/Subproc.cc @@ -0,0 +1,8 @@ +#include + +using namespace ncpp; + +ncsubproc_options Subproc::default_options = { + nullptr, // curry + 0, // restart_period +}; diff --git a/src/poc/ncpp_build.cpp b/src/poc/ncpp_build.cpp index dee4c346b..0e0d10a79 100644 --- a/src/poc/ncpp_build.cpp +++ b/src/poc/ncpp_build.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include using namespace ncpp; @@ -25,6 +27,9 @@ int run () const char *ncver = nc.version (); Plane plane (1, 1, 0, 0); + Plot plot1 (plane); + PlotU plot2 (plane); + PlotD plot3 (plane); nc.stop (); diff --git a/src/poc/ncpp_build_exceptions.cpp b/src/poc/ncpp_build_exceptions.cpp index aff65f658..25ae70e76 100644 --- a/src/poc/ncpp_build_exceptions.cpp +++ b/src/poc/ncpp_build_exceptions.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include using namespace ncpp; @@ -26,6 +28,9 @@ int run () const char *ncver = nc.version (); Plane plane (1, 1, 0, 0); + Plot plot1 (plane); + PlotU plot2 (plane); + PlotD plot3 (plane); nc.stop ();