death to sigset_t #1967

pull/1988/head
nick black 3 years ago
parent 14ca7b6bf5
commit 0d289958f9
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -2,6 +2,17 @@ This document attempts to list user-visible changes and any major internal
rearrangements of Notcurses.
* 2.3.12 (not yet released)
* `notcurses_getc()` and `ncdirect_getc()` no longer accept a `sigset_t*`
as their third argument. Instead, they accept a `void*`, with which
they will do nothing. This is due to POSIX signals being unportable in
addition to terrible, and this one wart complicating wrappers a great
deal. If you were using this functionality, you were probably using it
incorrectly, no offense. If you're certain you were doing it right,
roll your own with `pthread_sigmask()`, and accept the race condition.
For ABI3, these functions will be dropped entirely; for now they have
only been marked deprecated. New functions `ncdirect_get()` and
`notcurses_get()` elide this parameter entirely, and ought be used in
new code. All callers have been updated.
* 2.3.11 (2021-07-20)
* Notcurses now requires libz to build. In exchange, it can now generate

@ -98,7 +98,7 @@ typedef enum {
#define NCOPTION_NO_CLEAR_BITMAPS 0x0002ull
// We typically install a signal handler for SIGWINCH that generates a resize
// event in the notcurses_getc() queue. Set to inhibit this handler.
// event in the notcurses_get() queue. Set to inhibit this handler.
#define NCOPTION_NO_WINCH_SIGHANDLER 0x0004
// We typically install a signal handler for SIG{INT, SEGV, ABRT, QUIT} that
@ -575,20 +575,20 @@ control timing. Notcurses brooks no delay; all characters of an escape sequence
must be readable without delay for it to be interpreted as such.
```c
// All input is currently taken from stdin, though this will likely change. We
// attempt to read a single UTF8-encoded Unicode codepoint, *not* an entire
// Extended Grapheme Cluster. It is also possible that we will read a special
// keypress, i.e. anything that doesn't correspond to a Unicode codepoint (e.g.
// arrow keys, function keys, screen resize events, etc.). These are mapped
// into Unicode's Supplementary Private Use Area-B, starting at U+100000.
// All input is taken from stdin. We attempt to read a single UTF8-encoded
// Unicode codepoint, *not* an entire Extended Grapheme Cluster. It is also
// possible that we will read a special keypress, i.e. anything that doesn't
// correspond to a Unicode codepoint (e.g. arrow keys, function keys, screen
// resize events, etc.). These are mapped into Unicode's Supplementary
// Private Use Area-B, starting at U+100000. See <notcurses/nckeys.h>.
//
// notcurses_getc() and notcurses_getc_nblock() are both nonblocking.
// notcurses_getc_blocking() blocks until a codepoint or special key is read,
// or until interrupted by a signal.
// notcurses_getc_nblock() is nonblocking. notcurses_getc_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.
//
// In the case of a valid read, a 32-bit Unicode codepoint is returned. 0 is
// returned to indicate that no input was available, but only by
// notcurses_getc(). Otherwise (including on EOF) (char32_t)-1 is returned.
// returned to indicate that no input was available. Otherwise (including on
// EOF) (uint32_t)-1 is returned.
#define suppuabize(w) ((w) + 0x100000)
@ -627,7 +627,7 @@ must be readable without delay for it to be interpreted as such.
#define NCKEY_EXIT suppuabize(133)
#define NCKEY_PRINT suppuabize(134)
#define NCKEY_REFRESH suppuabize(135)
// Mouse events. We try to encode some details into the char32_t (i.e. which
// Mouse events. We try to encode some details into the uint32_t (i.e. which
// button was pressed), but some is embedded in the ncinput event. The release
// event is generic across buttons; callers must maintain state, if they care.
#define NCKEY_BUTTON1 suppuabize(201)
@ -636,15 +636,15 @@ must be readable without delay for it to be interpreted as such.
// ... up to 11 mouse buttons
#define NCKEY_RELEASE suppuabize(212)
// Is this char32_t a Supplementary Private Use Area-B codepoint?
// Is this uint32_t a Supplementary Private Use Area-B codepoint?
static inline bool
nckey_supppuab_p(char32_t w){
nckey_supppuab_p(uint32_t w){
return w >= 0x100000 && w <= 0x10fffd;
}
// An input event. Cell coordinates are currently defined only for mouse events.
typedef struct ncinput {
char32_t id; // identifier. Unicode codepoint or synthesized NCKEY event
uint32_t id; // identifier. Unicode codepoint or synthesized NCKEY event
int y; // y cell coordinate of event, -1 for undefined
int x; // x cell coordinate of event, -1 for undefined
bool alt; // was alt held?
@ -653,33 +653,28 @@ typedef struct ncinput {
uint64_t seqnum; // input event number
} ncinput;
// See ppoll(2) for more detail. Provide a NULL 'ts' to block at length, a 'ts'
// of 0 for non-blocking operation, and otherwise a timespec to bound blocking.
// Signals in sigmask (less several we handle internally) will be atomically
// masked and unmasked per ppoll(2). It should generally contain all signals.
// Returns a single Unicode code point, or (char32_t)-1 on error. 'sigmask' may
// be NULL. Returns 0 on a timeout. If an event is processed, the return value
// is the 'id' field from that event. 'ni' may be NULL.
char32_t notcurses_getc(struct notcurses* n, const struct timespec* ts,
sigset_t* sigmask, ncinput* ni);
// 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. 'sigmask' may be NULL. 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)
// 'ni' may be NULL if the caller is uninterested in event details. If no event
// is ready, returns 0.
static inline char32_t
static inline uint32_t
notcurses_getc_nblock(struct notcurses* n, ncinput* ni){
sigset_t sigmask;
sigfillset(&sigmask);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
return notcurses_getc(n, &ts, &sigmask, ni);
return notcurses_get(n, &ts, 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 char32_t
static inline uint32_t
notcurses_getc_blocking(struct notcurses* n, ncinput* ni){
sigset_t sigmask;
sigemptyset(&sigmask);
return notcurses_getc(n, NULL, &sigmask, ni);
return notcurses_get(n, NULL, ni);
}
static inline bool
@ -712,7 +707,7 @@ successful call to `notcurses_mouse_enable()`, and can later be disabled.
```c
// Enable the mouse in "button-event tracking" mode with focus detection and
// UTF8-style extended coordinates. On failure, -1 is returned. On success, 0
// is returned, and mouse events will be published to notcurses_getc().
// is returned, and mouse events will be published to notcurses_get().
int notcurses_mouse_enable(struct notcurses* n);
// Disable mouse events. Any events in the input queue can still be delivered.
@ -720,7 +715,7 @@ int notcurses_mouse_disable(struct notcurses* n);
// Is the event a synthesized mouse event?
static inline bool
nckey_mouse_p(char32_t r){
nckey_mouse_p(uint32_t r){
return r >= NCKEY_BUTTON1 && r <= NCKEY_RELEASE;
}
```

@ -15,7 +15,7 @@ struct timespec;
struct notcurses;
typedef struct ncinput {
char32_t id; // Unicode codepoint
uint32_t id; // Unicode codepoint
int y; // Y cell coordinate of event, -1 for undefined
int x; // X cell coordinate of event, -1 for undefined
bool alt; // Was Alt held during the event?
@ -25,15 +25,15 @@ typedef struct ncinput {
} ncinput;
```
**bool nckey_mouse_p(char32_t ***r***);**
**bool nckey_mouse_p(uint32_t ***r***);**
**bool ncinput_nomod_p(const ncinput* ***ni***);**
**char32_t notcurses_getc(struct notcurses* ***n***, const struct timespec* ***ts***, const sigset_t* ***sigmask***, ncinput* ***ni***);**
**uint32_t notcurses_get(struct notcurses* ***n***, const struct timespec* ***ts***, ncinput* ***ni***);**
**char32_t notcurses_getc_nblock(struct notcurses* ***n***, ncinput* ***ni***);**
**uint32_t notcurses_getc_nblock(struct notcurses* ***n***, ncinput* ***ni***);**
**char32_t notcurses_getc_blocking(struct notcurses* ***n***, ncinput* ***ni***);**
**uint32_t notcurses_getc_blocking(struct notcurses* ***n***, ncinput* ***ni***);**
**int notcurses_mouse_enable(struct notcurses* ***n***);**
@ -62,8 +62,8 @@ non-canonical mode (see **termios(3)**), and thus keys are received without line
notcurses maintains its own buffer of input characters, which it will attempt
to fill whenever it reads.
**notcurses_getc** allows a **struct timespec** to be specified as a timeout.
If **ts** is **NULL**, **notcurses_getc** will block until it reads input, or
**notcurses_get** allows a **struct timespec** to be specified as a timeout.
If **ts** is **NULL**, **notcurses_get** will block until it reads input, or
is interrupted by a signal. If its values are zeroes, there will be no blocking.
Otherwise, **ts** specifies a minimum time to wait for input before giving up.
On timeout, 0 is returned. Signals in **sigmask** will be masked and blocked in
@ -72,7 +72,7 @@ details will be reported in **ni**, unless **ni** is NULL.
**notcurses_inputready_fd** provides a file descriptor suitable for use with
I/O multiplexors such as **poll(2)**. This file descriptor might or might not
be the actual input file descriptor. If it readable, **notcurses_getc** can
be the actual input file descriptor. If it readable, **notcurses_get** can
be called without the possibility of blocking.
**ncinput_equal_p** compares two **ncinput** structs for data equality (i.e.
@ -122,11 +122,11 @@ generated.
# RETURN VALUES
On error, the **getc** family of functions return **(char32_t)-1**. The cause of the error may be determined
using **errno(3)**. Unless the error was a temporary one (especially e.g. **EINTR**),
**notcurses_getc** probably cannot be usefully called forthwith. On a
timeout, 0 is returned. Otherwise, the UCS-32 value of a Unicode codepoint, or
a synthesized event, is returned.
On error, the **get** family of functions return **(uint32_t)-1**. The cause
of the error may be determined using **errno(3)**. Unless the error was a
temporary one (especially e.g. **EINTR**), **notcurses_get** probably cannot
be usefully called forthwith. On a timeout, 0 is returned. Otherwise, the
UCS-32 value of a Unicode codepoint, or a synthesized event, is returned.
**notcurses_mouse_enable** returns 0 on success, and non-zero on failure, as
does **notcurses_mouse_disable**.
@ -137,12 +137,12 @@ the same input (though not necessarily the same input event), and
# NOTES
Like any other notcurses function, it is an error to call **notcurses_getc**
Like any other notcurses function, it is an error to call **notcurses_get**
during or after a call to **notcurses_stop**. If a thread is always sitting
on blocking input, it can be tricky to guarantee that this doesn't happen.
Only one thread may call into the input stack at once, but unlike almost every
other function in notcurses, **notcurses_getc** and friends can be called
other function in notcurses, **notcurses_get** and friends can be called
concurrently with **notcurses_render**.
Do not simply **poll** the input file descriptor. Instead, use the file

@ -207,16 +207,16 @@ namespace ncpp
return error_guard (ncdirect_flush (direct), -1);
}
char32_t getc (ncinput *ni, bool blocking) const noexcept
char32_t get (ncinput *ni, bool blocking) const noexcept
{
if (blocking)
return ncdirect_getc_blocking (direct, ni);
return ncdirect_getc_nblock (direct, ni);
}
char32_t getc (const struct timespec *ts, sigset_t *sigmask, ncinput *ni) const noexcept
char32_t get (const struct timespec *ts, ncinput *ni) const noexcept
{
return ncdirect_getc (direct, ts, sigmask, ni);
return ncdirect_get (direct, ts, ni);
}
int get_inputready_fd () const noexcept

@ -240,12 +240,12 @@ namespace ncpp
return static_cast<CellStyle>(notcurses_supported_styles (nc));
}
uint32_t getc (const timespec *ts, sigset_t *sigmask = nullptr, ncinput *ni = nullptr) const noexcept
uint32_t get (const timespec *ts, ncinput *ni = nullptr) const noexcept
{
return notcurses_getc (nc, ts, sigmask, ni);
return notcurses_get (nc, ts, ni);
}
uint32_t getc (bool blocking = false, ncinput *ni = nullptr) const noexcept
uint32_t get (bool blocking = false, ncinput *ni = nullptr) const noexcept
{
if (blocking)
return notcurses_getc_blocking (nc, ni);

@ -306,15 +306,13 @@ API int ncdirect_double_box(struct ncdirect* n, uint64_t ul, uint64_t ur,
int ylen, int xlen, unsigned ctlword)
__attribute__ ((nonnull (1)));
// See ppoll(2) for more detail. Provide a NULL 'ts' to block at length, a 'ts'
// of 0 for non-blocking operation, and otherwise a timespec to bound blocking.
// Signals in sigmask (less several we handle internally) will be atomically
// masked and unmasked per ppoll(2). '*sigmask' should generally contain all
// signals. Returns a single Unicode code point, or (uint32_t)-1 on error.
// 'sigmask' may be NULL. 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_getc(struct ncdirect* n, const struct timespec* ts,
sigset_t* sigmask, ncinput* ni)
// 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,
ncinput* ni)
__attribute__ ((nonnull (1)));
// Get a file descriptor suitable for input event poll()ing. When this
@ -328,19 +326,15 @@ API int ncdirect_inputready_fd(struct ncdirect* n)
// is ready, returns 0.
static inline uint32_t
ncdirect_getc_nblock(struct ncdirect* n, ncinput* ni){
sigset_t sigmask;
sigfillset(&sigmask);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
return ncdirect_getc(n, &ts, &sigmask, ni);
return ncdirect_get(n, &ts, 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){
sigset_t sigmask;
sigemptyset(&sigmask);
return ncdirect_getc(n, NULL, &sigmask, ni);
return ncdirect_get(n, NULL, ni);
}
// Release 'nc' and any associated resources. 0 on success, non-0 on failure.
@ -495,6 +489,11 @@ ncdirect_canbraille(const struct ncdirect* nc){
API bool ncdirect_canget_cursor(const struct ncdirect* nc)
__attribute__ ((nonnull (1)));
// Deprecated, to be removed for ABI3. Use ncdirect_get() in new code.
API uint32_t ncdirect_getc(struct ncdirect* n, const struct timespec* ts,
const void* unused, ncinput* ni)
__attribute__ ((deprecated)) __attribute__ ((nonnull (1)));
#undef ALLOC
#undef API

@ -27,7 +27,6 @@ extern "C" {
#define wcwidth(w) 1
#define wcswidth(w, s) (s)
#define sigset_t int
#define sigfillset(x)
#define sigemptyset(x)
#define O_CLOEXEC O_NOINHERIT
#define O_DIRECTORY 0

@ -94,7 +94,7 @@ typedef enum {
// -1 if a non-printable/illegal character is encountered.
API int ncstrwidth(const char* mbs);
// input functions like notcurses_getc() return ucs32-encoded uint32_t. convert
// input functions like notcurses_get() return ucs32-encoded uint32_t. convert
// a series of uint32_t to utf8. result must be at least 4 bytes per input
// uint32_t (6 bytes per uint32_t will future-proof against Unicode expansion).
// the number of bytes used is returned, or -1 if passed illegal ucs32, or too
@ -857,7 +857,7 @@ typedef enum {
#define NCOPTION_NO_CLEAR_BITMAPS 0x0002ull
// We typically install a signal handler for SIGWINCH that generates a resize
// event in the notcurses_getc() queue. Set to inhibit this handler.
// event in the notcurses_get() queue. Set to inhibit this handler.
#define NCOPTION_NO_WINCH_SIGHANDLER 0x0004ull
// We typically install a signal handler for SIG{INT, ILL, SEGV, ABRT, TERM,
@ -976,20 +976,20 @@ API struct ncplane* notcurses_bottom(struct notcurses* n);
// Destroy all ncplanes other than the stdplane.
API void notcurses_drop_planes(struct notcurses* nc);
// All input is currently taken from stdin, though this will likely change. We
// attempt to read a single UTF8-encoded Unicode codepoint, *not* an entire
// Extended Grapheme Cluster. It is also possible that we will read a special
// keypress, i.e. anything that doesn't correspond to a Unicode codepoint (e.g.
// arrow keys, function keys, screen resize events, etc.). These are mapped
// into Unicode's Supplementary Private Use Area-B, starting at U+100000.
// All input is taken from stdin. We attempt to read a single UTF8-encoded
// Unicode codepoint, *not* an entire Extended Grapheme Cluster. It is also
// possible that we will read a special keypress, i.e. anything that doesn't
// correspond to a Unicode codepoint (e.g. arrow keys, function keys, screen
// resize events, etc.). These are mapped into Unicode's Supplementary
// Private Use Area-B, starting at U+100000. See <notcurses/nckeys.h>.
//
// notcurses_getc() and notcurses_getc_nblock() are both nonblocking.
// notcurses_getc_blocking() blocks until a codepoint or special key is read,
// or until interrupted by a signal.
// notcurses_getc_nblock() is nonblocking. notcurses_getc_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.
//
// In the case of a valid read, a 32-bit Unicode codepoint is returned. 0 is
// returned to indicate that no input was available, but only by
// notcurses_getc(). Otherwise (including on EOF) (uint32_t)-1 is returned.
// returned to indicate that no input was available. Otherwise (including on
// EOF) (uint32_t)-1 is returned.
// Is this uint32_t a Supplementary Private Use Area-B codepoint?
static inline bool
@ -1031,15 +1031,14 @@ ncinput_equal_p(const ncinput* n1, const ncinput* n2){
return true;
}
// See ppoll(2) for more detail. Provide a NULL 'ts' to block at length, a 'ts'
// of 0 for non-blocking operation, and otherwise a timespec to bound blocking.
// Signals in sigmask (less several we handle internally) will be atomically
// masked and unmasked per ppoll(2). It should generally contain all signals.
// Returns a single Unicode code point, or (uint32_t)-1 on error. 'sigmask' may
// be NULL. 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_getc(struct notcurses* n, const struct timespec* ts,
const sigset_t* sigmask, ncinput* ni)
// 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. 'sigmask' may be NULL. 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)));
// Get a file descriptor suitable for input event poll()ing. When this
@ -1053,19 +1052,15 @@ API int notcurses_inputready_fd(struct notcurses* n)
// is ready, returns 0.
static inline uint32_t
notcurses_getc_nblock(struct notcurses* n, ncinput* ni){
sigset_t sigmask;
sigfillset(&sigmask);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
return notcurses_getc(n, &ts, &sigmask, ni);
return notcurses_get(n, &ts, 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){
sigset_t sigmask;
sigemptyset(&sigmask);
return notcurses_getc(n, NULL, &sigmask, ni);
return notcurses_get(n, NULL, ni);
}
static inline bool
@ -1075,7 +1070,7 @@ ncinput_nomod_p(const ncinput* ni){
// Enable the mouse in "button-event tracking" mode with focus detection and
// UTF8-style extended coordinates. On failure, -1 is returned. On success, 0
// is returned, and mouse events will be published to notcurses_getc().
// is returned, and mouse events will be published to notcurses_get().
API int notcurses_mouse_enable(struct notcurses* n);
// Disable mouse events. Any events in the input queue can still be delivered.
@ -4408,6 +4403,12 @@ typedef nccell cell; // FIXME backwards-compat, remove in ABI3
API void notcurses_debug_caps(const struct notcurses* nc, FILE* debugfp)
__attribute__ ((deprecated)) __attribute__ ((nonnull (1, 2)));
// Backwards-compatibility wrapper; this will be removed for ABI3.
// Use notcurses_get() in new code.
API uint32_t notcurses_getc(struct notcurses* n, const struct timespec* ts,
const void* unused, ncinput* ni)
__attribute__ ((deprecated)) __attribute__ ((nonnull (1)));
#define CELL_ALPHA_HIGHCONTRAST NCALPHA_HIGHCONTRAST
#define CELL_ALPHA_TRANSPARENT NCALPHA_TRANSPARENT
#define CELL_ALPHA_BLEND NCALPHA_BLEND

@ -252,7 +252,7 @@ int input_demo(ncpp::NotCurses* nc) {
start = timenow_to_ns();
std::thread tid(Ticker, nc);
ncinput ni;
while(errno = 0, (r = nc->getc(true, &ni)) != (char32_t)-1){
while(errno = 0, (r = nc->get(true, &ni)) != (char32_t)-1){
if(r == 0){ // interrupted by signal
continue;
}

@ -391,39 +391,27 @@ handle_getc(ncinputlayer* nc, int kpress, ncinput* ni, int leftmargin, int topma
// blocks up through ts (infinite with NULL ts), returning number of events
// (0 on timeout) or -1 on error/interruption.
#ifndef __MINGW64__
static int
block_on_input(int fd, const struct timespec* ts, const sigset_t* sigmask){
block_on_input(int fd, const struct timespec* ts){
struct pollfd pfd = {
.fd = fd,
.events = POLLIN,
.revents = 0,
};
// we don't want to persistently modify the provided sigmask
sigset_t scratchmask;
if(sigmask){
memcpy(&scratchmask, sigmask, sizeof(*sigmask));
}else{
sigfillset(&scratchmask);
}
sigdelset(&scratchmask, SIGCONT);
sigdelset(&scratchmask, SIGWINCH);
sigdelset(&scratchmask, SIGILL);
sigdelset(&scratchmask, SIGFPE);
sigdelset(&scratchmask, SIGSEGV);
sigdelset(&scratchmask, SIGABRT);
// now add those which we don't want while writing
sigaddset(&scratchmask, SIGINT);
sigaddset(&scratchmask, SIGQUIT);
sigaddset(&scratchmask, SIGTERM);
sigset_t smask;
sigfillset(&smask);
sigdelset(&smask, SIGCONT);
sigdelset(&smask, SIGWINCH);
#ifdef POLLRDHUP
pfd.events |= POLLRDHUP;
#endif
int events;
#ifdef __APPLE__
int timeoutms = ts ? ts->tv_sec * 1000 + ts->tv_nsec / 1000000 : -1;
while((events = poll(&pfd, 1, timeoutms)) < 0){ // FIXME scratchmask?
while((events = poll(&pfd, 1, timeoutms)) < 0){ // FIXME smask?
#else
while((events = ppoll(&pfd, 1, ts, &scratchmask)) < 0){
while((events = ppoll(&pfd, 1, ts, &smask)) < 0){
#endif
if(events == 0){
return 0;
@ -437,6 +425,9 @@ block_on_input(int fd, const struct timespec* ts, const sigset_t* sigmask){
}
return events;
}
#else
// FIXME windows block_on_input()
#endif
static inline size_t
input_queue_space(const ncinputlayer* nc){
@ -563,14 +554,13 @@ handle_ncinput(ncinputlayer* nc, ncinput* ni, int leftmargin, int topmargin){
// helper so we can do counter increment at a single location
static inline uint32_t
ncinputlayer_prestamp(ncinputlayer* nc, const struct timespec *ts,
const sigset_t* sigmask, ncinput* ni, int leftmargin,
int topmargin){
ncinput* ni, int leftmargin, int topmargin){
//fprintf(stderr, "PRESTAMP OCCUPADO: %d\n", nc->inputbuf_occupied);
if(nc->inputbuf_occupied){
return handle_queued_input(nc, ni, leftmargin, topmargin);
}
errno = 0;
if(block_on_input(nc->infd, ts, sigmask) > 0){
if(block_on_input(nc->infd, ts) > 0){
//fprintf(stderr, "%d events from input!\n", events);
return handle_ncinput(nc, ni, leftmargin, topmargin);
}
@ -579,9 +569,8 @@ ncinputlayer_prestamp(ncinputlayer* nc, const struct timespec *ts,
}
// infp has already been set non-blocking
uint32_t notcurses_getc(notcurses* nc, const struct timespec *ts,
const sigset_t* sigmask, ncinput* ni){
uint32_t r = ncinputlayer_prestamp(&nc->tcache.input, ts, sigmask, ni,
uint32_t notcurses_get(notcurses* nc, const struct timespec* ts, ncinput* ni){
uint32_t r = ncinputlayer_prestamp(&nc->tcache.input, ts, ni,
nc->margin_l, nc->margin_t);
if(r != (uint32_t)-1){
uint64_t stamp = nc->tcache.input.input_events++; // need increment even if !ni
@ -593,11 +582,16 @@ uint32_t notcurses_getc(notcurses* nc, const struct timespec *ts,
return r;
}
uint32_t ncdirect_getc(ncdirect* nc, const struct timespec *ts,
sigset_t* sigmask, ncinput* ni){
uint32_t r = ncinputlayer_prestamp(&nc->tcache.input, ts, sigmask, ni, 0, 0);
uint32_t notcurses_getc(notcurses* nc, const struct timespec* ts,
const void* unused, ncinput* ni){
(void)unused; // FIXME remove for abi3
return notcurses_get(nc, ts, ni);
}
uint32_t ncdirect_get(struct ncdirect* n, const struct timespec* ts, ncinput* ni){
uint32_t r = ncinputlayer_prestamp(&n->tcache.input, ts, ni, 0, 0);
if(r != (uint32_t)-1){
uint64_t stamp = nc->tcache.input.input_events++; // need increment even if !ni
uint64_t stamp = n->tcache.input.input_events++; // need increment even if !ni
if(ni){
ni->seqnum = stamp;
}
@ -605,6 +599,12 @@ uint32_t ncdirect_getc(ncdirect* nc, const struct timespec *ts,
return r;
}
uint32_t ncdirect_getc(ncdirect* nc, const struct timespec *ts,
const void* unused, ncinput* ni){
(void)unused; // FIXME remove for abi3
return ncdirect_get(nc, ts, ni);
}
// load all known special keys from terminfo, and build the input sequence trie
static int
prep_special_keys(ncinputlayer* nc){
@ -1527,7 +1527,7 @@ void ncinput_extract_clrs(ncinputlayer* ni){
// specify a NULL timeout, meaning we block as long as we need, until
// there's input available, or we are interrupted by a signal.
logdebug("Blocking on input");
if(block_on_input(ni->infd, NULL, NULL) < 1){
if(block_on_input(ni->infd, NULL) < 1){
pthread_mutex_lock(&ni->lock); // interrupted?
break;
}

@ -131,19 +131,19 @@ auto perframe(struct ncvisual* ncv, struct ncvisual_options* vopts,
struct timespec interval;
clock_gettime(CLOCK_MONOTONIC, &interval);
uint64_t nsnow = timespec_to_ns(&interval);
char32_t keyp;
uint32_t keyp;
ncinput ni;
if(absnow > nsnow){
ns_to_timespec(absnow - nsnow, &interval);
keyp = nc.getc(&interval, nullptr, &ni);
keyp = nc.get(&interval, &ni);
}else{
keyp = nc.getc();
keyp = nc.get();
}
if(keyp == (char32_t)-1){
if(keyp == (uint32_t)-1){
break;
}
if(keyp == ' '){
if((keyp = nc.getc(true)) == (char32_t)-1){
if((keyp = nc.get(true)) == (uint32_t)-1){
return -1;
}
}
@ -438,8 +438,8 @@ int rendered_mode_player_inner(NotCurses& nc, int argc, char** argv,
ncplane_destroy(n);
return -1;
}
char32_t ie = nc.getc(true);
if(ie == (char32_t)-1){
uint32_t ie = nc.get(true);
if(ie == (uint32_t)-1){
return -1;
}else if(ie == 'q'){
return 0;

@ -69,7 +69,7 @@ int main(int argc, char** argv){
ncplane_set_fg_rgb(n, 0x00bcaa);
ncplane_printf_aligned(n, -1, NCALIGN_CENTER, "press any key to continue (%s)", *argv);
notcurses_render(nc);
notcurses_getc(nc, NULL, NULL, NULL);
notcurses_get(nc, NULL, NULL);
}
done:

@ -56,7 +56,7 @@ auto main(int argc, const char** argv) -> int {
}
ncinput ni;
nc.render();
while(nc.getc(true, &ni) != (char32_t)-1){
while(nc.get(true, &ni) != (char32_t)-1){
if(ni.ctrl && ni.id == 'L'){
notcurses_refresh(nc, NULL, NULL);
}else if((ni.ctrl && ni.id == 'D') || ni.id == NCKEY_ENTER){

@ -2,7 +2,7 @@ bool IOLoop(ncpp::NotCurses& nc, Tetris& t, std::atomic_bool& gameover) {
ncpp::Plane* stdplane = nc.get_stdplane();
char32_t input = 0;
ncinput ni;
while(!gameover && (input = nc.getc(true, &ni)) != (char32_t)-1){
while(!gameover && (input = nc.get(true, &ni)) != (char32_t)-1){
if(input == 'q'){
break;
}

Loading…
Cancel
Save