mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
death to sigset_t #1967
This commit is contained in:
parent
14ca7b6bf5
commit
0d289958f9
11
NEWS.md
11
NEWS.md
@ -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
|
||||
|
65
USAGE.md
65
USAGE.md
@ -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…
x
Reference in New Issue
Block a user