diff --git a/NEWS.md b/NEWS.md index b9dadabeb..9bc8b132b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ rearrangements of Notcurses. without an obvious replacement is the `renderfp` field of `notcurses_options`, for which I make no apology. If you've been avoiding deprecated functionality, ABI3 ought require small changes, if any. + * `notcurses_get()` and `ncdirect_get()` now require an absolute deadline + rather than a delay bound; it ought be calculated using `CLOCK_MONOTONIC`. * The handling of geometry and distance has been normalized across all functions. Lengths are now `unsigned` as opposed to `int`. Where -1 was being used to indicate "everything", 0 is now required. This affects diff --git a/USAGE.md b/USAGE.md index d1c6880f5..17d52b222 100644 --- a/USAGE.md +++ b/USAGE.md @@ -652,7 +652,7 @@ must be readable without delay for it to be interpreted as such. // resize events, etc.). These are mapped into Unicode's Supplementary // Private Use Area-B, starting at U+100000. See . // -// notcurses_getc_nblock() is nonblocking. notcurses_getc_blocking() blocks +// notcurses_get_nblock() is nonblocking. notcurses_get_blocking() blocks // until a codepoint or special key is read, or until interrupted by a signal. // notcurses_get() allows an optional timeout to be controlled. // @@ -730,10 +730,10 @@ typedef struct ncinput { // Read a UTF-32-encoded Unicode codepoint from input. This might only be part // of a larger EGC. Provide a NULL 'ts' to block at length, and otherwise a -// timespec to bound blocking. Returns a single Unicode code point, or -// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the -// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an -// a delay bound against CLOCK_MONOTONIC (see clock_gettime(2)). +// timespec specifying an absolute deadline calculated using CLOCK_MONOTONIC. +// Returns a single Unicode code point, or a synthesized special key constant, +// or (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, +// the return value is the 'id' field from that event. 'ni' may be NULL. uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts, ncinput* ni); @@ -742,10 +742,10 @@ uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts, int notcurses_getvec(struct notcurses* n, const struct timespec* ts, ncinput* ni, int vcount); -// 'ni' may be NULL if the caller is uninterested in event details. If no event -// is ready, returns 0. +// 'ni' may be NULL if the caller is uninterested in event details. If no +// event is ready, returns 0. static inline uint32_t -notcurses_getc_nblock(struct notcurses* n, ncinput* ni){ +notcurses_get_nblock(struct notcurses* n, ncinput* ni){ struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; return notcurses_get(n, &ts, ni); } @@ -753,7 +753,7 @@ notcurses_getc_nblock(struct notcurses* n, ncinput* ni){ // 'ni' may be NULL if the caller is uninterested in event details. Blocks // until an event is processed or a signal is received. static inline uint32_t -notcurses_getc_blocking(struct notcurses* n, ncinput* ni){ +notcurses_get_blocking(struct notcurses* n, ncinput* ni){ return notcurses_get(n, NULL, ni); } diff --git a/doc/man/man3/notcurses_direct.3.md b/doc/man/man3/notcurses_direct.3.md index 897f1d919..ec0d2d842 100644 --- a/doc/man/man3/notcurses_direct.3.md +++ b/doc/man/man3/notcurses_direct.3.md @@ -118,6 +118,8 @@ notcurses_direct - minimal notcurses instances for styling text **bool ncdirect_canget_cursor(const struct ncdirect* ***nc***);** +**uint32_t ncdirect_get(struct ncdirect* ***n***, const struct timespec* ***absdl***, ncinput* ***ni***);** + ```c typedef struct ncvgeom { int pixy, pixx; // true pixel geometry of ncvisual data diff --git a/include/ncpp/Direct.hh b/include/ncpp/Direct.hh index 3b62f18d5..01e717d74 100644 --- a/include/ncpp/Direct.hh +++ b/include/ncpp/Direct.hh @@ -210,8 +210,8 @@ namespace ncpp char32_t get (ncinput *ni, bool blocking) const noexcept { if (blocking) - return ncdirect_getc_blocking (direct, ni); - return ncdirect_getc_nblock (direct, ni); + return ncdirect_get_blocking (direct, ni); + return ncdirect_get_nblock (direct, ni); } char32_t get (const struct timespec *ts, ncinput *ni) const noexcept diff --git a/include/ncpp/NotCurses.hh b/include/ncpp/NotCurses.hh index 2a8d1308f..92d570141 100644 --- a/include/ncpp/NotCurses.hh +++ b/include/ncpp/NotCurses.hh @@ -248,9 +248,9 @@ namespace ncpp uint32_t get (bool blocking = false, ncinput *ni = nullptr) const noexcept { if (blocking) - return notcurses_getc_blocking (nc, ni); + return notcurses_get_blocking (nc, ni); - return notcurses_getc_nblock (nc, ni); + return notcurses_get_nblock (nc, ni); } char* get_at (int yoff, int xoff, uint16_t* attr, uint64_t* channels) const noexcept diff --git a/include/notcurses/direct.h b/include/notcurses/direct.h index 35118b77c..2b3e750ac 100644 --- a/include/notcurses/direct.h +++ b/include/notcurses/direct.h @@ -241,16 +241,16 @@ API int ncdirect_double_box(struct ncdirect* n, uint64_t ul, uint64_t ur, __attribute__ ((nonnull (1))); // Provide a NULL 'ts' to block at length, a 'ts' of 0 for non-blocking -// operation, and otherwise a timespec to bound blocking. Returns a single -// Unicode code point, or (uint32_t)-1 on error. Returns 0 on a timeout. If -// an event is processed, the return value is the 'id' field from that -// event. 'ni' may be NULL. -API uint32_t ncdirect_get(struct ncdirect* n, const struct timespec* ts, +// operation, and otherwise an absolute deadline in terms of CLOCK_MONOTONIC. +// Returns a single Unicode code point, a synthesized special key constant, +// or (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, +// the return value is the 'id' field from that event. 'ni' may be NULL. +API uint32_t ncdirect_get(struct ncdirect* n, const struct timespec* absdl, ncinput* ni) __attribute__ ((nonnull (1))); // Get a file descriptor suitable for input event poll()ing. When this -// descriptor becomes available, you can call ncdirect_getc_nblock(), +// descriptor becomes available, you can call ncdirect_get_nblock(), // and input ought be ready. This file descriptor is *not* necessarily // the file descriptor associated with stdin (but it might be!). API int ncdirect_inputready_fd(struct ncdirect* n) @@ -259,7 +259,7 @@ API int ncdirect_inputready_fd(struct ncdirect* n) // 'ni' may be NULL if the caller is uninterested in event details. If no event // is ready, returns 0. static inline uint32_t -ncdirect_getc_nblock(struct ncdirect* n, ncinput* ni){ +ncdirect_get_nblock(struct ncdirect* n, ncinput* ni){ struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; return ncdirect_get(n, &ts, ni); } @@ -267,7 +267,7 @@ ncdirect_getc_nblock(struct ncdirect* n, ncinput* ni){ // 'ni' may be NULL if the caller is uninterested in event details. Blocks // until an event is processed or a signal is received. static inline uint32_t -ncdirect_getc_blocking(struct ncdirect* n, ncinput* ni){ +ncdirect_get_blocking(struct ncdirect* n, ncinput* ni){ return ncdirect_get(n, NULL, ni); } diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 6fccc7f54..88fe3ff77 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -1048,7 +1048,7 @@ API void notcurses_drop_planes(struct notcurses* nc) // resize events, etc.). These are mapped into Unicode's Supplementary // Private Use Area-B, starting at U+100000. See . // -// notcurses_getc_nblock() is nonblocking. notcurses_getc_blocking() blocks +// notcurses_get_nblock() is nonblocking. notcurses_get_blocking() blocks // until a codepoint or special key is read, or until interrupted by a signal. // notcurses_get() allows an optional timeout to be controlled. // @@ -1107,10 +1107,10 @@ ncinput_equal_p(const ncinput* n1, const ncinput* n2){ // Read a UTF-32-encoded Unicode codepoint from input. This might only be part // of a larger EGC. Provide a NULL 'ts' to block at length, and otherwise a -// timespec to bound blocking. Returns a single Unicode code point, or -// (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, the -// return value is the 'id' field from that event. 'ni' may be NULL. 'ts' is an -// a delay bound against CLOCK_MONOTONIC (see clock_gettime(2)). +// timespec specifying an absolute deadline calculated using CLOCK_MONOTONIC. +// Returns a single Unicode code point, or a synthesized special key constant, +// or (uint32_t)-1 on error. Returns 0 on a timeout. If an event is processed, +// the return value is the 'id' field from that event. 'ni' may be NULL. API uint32_t notcurses_get(struct notcurses* n, const struct timespec* ts, ncinput* ni) __attribute__ ((nonnull (1))); @@ -1122,7 +1122,7 @@ API int notcurses_getvec(struct notcurses* n, const struct timespec* ts, __attribute__ ((nonnull (1, 3))); // Get a file descriptor suitable for input event poll()ing. When this -// descriptor becomes available, you can call notcurses_getc_nblock(), +// descriptor becomes available, you can call notcurses_get_nblock(), // and input ought be ready. This file descriptor is *not* necessarily // the file descriptor associated with stdin (but it might be!). API int notcurses_inputready_fd(struct notcurses* n) @@ -1131,7 +1131,7 @@ API int notcurses_inputready_fd(struct notcurses* n) // 'ni' may be NULL if the caller is uninterested in event details. If no event // is immediately ready, returns 0. static inline uint32_t -notcurses_getc_nblock(struct notcurses* n, ncinput* ni){ +notcurses_get_nblock(struct notcurses* n, ncinput* ni){ struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 }; return notcurses_get(n, &ts, ni); } @@ -1139,7 +1139,7 @@ notcurses_getc_nblock(struct notcurses* n, ncinput* ni){ // 'ni' may be NULL if the caller is uninterested in event details. Blocks // until an event is processed or a signal is received (including resize events). static inline uint32_t -notcurses_getc_blocking(struct notcurses* n, ncinput* ni){ +notcurses_get_blocking(struct notcurses* n, ncinput* ni){ return notcurses_get(n, NULL, ni); } diff --git a/src/demo/input.c b/src/demo/input.c index 81b1e4795..3ccca94ce 100644 --- a/src/demo/input.c +++ b/src/demo/input.c @@ -129,7 +129,7 @@ ultramegaok_demo(void* vnc){ ncinput ni; struct notcurses* nc = vnc; uint32_t id; - while((id = notcurses_getc_blocking(nc, &ni)) != (uint32_t)-1){ + while((id = notcurses_get_blocking(nc, &ni)) != (uint32_t)-1){ if(id == 0){ continue; } diff --git a/src/lib/direct.c b/src/lib/direct.c index ea14bfa90..42ac33a5d 100644 --- a/src/lib/direct.c +++ b/src/lib/direct.c @@ -982,7 +982,7 @@ char* ncdirect_readline(ncdirect* n, const char* prompt){ ncinput ni; uint32_t id; unsigned oldx = xstart; - while((id = ncdirect_getc_blocking(n, &ni)) != (uint32_t)-1){ + while((id = ncdirect_get_blocking(n, &ni)) != (uint32_t)-1){ if(ni.evtype == NCTYPE_RELEASE){ continue; } diff --git a/src/lib/in.c b/src/lib/in.c index 12f3184b9..7724ad34e 100644 --- a/src/lib/in.c +++ b/src/lib/in.c @@ -2146,29 +2146,9 @@ internal_get(inputctx* ictx, const struct timespec* ts, ncinput* ni){ return id; } -// FIXME kill off for API3, and expect an absolute deadline directly -static inline void -delaybound_to_deadline(const struct timespec* ts, struct timespec* absdl){ - if(ts){ - // incoming ts is a delay bound, but we want an absolute deadline for - // pthread_cond_timedwait(). convert it, using CLOCK_MONOTONIC (we - // initialized the condvar with pthread_condmonotonic_init()). - struct timespec tspec; - clock_gettime(CLOCK_MONOTONIC, &tspec); - absdl->tv_sec = ts->tv_sec + tspec.tv_sec; - absdl->tv_nsec = ts->tv_nsec + tspec.tv_nsec; - if(absdl->tv_nsec > 1000000000){ - ++absdl->tv_sec; - absdl->tv_nsec -= 1000000000; - } - } -} - // infp has already been set non-blocking -uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){ - struct timespec absdl; - delaybound_to_deadline(ts, &absdl); - uint32_t id = internal_get(nc->tcache.ictx, ts ? &absdl : NULL, ni); +uint32_t notcurses_get(notcurses* nc, const struct timespec* absdl, ncinput* ni){ + uint32_t id = internal_get(nc->tcache.ictx, absdl, ni); if(ni){ if(id == (uint32_t)-1){ ni->id = id; @@ -2178,12 +2158,10 @@ uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){ } // FIXME better performance if we move this within the locked area -int notcurses_getvec(notcurses* n, const struct timespec* ts, +int notcurses_getvec(notcurses* n, const struct timespec* absdl, ncinput* ni, int vcount){ - struct timespec absdl; - delaybound_to_deadline(ts, &absdl); for(int v = 0 ; v < vcount ; ++v){ - uint32_t u = notcurses_get(n, ts ? &absdl : NULL, &ni[v]); + uint32_t u = notcurses_get(n, absdl, &ni[v]); if(u == (uint32_t)-1){ if(v == 0){ return -1; @@ -2196,8 +2174,8 @@ int notcurses_getvec(notcurses* n, const struct timespec* ts, return vcount; } -uint32_t ncdirect_get(ncdirect* n, const struct timespec* ts, ncinput* ni){ - return internal_get(n->tcache.ictx, ts, ni); +uint32_t ncdirect_get(ncdirect* n, const struct timespec* absdl, ncinput* ni){ + return internal_get(n->tcache.ictx, absdl, ni); } int get_cursor_location(inputctx* ictx, const char* u7, unsigned* y, unsigned* x){ diff --git a/src/poc/direct-input.c b/src/poc/direct-input.c index 00b27ca15..e19cbb337 100644 --- a/src/poc/direct-input.c +++ b/src/poc/direct-input.c @@ -10,7 +10,7 @@ int main(void){ } ncinput ni; uint32_t i; - while((i = ncdirect_getc_blocking(n, &ni)) != (uint32_t)-1){ + while((i = ncdirect_get_blocking(n, &ni)) != (uint32_t)-1){ unsigned char utf8[5] = {}; notcurses_ucs32_to_utf8(&i, 1, utf8, sizeof(utf8)); printf("Read input: [%c%c%c] %s\n", ni.ctrl ? 'C' : 'c', diff --git a/src/poc/interp.c b/src/poc/interp.c index eea0a3827..603439a04 100644 --- a/src/poc/interp.c +++ b/src/poc/interp.c @@ -111,7 +111,7 @@ int main(void){ } ncinput ni; do{ - notcurses_getc_blocking(nc, &ni); + notcurses_get_blocking(nc, &ni); }while(ni.id != (uint32_t)-1 && ni.evtype != NCTYPE_RELEASE); notcurses_stop(nc); return EXIT_SUCCESS; diff --git a/src/poc/menu.c b/src/poc/menu.c index 24ca2218c..df91a96c7 100644 --- a/src/poc/menu.c +++ b/src/poc/menu.c @@ -28,7 +28,7 @@ run_menu(struct notcurses* nc, struct ncmenu* ncm){ uint32_t keypress; ncinput ni; notcurses_render(nc); - while((keypress = notcurses_getc_blocking(nc, &ni)) != (uint32_t)-1){ + while((keypress = notcurses_get_blocking(nc, &ni)) != (uint32_t)-1){ if(!ncmenu_offer_input(ncm, &ni)){ if(ni.evtype == NCTYPE_RELEASE){ continue; diff --git a/src/poc/multiselect.c b/src/poc/multiselect.c index d5680a1e2..b5e7953c5 100644 --- a/src/poc/multiselect.c +++ b/src/poc/multiselect.c @@ -43,7 +43,7 @@ run_mselect(struct notcurses* nc, struct ncmultiselector* ns){ notcurses_render(nc); uint32_t keypress; ncinput ni; - while((keypress = notcurses_getc_blocking(nc, &ni)) != (uint32_t)-1){ + while((keypress = notcurses_get_blocking(nc, &ni)) != (uint32_t)-1){ if(ni.evtype == NCTYPE_RELEASE){ continue; } diff --git a/src/poc/procroller.c b/src/poc/procroller.c index 39b545c41..f5f793bed 100644 --- a/src/poc/procroller.c +++ b/src/poc/procroller.c @@ -75,7 +75,7 @@ int main(int argc, char** argv){ notcurses_render(nc); ncinput ni; do{ - notcurses_getc_blocking(nc, &ni); + notcurses_get_blocking(nc, &ni); }while(ni.evtype == NCTYPE_RELEASE); if(notcurses_stop(nc)){ return EXIT_FAILURE; diff --git a/src/poc/selector.c b/src/poc/selector.c index 88685c637..138ce7750 100644 --- a/src/poc/selector.c +++ b/src/poc/selector.c @@ -33,7 +33,7 @@ run_selector(struct notcurses* nc, struct ncselector* ns){ notcurses_render(nc); uint32_t keypress; ncinput ni; - while((keypress = notcurses_getc_blocking(nc, &ni)) != (uint32_t)-1){ + while((keypress = notcurses_get_blocking(nc, &ni)) != (uint32_t)-1){ if(!ncselector_offer_input(ns, &ni)){ if(ni.evtype == NCTYPE_RELEASE){ continue; diff --git a/src/poc/tabbed.c b/src/poc/tabbed.c index caddb17be..8ca0a909e 100644 --- a/src/poc/tabbed.c +++ b/src/poc/tabbed.c @@ -105,7 +105,7 @@ int main(int argc, char** argv){ int tabnameind = 0; uint32_t c; ncinput ni; - while((c = notcurses_getc_blocking(nc, &ni)) != 'q'){ + while((c = notcurses_get_blocking(nc, &ni)) != 'q'){ if(ni.evtype == NCTYPE_RELEASE){ continue; } diff --git a/src/poc/tree.c b/src/poc/tree.c index a12f031eb..e45022984 100644 --- a/src/poc/tree.c +++ b/src/poc/tree.c @@ -391,7 +391,7 @@ callback(struct ncplane* ncp, void* curry, int dizzy){ static int tree_ui(struct notcurses* nc, struct nctree* tree){ ncinput ni; - while(notcurses_getc_blocking(nc, &ni) != (uint32_t)-1){ + while(notcurses_get_blocking(nc, &ni) != (uint32_t)-1){ if(nctree_offer_input(tree, &ni)){ if(nctree_redraw(tree)){ return -1; diff --git a/src/pocpp/reel.cpp b/src/pocpp/reel.cpp index 3c41e0580..c171a15f3 100644 --- a/src/pocpp/reel.cpp +++ b/src/pocpp/reel.cpp @@ -120,7 +120,7 @@ int runreels(struct notcurses* nc, struct ncreel* nr){ int y, x; char32_t key; ncinput ni; - while((key = notcurses_getc_blocking(nc, &ni)) != (char32_t)-1){ + while((key = notcurses_get_blocking(nc, &ni)) != (char32_t)-1){ if(ni.evtype == EvType::Release){ continue; }