mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
Normalize ncplane_at_* / ncplane_set_base() (#479)
* ncplane_at_* and ncplane_at_cursor_* We had notcurses_at_yx() expanding into three distinct parts of the cell structure, and ncplane_at_yx() / ncplane_at_cursor() writing directly to a cell. It was annoying to remember which was which. The latter two now have a signature matching notcurses_at_yx(), while the old functionality has been moved to ncplane_at_yx_cell() and ncplane_at_cursor_yx(). #476
This commit is contained in:
parent
50e0870432
commit
c6a9997554
33
CHANGELOG.md
33
CHANGELOG.md
@ -1,19 +1,36 @@
|
||||
This document attempts to list user-visible changes and any major internal
|
||||
rearrangements of Notcurses.
|
||||
|
||||
* 1.3.1
|
||||
* 1.3.1 (not yet released)
|
||||
* `ncplane_at_yx()` and `ncplane_at_cursor()` have been changed to return a
|
||||
heap-allocated EGC, and write the attributes and channels to value-result
|
||||
`uint32_t*` and `uint64_t*` parameters, instead of to a `cell*`. This
|
||||
matches `notcurses_at_yx()`, and means they're no longer invalidated if the
|
||||
plane in question is destroyed. The previous functionality is available as
|
||||
new functions `ncplane_at_yx_cell()` and `ncplane_at_cursor_cell()`.
|
||||
* `ncplane_set_base()` inverted its `uint32_t attrword` and `uint64_t channels`
|
||||
parameters, thus matching every other function with these two parameters.
|
||||
It moved `const char* egc` before either, to force a type error, as the
|
||||
change would otherwise be likely to go overlooked.
|
||||
* The C++ `Notcurses::render()` function now returns non-zero on failure,
|
||||
mirroring the behavior of the core C `notcurses_render()`. This is an
|
||||
inversion of its previous behavior.
|
||||
mirroring the behavior of the core C `notcurses_render()`. This is an
|
||||
inversion of its previous behavior.
|
||||
|
||||
* 1.2.8
|
||||
|
||||
* 1.3.0 (2020-04-12)
|
||||
* No user-visible changes
|
||||
|
||||
* 1.2.9 (2020-04-11)
|
||||
* No user-visible changes
|
||||
|
||||
* 1.2.8 (2020-04-10)
|
||||
* `notcurses-tetris` now happily continues if it can't load its background.
|
||||
|
||||
* 1.2.7
|
||||
* 1.2.7 (2020-04-10)
|
||||
* Plots now always keep the most recent data to their far right (i.e., the
|
||||
gap that is initially filled is on the left, rather than the right).
|
||||
|
||||
* 1.2.6
|
||||
* 1.2.6 (2020-04-08)
|
||||
* `ncplane_putsimple_yx()` and `ncplane_putstr_yx()` have been exported as
|
||||
static inline functions.
|
||||
* `ncplane_set_scrolling()` has been added, allowing control over whether a
|
||||
@ -35,7 +52,7 @@ rearrangements of Notcurses.
|
||||
`notcurses_resize()` internally, as `notcurses_render()` always has).
|
||||
* First Fedora packaging.
|
||||
|
||||
* 1.2.5
|
||||
* 1.2.5 (2020-04-05)
|
||||
* Add ncplot, with support for sliding-windowed horizontal histograms.
|
||||
* gradient, polyfill, `ncplane_format()` and `ncplane_stain()` all now return
|
||||
the number of cells written on success. Failure still sees -1 returned.
|
||||
@ -51,6 +68,6 @@ rearrangements of Notcurses.
|
||||
and a source of blunders. The EGC is returned via the `char*` return
|
||||
value. https://github.com/dankamongmen/notcurses/issues/410
|
||||
|
||||
* 1.2.4 2020-03-24
|
||||
* 1.2.4 (2020-03-24)
|
||||
* Add ncmultiselector
|
||||
* Add `ncdirect_cursor_enable()` and `ncdirect_cursor_disable()`.
|
||||
|
27
README.md
27
README.md
@ -789,8 +789,8 @@ int ncplane_set_base_cell(struct ncplane* ncp, const cell* c);
|
||||
// rendering anywhere that the ncplane's gcluster is 0. Erasing the ncplane
|
||||
// does not reset the base cell; this function must be called with an empty
|
||||
// 'egc'. 'egc' must be a single extended grapheme cluster.
|
||||
int ncplane_set_base(struct ncplane* ncp, uint64_t channels,
|
||||
uint32_t attrword, const char* egc);
|
||||
int ncplane_set_base(struct ncplane* ncp, const char* egc,
|
||||
uint32_t attrword, uint64_t channels);
|
||||
|
||||
// Extract the ncplane's base cell into 'c'. The reference is invalidated if
|
||||
// 'ncp' is destroyed.
|
||||
@ -820,13 +820,24 @@ addition, the plane's virtual framebuffer can be accessed (note that this does
|
||||
not necessarily reflect anything on the actual screen).
|
||||
|
||||
```c
|
||||
// Retrieve the cell at the cursor location on the specified plane, returning
|
||||
// it in 'c'. This copy is safe to use until the ncplane is destroyed/erased.
|
||||
int ncplane_at_cursor(struct ncplane* n, cell* c);
|
||||
// Retrieve the current contents of the cell under the cursor. The EGC is
|
||||
// returned, or NULL on error. This EGC must be free()d by the caller. The
|
||||
// attrword and channels are written to 'attrword' and 'channels', respectively.
|
||||
char* ncplane_at_cursor(struct ncplane* n, uint32_t* attrword, uint64_t* channels);
|
||||
|
||||
// Retrieve the cell at the specified location on the specified plane, returning
|
||||
// it in 'c'. This copy is safe to use until the ncplane is destroyed/erased.
|
||||
int ncplane_at_yx(struct ncplane* n, int y, int x, cell* c);
|
||||
// Retrieve the current contents of the cell under the cursor into 'c'. This
|
||||
// cell is invalidated if the associated plane is destroyed.
|
||||
int ncplane_at_cursor_cell(struct ncplane* n, cell* c);
|
||||
|
||||
// Retrieve the current contents of the specified cell. The EGC is returned, or
|
||||
// NULL on error. This EGC must be free()d by the caller. The attrword and
|
||||
// channels are written to 'attrword' and 'channels', respectively.
|
||||
char* ncplane_at_yx(struct ncplane* n, int y, int x,
|
||||
uint32_t* attrword, uint64_t* channels);
|
||||
|
||||
// Retrieve the current contents of the specified cell into 'c'. This cell is
|
||||
// invalidated if the associated plane is destroyed.
|
||||
int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c);
|
||||
|
||||
// Manipulate the opaque user pointer associated with this plane.
|
||||
// ncplane_set_userptr() returns the previous userptr after replacing
|
||||
|
@ -28,7 +28,7 @@ notcurses_ncplane - operations on notcurses planes
|
||||
|
||||
**int ncplane_set_base_cell(struct ncplane* ncp, const cell* c);**
|
||||
|
||||
**int ncplane_set_base(struct ncplane* ncp, uint64_t channels, uint32_t attrword, const char* egc);**
|
||||
**int ncplane_set_base(struct ncplane* ncp, const char* egc, uint32_t attrword, uint64_t channels);**
|
||||
|
||||
**int ncplane_base(struct ncplane* ncp, cell* c);**
|
||||
|
||||
@ -42,9 +42,13 @@ notcurses_ncplane - operations on notcurses planes
|
||||
|
||||
**struct ncplane* ncplane_below(struct ncplane* n);**
|
||||
|
||||
**int ncplane_at_cursor(struct ncplane* n, cell* c);**
|
||||
**char* ncplane_at_cursor(struct ncplane* n, uint32_t* attrword, uint64_t* channels);**
|
||||
|
||||
**int ncplane_at_yx(struct ncplane* n, int y, int x, cell* c);**
|
||||
**int ncplane_at_cursor_cell(struct ncplane* n, cell* c);**
|
||||
|
||||
**char* ncplane_at_yx(struct ncplane* n, int y, int x, uint32_t* attrword, uint64_t* channels);**
|
||||
|
||||
**int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c);**
|
||||
|
||||
**void* ncplane_set_userptr(struct ncplane* n, void* opaque);**
|
||||
|
||||
@ -218,6 +222,12 @@ plane is the bottommost plane, NULL is returned. It cannot fail.
|
||||
**ncplane_set_scrolling** returns **true** if scrolling was previously enabled,
|
||||
and **false** otherwise.
|
||||
|
||||
**ncplane_at_yx** and **ncplane_at_cursor** return a heap-allocated copy of the
|
||||
EGC at the relevant cell, or NULL if the cell is invalid. The caller should free
|
||||
this result. **ncplane_at_yx_cell** and **ncplane_at_cursor_cell** instead load
|
||||
these values into a **cell**, which is invalidated if the associated plane is
|
||||
destroyed. The caller should release this cell with **cell_release**.
|
||||
|
||||
Functions returning **int** return 0 on success, and non-zero on error.
|
||||
|
||||
All other functions cannot fail (and return **void**).
|
||||
|
@ -585,8 +585,8 @@ namespace ncpp
|
||||
}
|
||||
|
||||
bool box (const Cell &ul, const Cell &ur, const Cell &ll, const Cell &lr,
|
||||
const Cell &hline, const Cell &vline, int ystop, int xstop,
|
||||
unsigned ctlword) const NOEXCEPT_MAYBE
|
||||
const Cell &hline, const Cell &vline, int ystop, int xstop,
|
||||
unsigned ctlword) const NOEXCEPT_MAYBE
|
||||
{
|
||||
return error_guard (ncplane_box (plane, ul, ur, ll, lr, hline, vline, ystop, xstop, ctlword), -1);
|
||||
}
|
||||
@ -779,9 +779,9 @@ namespace ncpp
|
||||
return error_guard_cond<bool, bool> (ret, ret);
|
||||
}
|
||||
|
||||
bool set_base (uint64_t channels, uint32_t attrword, const char *egc) const NOEXCEPT_MAYBE
|
||||
bool set_base (const char* egc, uint32_t attrword, uint64_t channels) const NOEXCEPT_MAYBE
|
||||
{
|
||||
bool ret = ncplane_set_base (plane, channels, attrword, egc) < 0;
|
||||
bool ret = ncplane_set_base (plane, egc, attrword, channels) < 0;
|
||||
return error_guard_cond<bool, bool> (ret, ret);
|
||||
}
|
||||
|
||||
@ -793,7 +793,7 @@ namespace ncpp
|
||||
|
||||
bool at_cursor (Cell &c) const NOEXCEPT_MAYBE
|
||||
{
|
||||
bool ret = ncplane_at_cursor (plane, c) < 0;
|
||||
bool ret = ncplane_at_cursor_cell (plane, c) < 0;
|
||||
return error_guard_cond<bool, bool> (ret, ret);
|
||||
}
|
||||
|
||||
@ -805,9 +805,17 @@ namespace ncpp
|
||||
return at_cursor (*c);
|
||||
}
|
||||
|
||||
char* at_cursor (uint32_t* attrword, uint64_t* channels) const
|
||||
{
|
||||
if (attrword == nullptr || channels == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return ncplane_at_cursor (plane, attrword, channels);
|
||||
}
|
||||
|
||||
int get_at (int y, int x, Cell &c) const NOEXCEPT_MAYBE
|
||||
{
|
||||
return error_guard (ncplane_at_yx (plane, y, x, c), -1);
|
||||
return error_guard<int> (ncplane_at_yx_cell (plane, y, x, c), -1);
|
||||
}
|
||||
|
||||
int get_at (int y, int x, Cell *c) const
|
||||
@ -818,6 +826,14 @@ namespace ncpp
|
||||
return get_at (y, x, *c);
|
||||
}
|
||||
|
||||
char* get_at (int y, int x, uint32_t* attrword, uint64_t* channels) const
|
||||
{
|
||||
if (attrword == nullptr || channels == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return ncplane_at_yx (plane, y, x, attrword, channels);
|
||||
}
|
||||
|
||||
void* set_userptr (void *opaque) const noexcept
|
||||
{
|
||||
return ncplane_set_userptr (plane, opaque);
|
||||
|
@ -524,6 +524,198 @@ typedef struct cell {
|
||||
uint64_t channels; // + 8B == 16B
|
||||
} cell;
|
||||
|
||||
#define CELL_TRIVIAL_INITIALIZER { .gcluster = '\0', .attrword = 0, .channels = 0, }
|
||||
#define CELL_SIMPLE_INITIALIZER(c) { .gcluster = (c), .attrword = 0, .channels = 0, }
|
||||
#define CELL_INITIALIZER(c, a, chan) { .gcluster = (c), .attrword = (a), .channels = (chan), }
|
||||
|
||||
static inline void
|
||||
cell_init(cell* c){
|
||||
memset(c, 0, sizeof(*c));
|
||||
}
|
||||
|
||||
// Breaks the UTF-8 string in 'gcluster' down, setting up the cell 'c'. Returns
|
||||
// the number of bytes copied out of 'gcluster', or -1 on failure. The styling
|
||||
// of the cell is left untouched, but any resources are released.
|
||||
API int cell_load(struct ncplane* n, cell* c, const char* gcluster);
|
||||
|
||||
// cell_load(), plus blast the styling with 'attr' and 'channels'.
|
||||
static inline int
|
||||
cell_prime(struct ncplane* n, cell* c, const char* gcluster,
|
||||
uint32_t attr, uint64_t channels){
|
||||
c->attrword = attr;
|
||||
c->channels = channels;
|
||||
int ret = cell_load(n, c, gcluster);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Duplicate 'c' into 'targ'; both must be/will be bound to 'n'.
|
||||
API int cell_duplicate(struct ncplane* n, cell* targ, const cell* c);
|
||||
|
||||
// Release resources held by the cell 'c'.
|
||||
API void cell_release(struct ncplane* n, cell* c);
|
||||
|
||||
#define NCSTYLE_MASK 0xffff0000ul
|
||||
#define NCSTYLE_STANDOUT 0x00800000ul
|
||||
#define NCSTYLE_UNDERLINE 0x00400000ul
|
||||
#define NCSTYLE_REVERSE 0x00200000ul
|
||||
#define NCSTYLE_BLINK 0x00100000ul
|
||||
#define NCSTYLE_DIM 0x00080000ul
|
||||
#define NCSTYLE_BOLD 0x00040000ul
|
||||
#define NCSTYLE_INVIS 0x00020000ul
|
||||
#define NCSTYLE_PROTECT 0x00010000ul
|
||||
#define NCSTYLE_ITALIC 0x01000000ul
|
||||
|
||||
// Set the specified style bits for the cell 'c', whether they're actively
|
||||
// supported or not.
|
||||
static inline void
|
||||
cell_styles_set(cell* c, unsigned stylebits){
|
||||
c->attrword = (c->attrword & ~NCSTYLE_MASK) | ((stylebits & NCSTYLE_MASK));
|
||||
}
|
||||
|
||||
// Extract the style bits from the cell's attrword.
|
||||
static inline unsigned
|
||||
cell_styles(const cell* c){
|
||||
return c->attrword & NCSTYLE_MASK;
|
||||
}
|
||||
|
||||
// Add the specified styles (in the LSBs) to the cell's existing spec, whether
|
||||
// they're actively supported or not.
|
||||
static inline void
|
||||
cell_styles_on(cell* c, unsigned stylebits){
|
||||
c->attrword |= (stylebits & NCSTYLE_MASK);
|
||||
}
|
||||
|
||||
// Remove the specified styles (in the LSBs) from the cell's existing spec.
|
||||
static inline void
|
||||
cell_styles_off(cell* c, unsigned stylebits){
|
||||
c->attrword &= ~(stylebits & NCSTYLE_MASK);
|
||||
}
|
||||
|
||||
// Use the default color for the foreground.
|
||||
static inline void
|
||||
cell_set_fg_default(cell* c){
|
||||
channels_set_fg_default(&c->channels);
|
||||
}
|
||||
|
||||
// Use the default color for the background.
|
||||
static inline void
|
||||
cell_set_bg_default(cell* c){
|
||||
channels_set_bg_default(&c->channels);
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_set_fg_alpha(cell* c, int alpha){
|
||||
return channels_set_fg_alpha(&c->channels, alpha);
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_set_bg_alpha(cell* c, int alpha){
|
||||
return channels_set_bg_alpha(&c->channels, alpha);
|
||||
}
|
||||
|
||||
// Does the cell contain an East Asian Wide codepoint?
|
||||
static inline bool
|
||||
cell_double_wide_p(const cell* c){
|
||||
return (c->channels & CELL_WIDEASIAN_MASK);
|
||||
}
|
||||
|
||||
// Is this the right half of a wide character?
|
||||
static inline bool
|
||||
cell_wide_right_p(const cell* c){
|
||||
return cell_double_wide_p(c) && c->gcluster == 0;
|
||||
}
|
||||
|
||||
// Is this the left half of a wide character?
|
||||
static inline bool
|
||||
cell_wide_left_p(const cell* c){
|
||||
return cell_double_wide_p(c) && c->gcluster;
|
||||
}
|
||||
|
||||
// Is the cell simple (a lone ASCII character, encoded as such)?
|
||||
static inline bool
|
||||
cell_simple_p(const cell* c){
|
||||
return c->gcluster < 0x80;
|
||||
}
|
||||
|
||||
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer
|
||||
// is invalidated by any further operation on the plane 'n', so...watch out!
|
||||
API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
|
||||
|
||||
// Extract the EGC from 'c' as a nul-terminated string.
|
||||
static inline char*
|
||||
cell_strdup(const struct ncplane* n, const cell* c){
|
||||
char* ret;
|
||||
if(cell_simple_p(c)){
|
||||
if( (ret = (char*)malloc(2)) ){ // cast is here for C++ clients
|
||||
ret[0] = c->gcluster;
|
||||
ret[1] = '\0';
|
||||
}
|
||||
}else{
|
||||
ret = strdup(cell_extended_gcluster(n, c));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Extract the three elements of a cell.
|
||||
static inline char*
|
||||
cell_extract(const struct ncplane* n, const cell* c, uint32_t* attrword, uint64_t* channels){
|
||||
if(attrword){
|
||||
*attrword = c->attrword;
|
||||
}
|
||||
if(channels){
|
||||
*channels = c->channels;
|
||||
}
|
||||
return cell_strdup(n, c);
|
||||
}
|
||||
|
||||
// Returns true if the two cells are distinct EGCs, attributes, or channels.
|
||||
// The actual egcpool index needn't be the same--indeed, the planes needn't even
|
||||
// be the same. Only the expanded EGC must be equal. The EGC must be bit-equal;
|
||||
// it would probably be better to test whether they're Unicode-equal FIXME.
|
||||
static inline bool
|
||||
cellcmp(const struct ncplane* n1, const cell* RESTRICT c1,
|
||||
const struct ncplane* n2, const cell* RESTRICT c2){
|
||||
if(c1->attrword != c2->attrword){
|
||||
return true;
|
||||
}
|
||||
if(c1->channels != c2->channels){
|
||||
return true;
|
||||
}
|
||||
if(cell_simple_p(c1) && cell_simple_p(c2)){
|
||||
return c1->gcluster != c2->gcluster;
|
||||
}
|
||||
if(cell_simple_p(c1) || cell_simple_p(c2)){
|
||||
return true;
|
||||
}
|
||||
return strcmp(cell_extended_gcluster(n1, c1), cell_extended_gcluster(n2, c2));
|
||||
}
|
||||
|
||||
// True if the cell does not generate foreground pixels (i.e., the cell is
|
||||
// entirely whitespace or special characters).
|
||||
// FIXME do this at cell prep time and set a bit in the channels
|
||||
static inline bool
|
||||
cell_noforeground_p(const cell* c){
|
||||
return cell_simple_p(c) && (c->gcluster == ' ' || !isprint(c->gcluster));
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_load_simple(struct ncplane* n, cell* c, char ch){
|
||||
cell_release(n, c);
|
||||
c->channels &= ~CELL_WIDEASIAN_MASK;
|
||||
c->gcluster = ch;
|
||||
if(cell_simple_p(c)){
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the offset into the egcpool for this cell's EGC. returns meaningless and
|
||||
// unsafe results if called on a simple cell.
|
||||
static inline uint32_t
|
||||
cell_egc_idx(const cell* c){
|
||||
return c->gcluster - 0x80;
|
||||
}
|
||||
|
||||
// These log levels consciously map cleanly to those of libav; notcurses itself
|
||||
// does not use this full granularity. The log level does not affect the opening
|
||||
// and closing banners, which can be disabled via the notcurses_option struct's
|
||||
@ -862,8 +1054,8 @@ API int ncplane_set_base_cell(struct ncplane* ncp, const cell* c);
|
||||
// rendering anywhere that the ncplane's gcluster is 0. Erasing the ncplane
|
||||
// does not reset the base cell; this function must be called with an empty
|
||||
// 'egc'. 'egc' must be a single extended grapheme cluster.
|
||||
API int ncplane_set_base(struct ncplane* ncp, uint64_t channels,
|
||||
uint32_t attrword, const char* egc);
|
||||
API int ncplane_set_base(struct ncplane* ncp, const char* egc,
|
||||
uint32_t attrword, uint64_t channels);
|
||||
|
||||
// Extract the ncplane's base cell into 'c'. The reference is invalidated if
|
||||
// 'ncp' is destroyed.
|
||||
@ -914,14 +1106,50 @@ API struct ncplane* ncplane_below(struct ncplane* n);
|
||||
API int ncplane_rotate_cw(struct ncplane* n);
|
||||
API int ncplane_rotate_ccw(struct ncplane* n);
|
||||
|
||||
// Retrieve the cell at the cursor location on the specified plane, returning
|
||||
// it in 'c'. This copy is safe to use until the ncplane is destroyed/erased.
|
||||
API int ncplane_at_cursor(struct ncplane* n, cell* c);
|
||||
// Retrieve the current contents of the cell under the cursor. The EGC is
|
||||
// returned, or NULL on error. This EGC must be free()d by the caller. The
|
||||
// attrword and channels are written to 'attrword' and 'channels', respectively.
|
||||
API char* ncplane_at_cursor(struct ncplane* n, uint32_t* attrword, uint64_t* channels);
|
||||
|
||||
// Retrieve the cell at the specified location on the specified plane, returning
|
||||
// it in 'c'. This copy is safe to use until the ncplane is destroyed/erased.
|
||||
// Returns the length of the EGC in bytes.
|
||||
API int ncplane_at_yx(struct ncplane* n, int y, int x, cell* c);
|
||||
// Retrieve the current contents of the cell under the cursor into 'c'. This
|
||||
// cell is invalidated if the associated plane is destroyed.
|
||||
static inline int
|
||||
ncplane_at_cursor_cell(struct ncplane* n, cell* c){
|
||||
char* egc = ncplane_at_cursor(n, &c->attrword, &c->channels);
|
||||
if(!egc){
|
||||
return -1;
|
||||
}
|
||||
uint64_t channels = c->channels; // need to preserve wide flag
|
||||
int r = cell_load(n, c, egc);
|
||||
c->channels = channels;
|
||||
if(r < 0){
|
||||
free(egc);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Retrieve the current contents of the specified cell. The EGC is returned, or
|
||||
// NULL on error. This EGC must be free()d by the caller. The attrword and
|
||||
// channels are written to 'attrword' and 'channels', respectively.
|
||||
API char* ncplane_at_yx(struct ncplane* n, int y, int x,
|
||||
uint32_t* attrword, uint64_t* channels);
|
||||
|
||||
// Retrieve the current contents of the specified cell into 'c'. This cell is
|
||||
// invalidated if the associated plane is destroyed.
|
||||
static inline int
|
||||
ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c){
|
||||
char* egc = ncplane_at_yx(n, y, x, &c->attrword, &c->channels);
|
||||
if(!egc){
|
||||
return -1;
|
||||
}
|
||||
uint64_t channels = c->channels; // need to preserve wide flag
|
||||
int r = cell_load(n, c, egc);
|
||||
c->channels = channels;
|
||||
if(r < 0){
|
||||
free(egc);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
// Manipulate the opaque user pointer associated with this plane.
|
||||
// ncplane_set_userptr() returns the previous userptr after replacing
|
||||
@ -958,174 +1186,6 @@ API void ncplane_cursor_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRI
|
||||
API uint64_t ncplane_channels(const struct ncplane* n);
|
||||
API uint32_t ncplane_attr(const struct ncplane* n);
|
||||
|
||||
// Working with cells
|
||||
|
||||
#define CELL_TRIVIAL_INITIALIZER { .gcluster = '\0', .attrword = 0, .channels = 0, }
|
||||
#define CELL_SIMPLE_INITIALIZER(c) { .gcluster = (c), .attrword = 0, .channels = 0, }
|
||||
#define CELL_INITIALIZER(c, a, chan) { .gcluster = (c), .attrword = (a), .channels = (chan), }
|
||||
|
||||
static inline void
|
||||
cell_init(cell* c){
|
||||
memset(c, 0, sizeof(*c));
|
||||
}
|
||||
|
||||
// Breaks the UTF-8 string in 'gcluster' down, setting up the cell 'c'. Returns
|
||||
// the number of bytes copied out of 'gcluster', or -1 on failure. The styling
|
||||
// of the cell is left untouched, but any resources are released.
|
||||
API int cell_load(struct ncplane* n, cell* c, const char* gcluster);
|
||||
|
||||
// cell_load(), plus blast the styling with 'attr' and 'channels'.
|
||||
static inline int
|
||||
cell_prime(struct ncplane* n, cell* c, const char* gcluster,
|
||||
uint32_t attr, uint64_t channels){
|
||||
c->attrword = attr;
|
||||
c->channels = channels;
|
||||
int ret = cell_load(n, c, gcluster);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Duplicate 'c' into 'targ'. Not intended for external use; exposed for the
|
||||
// benefit of unit tests.
|
||||
API int cell_duplicate(struct ncplane* n, cell* targ, const cell* c);
|
||||
|
||||
// Release resources held by the cell 'c'.
|
||||
API void cell_release(struct ncplane* n, cell* c);
|
||||
|
||||
#define NCSTYLE_MASK 0xffff0000ul
|
||||
#define NCSTYLE_STANDOUT 0x00800000ul
|
||||
#define NCSTYLE_UNDERLINE 0x00400000ul
|
||||
#define NCSTYLE_REVERSE 0x00200000ul
|
||||
#define NCSTYLE_BLINK 0x00100000ul
|
||||
#define NCSTYLE_DIM 0x00080000ul
|
||||
#define NCSTYLE_BOLD 0x00040000ul
|
||||
#define NCSTYLE_INVIS 0x00020000ul
|
||||
#define NCSTYLE_PROTECT 0x00010000ul
|
||||
#define NCSTYLE_ITALIC 0x01000000ul
|
||||
|
||||
// Set the specified style bits for the cell 'c', whether they're actively
|
||||
// supported or not.
|
||||
static inline void
|
||||
cell_styles_set(cell* c, unsigned stylebits){
|
||||
c->attrword = (c->attrword & ~NCSTYLE_MASK) | ((stylebits & NCSTYLE_MASK));
|
||||
}
|
||||
|
||||
// Extract the style bits from the cell's attrword.
|
||||
static inline unsigned
|
||||
cell_styles(const cell* c){
|
||||
return c->attrword & NCSTYLE_MASK;
|
||||
}
|
||||
|
||||
// Add the specified styles (in the LSBs) to the cell's existing spec, whether
|
||||
// they're actively supported or not.
|
||||
static inline void
|
||||
cell_styles_on(cell* c, unsigned stylebits){
|
||||
c->attrword |= (stylebits & NCSTYLE_MASK);
|
||||
}
|
||||
|
||||
// Remove the specified styles (in the LSBs) from the cell's existing spec.
|
||||
static inline void
|
||||
cell_styles_off(cell* c, unsigned stylebits){
|
||||
c->attrword &= ~(stylebits & NCSTYLE_MASK);
|
||||
}
|
||||
|
||||
// Use the default color for the foreground.
|
||||
static inline void
|
||||
cell_set_fg_default(cell* c){
|
||||
channels_set_fg_default(&c->channels);
|
||||
}
|
||||
|
||||
// Use the default color for the background.
|
||||
static inline void
|
||||
cell_set_bg_default(cell* c){
|
||||
channels_set_bg_default(&c->channels);
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_set_fg_alpha(cell* c, int alpha){
|
||||
return channels_set_fg_alpha(&c->channels, alpha);
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_set_bg_alpha(cell* c, int alpha){
|
||||
return channels_set_bg_alpha(&c->channels, alpha);
|
||||
}
|
||||
|
||||
// Does the cell contain an East Asian Wide codepoint?
|
||||
static inline bool
|
||||
cell_double_wide_p(const cell* c){
|
||||
return (c->channels & CELL_WIDEASIAN_MASK);
|
||||
}
|
||||
|
||||
// Is this the right half of a wide character?
|
||||
static inline bool
|
||||
cell_wide_right_p(const cell* c){
|
||||
return cell_double_wide_p(c) && c->gcluster == 0;
|
||||
}
|
||||
|
||||
// Is this the left half of a wide character?
|
||||
static inline bool
|
||||
cell_wide_left_p(const cell* c){
|
||||
return cell_double_wide_p(c) && c->gcluster;
|
||||
}
|
||||
|
||||
// Is the cell simple (a lone ASCII character, encoded as such)?
|
||||
static inline bool
|
||||
cell_simple_p(const cell* c){
|
||||
return c->gcluster < 0x80;
|
||||
}
|
||||
|
||||
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer
|
||||
// is invalidated by any further operation on the plane 'n', so...watch out!
|
||||
API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
|
||||
|
||||
// Returns true if the two cells are distinct EGCs, attributes, or channels.
|
||||
// The actual egcpool index needn't be the same--indeed, the planes needn't even
|
||||
// be the same. Only the expanded EGC must be equal. The EGC must be bit-equal;
|
||||
// it would probably be better to test whether they're Unicode-equal FIXME.
|
||||
static inline bool
|
||||
cellcmp(const struct ncplane* n1, const cell* RESTRICT c1,
|
||||
const struct ncplane* n2, const cell* RESTRICT c2){
|
||||
if(c1->attrword != c2->attrword){
|
||||
return true;
|
||||
}
|
||||
if(c1->channels != c2->channels){
|
||||
return true;
|
||||
}
|
||||
if(cell_simple_p(c1) && cell_simple_p(c2)){
|
||||
return c1->gcluster != c2->gcluster;
|
||||
}
|
||||
if(cell_simple_p(c1) || cell_simple_p(c2)){
|
||||
return true;
|
||||
}
|
||||
return strcmp(cell_extended_gcluster(n1, c1), cell_extended_gcluster(n2, c2));
|
||||
}
|
||||
|
||||
// True if the cell does not generate foreground pixels (i.e., the cell is
|
||||
// entirely whitespace or special characters).
|
||||
// FIXME do this at cell prep time and set a bit in the channels
|
||||
static inline bool
|
||||
cell_noforeground_p(const cell* c){
|
||||
return cell_simple_p(c) && (c->gcluster == ' ' || !isprint(c->gcluster));
|
||||
}
|
||||
|
||||
static inline int
|
||||
cell_load_simple(struct ncplane* n, cell* c, char ch){
|
||||
cell_release(n, c);
|
||||
c->channels &= ~CELL_WIDEASIAN_MASK;
|
||||
c->gcluster = ch;
|
||||
if(cell_simple_p(c)){
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get the offset into the egcpool for this cell's EGC. returns meaningless and
|
||||
// unsafe results if called on a simple cell.
|
||||
static inline uint32_t
|
||||
cell_egc_idx(const cell* c){
|
||||
return c->gcluster - 0x80;
|
||||
}
|
||||
|
||||
// Replace the cell at the specified coordinates with the provided cell 'c',
|
||||
// and advance the cursor by the width of the cell (but not past the end of the
|
||||
// plane). On success, returns the number of columns the cursor was advanced.
|
||||
|
@ -93,7 +93,7 @@ typedef struct ncinput {
|
||||
uint64_t seqnum;
|
||||
} ncinput;
|
||||
int ncplane_set_base_cell(struct ncplane* ncp, const cell* c);
|
||||
int ncplane_set_base(struct ncplane* ncp, uint64_t channels, uint32_t attrword, const char* egc);
|
||||
int ncplane_set_base(struct ncplane* ncp, const char* egc, uint32_t attrword, uint64_t channels);
|
||||
int ncplane_base(struct ncplane* ncp, cell* c);
|
||||
struct ncplane* notcurses_top(struct notcurses* n);
|
||||
void notcurses_drop_planes(struct notcurses* nc);
|
||||
@ -128,8 +128,10 @@ int ncplane_move_below(struct ncplane* n, struct ncplane* below);
|
||||
int ncplane_move_above(struct ncplane* n, struct ncplane* above);
|
||||
struct ncplane* ncplane_below(struct ncplane* n);
|
||||
char* notcurses_at_yx(struct notcurses* nc, int yoff, int xoff, uint32_t* attrword, uint64_t* channels);
|
||||
int ncplane_at_cursor(struct ncplane* n, cell* c);
|
||||
int ncplane_at_yx(struct ncplane* n, int y, int x, cell* c);
|
||||
char* ncplane_at_cursor(struct ncplane* n, uint32_t* attrword, uint64_t* channels);
|
||||
int ncplane_at_cursor_cell(struct ncplane* n, cell* c);
|
||||
char* ncplane_at_yx(struct ncplane* n, int y, int x, uint32_t* attrword, uint64_t* channels);
|
||||
int ncplane_at_yx_cell(struct ncplane* n, int y, int x, cell* c);
|
||||
void* ncplane_set_userptr(struct ncplane* n, void* opaque);
|
||||
void* ncplane_userptr(struct ncplane* n);
|
||||
int ncplane_resize(struct ncplane* n, int keepy, int keepx, int keepleny,
|
||||
|
@ -5,30 +5,24 @@
|
||||
static int
|
||||
reload_corners(struct ncplane* n, cell* ul, cell* ur, cell* ll, cell* lr){
|
||||
int dimy, dimx;
|
||||
|
||||
ncplane_dim_yx(n, &dimy, &dimx);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(n, 1, dimx - 1, &c) < 0){
|
||||
cell_release(n, &c);
|
||||
char* egc;
|
||||
if( (egc = ncplane_at_yx(n, 1, dimx - 1, NULL, &ul->channels)) == NULL){
|
||||
return -1;
|
||||
}
|
||||
ul->channels = c.channels;
|
||||
if(ncplane_at_yx(n, dimy - 1, dimx - 1, &c) < 0){
|
||||
cell_release(n, &c);
|
||||
free(egc);
|
||||
if( (egc = ncplane_at_yx(n, dimy - 1, dimx - 1, NULL, &ur->channels)) == NULL){
|
||||
return -1;
|
||||
}
|
||||
ur->channels = c.channels;
|
||||
if(ncplane_at_yx(n, dimy - 1, 0, &c) < 0){
|
||||
cell_release(n, &c);
|
||||
free(egc);
|
||||
if( (egc = ncplane_at_yx(n, dimy - 1, 0, NULL, &lr->channels)) == NULL){
|
||||
return -1;
|
||||
}
|
||||
lr->channels = c.channels;
|
||||
if(ncplane_at_yx(n, 1, 0, &c) < 0){
|
||||
cell_release(n, &c);
|
||||
free(egc);
|
||||
if( (egc = ncplane_at_yx(n, 1, 0, NULL, &ll->channels)) == NULL){
|
||||
return -1;
|
||||
}
|
||||
ll->channels = c.channels;
|
||||
cell_release(n, &c);
|
||||
free(egc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ int fallin_demo(struct notcurses* nc){
|
||||
continue;
|
||||
}
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(stdn, usey, usex, &c) < 0){
|
||||
if(ncplane_at_yx_cell(stdn, usey, usex, &c) < 0){
|
||||
return -1;
|
||||
}
|
||||
if(!cell_simple_p(&c)){
|
||||
|
@ -58,7 +58,7 @@ hud_standard_bg(struct ncplane* n){
|
||||
channels_set_fg_rgb(&channels, 0x0, 0x0, 0x0);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_BLEND);
|
||||
channels_set_bg_rgb(&channels, 0x0, 0x0, 0x0);
|
||||
if(ncplane_set_base(n, channels, 0, "") >= 0){
|
||||
if(ncplane_set_base(n, "", 0, channels) >= 0){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -103,7 +103,7 @@ about_toggle(struct notcurses* nc){
|
||||
channels_set_fg_rgb(&channels, 0x0, 0x0, 0x0);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_BLEND);
|
||||
channels_set_bg_rgb(&channels, 0x0, 0x0, 0x0);
|
||||
if(ncplane_set_base(n, channels, 0, "") >= 0){
|
||||
if(ncplane_set_base(n, "", 0, channels) >= 0){
|
||||
ncplane_set_fg(n, 0xc0f0c0);
|
||||
ncplane_set_bg(n, 0);
|
||||
ncplane_set_bg_alpha(n, CELL_ALPHA_BLEND);
|
||||
|
@ -114,7 +114,7 @@ draw_luigi(struct ncplane* n, const char* sprite){
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(n, channels, 0, "");
|
||||
ncplane_set_base(n, "", 0, channels);
|
||||
size_t s;
|
||||
int sbytes;
|
||||
// optimization so we can elide more color changes, see README's "#perf"
|
||||
@ -202,7 +202,7 @@ int luigi_demo(struct notcurses* nc){
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(ncvisual_plane(wmncv), channels, 0, "");
|
||||
ncplane_set_base(ncvisual_plane(wmncv), "", 0, channels);
|
||||
if(ncvisual_render(wmncv, 0, 0, -1, -1) <= 0){
|
||||
ncvisual_destroy(wmncv);
|
||||
return -1;
|
||||
|
@ -72,7 +72,7 @@ outro_message(struct notcurses* nc, int* rows, int* cols){
|
||||
ncplane_yx(non, NULL, &xs);
|
||||
uint64_t channels = 0;
|
||||
channels_set_bg_rgb(&channels, 0x58, 0x36, 0x58);
|
||||
if(ncplane_set_base(non, channels, 0, " ") < 0){
|
||||
if(ncplane_set_base(non, " ", 0, channels) < 0){
|
||||
return NULL;
|
||||
}
|
||||
ncplane_dim_yx(non, rows, cols);
|
||||
|
@ -188,7 +188,7 @@ int unicodeblocks_demo(struct notcurses* nc){
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_BLEND);
|
||||
channels_set_fg(&channels, 0x004000);
|
||||
channels_set_bg(&channels, 0x0);
|
||||
ncplane_set_base(header, channels, 0, "");
|
||||
ncplane_set_base(header, "", 0, channels);
|
||||
for(sindex = 0 ; sindex < sizeof(blocks) / sizeof(*blocks) ; ++sindex){
|
||||
ncplane_set_bg_rgb(n, 0, 0, 0);
|
||||
uint32_t blockstart = blocks[sindex].start;
|
||||
|
@ -38,7 +38,7 @@ legend(struct notcurses* nc, int dimy, int dimx){
|
||||
ncplane_set_bg_alpha(n, CELL_ALPHA_TRANSPARENT);
|
||||
uint64_t channels = 0;
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(n, channels, 0, " ");
|
||||
ncplane_set_base(n, " ", 0, channels);
|
||||
ncplane_styles_set(n, NCSTYLE_BOLD);
|
||||
ncplane_set_fg_rgb(n, 0xff, 0xff, 0xff);
|
||||
ncplane_set_fg_alpha(n, CELL_ALPHA_HIGHCONTRAST);
|
||||
@ -122,7 +122,7 @@ int view_demo(struct notcurses* nc){
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(ncvisual_plane(ncv2), channels, 0, "");
|
||||
ncplane_set_base(ncvisual_plane(ncv2), "", 0, channels);
|
||||
demo_render(nc);
|
||||
demo_nanosleep(nc, &demodelay);
|
||||
ncvisual_destroy(ncv);
|
||||
|
@ -27,7 +27,7 @@ mathplane(struct notcurses* nc){
|
||||
channels_set_fg(&channels, 0x2b50c8); // metallic gold, inverted
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_BLEND);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(n, channels, 0, "");
|
||||
ncplane_set_base(n, "", 0, channels);
|
||||
ncplane_set_fg(n, 0xd4af37); // metallic gold
|
||||
ncplane_set_bg(n, 0x0);
|
||||
if(n){
|
||||
@ -61,7 +61,7 @@ lighten(struct ncplane* n, cell* c, int distance, int y, int x){
|
||||
|
||||
static void
|
||||
surrounding_cells(struct ncplane* n, cell* lightup, int y, int x){
|
||||
ncplane_at_yx(n, y, x, lightup);
|
||||
ncplane_at_yx_cell(n, y, x, lightup);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -171,7 +171,7 @@ message(struct ncplane* n, int maxy, int maxx, int num, int total,
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(n, channels, 0, "");
|
||||
ncplane_set_base(n, "", 0, channels);
|
||||
ncplane_set_fg_rgb(n, 255, 255, 255);
|
||||
ncplane_set_bg_rgb(n, 32, 64, 32);
|
||||
channels = 0;
|
||||
|
@ -44,7 +44,7 @@ perframecb(struct notcurses* nc, struct ncvisual* ncv __attribute__ ((unused)),
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(n, channels, 0, " ");
|
||||
ncplane_set_base(n, " ", 0, channels);
|
||||
ncplane_set_bg_alpha(n, CELL_ALPHA_BLEND);
|
||||
ncplane_set_scrolling(n, true);
|
||||
}
|
||||
|
@ -455,10 +455,10 @@ static int
|
||||
rotate_2x1_cw(ncplane* src, ncplane* dst, int srcy, int srcx, int dsty, int dstx){
|
||||
cell c1 = CELL_TRIVIAL_INITIALIZER;
|
||||
cell c2 = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(src, srcy, srcx, &c1) < 0){
|
||||
if(ncplane_at_yx_cell(src, srcy, srcx, &c1) < 0){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_at_yx(src, srcy, srcx + 1, &c2) < 0){
|
||||
if(ncplane_at_yx_cell(src, srcy, srcx + 1, &c2) < 0){
|
||||
cell_release(src, &c1);
|
||||
return -1;
|
||||
}
|
||||
@ -494,10 +494,10 @@ rotate_2x1_cw(ncplane* src, ncplane* dst, int srcy, int srcx, int dsty, int dstx
|
||||
int rotate_2x1_ccw(ncplane* src, ncplane* dst, int srcy, int srcx, int dsty, int dstx){
|
||||
cell c1 = CELL_TRIVIAL_INITIALIZER;
|
||||
cell c2 = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(src, srcy, srcx, &c1) < 0){
|
||||
if(ncplane_at_yx_cell(src, srcy, srcx, &c1) < 0){
|
||||
return -1;
|
||||
}
|
||||
if(ncplane_at_yx(src, srcy, srcx + 1, &c2) < 0){
|
||||
if(ncplane_at_yx_cell(src, srcy, srcx + 1, &c2) < 0){
|
||||
cell_release(src, &c1);
|
||||
return -1;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ write_header(ncmenu* ncm){ ncm->ncp->channels = ncm->headerchannels;
|
||||
}
|
||||
if(ncm->sections[i].shortcut_offset >= 0){
|
||||
cell cl = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(ncm->ncp, ypos, xoff + ncm->sections[i].shortcut_offset, &cl) < 0){
|
||||
if(ncplane_at_yx_cell(ncm->ncp, ypos, xoff + ncm->sections[i].shortcut_offset, &cl) < 0){
|
||||
return -1;
|
||||
}
|
||||
cell_styles_on(&cl, NCSTYLE_UNDERLINE|NCSTYLE_BOLD);
|
||||
@ -396,7 +396,7 @@ int ncmenu_unroll(ncmenu* n, int sectionidx){
|
||||
}
|
||||
if(sec->items[i].shortcut_offset >= 0){
|
||||
cell cl = CELL_TRIVIAL_INITIALIZER;
|
||||
if(ncplane_at_yx(n->ncp, ypos, xpos + 1 + sec->items[i].shortcut_offset, &cl) < 0){
|
||||
if(ncplane_at_yx_cell(n->ncp, ypos, xpos + 1 + sec->items[i].shortcut_offset, &cl) < 0){
|
||||
return -1;
|
||||
}
|
||||
cell_styles_on(&cl, NCSTYLE_UNDERLINE|NCSTYLE_BOLD);
|
||||
|
@ -184,18 +184,18 @@ cursor_invalid_p(const ncplane* n){
|
||||
return false;
|
||||
}
|
||||
|
||||
int ncplane_at_cursor(ncplane* n, cell* c){
|
||||
char* ncplane_at_cursor(ncplane* n, uint32_t* attrword, uint64_t* channels){
|
||||
if(cursor_invalid_p(n)){
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
return cell_duplicate(n, c, &n->fb[nfbcellidx(n, n->y, n->x)]);
|
||||
return cell_extract(n, &n->fb[nfbcellidx(n, n->y, n->x)], attrword, channels);
|
||||
}
|
||||
|
||||
int ncplane_at_yx(ncplane* n, int y, int x, cell* c){
|
||||
int ret = -1;
|
||||
char* ncplane_at_yx(ncplane* n, int y, int x, uint32_t* attrword, uint64_t* channels){
|
||||
char* ret = NULL;
|
||||
if(y < n->leny && x < n->lenx){
|
||||
if(y >= 0 && x >= 0){
|
||||
ret = cell_duplicate(n, c, &n->fb[nfbcellidx(n, y, x)]);
|
||||
ret = cell_extract(n, &n->fb[nfbcellidx(n, y, x)], attrword, channels);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -1123,7 +1123,7 @@ int ncplane_set_base_cell(ncplane* ncp, const cell* c){
|
||||
return cell_duplicate(ncp, &ncp->basecell, c);
|
||||
}
|
||||
|
||||
int ncplane_set_base(ncplane* ncp, uint64_t channels, uint32_t attrword, const char* egc){
|
||||
int ncplane_set_base(ncplane* ncp, const char* egc, uint32_t attrword, uint64_t channels){
|
||||
return cell_prime(ncp, &ncp->basecell, egc, attrword, channels);
|
||||
}
|
||||
|
||||
|
@ -616,7 +616,7 @@ ncreel* ncreel_create(ncplane* w, const ncreel_options* ropts, int efd){
|
||||
free(nr);
|
||||
return NULL;
|
||||
}
|
||||
ncplane_set_base(nr->p, ropts->bgchannel, 0, "");
|
||||
ncplane_set_base(nr->p, "", 0, ropts->bgchannel);
|
||||
if(ncreel_redraw(nr)){
|
||||
ncplane_destroy(nr->p);
|
||||
free(nr);
|
||||
|
@ -220,7 +220,7 @@ ncselector* ncselector_create(ncplane* n, int y, int x, const selector_options*
|
||||
uint64_t transchan = 0;
|
||||
channels_set_fg_alpha(&transchan, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&transchan, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(ns->ncp, transchan, 0, "");
|
||||
ncplane_set_base(ns->ncp, "", 0, transchan);
|
||||
if(cell_prime(ns->ncp, &ns->background, " ", 0, opts->bgchannels) < 0){
|
||||
ncplane_destroy(ns->ncp);
|
||||
goto freeitems;
|
||||
@ -707,7 +707,7 @@ ncmultiselector* ncmultiselector_create(ncplane* n, int y, int x, const multisel
|
||||
uint64_t transchan = 0;
|
||||
channels_set_fg_alpha(&transchan, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&transchan, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(ns->ncp, transchan, 0, "");
|
||||
ncplane_set_base(ns->ncp, "", 0, transchan);
|
||||
if(cell_prime(ns->ncp, &ns->background, " ", 0, opts->bgchannels) < 0){
|
||||
ncplane_destroy(ns->ncp);
|
||||
goto freeitems;
|
||||
|
@ -15,7 +15,7 @@ run_menu(struct notcurses* nc, struct ncmenu* ncm){
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg(&channels, 0x000088);
|
||||
channels_set_bg(&channels, 0x88aa00);
|
||||
if(ncplane_set_base(selplane, channels, 0, " ") < 0){
|
||||
if(ncplane_set_base(selplane, " ", 0, channels) < 0){
|
||||
goto err;
|
||||
}
|
||||
char32_t keypress;
|
||||
@ -119,7 +119,7 @@ int main(void){
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg(&channels, 0x88aa00);
|
||||
channels_set_bg(&channels, 0x000088);
|
||||
if(ncplane_set_base(n, channels, 0, "x") < 0){
|
||||
if(ncplane_set_base(n, "x", 0, channels) < 0){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ int main(void){
|
||||
char c = 'A';
|
||||
ncplane_set_scrolling(n, true);
|
||||
while(true){
|
||||
struct timespec req = { .tv_sec = 0, .tv_nsec = 10000000, };
|
||||
struct timespec req = { .tv_sec = 0, .tv_nsec = 1000000, };
|
||||
nanosleep(&req, NULL);
|
||||
if(ncplane_putsimple(n, c) != 1){
|
||||
break;
|
||||
|
@ -23,9 +23,6 @@ int main(int argc, char** argv){
|
||||
if(n->load(c, "🐳") < 0){
|
||||
goto err;
|
||||
}
|
||||
if(dimy > 5){
|
||||
dimy = 5;
|
||||
}
|
||||
for(int i = 0 ; i < dimy ; ++i){
|
||||
for(int j = 8 ; j < dimx / 2 ; ++j){ // leave some empty spaces
|
||||
if(n->putc(i, j * 2, &c) < 0){
|
||||
@ -57,7 +54,6 @@ int main(int argc, char** argv){
|
||||
if(!nc.render()){
|
||||
goto err;
|
||||
}
|
||||
printf("\n");
|
||||
return !nc.stop() ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
|
||||
err:
|
||||
|
@ -36,7 +36,7 @@ void DrawBoard() { // draw all fixed components of the game
|
||||
throw TetrisNotcursesErr("double_box()");
|
||||
}
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
board_->set_base(channels, 0, "");
|
||||
board_->set_base("", 0, channels);
|
||||
scoreplane_ = std::make_unique<ncpp::Plane>(2, 30, y - BOARD_HEIGHT, 2, nullptr);
|
||||
if(!scoreplane_){
|
||||
throw TetrisNotcursesErr("Plane()");
|
||||
@ -44,7 +44,7 @@ void DrawBoard() { // draw all fixed components of the game
|
||||
uint64_t scorechan = 0;
|
||||
channels_set_bg_alpha(&scorechan, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_fg_alpha(&scorechan, CELL_ALPHA_TRANSPARENT);
|
||||
if(!scoreplane_->set_base(scorechan, 0, "")){
|
||||
if(!scoreplane_->set_base("", 0, scorechan)){
|
||||
throw TetrisNotcursesErr("set_base()");
|
||||
}
|
||||
scoreplane_->set_bg_alpha(CELL_ALPHA_TRANSPARENT);
|
||||
|
@ -23,7 +23,7 @@ std::unique_ptr<ncpp::Plane> NewPiece() {
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
n->set_fg(t->color);
|
||||
n->set_bg_alpha(CELL_ALPHA_TRANSPARENT);
|
||||
n->set_base(channels, 0, "");
|
||||
n->set_base("", 0, channels);
|
||||
y = 0; x = 0;
|
||||
for(size_t i = 0 ; i < strlen(t->texture) ; ++i){
|
||||
if(t->texture[i] == '*'){
|
||||
|
@ -23,7 +23,7 @@ static void usage(std::ostream& os, const char* name, int exitcode)
|
||||
__attribute__ ((noreturn));
|
||||
|
||||
void usage(std::ostream& o, const char* name, int exitcode){
|
||||
o << "usage: " << name << " [ -h ] [ -l loglevel ] [ -d mult ] [ -s scaletype ] files" << '\n';
|
||||
o << "usage: " << name << " [ -h ] [ -l loglevel ] [ -d mult ] [ -s scaling ] files" << '\n';
|
||||
o << " -l loglevel: integer between 0 and 9, goes to stderr'\n";
|
||||
o << " -s scaletype: one of 'none', 'scale', or 'stretch'\n";
|
||||
o << " -d mult: non-negative floating point scale for frame time" << std::endl;
|
||||
@ -67,7 +67,7 @@ int perframe([[maybe_unused]] struct notcurses* _nc, struct ncvisual* ncv, void*
|
||||
uint64_t channels = 0;
|
||||
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
|
||||
ncplane_set_base(subtitle_plane, channels, 0, "");
|
||||
ncplane_set_base(subtitle_plane, "", 0, channels);
|
||||
ncplane_set_fg(subtitle_plane, 0x00ffff);
|
||||
ncplane_set_fg_alpha(subtitle_plane, CELL_ALPHA_HIGHCONTRAST);
|
||||
ncplane_set_bg_alpha(subtitle_plane, CELL_ALPHA_TRANSPARENT);
|
||||
|
@ -95,7 +95,7 @@ TEST_CASE("Fills") {
|
||||
// check all squares
|
||||
for(int y = 0 ; y < dimy ; ++y){
|
||||
for(int x = 0 ; x < dimx ; ++x){
|
||||
REQUIRE(0 <= ncplane_at_yx(n_, y, x, &cl));
|
||||
REQUIRE(0 <= ncplane_at_yx_cell(n_, y, x, &cl));
|
||||
CHECK('M' == cl.gcluster);
|
||||
CHECK(0 == cl.attrword);
|
||||
CHECK(channels == cl.channels);
|
||||
@ -129,7 +129,7 @@ TEST_CASE("Fills") {
|
||||
for(int y = 0 ; y < dimy ; ++y){
|
||||
lastxrgb = -1;
|
||||
for(int x = 0 ; x < dimx ; ++x){
|
||||
REQUIRE(0 <= ncplane_at_yx(n_, y, x, &c));
|
||||
REQUIRE(0 <= ncplane_at_yx_cell(n_, y, x, &c));
|
||||
CHECK('V' == c.gcluster);
|
||||
CHECK(0 == c.attrword);
|
||||
if(lastxrgb == (uint64_t)-1){
|
||||
@ -222,7 +222,7 @@ TEST_CASE("Fills") {
|
||||
cell_styles_on(&c, NCSTYLE_BOLD);
|
||||
CHECK(0 < ncplane_format(n_, 0, 0, c.attrword));
|
||||
cell d = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 0, &d));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 0, &d));
|
||||
CHECK(d.attrword == c.attrword);
|
||||
CHECK(0x444444 == cell_fg(&d));
|
||||
}
|
||||
@ -246,7 +246,7 @@ TEST_CASE("Fills") {
|
||||
cell d = CELL_TRIVIAL_INITIALIZER;
|
||||
for(int y = 0 ; y < 8 ; ++y){
|
||||
for(int x = 0 ; x < 8 ; ++x){
|
||||
CHECK(1 == ncplane_at_yx(n_, y, x, &d));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, y, x, &d));
|
||||
CHECK(channels == d.channels);
|
||||
REQUIRE(cell_simple_p(&d));
|
||||
CHECK('A' == d.gcluster);
|
||||
@ -267,7 +267,7 @@ TEST_CASE("Fills") {
|
||||
REQUIRE(0 < ncplane_gradient(n_, "A", 0, channels, channels, channels, channels, 0, 0));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell d = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 0, &d));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 0, &d));
|
||||
CHECK(channels == d.channels);
|
||||
REQUIRE(cell_simple_p(&d));
|
||||
CHECK('A' == d.gcluster);
|
||||
@ -288,13 +288,13 @@ TEST_CASE("Fills") {
|
||||
REQUIRE(0 < ncplane_gradient(n_, "A", 0, chan1, chan2, chan1, chan2, 0, 3));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell d = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 0, &d));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 0, &d));
|
||||
CHECK(chan1 == d.channels);
|
||||
REQUIRE(cell_simple_p(&d));
|
||||
CHECK('A' == d.gcluster);
|
||||
CHECK(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(0 < ncplane_gradient(n_, "A", 0, chan2, chan1, chan2, chan1, 0, 3));
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 0, &d));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 0, &d));
|
||||
REQUIRE(cell_simple_p(&d));
|
||||
CHECK('A' == d.gcluster);
|
||||
CHECK(chan2 == d.channels);
|
||||
@ -337,8 +337,8 @@ TEST_CASE("Fills") {
|
||||
cell cbase = CELL_TRIVIAL_INITIALIZER;
|
||||
cell cp = CELL_TRIVIAL_INITIALIZER;
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p1, 0, i, &cp));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p1, 0, i, &cp));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p1, &cp));
|
||||
}
|
||||
CHECK(0 == ncplane_cursor_move_yx(p1, 0, 0));
|
||||
@ -346,8 +346,8 @@ TEST_CASE("Fills") {
|
||||
CHECK(0 < ncplane_putstr(p1, "9876543210"));
|
||||
CHECK(0 == ncplane_mergedown(p1, n_));
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p1, 0, i, &cp));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p1, 0, i, &cp));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p1, &cp));
|
||||
}
|
||||
// make sure nulls do not replace glyphs
|
||||
@ -355,8 +355,8 @@ TEST_CASE("Fills") {
|
||||
CHECK(0 == ncplane_mergedown(p2, n_));
|
||||
ncplane_destroy(p2);
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p1, 0, i, &cp));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p1, 0, i, &cp));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p1, &cp));
|
||||
}
|
||||
ncplane_destroy(p1);
|
||||
@ -371,8 +371,8 @@ TEST_CASE("Fills") {
|
||||
cell cbase = CELL_TRIVIAL_INITIALIZER;
|
||||
cell cp = CELL_TRIVIAL_INITIALIZER;
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p1, 0, i, &cp));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p1, 0, i, &cp));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p1, &cp));
|
||||
}
|
||||
ncplane_destroy(p1);
|
||||
@ -384,8 +384,8 @@ TEST_CASE("Fills") {
|
||||
CHECK(0 == ncplane_mergedown(p3, NULL));
|
||||
cell c3 = CELL_TRIVIAL_INITIALIZER;
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p3, 0, i, &c3));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p3, 0, i, &c3));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p3, &c3));
|
||||
}
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
@ -394,8 +394,8 @@ TEST_CASE("Fills") {
|
||||
CHECK(0 == ncplane_mergedown(p2, NULL));
|
||||
ncplane_destroy(p2);
|
||||
for(int i = 0 ; i < 10 ; ++i){
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx(p3, 0, i, &c3));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, i, &cbase));
|
||||
CHECK(0 < ncplane_at_yx_cell(p3, 0, i, &c3));
|
||||
CHECK(0 == cellcmp(n_, &cbase, p3, &c3));
|
||||
}
|
||||
ncplane_destroy(p3);
|
||||
@ -426,11 +426,11 @@ TEST_CASE("Fills") {
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
for(int y = 0 ; y < DIMY ; ++y){
|
||||
for(int x = 0 ; x < DIMX ; ++x){
|
||||
CHECK(0 < ncplane_at_yx(p1, y, x, &c1));
|
||||
CHECK(0 < ncplane_at_yx_cell(p1, y, x, &c1));
|
||||
if(y < 1 || y > 5 || x < 1 || x > 5){
|
||||
CHECK(0 == strcmp(extended_gcluster(p1, &c1), "█"));
|
||||
}else{
|
||||
CHECK(0 < ncplane_at_yx(p2, y - 1, x - 1, &c2));
|
||||
CHECK(0 < ncplane_at_yx_cell(p2, y - 1, x - 1, &c2));
|
||||
CHECK(0 == cellcmp(p1, &c1, p2, &c2));
|
||||
}
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ TEST_CASE("NCPlane") {
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(0 < ncplane_putstr(n_, STR1));
|
||||
cell testcell = CELL_TRIVIAL_INITIALIZER;
|
||||
REQUIRE(0 == ncplane_at_cursor(n_, &testcell)); // want nothing at the cursor
|
||||
REQUIRE(0 == ncplane_at_cursor_cell(n_, &testcell)); // want nothing at the cursor
|
||||
CHECK(0 == testcell.gcluster);
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
@ -518,12 +518,12 @@ TEST_CASE("NCPlane") {
|
||||
REQUIRE(dimx == x);
|
||||
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want first char of STR1
|
||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
||||
CHECK(STR1[0] == testcell.gcluster);
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - 1));
|
||||
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want last char of STR2
|
||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want last char of STR2
|
||||
CHECK(STR2[strlen(STR2) - 1] == testcell.gcluster);
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
@ -540,7 +540,7 @@ TEST_CASE("NCPlane") {
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(0 < ncplane_putstr(n_, STR1));
|
||||
cell testcell = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_cursor(n_, &testcell); // should be nothing at the cursor
|
||||
ncplane_at_cursor_cell(n_, &testcell); // should be nothing at the cursor
|
||||
CHECK(0 == testcell.gcluster);
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
@ -554,12 +554,12 @@ TEST_CASE("NCPlane") {
|
||||
REQUIRE(dimx == x);
|
||||
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want first char of STR1
|
||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
||||
CHECK(!strcmp("Σ", cell_extended_gcluster(n_, &testcell)));
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - mbstowcs(NULL, STR2, 0)));
|
||||
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want first char of STR2
|
||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR2
|
||||
CHECK(!strcmp("α", cell_extended_gcluster(n_, &testcell)));
|
||||
CHECK(0 == testcell.attrword);
|
||||
CHECK(0 == testcell.channels);
|
||||
@ -589,13 +589,13 @@ TEST_CASE("NCPlane") {
|
||||
CHECK(newx == x);
|
||||
cell testcell = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(0 == ncplane_cursor_move_yx(n_, y - 2, x - 1));
|
||||
REQUIRE(1 == ncplane_at_cursor(n_, &testcell));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n_, &testcell));
|
||||
CHECK(testcell.gcluster == STR1[strlen(STR1) - 1]);
|
||||
CHECK(0 == ncplane_cursor_move_yx(n_, y - 1, x - 1));
|
||||
REQUIRE(1 == ncplane_at_cursor(n_, &testcell));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n_, &testcell));
|
||||
CHECK(testcell.gcluster == STR2[strlen(STR2) - 1]);
|
||||
CHECK(0 == ncplane_cursor_move_yx(n_, y, x - 1));
|
||||
REQUIRE(1 == ncplane_at_cursor(n_, &testcell));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n_, &testcell));
|
||||
CHECK(testcell.gcluster == STR3[strlen(STR3) - 1]);
|
||||
}
|
||||
|
||||
@ -701,7 +701,7 @@ TEST_CASE("NCPlane") {
|
||||
REQUIRE(0 == cells_rounded_box(ncp, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
|
||||
CHECK(0 == ncplane_box(ncp, &ul, &ur, &ll, &lr, &hl, &vl, y + 1, x + 1, 0));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
// FIXME verify with ncplane_at_cursor()
|
||||
// FIXME verify with ncplane_at_cursor_cell()
|
||||
CHECK(0 == ncplane_destroy(ncp));
|
||||
}
|
||||
SUBCASE("MoveToLowerRight") {
|
||||
@ -718,7 +718,7 @@ TEST_CASE("NCPlane") {
|
||||
CHECK(0 == ncplane_move_yx(ncp, nrows - 3, ncols - 3));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
CHECK(0 == ncplane_destroy(ncp));
|
||||
// FIXME verify with ncplane_at_cursor()
|
||||
// FIXME verify with ncplane_at_cursor_cell()
|
||||
}
|
||||
|
||||
SUBCASE("Perimeter") {
|
||||
@ -741,12 +741,12 @@ TEST_CASE("NCPlane") {
|
||||
CHECK(1 == ncplane_putegc_stainable(n_, "C", &sbytes));
|
||||
CHECK(1 == ncplane_putegc_stainable(n_, "D", &sbytes));
|
||||
uint64_t channels = 0;
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 0, &c));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 0, &c));
|
||||
CHECK(cell_simple_p(&c));
|
||||
CHECK('C' == c.gcluster);
|
||||
CHECK(0 == channels_set_fg(&channels, 0x444444));
|
||||
CHECK(channels == c.channels);
|
||||
CHECK(1 == ncplane_at_yx(n_, 0, 1, &c));
|
||||
CHECK(1 == ncplane_at_yx_cell(n_, 0, 1, &c));
|
||||
CHECK(cell_simple_p(&c));
|
||||
CHECK('D' == c.gcluster);
|
||||
CHECK(0 == channels_set_fg(&channels, 0x888888));
|
||||
|
@ -81,7 +81,7 @@ TEST_CASE("Palette256") {
|
||||
CHECK(0 < ncplane_putc_yx(n_, 0, 0, &c));
|
||||
cell_release(n_, &c);
|
||||
cell r = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(0 < ncplane_at_yx(n_, 0, 0, &r));
|
||||
CHECK(0 < ncplane_at_yx_cell(n_, 0, 0, &r));
|
||||
CHECK(cell_fg_palindex_p(&r));
|
||||
CHECK(cell_bg_palindex_p(&r));
|
||||
CHECK(CELL_ALPHA_OPAQUE == cell_fg_alpha(&r));
|
||||
|
@ -58,7 +58,7 @@ TEST_CASE("Rotate") {
|
||||
uint64_t channels = 0;
|
||||
CHECK(0 == channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT));
|
||||
CHECK(0 == channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT));
|
||||
REQUIRE(0 >= ncplane_set_base(testn, channels, 0, ""));
|
||||
REQUIRE(0 >= ncplane_set_base(testn, "", 0, channels));
|
||||
cell tl = CELL_TRIVIAL_INITIALIZER; cell tr = CELL_TRIVIAL_INITIALIZER;
|
||||
cell bl = CELL_TRIVIAL_INITIALIZER; cell br = CELL_TRIVIAL_INITIALIZER;
|
||||
cell hl = CELL_TRIVIAL_INITIALIZER; cell vl = CELL_TRIVIAL_INITIALIZER;
|
||||
|
@ -77,7 +77,7 @@ TEST_CASE("Wide") {
|
||||
for(auto i = 0u ; i < tcells.size() ; ++i){
|
||||
CHECK(0 == ncplane_cursor_move_yx(n_, 0, x));
|
||||
cell testcell = CELL_TRIVIAL_INITIALIZER;
|
||||
REQUIRE(0 < ncplane_at_cursor(n_, &testcell));
|
||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell));
|
||||
CHECK(!strcmp(cell_extended_gcluster(n_, &tcells[i]),
|
||||
cell_extended_gcluster(n_, &testcell)));
|
||||
CHECK(0 == testcell.attrword);
|
||||
@ -109,19 +109,19 @@ TEST_CASE("Wide") {
|
||||
CHECK(0 < ncplane_putegc_yx(n_, 0, 0, w, &sbytes));
|
||||
CHECK(0 < ncplane_putegc_yx(n_, 1, 0, w, &sbytes));
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_yx(n_, 0, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 0, &c);
|
||||
const char* wres = extended_gcluster(n_, &c);
|
||||
CHECK(0 == strcmp(wres, "\xf0\x9f\x90\xb8")); // should be frog
|
||||
ncplane_at_yx(n_, 0, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 1, &c);
|
||||
CHECK(cell_double_wide_p(&c)); // should be wide
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(0 == c.gcluster); // should be nothing
|
||||
ncplane_at_yx(n_, 1, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 1, 0, &c);
|
||||
wres = extended_gcluster(n_, &c);
|
||||
CHECK(0 == strcmp(wres, "\xf0\x9f\x90\xb8")); // should be frog
|
||||
ncplane_at_yx(n_, 1, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 1, 1, &c);
|
||||
CHECK(cell_double_wide_p(&c)); //should be wide
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(0 == c.gcluster);
|
||||
CHECK(0 == notcurses_render(nc_)); // should be nothing
|
||||
}
|
||||
@ -139,12 +139,12 @@ TEST_CASE("Wide") {
|
||||
CHECK(0 == y);
|
||||
CHECK(3 == x);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_yx(n_, 0, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 0, &c);
|
||||
CHECK(0 == c.gcluster); // should be nothing
|
||||
ncplane_at_yx(n_, 0, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 1, &c);
|
||||
const char* wres = extended_gcluster(n_, &c);
|
||||
CHECK(0 == strcmp(wres, "\xf0\x9f\x90\x8d")); // should be snake
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(cell_double_wide_p(&c)); // should be wide
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
}
|
||||
@ -165,13 +165,13 @@ TEST_CASE("Wide") {
|
||||
CHECK(0 == y);
|
||||
CHECK(3 == x);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_yx(n_, 0, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 0, &c);
|
||||
CHECK(0 == c.gcluster); // should be nothing
|
||||
ncplane_at_yx(n_, 0, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 1, &c);
|
||||
CHECK(cc == c.gcluster); // should be 'X'
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(cc == c.gcluster); // should be 'X"
|
||||
ncplane_at_yx(n_, 0, 3, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 3, &c);
|
||||
CHECK(0 == c.gcluster); // should be nothing
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
}
|
||||
@ -191,17 +191,17 @@ TEST_CASE("Wide") {
|
||||
CHECK(0 == y);
|
||||
CHECK(3 == x);
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_yx(n_, 0, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 0, &c);
|
||||
const char* wres = extended_gcluster(n_, &c);
|
||||
CHECK(0 == strcmp(wres, "\xf0\x9f\x90\x8d")); // should be snake
|
||||
ncplane_at_yx(n_, 0, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 1, &c);
|
||||
CHECK(cell_double_wide_p(&c)); // should be snake
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(cc == c.gcluster); // should be 'X'
|
||||
ncplane_at_yx(n_, 0, 3, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 3, &c);
|
||||
wres = extended_gcluster(n_, &c);
|
||||
CHECK(0 == strcmp(wres, "\xf0\x9f\xa6\x82")); // should be scorpion
|
||||
ncplane_at_yx(n_, 0, 4, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 4, &c);
|
||||
CHECK(cell_double_wide_p(&c)); // should be scorpion
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
}
|
||||
@ -215,14 +215,14 @@ TEST_CASE("Wide") {
|
||||
CHECK(2 == ncplane_putegc_yx(ncp, 1, 1, "\xf0\x9f\xa6\x82", NULL)); // scorpion
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
REQUIRE(0 < ncplane_at_yx(ncp, 1, 0, &c));
|
||||
REQUIRE(0 < ncplane_at_yx_cell(ncp, 1, 0, &c));
|
||||
CHECK(!strcmp(cell_extended_gcluster(ncp, &c), "│"));
|
||||
cell_release(ncp, &c);
|
||||
char* egc = notcurses_at_yx(nc_, 1, 0, &c.attrword, &c.channels);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp(egc, "│"));
|
||||
free(egc);
|
||||
REQUIRE(0 < ncplane_at_yx(ncp, 1, 3, &c));
|
||||
REQUIRE(0 < ncplane_at_yx_cell(ncp, 1, 3, &c));
|
||||
CHECK(!strcmp(cell_extended_gcluster(ncp, &c), "│"));
|
||||
cell_release(ncp, &c);
|
||||
egc = notcurses_at_yx(nc_, 1, 3, &c.attrword, &c.channels);
|
||||
@ -235,15 +235,15 @@ TEST_CASE("Wide") {
|
||||
SUBCASE("RenderWides") {
|
||||
CHECK(0 <= ncplane_putstr(n_, "\xe5\xbd\xa2\xe5\x85\xa8"));
|
||||
cell c = CELL_TRIVIAL_INITIALIZER;
|
||||
ncplane_at_yx(n_, 0, 0, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 0, &c);
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
ncplane_at_yx(n_, 0, 1, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 1, &c);
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
ncplane_at_yx(n_, 0, 2, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 2, &c);
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
ncplane_at_yx(n_, 0, 3, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 3, &c);
|
||||
CHECK(cell_double_wide_p(&c));
|
||||
ncplane_at_yx(n_, 0, 4, &c);
|
||||
ncplane_at_yx_cell(n_, 0, 4, &c);
|
||||
CHECK(!cell_double_wide_p(&c));
|
||||
REQUIRE(0 == notcurses_render(nc_));
|
||||
notcurses_at_yx(nc_, 0, 0, &c.attrword, &c.channels);
|
||||
@ -280,7 +280,7 @@ TEST_CASE("Wide") {
|
||||
CHECK(!notcurses_render(nc_));
|
||||
|
||||
// should be wide char 1
|
||||
REQUIRE(3 == ncplane_at_yx(n_, 0, 0, &c));
|
||||
REQUIRE(3 == ncplane_at_yx_cell(n_, 0, 0, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("\xe5\x85\xa8", egc));
|
||||
@ -293,7 +293,7 @@ TEST_CASE("Wide") {
|
||||
free(egc);
|
||||
cell_init(&c);
|
||||
// should be wide char 1 right side
|
||||
REQUIRE(0 == ncplane_at_yx(n_, 0, 1, &c));
|
||||
REQUIRE(0 == ncplane_at_yx_cell(n_, 0, 1, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("", egc));
|
||||
@ -307,7 +307,7 @@ TEST_CASE("Wide") {
|
||||
cell_init(&c);
|
||||
|
||||
// should be wide char 2
|
||||
REQUIRE(3 == ncplane_at_yx(n_, 0, 2, &c));
|
||||
REQUIRE(3 == ncplane_at_yx_cell(n_, 0, 2, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("\xe5\xbd\xa2", egc));
|
||||
@ -320,7 +320,7 @@ TEST_CASE("Wide") {
|
||||
free(egc);
|
||||
cell_init(&c);
|
||||
// should be wide char 2 right side
|
||||
CHECK(0 == ncplane_at_yx(n_, 0, 3, &c));
|
||||
CHECK(0 == ncplane_at_yx_cell(n_, 0, 3, &c));
|
||||
egc = cell_egc_copy(n_, &c);
|
||||
REQUIRE(egc);
|
||||
CHECK(!strcmp("", egc));
|
||||
@ -380,7 +380,7 @@ TEST_CASE("Wide") {
|
||||
uint64_t channels = 0;
|
||||
channels_set_bg_alpha(&channels, CELL_ALPHA_BLEND);
|
||||
channels_set_bg_rgb(&channels, 0x80, 0xf0, 0x10);
|
||||
CHECK(1 == ncplane_set_base(p, channels, 0, " "));
|
||||
CHECK(1 == ncplane_set_base(p, " ", 0, channels));
|
||||
CHECK(0 == notcurses_render(nc_));
|
||||
uint32_t attrword;
|
||||
uint64_t chanleft, chanright;
|
||||
@ -393,10 +393,10 @@ TEST_CASE("Wide") {
|
||||
CHECK(0 == strcmp(" ", egc));
|
||||
free(egc);
|
||||
cell cl = CELL_TRIVIAL_INITIALIZER, cr = CELL_TRIVIAL_INITIALIZER;
|
||||
CHECK(3 == ncplane_at_yx(n_, 1, 1, &cl));
|
||||
CHECK(3 == ncplane_at_yx_cell(n_, 1, 1, &cl));
|
||||
REQUIRE(cell_extended_gcluster(n_, &cl));
|
||||
CHECK(0 == strcmp("六", extended_gcluster(n_, &cl)));
|
||||
CHECK(0 == ncplane_at_yx(n_, 1, 2, &cr));
|
||||
CHECK(0 == ncplane_at_yx_cell(n_, 1, 2, &cr));
|
||||
REQUIRE(cell_simple_p(&cr));
|
||||
CHECK(0 == cr.gcluster);
|
||||
cell_release(n_, &cl);
|
||||
|
@ -95,7 +95,7 @@ TEST_CASE("ZAxisTest") {
|
||||
REQUIRE(1 == ncplane_putc(n_, &c));
|
||||
CHECK(!notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n_, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n_, &cat));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n_, &cat));
|
||||
REQUIRE(cell_simple_p(&cat));
|
||||
REQUIRE('x' == cat.gcluster);
|
||||
struct ncplane* n2 = ncplane_new(nc_, 2, 2, 0, 0, nullptr);
|
||||
@ -104,7 +104,7 @@ TEST_CASE("ZAxisTest") {
|
||||
REQUIRE(1 == ncplane_putc(n2, &c));
|
||||
CHECK_EQ(0, notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n2, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n2, &cat));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n2, &cat));
|
||||
REQUIRE('y' == cat.gcluster);
|
||||
struct ncplane* n3 = ncplane_new(nc_, 2, 2, 0, 0, nullptr);
|
||||
REQUIRE(1 == cell_load(n3, &c, "z"));
|
||||
@ -112,7 +112,7 @@ TEST_CASE("ZAxisTest") {
|
||||
REQUIRE(1 == ncplane_putc(n3, &c));
|
||||
CHECK(!notcurses_render(nc_));
|
||||
REQUIRE(!ncplane_cursor_move_yx(n3, 0, 0));
|
||||
REQUIRE(1 == ncplane_at_cursor(n3, &cat));
|
||||
REQUIRE(1 == ncplane_at_cursor_cell(n3, &cat));
|
||||
REQUIRE('z' == cat.gcluster);
|
||||
// FIXME testing damage requires notcurses keeping a copy of the screen....
|
||||
// FIXME move y atop z
|
||||
|
Loading…
x
Reference in New Issue
Block a user