diff --git a/USAGE.md b/USAGE.md
index 7f5e9a66b..6068eb966 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -9,7 +9,7 @@ version 2, notcurses will honor Semantic Versioning.
* [Planes](#planes) ([Plane Channels API](#plane-channels-api))
* [Cells](#cells) ([Cell Channels API](#cell-channels-api))
* [Reels](#reels) ([ncreel Examples](#ncreel-examples))
-* [Widgets](#widgets)
+* [Widgets](#widgets) ([Readers](#readers))
* [Channels](#channels)
* [Media](#media)
@@ -2101,6 +2101,44 @@ xxxxxxxxxxxxxxxx│Quit Ctrl+q│xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxx╰─────────────╯xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
+### Readers
+
+```c
+typedef struct ncreader_options {
+ uint64_t tchannels; // channels used for input
+ uint64_t echannels; // channels used for empty space
+ uint32_t tattrword; // attributes used for input
+ uint32_t eattrword; // attributes used for empty space
+ char* egc; // egc used for empty space
+ int physrows;
+ int physcols;
+ bool scroll; // allow more than the physical area's worth of input
+} ncreader_options;
+
+// ncreaders provide freeform input in a (possibly multiline) region,
+// supporting readline keybindings. 'rows' and 'cols' both must be negative.
+// there are no restrictions on 'y' or 'x'. creates its own plane.
+struct ncreader* ncreader_create(struct notcurses* nc, int y, int x,
+ const ncreader_options* opts);
+
+// empty the ncreader of any user input, and home the cursor.
+int ncreader_clear(struct ncreader* n);
+
+struct ncplane* ncreader_plane(struct ncreader* n);
+
+// Offer the input to the ncreader. If it's relevant, this function returns
+// true, and the input ought not be processed further. Almost all inputs
+// are relevant to an ncreader, save synthesized ones.
+bool ncreader_offer_input(struct ncreader* n, const struct ncinput* ni);
+
+// return a heap-allocated copy of the current (UTF-8) contents.
+char* ncreader_contents(const struct ncreader* n);
+
+// destroy the reader and its bound plane. if 'contents' is not NULL, the
+// UTF-8 input will be heap-duplicated and written to 'contents'.
+void ncreader_destroy(struct ncreader* n, char** contents);
+```
+
## Channels
A channel encodes 24 bits of RGB color, using 8 bits for each component. It
diff --git a/doc/man/index.html b/doc/man/index.html
index 4e8e1681b..3247d8509 100644
--- a/doc/man/index.html
+++ b/doc/man/index.html
@@ -35,15 +35,16 @@
notcurses_input—collecting input
notcurses_lines—drawing lines and boxes on ncplanes
notcurses_menu—menus on the top or bottom rows
+ notcurses_multiselector—high-level widget for selecting items from a set
notcurses_reel—high-level widget for hierarchical data
notcurses_output—drawing text on ncplanes
notcurses_palette—operations on notcurses palettes
notcurses_plane—operations on ncplane objects
notcurses_plot—drawing histograms and lineplots
+ notcurses_reader—high-level widget for collecting input
notcurses_refresh—refresh an externally-damaged display
notcurses_render—sync the physical display
notcurses_selector—high-level widget for selecting one item from a set
- notcurses_multiselector—high-level widget for selecting items from a set
notcurses_stats—notcurses runtime statistics
notcurses_stdplane—acquire the standard ncplane
notcurses_stop—collapse the context
diff --git a/include/ncpp/NotCurses.hh b/include/ncpp/NotCurses.hh
index 0015014af..4a31ff731 100644
--- a/include/ncpp/NotCurses.hh
+++ b/include/ncpp/NotCurses.hh
@@ -36,12 +36,7 @@ namespace ncpp
NotCurses (NotCurses &&other) = delete;
~NotCurses ();
- operator notcurses* () noexcept
- {
- return nc;
- }
-
- operator notcurses const* () const noexcept
+ notcurses* operator*() noexcept
{
return nc;
}
@@ -58,7 +53,7 @@ namespace ncpp
static bool is_notcurses_stopped ()
{
- return *_instance == nullptr || _instance->nc == nullptr;
+ return _instance == nullptr || _instance->nc == nullptr;
}
static const char* ncmetric (uintmax_t val, unsigned decimal, char *buf, int omitdec, unsigned mult, int uprefix) noexcept
diff --git a/include/ncpp/Reader.hh b/include/ncpp/Reader.hh
index 1106876ee..f305827b9 100644
--- a/include/ncpp/Reader.hh
+++ b/include/ncpp/Reader.hh
@@ -15,7 +15,7 @@ namespace ncpp
{
public:
explicit Reader (NotCurses *nc, int y, int x, const ncreader_options *opts)
- : Reader (reinterpret_cast(nc), y, x, opts)
+ : Reader (*nc, y, x, opts)
{}
explicit Reader (NotCurses const* nc, int y, int x, const ncreader_options *opts)
diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h
index a38b44869..101a64406 100644
--- a/include/notcurses/notcurses.h
+++ b/include/notcurses/notcurses.h
@@ -2789,6 +2789,11 @@ API int ncreader_clear(struct ncreader* n);
API struct ncplane* ncreader_plane(struct ncreader* n);
+// Offer the input to the ncreader. If it's relevant, this function returns
+// true, and the input ought not be processed further. Almost all inputs
+// are relevant to an ncreader, save synthesized ones.
+API bool ncreader_offer_input(struct ncreader* n, const struct ncinput* ni);
+
// return a heap-allocated copy of the current (UTF-8) contents.
API char* ncreader_contents(const struct ncreader* n);
diff --git a/src/lib/reader.c b/src/lib/reader.c
index d6a296312..994cb14d7 100644
--- a/src/lib/reader.c
+++ b/src/lib/reader.c
@@ -33,6 +33,14 @@ ncplane* ncreader_plane(ncreader* n){
return n->ncp;
}
+bool ncreader_offer_input(ncreader* n, const ncinput* ni){
+ if(nckey_supppuab_p(ni->id)){
+ return false;
+ }
+ // FIXME add ni to n->content
+ return true;
+}
+
char* ncreader_contents(const ncreader* n){
return strdup(n->contents);
}
diff --git a/src/libcpp/Root.cc b/src/libcpp/Root.cc
index 04d0b908b..40c04022b 100644
--- a/src/libcpp/Root.cc
+++ b/src/libcpp/Root.cc
@@ -5,7 +5,7 @@ using namespace ncpp;
notcurses* Root::get_notcurses () const
{
- notcurses *ret = NotCurses::get_instance ();
+ notcurses *ret = *NotCurses::get_instance ();
if (ret == nullptr)
throw new invalid_state_error (ncpp_invalid_state_message);
return ret;
diff --git a/src/poc/reader.cpp b/src/poc/reader.cpp
index b2a4e3684..0d55c6bf4 100644
--- a/src/poc/reader.cpp
+++ b/src/poc/reader.cpp
@@ -17,7 +17,16 @@ auto main() -> int {
opts.physrows = dimy / 2;
opts.physcols = dimx / 2;
opts.egc = strdup("░");
- ncpp::Reader ncread(nc, 0, 0, &opts);
+ //ncpp::Reader nr(nc, 0, 0, &opts);
+ auto nr = ncreader_create(*nc, 2, 2, &opts);
+ char32_t id;
+ ncinput ni;
+ nc.render();
+ while((id = nc.getc(true, &ni)) != (char32_t)-1){
+ if(!ncreader_offer_input(nr, &ni)){
+ break;
+ }
+ }
nc.render();
nc.stop();
return EXIT_SUCCESS;