ABI3 changes (#2333)

Long-planned changes for API/ABI3 #1777

* remove old-style notcurses_ rendering functions
* Make notcurses_render() a static inline wrapper around
 ncpile_render(). Remove the deprecated
 notcurses_render_to_file() and ncpile_render_to_file().
* ncstrwidth() becomes static inline wrapper #1777
* remove deprecated ncvisual_subtitle()
* kill ncvisual_inflate(), long deprecated #1777
* remove deprecated palette256 wrappers #1777
* kill ncplane_new() #1777
* remove deprecated renderfp field from notcurses_options #1777
* reorder ncstats fields to match documentation #1777
* kill deprecated style functions #1777
* ncplane_move{top, bottom} become static inline #1777
** ncplane_pixelgeom -> ncplane_pixel_geom() #1777
* ncstyle functions ought return uint16_t #1777 #2200
* ncvisualplane_create: provide new pile functionality #1462
* [heuristics] GNU screen 4x never has rgb
* [BitmapSmoothMove] only WARN in test until sixel supports this #2258
* contour: enable sextants
* interp PoC: clean up ncvisual #2266
* ncselector_options: constify string arguments
* Constify strings in selector/mselector_items
 Use internal types to track items within the
 selector/mselector widgets, rather than pressing the
 user-provided item structs into double-duty. With this
 change, we can constify the strings within those
 user-provided items. Do so, also removing the internal-side
 elements. Update documentation. Closes #2267.
* constify ncmenu_item/_section strings
* constify strings in nctabbed_options
* notcurses-demo FPS graph: back to straight seconds
* remove unused wchar_from_utf8()
* nstrwidth_valid(): properly initialize bytes/width
* [ncneofetch] use GetSystemInfo on Windows
pull/2345/head
nick black 3 years ago committed by GitHub
parent 12e01fdf5c
commit fe924be5ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,6 +10,20 @@ rearrangements of Notcurses.
without an obvious replacement is the `renderfp` field of
`notcurses_options`, for which I make no apology. If you've been avoiding
deprecated functionality, ABI3 ought require small changes, if any.
* The handling of geometry and distance has been normalized across all
functions. Lengths are now `unsigned` as opposed to `int`. Where -1 was
being used to indicate "everything", 0 is now required. This affects
`ncplane_as_rgba()`, `ncplane_contents()`, and `ncvisual_from_plane()`,
which all used -1. A length of zero passed to line-drawing functions is
now an error. Several line-drawing functions now reliably return errors
as opposed to short successes. Dimensions of 0 to `ncplane_mergedown()`
now mean "everything". Almost all coordinates now accept -1 to indicate the
current cursor position in that dimension. `ncplane_highgradient()` has
been deprecated in favor of the new `ncplane_gradient2x1()`, which takes
origin coordinates. `ncplane_format()` and `ncplane_stain()` now take
origin coordinates. All now interpret their `unsigned` argument as
lengths rather than closing coordinates, observing the same semantics as
outlined above.
* 2.4.9 (not yet released)
* Added `ncnmetric()`, which uses `snprintf()` internally. `ncmetric()`
@ -28,20 +42,6 @@ rearrangements of Notcurses.
`notcurses_mice_disable()` is now a `static inline` wrapper around the
former, passing 0 as the event mask. This can be used to get mouse
movement buttons and focus events, which were previously unavailable.
* The handling of geometry and distance has been normalized across all
functions. Lengths are now `unsigned` as opposed to `int`. Where -1 was
being used to indicate "everything", 0 is now required. This affects
`ncplane_as_rgba()`, `ncplane_contents()`, and `ncvisual_from_plane()`,
which all used -1. A length of zero passed to line-drawing functions is
now an error. Several line-drawing functions now reliably return errors
as opposed to short successes. Dimensions of 0 to `ncplane_mergedown()`
now mean "everything". Almost all coordinates now accept -1 to indicate the
current cursor position in that dimension. `ncplane_highgradient()` has
been deprecated in favor of the new `ncplane_gradient2x1()`, which takes
origin coordinates. `ncplane_format()` and `ncplane_stain()` now take
origin coordinates. All now interpret their `unsigned` argument as
lengths rather than closing coordinates, observing the same semantics as
outlined above.
* `ncvisual_geom()` has been introduced, using the `ncvgeom` struct
introduced for direct mode. This allows complete statement of geometry
for an `ncvisual`. It replaces `ncvisual_blitter_geom()`, which has been
@ -231,7 +231,7 @@ rearrangements of Notcurses.
* `notcurses_detected_terminal()` and `ncdirect_detected_terminal()` now
both return a heap-allocated string, which will contain the terminal
version if Notcurses was able to detect it. This result ought be free()d.
* Added `ncplane_moverel()`.
* Added `ncplane_move_rel()`.
* Documented `ncplane_move_yx()` in `notcurses_plane.3`, and removed the
false comment that "passing -1 as a coordinate will hold that axis
constant" from `USAGE.md` and `notcurses.h`. This has never been true.

@ -223,8 +223,10 @@ int notcurses_render(struct notcurses* nc);
// must be freed by the caller.
int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen);
// Write the last rendered frame, in its entirety, to 'fp'. If
// notcurses_render() has not yet been called, nothing will be written.
// Write the last rendered frame, in its entirety, to 'fp'. If a frame has
// not yet been rendered, nothing will be written.
int ncpile_render_to_file(struct ncplane* p, FILE* fp);
int ncpile_render_to_file(struct ncplane* p, FILE* fp);
// Retrieve the contents of the specified cell as last rendered. The EGC is
@ -1045,7 +1047,7 @@ int ncplane_move_yx(struct ncplane* n, int y, int x);
// Move this plane relative to its current location. Negative values move up
// and left, respectively. Pass 0 to hold an axis constant.
__attribute__ ((nonnull (1))) static inline int
ncplane_moverel(struct ncplane* n, int y, int x){
ncplane_move_rel(struct ncplane* n, int y, int x){
int oy, ox;
ncplane_yx(n, &oy, &ox);
return ncplane_move_yx(n, oy + y, ox + x);
@ -1084,10 +1086,10 @@ ncplane_dim_x(const struct ncplane* n){
// ('celldimy', 'celldimx'), and the maximum displayable bitmap ('maxbmapy',
// 'maxbmapx'). If bitmaps are not supported, 'maxbmapy' and 'maxbmapx' will
// be 0. Any of the geometry arguments may be NULL.
void ncplane_pixelgeom(struct ncplane* n,
unsigned* restrict pxy, unsigned* restrict pxx,
unsigned* restrict celldimy, unsigned* restrict celldimx,
unsigned* restrict maxbmapy, unsigned* restrict maxbmapx);
void ncplane_pixel_geom(struct ncplane* n,
unsigned* restrict pxy, unsigned* restrict pxx,
unsigned* restrict celldimy, unsigned* restrict celldimx,
unsigned* restrict maxbmapy, unsigned* restrict maxbmapx);
// provided a coordinate relative to the origin of 'src', map it to the same
// absolute coordinate relative to the origin of 'dst'. either or both of 'y'
@ -1144,8 +1146,17 @@ int ncplane_base(struct ncplane* ncp, nccell* c);
```c
// Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or bottom.
void ncplane_move_top(struct ncplane* n);
void ncplane_move_bottom(struct ncplane* n);
__attribute__ ((nonnull (1)))
static inline void
ncplane_move_top(struct ncplane* n){
ncplane_move_below(n, NULL);
}
__attribute__ ((nonnull (1)))
static inline void
ncplane_move_bottom(struct ncplane* n){
ncplane_move_above(n, NULL);
}
// Splice ncplane 'n' and its bound planes out of the z-buffer, and reinsert
// them at the top or bottom. Relative order will be maintained between the
@ -3602,12 +3613,12 @@ typedef struct ncstats {
uint64_t writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes
uint64_t render_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame
uint64_t raster_bytes; // bytes emitted to ttyfp
int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t raster_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max ns spent in render+raster for a frame
int64_t render_min_ns; // min ns spent in render+raster for a frame
int64_t render_max_ns; // max ns spent in render for a frame
int64_t render_min_ns; // min ns spent in render for a frame
uint64_t raster_ns; // nanoseconds spent rasterizing
int64_t raster_max_ns; // max ns spent in raster for a frame
int64_t raster_min_ns; // min ns spent in raster for a frame
@ -3626,8 +3637,9 @@ typedef struct ncstats {
uint64_t sprixelemissions; // sprixel draw count
uint64_t sprixelelisions; // sprixel elision count
uint64_t sprixelbytes; // sprixel bytes emitted
uint64_t appsync_updates; // application-synchronized updates
uint64_t appsync_updates; // how many application-synchronized updates?
uint64_t input_errors; // errors processing control sequences/utf8
uint64_t input_events; // characters returned to userspace
uint64_t hpa_gratuitous; // unnecessary hpas issued
// current state -- these can decrease

@ -197,7 +197,7 @@ issues are resolved. You can determine whether the protocol is in use
by examining the output of **notcurses-info(1)**. If the **kbd** property
is indicated, you're using the Kitty protocol.
Mouse events in the top and left margins will never be delivered to the
Mouse events in the left margins will never be delivered to the
application (as is intended), but mouse events in the bottom and right margins
sometimes can be if the event occurs prior to a window resize.

@ -23,7 +23,7 @@ notcurses_metric - fixed-width numeric output with metric suffixes
#define NCBPREFIXFMT(x) NCMETRICFWIDTH((x), NCBPREFIXCOLUMNS), (x)
```
**const char* ncmetric(uintmax_t ***val***, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***, unsigned ***mult***, int ***uprefix***);**
**const char* ncnmetric(uintmax_t ***val***, size_t s, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***, unsigned ***mult***, int ***uprefix***);**
**static inline const char* ncqprefix(uintmax_t ***val***, uintmax_t ***decimal***, char* ***buf***, int ***omitdec***);**
@ -44,15 +44,18 @@ Giga, Tera, Peta, Exa, Zetta, and Yotta) and the small suffixes mµnpfazy
range 1e24 (one septillion) through 1e-24, sufficing for all possible values of
a 64-bit **uintmax_t**.
**val** is the value being output, having been scaled by **decimal**.
**decimal** will typically be 1; to represent values less than 1, **decimal**
should be larger than **val**. The output will be written to **buf**, which
***val*** is the value being output, having been scaled by ***decimal***.
***decimal*** will typically be 1; to represent values less than 1, ***decimal***
should be larger than ***val***. The output will be written to ***buf***, which
must be at least:
* **NCPREFIXSTRLEN** + 1 bytes for a 1000-based value
* **NCIPREFIXSTRLEN** + 1 bytes for a 1024-based value
* **NCBPREFIXSTRLEN** + 1 bytes for a 1024-based value with an 'i' suffix
***s*** is the maximum output size, including '\0', used in the same
fashion as **snprintf(3)** (which **ncnmetric** calls).
Three helper functions are provided to simplify these common cases:
```
@ -78,7 +81,7 @@ ncbprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
If **omitdec** is not zero, the decimal point and mantissa will be
omitted if all digits to be displayed would be zero. The decimal point takes
the current locale into account (see **setlocale(3)** and **localeconv(3)**).
**mult** is the relative multiple for each suffix. **uprefix**, if not zero,
***mult*** is the relative multiple for each suffix. ***uprefix***, if not zero,
will be used as a suffix following any metric suffix.
The maximum number of columns is not directly related to the maximum number of
@ -93,9 +96,9 @@ length are:
In general, the maximum-width output will take the form **CCC.mmMu**, where C
are digits of the characteristic (up to ceil(log10(**mult**)) digits), the
decimal point follows, m are digits of the mantissa (up to 2), M is the metric
suffix, and u is the **uprefix**. The minimum-width output will take the form
**C**. This minimal form can occur if **omitdec** is non-zero and a
single-column value such as 5 is passed for **val**.
suffix, and u is the ***uprefix***. The minimum-width output will take the form
**C**. This minimal form can occur if ***omitdec*** is non-zero and a
single-column value such as 5 is passed for ***val***.
Three more defines are provided to simplify formatted fixed-width output using
the results of **ncmetric**. Each of these macros accepts a character buffer
@ -113,26 +116,26 @@ to ensure that the output is always **NCPREFIXCOLUMNS** wide.
# RETURN VALUES
**NULL** if input parameters were invalid. Otherwise, a pointer to **buf**,
**NULL** if input parameters were invalid. Otherwise, a pointer to ***buf***,
filled in with the formatted output.
# EXAMPLES
**ncmetric(0, 1, buf, 0, 1000, '\0')**: "0.00".
**ncnmetric(0, INT_MAX, buf, 0, 1000, '\0')**: "0.00".
**ncmetric(0, 1, buf, 1, 1000, '\0')**: "0".
**ncnmetric(0, INT_MAX, buf, 1, 1000, '\0')**: "0".
**ncmetric(1023, 1, buf, 1, 1000, '\0')**: "1.02K".
**ncnmetric(1023, INT_MAX, buf, 1, 1000, '\0')**: "1.02K".
**ncmetric(1023, 1, buf, 1, 1024, 'i')**: "1023".
**ncnmetric(1023, INT_MAX, buf, 1, 1024, 'i')**: "1023".
**ncmetric(1024, 1, buf, 1, 1024, 'i')**: "1Ki".
**ncnmetric(1024, INT_MAX, buf, 1, 1024, 'i')**: "1Ki".
**ncmetric(4096, 1, buf, 0, 1024, 'i')**: "4.00Ki".
**ncnmetric(4096, INT_MAX, buf, 0, 1024, 'i')**: "4.00Ki".
**ncmetric(0x7fffffffffffffff, 1, buf, 0, 1000, '\0')**: "9.22E".
**ncnmetric(0x7fffffffffffffff, INT_MAX, buf, 0, 1000, '\0')**: "9.22E".
**ncmetric(0xffffffffffffffff, 1, buf, 0, 1000, '\0')**: "18.45E".
**ncnmetric(0xffffffffffffffff, INT_MAX, buf, 0, 1000, '\0')**: "18.45E".
# BUGS
@ -143,4 +146,5 @@ This function is difficult to understand.
**localeconv(3)**,
**notcurses(3)**,
**notcurses_output(3)**,
**setlocale(3)**
**setlocale(3)**,
**snprintf(3)**

@ -71,7 +71,7 @@ typedef struct ncplane_options {
**int ncplane_move_yx(struct ncplane* ***n***, int ***y***, int ***x***);**
**int ncplane_moverel(struct ncplane* ***n***, int ***y***, int ***x***);**
**int ncplane_move_rel(struct ncplane* ***n***, int ***y***, int ***x***);**
**void ncplane_yx(const struct ncplane* ***n***, int* restrict ***y***, int* restrict ***x***);**
@ -95,9 +95,9 @@ typedef struct ncplane_options {
**int ncplane_base(struct ncplane* ***ncp***, nccell* ***c***);**
**void ncplane_move_top(struct ncplane* ***n***);**
**static inline void ncplane_move_top(struct ncplane* ***n***);**
**void ncplane_move_bottom(struct ncplane* ***n***);**
**static inline void ncplane_move_bottom(struct ncplane* ***n***);**
**void ncplane_move_family_top(struct ncplane* ***n***);**
@ -225,7 +225,7 @@ typedef struct ncplane_options {
**int ncplane_rotate_ccw(struct ncplane* ***n***);**
**void ncplane_pixelgeom(const struct notcurses* ***n***, unsigned* restrict ***pxy***, unsigned* restrict ***pxx***, unsigned* restrict ***celldimy***, unsigned* restrict ***celldimx***, unsigned* restrict ***maxbmapy***, unsigned* restrict ***maxbmapx***);**
**void ncplane_pixel_geom(const struct notcurses* ***n***, unsigned* restrict ***pxy***, unsigned* restrict ***pxx***, unsigned* restrict ***celldimy***, unsigned* restrict ***celldimx***, unsigned* restrict ***maxbmapy***, unsigned* restrict ***maxbmapx***);**
**int ncplane_set_name(struct ncplane* ***n***, const char* ***name***);**
@ -433,7 +433,7 @@ they intersect the plane. This can be disabled with the
## Bitmaps
**ncplane_pixelgeom** retrieves pixel geometry details. **pxy** and **pxx**
**ncplane_pixel_geom** retrieves pixel geometry details. **pxy** and **pxx**
return the size of the plane in pixels. **celldimy** and **celldimx** return
the size of a cell in pixels (these ought be the same across planes).
**maxbmapy** and **maxbmapx** describe the largest bitmap which can be
@ -505,9 +505,6 @@ All other functions cannot fail (and return **void**).
# NOTES
**ncplane_new** is defined as a deprecated wrapper around **ncplane_create**.
It should not be used in new code.
# BUGS
**ncplane_at_yx** doesn't yet account for bitmap-based graphics (see

@ -63,9 +63,7 @@ requires determining an extended grapheme cluster, foreground color, background
color, and style for each cell of the physical terminal. Writing the scene
requires synthesizing a set of UTF-8-encoded characters and escape codes
appropriate for the terminal (relying on terminfo(5)), and writing this
sequence to the output **FILE**. If the **renderfp** value was not NULL in the
original call to **notcurses_init**, the frame will be written to that **FILE**
as well. This write does not affect statistics.
sequence to the output **FILE**.
Each cell can be rendered in isolation, though synthesis of the stream carries
dependencies between cells.

@ -17,9 +17,9 @@ typedef struct ncstats {
uint64_t writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes
uint64_t render_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame
uint64_t raster_bytes; // bytes emitted to ttyfp
int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t raster_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max ns spent for a frame
int64_t render_min_ns; // min ns spent for a frame
@ -76,7 +76,7 @@ renders are not expected to fail except under exceptional circumstances.
should **notcurses_render(3)** fail while writing out a frame to the terminal,
it counts as a failed render.
**render_max_bytes** and **render_min_bytes** track the maximum and minimum
**raster_max_bytes** and **raster_min_bytes** track the maximum and minimum
number of bytes used rasterizing a frame. A given state of Notcurses does not
correspond to a unique number of bytes; the size is also dependent on the
existing terminal state. As a first approximation, the time a terminal takes to
@ -135,7 +135,7 @@ Linux framebuffer bitmaps are not written through the terminal device, but
instead directly into the memory-mapped framebuffer (see **mmap(2)**). Bytes
used for framebuffer graphics are thus independent of bytes written to the
terminal. This explains why **sprixelbytes** may be surprising given the
value of **render_bytes**.
value of **raster_bytes**.
# RETURN VALUES

@ -66,7 +66,7 @@ namespace ncpp
static const char* ncmetric (uintmax_t val, uintmax_t decimal, char *buf, int omitdec, unsigned mult, int uprefix) noexcept
{
return ::ncmetric (val, decimal, buf, omitdec, mult, uprefix);
return ::ncnmetric (val, INT_MAX, decimal, buf, omitdec, mult, uprefix);
}
static const char* ncqprefix (uintmax_t val, uintmax_t decimal, char *buf, int omitdec) noexcept

@ -71,43 +71,11 @@ API int ncdirect_set_fg_rgb(struct ncdirect* nc, unsigned rgb)
API int ncdirect_set_bg_rgb(struct ncdirect* nc, unsigned rgb)
__attribute__ ((nonnull (1)));
static inline int ncdirect_fg_rgb(struct ncdirect* nc, unsigned rgb)
__attribute__ ((deprecated));
static inline int
ncdirect_fg_rgb(struct ncdirect* nc, unsigned rgb){
return ncdirect_set_fg_rgb(nc, rgb);
}
static inline int ncdirect_bg_rgb(struct ncdirect* nc, unsigned rgb)
__attribute__ ((deprecated));
static inline int
ncdirect_bg_rgb(struct ncdirect* nc, unsigned rgb){
return ncdirect_set_bg_rgb(nc, rgb);
}
API int ncdirect_set_fg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((nonnull (1)));
API int ncdirect_set_bg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((nonnull (1)));
static inline int ncdirect_fg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((deprecated));
static inline int
ncdirect_fg_palindex(struct ncdirect* nc, int pidx){
return ncdirect_set_fg_palindex(nc, pidx);
}
static inline int ncdirect_bg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((deprecated));
static inline int
ncdirect_bg_palindex(struct ncdirect* nc, int pidx){
return ncdirect_set_bg_palindex(nc, pidx);
}
// Returns the number of simultaneous colors claimed to be supported, or 1 if
// there is no color support. Note that several terminal emulators advertise
// more colors than they actually support, downsampling internally.
@ -154,45 +122,11 @@ ncdirect_set_fg_rgb8(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
return ncdirect_set_fg_rgb(nc, (r << 16u) + (g << 8u) + b);
}
static inline int
ncdirect_fg_rgb8(struct ncdirect* nc, unsigned r, unsigned g, unsigned b)
__attribute__ ((deprecated));
static inline int
ncdirect_fg_rgb8(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
return ncdirect_set_fg_rgb8(nc, r, g, b);
}
static inline int
ncdirect_bg_rgb8(struct ncdirect* nc, unsigned r, unsigned g, unsigned b)
__attribute__ ((deprecated));
static inline int
ncdirect_bg_rgb8(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
return ncdirect_set_bg_rgb8(nc, r, g, b);
}
API int ncdirect_set_fg_default(struct ncdirect* nc)
__attribute__ ((nonnull (1)));
API int ncdirect_set_bg_default(struct ncdirect* nc)
__attribute__ ((nonnull (1)));
static inline int ncdirect_fg_default(struct ncdirect* nc)
__attribute__ ((deprecated));
static inline int
ncdirect_fg_default(struct ncdirect* nc){
return ncdirect_set_fg_default(nc);
}
static inline int ncdirect_bg_default(struct ncdirect* nc)
__attribute__ ((deprecated));
static inline int
ncdirect_bg_default(struct ncdirect* nc){
return ncdirect_set_bg_default(nc);
}
// Get the current number of columns/rows.
API unsigned ncdirect_dim_x(struct ncdirect* nc) __attribute__ ((nonnull (1)));
API unsigned ncdirect_dim_y(struct ncdirect* nc) __attribute__ ((nonnull (1)));
@ -201,7 +135,7 @@ API unsigned ncdirect_dim_y(struct ncdirect* nc) __attribute__ ((nonnull (1)));
// (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
// indicated as supported if the terminal can support it together with color.
// For more information, see the "ncv" capability in terminfo(5).
API unsigned ncdirect_supported_styles(const struct ncdirect* nc)
API uint16_t ncdirect_supported_styles(const struct ncdirect* nc)
__attribute__ ((nonnull (1)));
// ncplane_styles_*() analogues
@ -211,17 +145,9 @@ API int ncdirect_on_styles(struct ncdirect* n, unsigned stylebits)
__attribute__ ((nonnull (1)));
API int ncdirect_off_styles(struct ncdirect* n, unsigned stylebits)
__attribute__ ((nonnull (1)));
API unsigned ncdirect_styles(const struct ncdirect* n)
API uint16_t ncdirect_styles(const struct ncdirect* n)
__attribute__ ((nonnull (1)));
// Deprecated forms of above.
API int ncdirect_styles_set(struct ncdirect* n, unsigned stylebits)
__attribute__ ((deprecated));
API int ncdirect_styles_on(struct ncdirect* n, unsigned stylebits)
__attribute__ ((deprecated));
API int ncdirect_styles_off(struct ncdirect* n, unsigned stylebits)
__attribute__ ((deprecated));
// Move the cursor in direct mode. -1 to retain current location on that axis.
API int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x)
__attribute__ ((nonnull (1)));

@ -95,11 +95,6 @@ typedef enum {
NCSCALE_SCALE_HIRES,
} ncscale_e;
// Returns the number of columns occupied by a multibyte (UTF-8) string, or
// -1 if a non-printable/illegal character is encountered.
// FIXME becomes a static inline in ABI3.
API int ncstrwidth(const char* mbs);
// Returns the number of columns occupied by a the valid prefix of a multibyte
// (UTF-8) string. If an invalid character is encountered, -1 will be returned,
// and the number of valid bytes and columns will be written into *|validbytes|
@ -107,6 +102,13 @@ API int ncstrwidth(const char* mbs);
// *|validbytes| and *|validwidth| reflect the entire string.
API int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth);
// Returns the number of columns occupied by a multibyte (UTF-8) string, or
// -1 if a non-printable/illegal character is encountered.
static inline int
ncstrwidth(const char* mbs){
return ncstrwidth_valid(mbs, NULL, NULL);
}
// Returns a heap-allocated copy of the user name under which we are running.
API ALLOC char* notcurses_accountname(void);
@ -716,7 +718,7 @@ nccell_set_styles(nccell* c, unsigned stylebits){
}
// Extract the style bits from the nccell.
static inline unsigned
static inline uint16_t
nccell_styles(const nccell* c){
return c->stylemask;
}
@ -923,7 +925,6 @@ typedef struct notcurses_options {
// the environment variable TERM is used. Failure to open the terminal
// definition will result in failure to initialize notcurses.
const char* termtype;
FILE* renderfp; // deprecated, must be NULL, will be removed for ABI3 FIXME
// Progressively higher log levels result in more logging to stderr. By
// default, nothing is printed to stderr once fullscreen service begins.
ncloglevel_e loglevel;
@ -981,6 +982,12 @@ API int notcurses_enter_alternate_screen(struct notcurses* nc)
API int notcurses_leave_alternate_screen(struct notcurses* nc)
__attribute__ ((nonnull (1)));
// Get a reference to the standard plane (one matching our current idea of the
// terminal size) for this terminal. The standard plane always exists, and its
// origin is always at the uppermost, leftmost cell of the terminal.
API struct ncplane* notcurses_stdplane(struct notcurses* nc);
API const struct ncplane* notcurses_stdplane_const(const struct notcurses* nc);
// Return the topmost plane of the pile containing 'n'.
API struct ncplane* ncpile_top(struct ncplane* n)
__attribute__ ((nonnull (1)));
@ -1001,8 +1008,14 @@ API int ncpile_rasterize(struct ncplane* n)
__attribute__ ((nonnull (1)));
// Renders and rasterizes the standard pile in one shot. Blocking call.
API int notcurses_render(struct notcurses* nc)
__attribute__ ((nonnull (1)));
static inline int
notcurses_render(struct notcurses* nc){
struct ncplane* stdn = notcurses_stdplane(nc);
if(ncpile_render(stdn)){
return -1;
}
return ncpile_rasterize(stdn);
}
// Perform the rendering and rasterization portion of ncpile_render() and
// ncpile_rasterize(), but do not write the resulting buffer out to the
@ -1011,8 +1024,8 @@ API int notcurses_render(struct notcurses* nc)
API int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen)
__attribute__ ((nonnull (1, 2, 3)));
// Write the last rendered frame, in its entirety, to 'fp'. If
// notcurses_render() has not yet been called, nothing will be written.
// Write the last rendered frame, in its entirety, to 'fp'. If a frame has
// not yet been rendered, nothing will be written.
API int ncpile_render_to_file(struct ncplane* p, FILE* fp)
__attribute__ ((nonnull (1, 2)));
@ -1223,7 +1236,7 @@ ncplane_dim_x(const struct ncplane* n){
// 'maxbmapx'). If bitmaps are not supported, or if there is no artificial
// limit on bitmap size, 'maxbmapy' and 'maxbmapx' will be 0. Any of the
// geometry arguments may be NULL.
API void ncplane_pixelgeom(const struct ncplane* n,
API void ncplane_pixel_geom(const struct ncplane* n,
unsigned* RESTRICT pxy, unsigned* RESTRICT pxx,
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx)
@ -1420,7 +1433,7 @@ typedef struct nccapabilities {
// (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
// indicated as supported if the terminal can support it together with color.
// For more information, see the "ncv" capability in terminfo(5).
API unsigned notcurses_supported_styles(const struct notcurses* nc)
API uint16_t notcurses_supported_styles(const struct notcurses* nc)
__attribute__ ((nonnull (1))) __attribute__ ((pure));
// Returns the number of simultaneous colors claimed to be supported, or 1 if
@ -1529,13 +1542,15 @@ typedef struct ncstats {
uint64_t writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes
// FIXME these next three all ought be "writeout" or "raster"
uint64_t render_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame
uint64_t raster_bytes; // bytes emitted to ttyfp
int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t raster_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max ns spent in render for a frame
int64_t render_min_ns; // min ns spent in render for a frame
uint64_t raster_ns; // nanoseconds spent rasterizing
int64_t raster_max_ns; // max ns spent in raster for a frame
int64_t raster_min_ns; // min ns spent in raster for a frame
uint64_t writeout_ns; // nanoseconds spent writing frames to terminal
int64_t writeout_max_ns; // max ns spent writing out a frame
int64_t writeout_min_ns; // min ns spent writing out a frame
@ -1548,22 +1563,17 @@ typedef struct ncstats {
uint64_t defaultelisions; // default color was emitted
uint64_t defaultemissions; // default color was elided
uint64_t refreshes; // refresh requests (non-optimized redraw)
uint64_t appsync_updates; // how many application-synchronized updates?
// current state -- these can decrease
uint64_t fbbytes; // total bytes devoted to all active framebuffers
unsigned planes; // number of planes currently in existence
// FIXME placed here for ABI compatibility; move up for ABI3
uint64_t raster_ns; // nanoseconds spent rasterizing
int64_t raster_max_ns; // max ns spent in raster for a frame
int64_t raster_min_ns; // min ns spent in raster for a frame
uint64_t sprixelemissions; // sprixel draw count
uint64_t sprixelelisions; // sprixel elision count
uint64_t sprixelbytes; // sprixel bytes emitted
uint64_t appsync_updates; // how many application-synchronized updates?
uint64_t input_errors; // errors processing control sequences/utf8
uint64_t input_events; // characters returned to userspace
uint64_t hpa_gratuitous; // unnecessary hpas issued
// current state -- these can decrease
uint64_t fbbytes; // total bytes devoted to all active framebuffers
unsigned planes; // number of planes currently in existence
} ncstats;
// Allocate an ncstats object. Use this rather than allocating your own, since
@ -1648,7 +1658,7 @@ API int ncplane_move_yx(struct ncplane* n, int y, int x);
// Move this plane relative to its current location. Negative values move up
// and left, respectively. Pass 0 to hold an axis constant.
__attribute__ ((nonnull (1))) static inline int
ncplane_moverel(struct ncplane* n, int y, int x){
ncplane_move_rel(struct ncplane* n, int y, int x){
int oy, ox;
ncplane_yx(n, &oy, &ox);
return ncplane_move_yx(n, oy + y, ox + x);
@ -1694,13 +1704,18 @@ API int ncplane_move_below(struct ncplane* RESTRICT n,
struct ncplane* RESTRICT below)
__attribute__ ((nonnull (1)));
// Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or
// bottom. FIXME these both become static inline wrappers around
// ncplane_move_below() and ncplane_move_above() in ABI3.
API void ncplane_move_top(struct ncplane* n)
__attribute__ ((nonnull (1)));
API void ncplane_move_bottom(struct ncplane* n)
__attribute__ ((nonnull (1)));
// Splice ncplane 'n' out of the z-buffer; reinsert it at the top or bottom.
__attribute__ ((nonnull (1)))
static inline void
ncplane_move_top(struct ncplane* n){
ncplane_move_below(n, NULL);
}
__attribute__ ((nonnull (1)))
static inline void
ncplane_move_bottom(struct ncplane* n){
ncplane_move_above(n, NULL);
}
// Splice ncplane 'n' and its bound planes out of the z-buffer, and reinsert
// them above or below 'targ'. Relative order will be maintained between the
@ -1980,19 +1995,68 @@ API int ncplane_putwegc_stained(struct ncplane* n, const wchar_t* gclust, int* s
// (though not beyond the end of the plane); this number is returned on success.
// On error, a non-positive number is returned, indicating the number of columns
// which were written before the error.
API int ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclusters);
static inline int
ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclusters){
int ret = 0;
while(*gclusters){
int wcs;
int cols = ncplane_putegc_yx(n, y, x, gclusters, &wcs);
//fprintf(stderr, "wrote %.*s %d cols %d bytes now at %d/%d\n", wcs, gclusters, cols, wcs, n->y, n->x);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
// after the first iteration, just let the cursor code control where we
// print, so that scrolling is taken into account
y = -1;
x = -1;
gclusters += wcs;
ret += cols;
}
return ret;
}
static inline int
ncplane_putstr(struct ncplane* n, const char* gclustarr){
return ncplane_putstr_yx(n, -1, -1, gclustarr);
}
API int ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align,
const char* s);
static inline int
ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align, const char* s){
int validbytes, validwidth;
// we'll want to do the partial write if there's an error somewhere within
ncstrwidth_valid(s, &validbytes, &validwidth);
int xpos = ncplane_halign(n, align, validwidth);
if(xpos < 0){
return -1;
}
return ncplane_putstr_yx(n, y, xpos, s);
}
// Replace a string's worth of glyphs at the current cursor location, but
// retain the styling. The current styling of the plane will not be changed.
API int ncplane_putstr_stained(struct ncplane* n, const char* s);
static inline int
ncplane_putstr_stained(struct ncplane* n, const char* gclusters){
int ret = 0;
while(*gclusters){
int wcs;
int cols = ncplane_putegc_stained(n, gclusters, &wcs);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
gclusters += wcs;
ret += cols;
}
return ret;
}
API int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align, size_t s, const char* str)
__attribute__ ((nonnull (1, 5)));
// Write a series of EGCs to the current location, using the current style.
// They will be interpreted as a series of columns (according to the definition
@ -2000,16 +2064,35 @@ API int ncplane_putstr_stained(struct ncplane* n, const char* s);
// (though not beyond the end of the plane); this number is returned on success.
// On error, a non-positive number is returned, indicating the number of columns
// which were written before the error. No more than 's' bytes will be written.
API int ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters);
static inline int
ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters){
int ret = 0;
int offset = 0;
//fprintf(stderr, "PUT %zu at %d/%d [%.*s]\n", s, y, x, (int)s, gclusters);
while((size_t)offset < s && gclusters[offset]){
int wcs;
int cols = ncplane_putegc_yx(n, y, x, gclusters + offset, &wcs);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
// after the first iteration, just let the cursor code control where we
// print, so that scrolling is taken into account
y = -1;
x = -1;
offset += wcs;
ret += cols;
}
return ret;
}
static inline int
ncplane_putnstr(struct ncplane* n, size_t s, const char* gclustarr){
return ncplane_putnstr_yx(n, -1, -1, s, gclustarr);
}
API int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align,
size_t s, const char* gclustarr);
// ncplane_putstr(), but following a conversion from wchar_t to UTF-8 multibyte.
// FIXME do this as a loop over ncplane_putegc_yx and save the big allocation+copy
static inline int
@ -2687,16 +2770,30 @@ nccells_load_box(struct ncplane* n, uint32_t styles, uint64_t channels,
return -1;
}
API int nccells_rounded_box(struct ncplane* n, uint16_t styles, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll,
nccell* lr, nccell* hl, nccell* vl);
static inline int
nccells_ascii_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
return nccells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, NCBOXASCII);
}
static inline int
nccells_double_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
if(notcurses_canutf8(ncplane_notcurses(n))){
return nccells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, NCBOXDOUBLE);
}
return nccells_ascii_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
static inline int
nccells_rounded_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
if(notcurses_canutf8(ncplane_notcurses(n))){
return nccells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, NCBOXROUND);
}
return nccells_ascii_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
static inline int
nccells_light_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
@ -2764,10 +2861,6 @@ ncplane_rounded_box_sized(struct ncplane* n, uint16_t styles, uint64_t channels,
x + xlen - 1, ctlword);
}
API int nccells_double_box(struct ncplane* n, uint16_t styles, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll,
nccell* lr, nccell* hl, nccell* vl);
static inline int
ncplane_double_box(struct ncplane* n, uint16_t styles, uint64_t channels,
unsigned ylen, unsigned xlen, unsigned ctlword){
@ -3000,21 +3093,6 @@ API int ncvisual_set_yx(const struct ncvisual* n, unsigned y, unsigned x,
uint32_t pixel)
__attribute__ ((nonnull (1)));
// Render the decoded frame according to the provided options (which may be
// NULL). The plane used for rendering depends on vopts->n and vopts->flags. If
// NCVISUAL_OPTION_CHILDPLANE is set, vopts->n must not be NULL, and the plane
// will always be created as a child of vopts->n. If this flag is not set, and
// vopts->n is NULL, a new plane is created as a child of the standard plane.
// If the flag is not set and vopts->n is not NULL, we render to vopts->n. A
// subregion of the visual can be rendered using 'begx', 'begy', 'lenx', and
// 'leny'. Negative values for 'begy' or 'begx' are an error. It is an error to
// specify any region beyond the boundaries of the frame. Returns the (possibly
// newly-created) plane to which we drew. Pixels may not be blitted to the
// standard plane.
API struct ncplane* ncvisual_render(struct notcurses* nc, struct ncvisual* ncv,
const struct ncvisual_options* vopts)
__attribute__ ((deprecated)) __attribute__ ((nonnull (2)));
// Render the decoded frame according to the provided options (which may be
// NULL). The plane used for rendering depends on vopts->n and vopts->flags.
// If NCVISUAL_OPTION_CHILDPLANE is set, vopts->n must not be NULL, and the
@ -3343,11 +3421,14 @@ API void* nctablet_userptr(struct nctablet* t);
API struct ncplane* nctablet_plane(struct nctablet* t);
// Takes an arbitrarily large number, and prints it into a fixed-size buffer by
// adding the necessary SI suffix. Usually, pass a |[IB]PREFIXSTRLEN+1|-sized
// buffer to generate up to |[IB]PREFIXCOLUMNS| columns' worth of EGCs. The
// adding the necessary SI suffix. Usually, pass a |NC[IB]?PREFIXSTRLEN+1|-sized
// buffer to generate up to |NC[IB]?PREFIXCOLUMNS| columns' worth of EGCs. The
// characteristic can occupy up through |mult-1| characters (3 for 1000, 4 for
// 1024). The mantissa can occupy either zero or two characters.
//
// snprintf(3) is used internally, with 's' as its size bound. If the output
// requires more size than is available, NULL will be returned.
//
// Floating-point is never used, because an IEEE758 double can only losslessly
// represent integers through 2^53-1.
//
@ -3355,6 +3436,7 @@ API struct ncplane* nctablet_plane(struct nctablet* t);
// an 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
// 2^-63 is 0.000000000000000000108, 1.08a(tto).
// val: value to print
// s: maximum output size; see snprintf(3)
// decimal: scaling. '1' if none has taken place.
// buf: buffer in which string will be generated
// omitdec: inhibit printing of all-0 decimal portions
@ -3363,11 +3445,6 @@ API struct ncplane* nctablet_plane(struct nctablet* t);
// only printed if suffix is actually printed (input >= mult).
//
// You are encouraged to consult notcurses_metric(3).
API const char* ncmetric(uintmax_t val, uintmax_t decimal, char* buf,
int omitdec, uintmax_t mult, int uprefix)
__attribute__ ((nonnull (3)));
// uses snprintf() internally with the argument 's' as its bound
API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
char* buf, int omitdec, uintmax_t mult,
int uprefix)
@ -3376,7 +3453,7 @@ API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
// The number of columns is one fewer, as the STRLEN expressions must leave
// an extra byte open in case 'µ' (U+00B5, 0xC2 0xB5) shows up. NCPREFIXCOLUMNS
// is the maximum number of columns used by a mult == 1000 (standard)
// ncmetric() call. NCIPREFIXCOLUMNS is the maximum number of columns used by a
// ncnmetric() call. NCIPREFIXCOLUMNS is the maximum number of columns used by a
// mult == 1024 (digital information) ncmetric(). NCBPREFIXSTRLEN is the maximum
// number of columns used by a mult == 1024 call making use of the 'i' suffix.
// This is the true number of columns; to set up a printf()-style maximum
@ -3397,19 +3474,19 @@ API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
// Mega, kilo, gigafoo. Use PREFIXSTRLEN + 1 and PREFIXCOLUMNS.
static inline const char*
ncqprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1000, '\0');
return ncnmetric(val, NCPREFIXSTRLEN + 1, decimal, buf, omitdec, 1000, '\0');
}
// Mibi, kebi, gibibytes sans 'i' suffix. Use IPREFIXSTRLEN + 1.
static inline const char*
nciprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, '\0');
return ncnmetric(val, NCIPREFIXSTRLEN + 1, decimal, buf, omitdec, 1024, '\0');
}
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
static inline const char*
ncbprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
return ncnmetric(val, NCBPREFIXSTRLEN + 1, decimal, buf, omitdec, 1024, 'i');
}
// Enable or disable the terminal's cursor, if supported, placing it at
@ -4204,122 +4281,6 @@ API void ncreader_destroy(struct ncreader* n, char** contents);
API void notcurses_debug(const struct notcurses* nc, FILE* debugfp)
__attribute__ ((nonnull (1, 2)));
// DEPRECATED MATERIAL, GOING AWAY IN ABI3
__attribute__ ((deprecated)) API int cell_duplicate(struct ncplane* n, nccell* targ, const nccell* c);
__attribute__ ((deprecated)) API void cell_release(struct ncplane* n, nccell* c);
// This function will be removed in ABI3 in favor of ncplane_create().
// It persists in ABI2 only for backwards compatibility.
API ALLOC struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, int x, void* opaque, const char* name)
__attribute__ ((deprecated));
API void ncplane_styles_set(struct ncplane* n, unsigned stylebits)
__attribute__ ((deprecated));
API void ncplane_styles_on(struct ncplane* n, unsigned stylebits)
__attribute__ ((deprecated));
API void ncplane_styles_off(struct ncplane* n, unsigned stylebits)
__attribute__ ((deprecated));
__attribute__ ((deprecated)) API int
cells_rounded_box(struct ncplane* n, uint16_t styles, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll,
nccell* lr, nccell* hl, nccell* vl);
__attribute__ ((deprecated)) API int
cells_double_box(struct ncplane* n, uint16_t styles, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll,
nccell* lr, nccell* hl, nccell* vl);
// Deprecated form of nctablet_plane().
API struct ncplane* nctablet_ncplane(struct nctablet* t)
__attribute__ ((deprecated));
API ALLOC ncpalette* palette256_new(struct notcurses* nc)
__attribute__ ((deprecated));
API int palette256_use(struct notcurses* nc, const ncpalette* p)
__attribute__ ((deprecated));
API void palette256_free(ncpalette* p) __attribute__ ((deprecated));
// Inflate each pixel in the image to 'scale'x'scale' pixels. It is an error
// if 'scale' is less than 1. The original color is retained.
// Deprecated; use ncvisual_resize_noninterpolative(), which this now wraps.
API __attribute__ ((deprecated)) int ncvisual_inflate(struct ncvisual* n, int scale)
__attribute__ ((nonnull (1)));
API int notcurses_render_to_buffer(struct notcurses* nc, char** buf, size_t* buflen)
__attribute__ ((deprecated));
API int notcurses_render_to_file(struct notcurses* nc, FILE* fp)
__attribute__ ((deprecated));
API void notcurses_debug_caps(const struct notcurses* nc, FILE* debugfp)
__attribute__ ((deprecated)) __attribute__ ((nonnull (1, 2)));
__attribute__ ((deprecated)) API int nccell_width(const struct ncplane* n, const nccell* c);
API ALLOC char* ncvisual_subtitle(const struct ncvisual* ncv)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
API uint32_t notcurses_getc(struct notcurses* nc, const struct timespec* ts,
const void* unused, ncinput* ni)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
API uint32_t ncdirect_getc(struct ncdirect* nc, const struct timespec *ts,
const void* unused, ncinput* ni)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
// Get the size and ratio of ncvisual pixels to output cells along the y
// and x axes. The input size (in pixels) will be written to 'y' and 'x'.
// The scaling will be written to 'scaley' and 'scalex'. With these:
// rows = (y / scaley) + !!(y % scaley) or (y + scaley - 1) / scaley
// cols = (x / scalex) + !!(x % scalex) or (x + scalex - 1) / scalex
// Returns non-zero for an invalid 'vopts'. The blitter that will be used
// is returned in '*blitter'.
API int ncvisual_blitter_geom(const struct notcurses* nc, const struct ncvisual* n,
const struct ncvisual_options* vopts, int* y, int* x,
int* scaley, int* scalex, ncblitter_e* blitter)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
API int notcurses_mouse_enable(struct notcurses* n)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
API int notcurses_mouse_disable(struct notcurses* n)
__attribute__ ((nonnull (1))) __attribute__ ((deprecated));
API int ncplane_highgradient_sized(struct ncplane* n, uint32_t ul, uint32_t ur,
uint32_t ll, uint32_t lr, int ylen, int xlen)
__attribute__ ((deprecated));
__attribute__ ((deprecated)) static inline const char*
qprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1000, '\0');
}
// Mibi, kebi, gibibytes sans 'i' suffix. Use IPREFIXSTRLEN + 1.
__attribute__ ((deprecated)) static inline const char*
iprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, '\0');
}
// Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
__attribute__ ((deprecated)) static inline const char*
bprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){
return ncmetric(val, decimal, buf, omitdec, 1024, 'i');
}
#define PREFIXCOLUMNS 7
#define IPREFIXCOLUMNS 8
#define BPREFIXCOLUMNS 9
#define PREFIXSTRLEN (PREFIXCOLUMNS + 1) // Does not include a '\0' (xxx.xxU)
#define IPREFIXSTRLEN (IPREFIXCOLUMNS + 1) // Does not include a '\0' (xxxx.xxU)
#define BPREFIXSTRLEN (BPREFIXCOLUMNS + 1) // Does not include a '\0' (xxxx.xxUi), i == prefix
#define PREFIXFMT(x) NCMETRICFWIDTH((x), PREFIXCOLUMNS), (x)
#define IPREFIXFMT(x) NCMETRIXFWIDTH((x), IPREFIXCOLUMNS), (x)
#define BPREFIXFMT(x) NCMETRICFWIDTH((x), BPREFIXCOLUMNS), (x)
#undef API
#undef ALLOC

@ -524,7 +524,7 @@ class NcPlane:
"""Return Y dimension of this NcPlane."""
raise NotImplementedError('Stub')
def pixelgeom(self) -> Tuple[int, int, int, int, int, int]:
def pixel_geom(self) -> Tuple[int, int, int, int, int, int]:
"""Retrieve pixel geometry for the display region, each cell
and the maximum displayable bitmap."""
raise NotImplementedError('Stub')

@ -110,10 +110,10 @@ NcPlane_dim_y(NcPlaneObject *self, PyObject *Py_UNUSED(args))
}
static PyObject *
NcPlane_pixelgeom(NcPlaneObject *self, PyObject *Py_UNUSED(args))
NcPlane_pixel_geom(NcPlaneObject *self, PyObject *Py_UNUSED(args))
{
unsigned pxy = 0, pxx = 0, celldimy = 0, celldimx = 0, maxbmapy = 0, maxbmapx = 0;
ncplane_pixelgeom(self->ncplane_ptr, &pxy, &pxx, &celldimy, &celldimx, &maxbmapy, &maxbmapx);
ncplane_pixel_geom(self->ncplane_ptr, &pxy, &pxx, &celldimy, &celldimx, &maxbmapy, &maxbmapx);
return Py_BuildValue("II II II", pxy, pxx, celldimy, celldimx, maxbmapy, maxbmapx);
}
@ -1666,7 +1666,7 @@ static PyMethodDef NcPlane_methods[] = {
{"dim_yx", (PyCFunction)NcPlane_dim_yx, METH_NOARGS, PyDoc_STR("Return the dimensions of this ncplane.")},
{"dim_x", (PyCFunction)NcPlane_dim_x, METH_NOARGS, PyDoc_STR("Return X dimension of this ncplane.")},
{"dim_y", (PyCFunction)NcPlane_dim_y, METH_NOARGS, PyDoc_STR("Return Y dimension of this ncplane.")},
{"pixelgeom", (PyCFunction)NcPlane_pixelgeom, METH_NOARGS, PyDoc_STR("Retrieve pixel geometry for the display region ('pxy', 'pxx'), each cell ('celldimy', 'celldimx'), and the maximum displayable bitmap ('maxbmapy', 'maxbmapx'). Note that this will call notcurses_check_pixel_support(), possibly leading to an interrogation of the terminal. If bitmaps are not supported, 'maxbmapy' and 'maxbmapx' will be 0. Any of the geometry arguments may be NULL.")},
{"pixel_geom", (PyCFunction)NcPlane_pixel_geom, METH_NOARGS, PyDoc_STR("Retrieve pixel geometry for the display region ('pxy', 'pxx'), each cell ('celldimy', 'celldimx'), and the maximum displayable bitmap ('maxbmapy', 'maxbmapx'). Note that this will call notcurses_check_pixel_support(), possibly leading to an interrogation of the terminal. If bitmaps are not supported, 'maxbmapy' and 'maxbmapx' will be 0. Any of the geometry arguments may be NULL.")},
{"set_resizecb", (PyCFunction)NcPlane_set_resizecb, METH_VARARGS, PyDoc_STR("Replace the ncplane's existing resizecb with 'resizecb' (which may be NULL). The standard plane's resizecb may not be changed.")},
{"reparent", (PyCFunction)NcPlane_reparent, METH_VARARGS, PyDoc_STR("Plane 'n' will be unbound from its parent plane, and will be made a bound child of 'newparent'.")},

@ -44,8 +44,6 @@ extern "C" {
typedef struct siginfo_t {
int aieeee;
} siginfo_t;
// not declared in MSYS2 header files, but implemented...?
int faccessat(int dirfd, const char *pathname, int mode, int flags);
#define sigset_t int
#define nl_langinfo(x) "UTF-8"
#define ppoll(w, x, y, z) WSAPoll((w), (x), (y))

@ -130,7 +130,7 @@ get_ships(struct notcurses* nc, struct ship* ships, unsigned shipcount){
return -1;
}
unsigned cdimy, cdimx;
ncplane_pixelgeom(notcurses_stdplane(nc), NULL, NULL, &cdimy, &cdimx, NULL, NULL);
ncplane_pixel_geom(notcurses_stdplane(nc), NULL, NULL, &cdimy, &cdimx, NULL, NULL);
if(ncvisual_resize(wmv, cdimy * SHIPHEIGHT, cdimx * SHIPWIDTH)){
ncvisual_destroy(wmv);
return -1;

@ -377,7 +377,7 @@ summary_json(FILE* f, const char* spec, int rows, int cols){
continue;
}
ret |= (fprintf(f, "\"%s\":{\"bytes\":\"%"PRIu64"\",\"frames\":\"%"PRIu64"\",\"ns\":\"%"PRIu64"\"}%s",
demos[results[i].selector - 'a'].name, results[i].stats.render_bytes,
demos[results[i].selector - 'a'].name, results[i].stats.raster_bytes,
results[i].stats.renders, results[i].timens, i < strlen(spec) - 1 ? "," : "") < 0);
}
ret |= (fprintf(f, "}}}\n") < 0);
@ -411,7 +411,7 @@ summary_table(struct notcurses* nc, const char* spec, bool canimage, bool canvid
for(size_t i = 0 ; i < strlen(spec) ; ++i){
nsdelta += results[i].timens;
ncqprefix(results[i].timens, NANOSECS_IN_SEC, timebuf, 0);
ncbprefix(results[i].stats.render_bytes, 1, totalbuf, 0);
ncbprefix(results[i].stats.raster_bytes, 1, totalbuf, 0);
uint64_t divisor = results[i].stats.render_ns + results[i].stats.writeout_ns + results[i].stats.raster_ns;
if(divisor){
ncqprefix((uintmax_t)results[i].stats.writeouts * NANOSECS_IN_SEC * 1000 / divisor,
@ -455,7 +455,7 @@ summary_table(struct notcurses* nc, const char* spec, bool canimage, bool canvid
failed = true;
}
totalframes += results[i].stats.renders;
totalbytes += results[i].stats.render_bytes;
totalbytes += results[i].stats.raster_bytes;
totalrenderns += results[i].stats.render_ns;
totalwriteoutns += results[i].stats.writeout_ns;
}

@ -14,6 +14,7 @@ draw_background(struct notcurses* nc){
struct ncvisual_options vopts = {
.scaling = NCSCALE_STRETCH,
.n = n,
.flags = NCVISUAL_OPTION_CHILDPLANE,
};
if(ncvisual_blit(nc, ncv, &vopts) == NULL){
ncvisual_destroy(ncv);

@ -65,29 +65,6 @@ fetch_env_vars(struct notcurses* nc, fetched_info* fi){
return 0;
}
static distro_info distros[] = {
{
.name = "arch",
// from core/filesystem
.logofile = "/usr/share/pixmaps/archlinux.png",
}, {
.name = "artix",
// from system/filesystem
.logofile = "/usr/share/pixmaps/artixlinux-logo.png",
}, {
.name = "debian",
// from desktop-base package
.logofile = "/usr/share/desktop-base/debian-logos/logo-text-256.png",
}, {
.name = "fedora",
// from redhat-lsb-core package
.logofile = "/usr/share/pixmaps/fedora-logo.png",
}, {
.name = NULL,
.logofile = NULL,
},
};
static int
fetch_bsd_cpuinfo(fetched_info* fi){
#if defined(__linux__) || defined(__gnu_hurd__) || defined(__MINGW64__)
@ -110,6 +87,32 @@ fetch_bsd_cpuinfo(fetched_info* fi){
return 0;
}
static int
fetch_windows_cpuinfo(fetched_info* fi){
#ifdef __MINGW64__
LPSYSTEM_INFO info;
GetSystemInfo(info);
switch(info->wProcessorArchitecture){
case PROCESSOR_ARCHITECTURE_AMD64:
fi->cpu_model = strdup("amd64"); break;
case PROCESSOR_ARCHITECTURE_ARM:
fi->cpu_model = strdup("ARM"); break;
case PROCESSOR_ARCHITECTURE_ARM64:
fi->cpu_model = strdup("AArch64"); break;
case PROCESSOR_ARCHITECTURE_IA64:
fi->cpu_model = strdup("Itanium"); break;
case PROCESSOR_ARCHITECTURE_INTEL:
fi->cpu_model = strdup("i386"); break;
default:
fi->cpu_model = strdup("Unknown processor"); break;
}
fi->core_count = info->dwNumberOfProcessors;
#else
(void)fi;
#endif
return 0;
}
static int
fetch_cpu_info(fetched_info* fi){
FILE* cpuinfo = fopen("/proc/cpuinfo", "re");
@ -197,6 +200,7 @@ fetch_x_props(fetched_info* fi){
return 0;
}
#ifdef __linux__
// Given a filename, check for its existence in the directories specified by
// https://specifications.freedesktop.org/icon-theme-spec/latest/ar01s03.html.
// Returns NULL if no such file can be found. Return value is heap-allocated.
@ -217,10 +221,35 @@ get_xdg_logo(const char *spec){
strcat(p, spec);
return p;
}
#endif
// FIXME deal more forgivingly with quotation marks
static const distro_info*
linux_ncneofetch(fetched_info* fi){
const distro_info* dinfo = NULL;
#ifdef __linux__
static const distro_info distros[] = {
{
.name = "arch",
// from core/filesystem
.logofile = "/usr/share/pixmaps/archlinux.png",
}, {
.name = "artix",
// from system/filesystem
.logofile = "/usr/share/pixmaps/artixlinux-logo.png",
}, {
.name = "debian",
// from desktop-base package
.logofile = "/usr/share/desktop-base/debian-logos/logo-text-256.png",
}, {
.name = "fedora",
// from redhat-lsb-core package
.logofile = "/usr/share/pixmaps/fedora-logo.png",
}, {
.name = NULL,
.logofile = NULL,
},
};
FILE* osinfo = fopen("/etc/os-release", "re");
if(osinfo == NULL){
return NULL;
@ -266,7 +295,6 @@ linux_ncneofetch(fetched_info* fi){
if(distro == NULL){
return NULL;
}
const distro_info* dinfo = NULL;
for(dinfo = distros ; dinfo->name ; ++dinfo){
if(strcmp(dinfo->name, distro) == 0){
break;
@ -276,6 +304,9 @@ linux_ncneofetch(fetched_info* fi){
fi->neologo = get_neofetch_art(distro);
}
free(distro);
#else
(void)fi;
#endif
return dinfo;
}
@ -309,7 +340,14 @@ get_kernel(fetched_info* fi){
}
fprintf(stderr, "Unknown operating system via uname: %s\n", uts.sysname);
#else
(void)fi;
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
char ver[20]; // sure why not
snprintf(ver, sizeof(ver), "%lu.%lu", osvi.dwMajorVersion, osvi.dwMinorVersion);
fi->kernver = strdup(ver);
fi->kernel = strdup("Windows NT");
return NCNEO_WINDOWS;
#endif
return NCNEO_UNKNOWN;
@ -440,7 +478,7 @@ infoplane_notcurses(struct notcurses* nc, const fetched_info* fi, int planeheigh
size_t oldlenp = sizeof(ram);
if(sysctlbyname("hw.memsize", &ram, &oldlenp, NULL, 0) == 0){
char tram[NCBPREFIXSTRLEN + 1];
bprefix(ram, 1, tram, 1);
ncbprefix(ram, 1, tram, 1);
ncplane_printf_aligned(infop, 2, NCALIGN_LEFT, " RAM: %sB", tram);
}
#endif
@ -664,6 +702,8 @@ ncneofetch(struct notcurses* nc){
}
if(kern == NCNEO_LINUX){
fetch_cpu_info(&fi);
}else if(kern == NCNEO_WINDOWS){
fetch_windows_cpuinfo(&fi);
}else{
fetch_bsd_cpuinfo(&fi);
}

@ -331,7 +331,7 @@ unicodedumper(struct ncplane* n, const char* indent){
static int
display_logo(struct ncplane* n, const char* path){
unsigned cpixy, cpixx;
ncplane_pixelgeom(n, NULL, NULL, &cpixy, &cpixx, NULL, NULL);
ncplane_pixel_geom(n, NULL, NULL, &cpixy, &cpixx, NULL, NULL);
struct ncvisual* ncv = ncvisual_from_file(path);
if(ncv == NULL){
return -1;

@ -255,7 +255,7 @@ int input_demo(ncpp::NotCurses* nc) {
auto n = nc->get_stdplane(&dimy, &dimx);
// FIXME no ncpp wrapper for Plane::pixelgeom?
unsigned celldimx, maxbmapx;
ncplane_pixelgeom(*n, nullptr, nullptr, nullptr, &celldimx, nullptr, &maxbmapx);
ncplane_pixel_geom(*n, nullptr, nullptr, nullptr, &celldimx, nullptr, &maxbmapx);
struct ncplane_options nopts = {
.y = static_cast<int>(dimy) - PLOTHEIGHT - 1,
.x = NCALIGN_CENTER,

@ -2,12 +2,6 @@
int loglevel = NCLOGLEVEL_SILENT;
void notcurses_debug_caps(const notcurses* nc, FILE* debugfp){
// FIXME deprecated, remove for ABI3
(void)nc;
(void)debugfp;
}
void notcurses_debug(const notcurses* nc, FILE* debugfp){
fbuf f;
if(fbuf_init_small(&f)){

@ -1124,11 +1124,6 @@ ncdirect_style_emit(ncdirect* n, unsigned stylebits, fbuf* f){
return r;
}
// turn on any specified stylebits
int ncdirect_styles_on(ncdirect* n, unsigned stylebits){
return ncdirect_on_styles(n, stylebits);
}
int ncdirect_on_styles(ncdirect* n, unsigned stylebits){
if((stylebits & n->tcache.supported_styles) < stylebits){ // unsupported styles
return -1;
@ -1148,11 +1143,7 @@ int ncdirect_on_styles(ncdirect* n, unsigned stylebits){
return 0;
}
int ncdirect_styles_off(ncdirect* n, unsigned stylebits){
return ncdirect_off_styles(n, stylebits);
}
unsigned ncdirect_styles(const ncdirect* n){
uint16_t ncdirect_styles(const ncdirect* n){
return n->stylemask;
}
@ -1173,10 +1164,6 @@ int ncdirect_off_styles(ncdirect* n, unsigned stylebits){
return 0;
}
int ncdirect_styles_set(ncdirect* n, unsigned stylebits){
return ncdirect_set_styles(n, stylebits);
}
// set the current stylebits to exactly those provided
int ncdirect_set_styles(ncdirect* n, unsigned stylebits){
if((stylebits & n->tcache.supported_styles) < stylebits){ // unsupported styles
@ -1595,7 +1582,7 @@ int ncdirectf_geom(ncdirect* n, ncdirectf* frame,
&placey, &placex);
}
unsigned ncdirect_supported_styles(const ncdirect* nc){
uint16_t ncdirect_supported_styles(const ncdirect* nc){
return term_supported_styles(&nc->tcache);
}

@ -233,11 +233,11 @@ launch_pipe_process(int* pipefd, int* pidfd, unsigned usepath,
}
#endif
#ifndef __MINGW64__
// nuke the just-spawned process, and reap it. called before the subprocess
// reader thread is launched (which otherwise reaps the subprocess).
static int
kill_and_wait_subproc(pid_t pid, int pidfd, int* status){
#ifndef __MINGW64__
int ret = -1;
// on linux, we try pidfd_send_signal, if the pidfd has been defined.
// otherwise, we fall back to regular old kill();
@ -258,12 +258,6 @@ kill_and_wait_subproc(pid_t pid, int pidfd, int* status){
return -1;
}
return 0;
#else
(void)pid;
(void)pidfd;
(void)status;
return -1;
#endif
}
// need a poll on both main fd and pidfd
@ -335,6 +329,7 @@ ncsubproc_launch(ncplane* n, ncsubproc* ret, const ncsubproc_options* opts, int
}
return ret->nfp;
}
#endif
// use of env implies usepath
static ncsubproc*

@ -502,11 +502,11 @@ mouse_click(inputctx* ictx, unsigned release, char follow){
logwarn("dropping click in margins %ld/%ld\n", y, x);
return;
}
if(x >= ictx->ti->dimx - (ictx->rmargin + ictx->lmargin)){
if((unsigned)x >= ictx->ti->dimx - (ictx->rmargin + ictx->lmargin)){
logwarn("dropping click in margins %ld/%ld\n", y, x);
return;
}
if(y >= ictx->ti->dimy - (ictx->bmargin + ictx->tmargin)){
if((unsigned)y >= ictx->ti->dimy - (ictx->bmargin + ictx->tmargin)){
logwarn("dropping click in margins %ld/%ld\n", y, x);
return;
}
@ -2200,18 +2200,6 @@ uint32_t ncdirect_get(ncdirect* n, const struct timespec* ts, ncinput* ni){
return internal_get(n->tcache.ictx, ts, ni);
}
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_getc(ncdirect* nc, const struct timespec *ts,
const void* unused, ncinput* ni){
(void)unused; // FIXME remove for abi3
return ncdirect_get(nc, ts, ni);
}
int get_cursor_location(inputctx* ictx, const char* u7, unsigned* y, unsigned* x){
pthread_mutex_lock(&ictx->clock);
while(ictx->cvalid == 0){

@ -393,7 +393,7 @@ void summarize_stats(notcurses* nc);
void update_raster_stats(const struct timespec* time1, const struct timespec* time0, ncstats* stats);
void update_render_stats(const struct timespec* time1, const struct timespec* time0, ncstats* stats);
void update_render_bytes(ncstats* stats, int bytes);
void update_raster_bytes(ncstats* stats, int bytes);
void update_write_stats(const struct timespec* time1, const struct timespec* time0, ncstats* stats, int bytes);
void sigwinch_handler(int signo);

@ -116,8 +116,3 @@ const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
}
return buf;
}
const char *ncmetric(uintmax_t val, uintmax_t decimal, char *buf, int omitdec,
uintmax_t mult, int uprefix){
return ncnmetric(val, INT_MAX, decimal, buf, omitdec, mult, uprefix);
}

@ -125,35 +125,6 @@ notcurses_stop_minimal(void* vnc){
return ret;
}
// make a heap-allocated wchar_t expansion of the multibyte string at s
wchar_t* wchar_from_utf8(const char* s){
mbstate_t ps;
memset(&ps, 0, sizeof(ps));
// worst case is a wchar_t for every byte of input (all-ASCII case)
const size_t maxw = strlen(s) + 1;
wchar_t* dst = malloc(sizeof(*dst) * maxw);
size_t wcount = mbsrtowcs(dst, &s, maxw, &ps);
if(wcount == (size_t)-1){
free(dst);
return NULL;
}
if(s){
free(dst);
return NULL;
}
return dst;
}
int ncplane_putstr_aligned(ncplane* n, int y, ncalign_e align, const char* s){
wchar_t* w = wchar_from_utf8(s);
if(w == NULL){
return -1;
}
int r = ncplane_putwstr_aligned(n, y, align, w);
free(w);
return r;
}
static const char NOTCURSES_VERSION[] =
NOTCURSES_VERSION_MAJOR "."
NOTCURSES_VERSION_MINOR "."
@ -605,20 +576,6 @@ ncplane* ncpile_create(notcurses* nc, const struct ncplane_options* nopts){
return ncplane_new_internal(nc, NULL, nopts);
}
struct ncplane* ncplane_new(struct ncplane* n, int rows, int cols, int y, int x, void* opaque, const char* name){
ncplane_options nopts = {
.y = y,
.x = x,
.rows = rows,
.cols = cols,
.userptr = opaque,
.name = name,
.resizecb = NULL,
.flags = 0,
};
return ncplane_create(n, &nopts);
}
void ncplane_home(ncplane* n){
n->x = 0;
n->y = 0;
@ -1383,32 +1340,44 @@ const char* cell_extended_gcluster(const struct ncplane* n, const nccell* c){
// 'n' ends up above 'above'
int ncplane_move_above(ncplane* restrict n, ncplane* restrict above){
if(n == above){
if(n == above){ // probably gets optimized out =/
return -1;
}
ncpile* p = ncplane_pile(n);
if(above == NULL){
ncplane_move_bottom(n);
if(n->below){
if( (n->below->above = n->above) ){
n->above->below = n->below;
}else{
p->top = n->below;
}
n->below = NULL;
if( (n->above = p->bottom) ){
n->above->below = n;
}
p->bottom = n;
}
return 0;
}
if(ncplane_pile(n) != ncplane_pile(above)){ // can't move among piles
return -1;
}
if(n->below != above){
if(p != ncplane_pile(above)){ // can't move among piles
return -1;
}
// splice out 'n'
if(n->below){
n->below->above = n->above;
}else{
ncplane_pile(n)->bottom = n->above;
p->bottom = n->above;
}
if(n->above){
n->above->below = n->below;
}else{
ncplane_pile(n)->top = n->below;
p->top = n->below;
}
if( (n->above = above->above) ){
above->above->below = n;
}else{
ncplane_pile(n)->top = n;
p->top = n;
}
above->above = n;
n->below = above;
@ -1416,33 +1385,45 @@ int ncplane_move_above(ncplane* restrict n, ncplane* restrict above){
return 0;
}
// 'n' ends up below 'below'
// 'n' ends up below 'below', or on top if 'below' == NULL
int ncplane_move_below(ncplane* restrict n, ncplane* restrict below){
if(n == below){
if(n == below){ // probably gets optimized out =/
return -1;
}
ncpile* p = ncplane_pile(n);
if(below == NULL){
ncplane_move_top(n);
if(n->above){
if( (n->above->below = n->below) ){
n->below->above = n->above;
}else{
p->bottom = n->above;
}
n->above = NULL;
if( (n->below = p->top) ){
n->below->above = n;
}
p->top = n;
}
return 0;
}
if(ncplane_pile(n) != ncplane_pile(below)){ // can't move among piles
return -1;
}
if(n->above != below){
if(p != ncplane_pile(below)){ // can't move among piles
return -1;
}
if(n->below){
n->below->above = n->above;
}else{
ncplane_pile(n)->bottom = n->above;
p->bottom = n->above;
}
if(n->above){
n->above->below = n->below;
}else{
ncplane_pile(n)->top = n->below;
p->top = n->below;
}
if( (n->below = below->below) ){
below->below->above = n;
}else{
ncplane_pile(n)->bottom = n;
p->bottom = n;
}
below->below = n;
n->above = below;
@ -1450,36 +1431,6 @@ int ncplane_move_below(ncplane* restrict n, ncplane* restrict below){
return 0;
}
void ncplane_move_top(ncplane* n){
if(n->above){
if( (n->above->below = n->below) ){
n->below->above = n->above;
}else{
ncplane_pile(n)->bottom = n->above;
}
n->above = NULL;
if( (n->below = ncplane_pile(n)->top) ){
n->below->above = n;
}
ncplane_pile(n)->top = n;
}
}
void ncplane_move_bottom(ncplane* n){
if(n->below){
if( (n->below->above = n->above) ){
n->above->below = n->below;
}else{
ncplane_pile(n)->top = n->below;
}
n->below = NULL;
if( (n->above = ncplane_pile(n)->bottom) ){
n->above->below = n;
}
ncplane_pile(n)->bottom = n;
}
}
// if above is NULL, we're moving to the bottom
int ncplane_move_family_above(ncplane* restrict n, ncplane* restrict bpoint){
ncplane* above = ncplane_above(n);
@ -1584,7 +1535,7 @@ void scroll_down(ncplane* n){
for(struct ncplane* c = n->blist ; c ; c = c->bnext){
if(!c->fixedbound){
if(ncplanes_intersect_p(n, c)){
ncplane_moverel(c, -1, 0);
ncplane_move_rel(c, -1, 0);
}
}
}
@ -1627,10 +1578,6 @@ int ncplane_scrollup_child(ncplane* n, const ncplane* child){
return ret;
}
int nccell_width(const ncplane* n __attribute__ ((unused)), const nccell* c){
return nccell_cols(c);
}
int nccell_load(ncplane* n, nccell* c, const char* gcluster){
int cols;
int bytes = utf8_egc_len(gcluster, &cols);
@ -1787,7 +1734,7 @@ int ncplane_putegc_stained(ncplane* n, const char* gclust, int* sbytes){
}
int ncplane_cursor_at(const ncplane* n, nccell* c, char** gclust){
if(n->y == n->leny && n->x == n->lenx){
if(n->y >= n->leny || n->x >= n->lenx){
return -1;
}
const nccell* src = &n->fb[nfbcellidx(n, n->y, n->x)];
@ -1800,7 +1747,7 @@ int ncplane_cursor_at(const ncplane* n, nccell* c, char** gclust){
return 0;
}
unsigned notcurses_supported_styles(const notcurses* nc){
uint16_t notcurses_supported_styles(const notcurses* nc){
return term_supported_styles(&nc->tcache);
}
@ -1821,28 +1768,16 @@ void ncplane_set_styles(ncplane* n, unsigned stylebits){
n->stylemask = (stylebits & NCSTYLE_MASK);
}
void ncplane_styles_set(ncplane* n, unsigned stylebits){ // deprecated
ncplane_set_styles(n, stylebits);
}
// turn on any specified stylebits
void ncplane_on_styles(ncplane* n, unsigned stylebits){
n->stylemask |= (stylebits & NCSTYLE_MASK);
}
void ncplane_styles_on(ncplane* n, unsigned stylebits){ // deprecated
ncplane_on_styles(n, stylebits);
}
// turn off any specified stylebits
void ncplane_off_styles(ncplane* n, unsigned stylebits){
n->stylemask &= ~(stylebits & NCSTYLE_MASK);
}
void ncplane_styles_off(ncplane* n, unsigned stylebits){ // deprecated
ncplane_off_styles(n, stylebits);
}
// i hate the big allocation and two copies here, but eh what you gonna do?
// well, for one, we don't need the huge allocation FIXME
char* ncplane_vprintf_prep(const char* format, va_list ap){
@ -1904,6 +1839,13 @@ int ncplane_vprintf_stained(struct ncplane* n, const char* format, va_list ap){
return ret;
}
int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align, size_t s, const char* str){
char* chopped = strndup(str, s);
int ret = ncplane_putstr_aligned(n, y, align, chopped);
free(chopped);
return ret;
}
int ncplane_hline_interp(ncplane* n, const nccell* c, unsigned len,
uint64_t c1, uint64_t c2){
if(len <= 0){
@ -2370,10 +2312,6 @@ ncpalette* ncpalette_new(notcurses* nc){
return p;
}
ncpalette* palette256_new(notcurses* nc){
return ncpalette_new(nc);
}
int ncpalette_use(notcurses* nc, const ncpalette* p){
int ret = -1;
if(!notcurses_canchangecolor(nc)){
@ -2389,18 +2327,10 @@ int ncpalette_use(notcurses* nc, const ncpalette* p){
return ret;
}
int palette256_use(notcurses* nc, const ncpalette* p){
return ncpalette_use(nc, p);
}
void ncpalette_free(ncpalette* p){
free(p);
}
void palette256_free(ncpalette* p){
ncpalette_free(p);
}
bool ncplane_translate_abs(const ncplane* n, int* restrict y, int* restrict x){
ncplane_translate(ncplane_stdplane_const(n), n, y, x);
if(y){
@ -3006,32 +2936,6 @@ char* ncplane_contents(ncplane* nc, int begy, int begx, unsigned leny, unsigned
return ret;
}
int nccells_double_box(ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
if(notcurses_canutf8(ncplane_notcurses(n))){
return nccells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, NCBOXDOUBLE);
}
return nccells_ascii_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
int cells_double_box(ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
return nccells_double_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
int nccells_rounded_box(ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
if(notcurses_canutf8(ncplane_notcurses(n))){
return nccells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, NCBOXROUND);
}
return nccells_ascii_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
int cells_rounded_box(ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){
return nccells_rounded_box(n, attr, channels, ul, ur, ll, lr, hl, vl);
}
// find the center coordinate of a plane, preferring the top/left in the
// case of an even number of rows/columns (in such a case, there will be one
// more cell to the bottom/right of the center than the top/left). the
@ -3053,45 +2957,6 @@ void nclog(const char* fmt, ...){
va_end(va);
}
int ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclusters){
int ret = 0;
while(*gclusters){
int wcs;
int cols = ncplane_putegc_yx(n, y, x, gclusters, &wcs);
//fprintf(stderr, "wrote %.*s %d cols %d bytes now at %d/%d\n", wcs, gclusters, cols, wcs, n->y, n->x);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
// after the first iteration, just let the cursor code control where we
// print, so that scrolling is taken into account
y = -1;
x = -1;
gclusters += wcs;
ret += cols;
}
return ret;
}
int ncplane_putstr_stained(struct ncplane* n, const char* gclusters){
int ret = 0;
while(*gclusters){
int wcs;
int cols = ncplane_putegc_stained(n, gclusters, &wcs);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
gclusters += wcs;
ret += cols;
}
return ret;
}
int ncplane_putwstr_stained(ncplane* n, const wchar_t* gclustarr){
mbstate_t ps = {};
const wchar_t** wset = &gclustarr;
@ -3115,36 +2980,6 @@ int ncplane_putwstr_stained(ncplane* n, const wchar_t* gclustarr){
return r;
}
int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align, size_t s, const char* str){
char* chopped = strndup(str, s);
int ret = ncplane_putstr_aligned(n, y, align, chopped);
free(chopped);
return ret;
}
int ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters){
int ret = 0;
int offset = 0;
//fprintf(stderr, "PUT %zu at %d/%d [%.*s]\n", s, y, x, (int)s, gclusters);
while((size_t)offset < s && gclusters[offset]){
int wcs;
int cols = ncplane_putegc_yx(n, y, x, gclusters + offset, &wcs);
if(cols < 0){
return -ret;
}
if(wcs == 0){
break;
}
// after the first iteration, just let the cursor code control where we
// print, so that scrolling is taken into account
y = -1;
x = -1;
offset += wcs;
ret += cols;
}
return ret;
}
int notcurses_ucs32_to_utf8(const uint32_t* ucs32, unsigned ucs32count,
unsigned char* resultbuf, size_t buflen){
if(u32_to_u8(ucs32, ucs32count, resultbuf, &buflen) == NULL){
@ -3153,19 +2988,17 @@ int notcurses_ucs32_to_utf8(const uint32_t* ucs32, unsigned ucs32count,
return buflen;
}
int ncstrwidth(const char* mbs){
return ncstrwidth_valid(mbs, NULL, NULL);
}
int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){
int cols = 0; // number of columns consumed thus far
int cols;
if(validwidth == NULL){
validwidth = &cols;
}
int bytes = 0; // number of bytes consumed thus far
*validwidth = 0;
int bytes;
if(validbytes == NULL){
validbytes = &bytes;
}
*validbytes = 0;
do{
int thesecols, thesebytes;
thesebytes = utf8_egc_len(egcs, &thesecols);
@ -3179,9 +3012,10 @@ int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){
return *validwidth;
}
void ncplane_pixelgeom(const ncplane* n, unsigned* RESTRICT pxy, unsigned* RESTRICT pxx,
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx){
void ncplane_pixel_geom(const ncplane* n,
unsigned* RESTRICT pxy, unsigned* RESTRICT pxx,
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx){
notcurses* nc = ncplane_notcurses(n);
if(celldimy){
*celldimy = nc->tcache.cellpixy;

@ -127,12 +127,12 @@ int redraw_pixelplot_##T(nc##X##plot* ncp){ \
char buf[NCPREFIXSTRLEN + 1]; \
if(ncp->plot.exponentiali){ \
if(y == dimy - 1){ /* we cheat on the top row to exactly match maxy */ \
ncmetric(ncp->maxy * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix(ncp->maxy * 100, 100, buf, 0); \
}else{ \
ncmetric(pow(interval, (y + 1) * states) * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix(pow(interval, (y + 1) * states) * 100, 100, buf, 0); \
} \
}else{ \
ncmetric((ncp->maxy - interval * states * (dimy - y - 1)) * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix((ncp->maxy - interval * states * (dimy - y - 1)) * 100, 100, buf, 0); \
} \
if(y == dimy - 1 && strlen(ncp->plot.title)){ \
ncplane_printf_yx(ncp->plot.ncp, dimy - y - 1, 0, "%*.*s %s", \
@ -297,12 +297,12 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
char buf[NCPREFIXSTRLEN + 1]; \
if(ncp->plot.exponentiali){ \
if(y == dimy - 1){ /* we cheat on the top row to exactly match maxy */ \
ncmetric(ncp->maxy * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix(ncp->maxy * 100, 100, buf, 0); \
}else{ \
ncmetric(pow(interval, (y + 1) * states) * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix(pow(interval, (y + 1) * states) * 100, 100, buf, 0); \
} \
}else{ \
ncmetric((ncp->maxy - interval * states * (dimy - y - 1)) * 100, 100, buf, 0, 1000, '\0'); \
ncqprefix((ncp->maxy - interval * states * (dimy - y - 1)) * 100, 100, buf, 0); \
} \
if(y == dimy - 1 && strlen(ncp->plot.title)){ \
ncplane_printf_yx(ncp->plot.ncp, dimy - y - 1, NCPREFIXCOLUMNS - strlen(buf), "%s %s", buf, ncp->plot.title); \

@ -754,10 +754,6 @@ ncplane* nctablet_plane(nctablet* t){
return t->cbp;
}
ncplane* nctablet_ncplane(nctablet* t){ // deprecated
return nctablet_plane(t);
}
ncplane* ncreel_plane(ncreel* nr){
return nr->p;
}

@ -122,11 +122,6 @@ void nccell_release(ncplane* n, nccell* c){
pool_release(&n->pool, c);
}
// FIXME deprecated, goes away in abi3
void cell_release(ncplane* n, nccell* c){
nccell_release(n, c);
}
// Duplicate one cell onto another when they share a plane. Convenience wrapper.
int nccell_duplicate(ncplane* n, nccell* targ, const nccell* c){
if(cell_duplicate_far(&n->pool, targ, n, c) < 0){
@ -136,11 +131,6 @@ int nccell_duplicate(ncplane* n, nccell* targ, const nccell* c){
return 0;
}
// deprecated, goes away in abi3
int cell_duplicate(struct ncplane* n, nccell* targ, const nccell* c){
return nccell_duplicate(n, targ, c);
}
// Emit fchannel with RGB changed to contrast effectively against bchannel.
static uint32_t
highcontrast(const tinfo* ti, uint32_t bchannel){
@ -1458,10 +1448,6 @@ int ncpile_render_to_file(ncplane* n, FILE* fp){
return ret;
}
int notcurses_render_to_file(notcurses* nc, FILE* fp){
return ncpile_render_to_file(notcurses_stdplane(nc), fp);
}
// We execute the painter's algorithm, starting from our topmost plane. The
// damagevector should be all zeros on input. On success, it will reflect
// which cells were changed. We solve for each coordinate's cell by walking
@ -1505,7 +1491,7 @@ int ncpile_rasterize(ncplane* n){
// accepts -1 as an indication of failure
clock_gettime(CLOCK_MONOTONIC, &writedone);
pthread_mutex_lock(&nc->stats.lock);
update_render_bytes(&nc->stats.s, bytes);
update_raster_bytes(&nc->stats.s, bytes);
update_raster_stats(&rasterdone, &start, &nc->stats.s);
update_write_stats(&writedone, &rasterdone, &nc->stats.s, bytes);
pthread_mutex_unlock(&nc->stats.lock);
@ -1556,18 +1542,6 @@ int ncpile_render(ncplane* n){
return 0;
}
int notcurses_render(notcurses* nc){
//fprintf(stderr, "--------------- BEGIN RENDER\n");
//notcurses_debug(nc, stderr);
ncplane* stdn = notcurses_stdplane(nc);
if(ncpile_render(stdn)){
return -1;
}
int i = ncpile_rasterize(stdn);
//fprintf(stderr, "----------------- END RENDER\n");
return i;
}
// run the top half of notcurses_render(), and steal the buffer from rstate.
int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
if(ncpile_render(p)){
@ -1578,7 +1552,7 @@ int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
fbuf_reset(&nc->rstate.f);
int bytes = notcurses_rasterize_inner(nc, ncplane_pile(p), &nc->rstate.f, &useasu);
pthread_mutex_lock(&nc->stats.lock);
update_render_bytes(&nc->stats.s, bytes);
update_raster_bytes(&nc->stats.s, bytes);
pthread_mutex_unlock(&nc->stats.lock);
if(bytes < 0){
return -1;
@ -1589,10 +1563,6 @@ int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
return 0;
}
int notcurses_render_to_buffer(notcurses* nc, char** buf, size_t* buflen){
return ncpile_render_to_buffer(notcurses_stdplane(nc), buf, buflen);
}
// copy the UTF8-encoded EGC out of the cell, whether simple or complex. the
// result is not tied to the ncplane, and persists across erases / destruction.
static inline char*

@ -22,16 +22,16 @@ void update_write_stats(const struct timespec* time1, const struct timespec* tim
}
// negative 'bytes' are ignored as failures. call only while holding statlock.
// we don't increment failed_renders here because 'bytes' < 0 actually indicates
// a rasterization failure -- we can't fail in rendering anymore.
void update_render_bytes(ncstats* stats, int bytes){
// we don't increment failed_rasters here because 'bytes' < 0 actually indicates
// a rasterization failure -- we can't fail in rastering anymore.
void update_raster_bytes(ncstats* stats, int bytes){
if(bytes >= 0){
stats->render_bytes += bytes;
if(bytes > stats->render_max_bytes){
stats->render_max_bytes = bytes;
stats->raster_bytes += bytes;
if(bytes > stats->raster_max_bytes){
stats->raster_max_bytes = bytes;
}
if(bytes < stats->render_min_bytes){
stats->render_min_bytes = bytes;
if(bytes < stats->raster_min_bytes){
stats->raster_min_bytes = bytes;
}
}
}
@ -76,7 +76,7 @@ void reset_stats(ncstats* stats){
unsigned planes = stats->planes;
memset(stats, 0, sizeof(*stats));
stats->render_min_ns = 1ull << 62u;
stats->render_min_bytes = 1ull << 62u;
stats->raster_min_bytes = 1ull << 62u;
stats->raster_min_ns = 1ull << 62u;
stats->writeout_min_ns = 1ull << 62u;
stats->fbbytes = fbbytes;
@ -108,8 +108,8 @@ void notcurses_stats_reset(notcurses* nc, ncstats* stats){
if(nc->stats.s.render_min_ns < stash->render_min_ns){
stash->render_min_ns = nc->stats.s.render_min_ns;
}
if(nc->stats.s.render_min_bytes < stash->render_min_bytes){
stash->render_min_bytes = nc->stats.s.render_min_bytes;
if(nc->stats.s.raster_min_bytes < stash->raster_min_bytes){
stash->raster_min_bytes = nc->stats.s.raster_min_bytes;
}
if(nc->stats.s.raster_min_ns < stash->raster_min_ns){
stash->raster_min_ns = nc->stats.s.raster_min_ns;
@ -120,8 +120,8 @@ void notcurses_stats_reset(notcurses* nc, ncstats* stats){
if(nc->stats.s.render_max_ns > stash->render_max_ns){
stash->render_max_ns = nc->stats.s.render_max_ns;
}
if(nc->stats.s.render_max_bytes > stash->render_max_bytes){
stash->render_max_bytes = nc->stats.s.render_max_bytes;
if(nc->stats.s.raster_max_bytes > stash->raster_max_bytes){
stash->raster_max_bytes = nc->stats.s.raster_max_bytes;
}
if(nc->stats.s.raster_max_ns > stash->raster_max_ns){
stash->raster_max_ns = nc->stats.s.raster_max_ns;
@ -132,7 +132,7 @@ void notcurses_stats_reset(notcurses* nc, ncstats* stats){
stash->writeout_ns += nc->stats.s.writeout_ns;
stash->raster_ns += nc->stats.s.raster_ns;
stash->render_ns += nc->stats.s.render_ns;
stash->render_bytes += nc->stats.s.render_bytes;
stash->raster_bytes += nc->stats.s.raster_bytes;
stash->failed_renders += nc->stats.s.failed_renders;
stash->failed_writeouts += nc->stats.s.failed_writeouts;
stash->renders += nc->stats.s.renders;
@ -199,11 +199,11 @@ void summarize_stats(notcurses* nc){
totalbuf, minbuf, avgbuf, maxbuf);
}
if(stats->renders || stats->input_events){
ncbprefix(stats->render_bytes, 1, totalbuf, 1),
ncbprefix(stats->render_bytes ? stats->render_min_bytes : 0,
1, minbuf, 1),
ncbprefix(stats->renders ? stats->render_bytes / stats->renders : 0, 1, avgbuf, 1);
ncbprefix(stats->render_max_bytes, 1, maxbuf, 1),
ncbprefix(stats->raster_bytes, 1, totalbuf, 1),
ncbprefix(stats->raster_bytes ? stats->raster_min_bytes : 0,
1, minbuf, 1),
ncbprefix(stats->renders ? stats->raster_bytes / stats->renders : 0, 1, avgbuf, 1);
ncbprefix(stats->raster_max_bytes, 1, maxbuf, 1),
fprintf(stderr, "%s%sB (%sB min, %sB avg, %sB max) %"PRIu64" input%s Ghpa: %"PRIu64 NL,
clreol, totalbuf, minbuf, avgbuf, maxbuf,
stats->input_events,
@ -240,7 +240,7 @@ void summarize_stats(notcurses* nc){
(stats->sprixelemissions + stats->sprixelelisions) == 0 ? 0 :
(stats->sprixelelisions * 100.0) / (stats->sprixelemissions + stats->sprixelelisions),
totalbuf,
stats->render_bytes ? (stats->sprixelbytes * 100.0) / stats->render_bytes : 0,
stats->raster_bytes ? (stats->sprixelbytes * 100.0) / stats->raster_bytes : 0,
stats->appsync_updates,
stats->writeouts ? stats->appsync_updates * 100.0 / stats->writeouts : 0);
}

@ -832,8 +832,10 @@ int interrogate_terminfo(tinfo* ti, FILE* out, unsigned utf8,
logpanic("failed opening Windows ConPTY\n");
return -1;
}
if(cursor_y && cursor_x){
locate_cursor(ti, cursor_y, cursor_x);
unsigned ucy, ucx;
if(locate_cursor(ti, &ucy, &ucx) == 0){
*cursor_y = ucy;
*cursor_x = ucx;
}
#elif defined(__linux__)
ti->linux_fb_fd = -1;

@ -221,7 +221,7 @@ get_escape(const tinfo* tdesc, escape_e e){
return NULL;
}
static inline int
static inline uint16_t
term_supported_styles(const tinfo* ti){
return ti->supported_styles;
}

@ -70,11 +70,6 @@ ncplane* ncvisual_subtitle_plane(ncplane* parent, const ncvisual* ncv){
return visual_implementation.visual_subtitle(parent, ncv);
}
char* ncvisual_subtitle(const ncvisual* ncv){
(void)ncv; // FIXME remove for abi3
return NULL;
}
int ncvisual_blit_internal(ncvisual* ncv, int rows, int cols, ncplane* n,
const struct blitset* bset, const blitterargs* barg){
if(!(barg->flags & NCVISUAL_OPTION_NOINTERPOLATE)){
@ -127,38 +122,6 @@ ncvisual_origin(const struct ncvisual_options* vopts, unsigned* restrict begy,
*begx = vopts ? vopts->begx : 0;
}
int ncvisual_blitter_geom(const notcurses* nc, const ncvisual* n,
const struct ncvisual_options* vopts,
int* y, int* x, int* scaley, int* scalex,
ncblitter_e* blitter){
ncvgeom geom;
const struct blitset* bset;
unsigned disppxy, disppxx, outy, outx;
int placey, placex;
if(ncvisual_geom_inner(&nc->tcache, n, vopts, &geom, &bset,
&disppxy, &disppxx, &outy, &outx,
&placey, &placex)){
return -1;
}
if(y){
*y = geom.pixy;
}
if(x){
*x = geom.pixx;
}
if(scaley){
*scaley = geom.scaley;
}
if(scalex){
*scalex = geom.scalex;
}
if(blitter){
*blitter = bset->geom;
}
return 0;
}
// create a plane in which to blit the sprixel. |disppixx| and |disppixy| are
// scaled pixel geometry on output, and unused on input. |placey| and |placex|
// are used to position the new plane, and reset to 0 on output. |outy| and
@ -1175,23 +1138,6 @@ ncplane* ncvisual_blit(notcurses* nc, ncvisual* ncv, const struct ncvisual_optio
return n;
}
// compatability wrapper around ncvisual_blit that provides the standard plane
// plus NCVISUAL_OPTION_CHILDPLANE if vopts->n is NULL.
ncplane* ncvisual_render(notcurses* nc, ncvisual* ncv, const struct ncvisual_options* vopts){
struct ncvisual_options fakevopts;
if(vopts == NULL){
memset(&fakevopts, 0, sizeof(fakevopts));
}else{
memcpy(&fakevopts, vopts, sizeof(fakevopts));
}
vopts = &fakevopts;
if(vopts->n == NULL){
fakevopts.n = notcurses_stdplane(nc);
fakevopts.flags |= NCVISUAL_OPTION_CHILDPLANE;
}
return ncvisual_blit(nc, ncv, vopts);
}
ncvisual* ncvisual_from_plane(const ncplane* n, ncblitter_e blit,
int begy, int begx,
unsigned leny, unsigned lenx){
@ -1345,10 +1291,3 @@ bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))){
}
return visual_implementation.canopen_videos;
}
int ncvisual_inflate(ncvisual* n, int scale){
if(scale <= 0){
return -1;
}
return ncvisual_resize_noninterpolative(n, n->pixy * scale, n->pixx * scale);
}

@ -5,7 +5,6 @@ using namespace ncpp;
notcurses_options NotCurses::default_notcurses_options = {
/* termtype */ nullptr,
/* renderfp */ nullptr,
/* loglevel */ NCLogLevel::Silent,
/* margin_t */ 0,
/* margin_r */ 0,

@ -12,8 +12,8 @@ emit(struct ncplane* n, const char* str){
static int
wipebitmap(struct notcurses* nc){
unsigned cellpxy, cellpxx;
ncplane_pixelgeom(notcurses_stdplane(nc), NULL, NULL,
&cellpxy, &cellpxx, NULL, NULL);
ncplane_pixel_geom(notcurses_stdplane(nc), NULL, NULL,
&cellpxy, &cellpxx, NULL, NULL);
int pixy = cellpxy * 6;
int pixx = cellpxx * 6;
uint32_t* pixels = malloc(sizeof(*pixels) * pixx * pixy);

@ -4,7 +4,7 @@ struct ncvisual*
draw_grid(struct ncplane* stdn){
unsigned maxby, maxbx;
unsigned cellpxy, cellpxx;
ncplane_pixelgeom(stdn, NULL, NULL, &cellpxy, &cellpxx, &maxby, &maxbx);
ncplane_pixel_geom(stdn, NULL, NULL, &cellpxy, &cellpxx, &maxby, &maxbx);
if(cellpxy <= 1 || cellpxx <= 1){
fprintf(stderr, "cell-pixel geometry: %d %d\n", cellpxy, cellpxx);
return NULL;

@ -105,14 +105,14 @@ int main(void){
}
struct ncplane* stdn = notcurses_stdplane(nc);
unsigned cellpixy, cellpixx;
ncplane_pixelgeom(stdn, NULL, NULL, &cellpixy, &cellpixx, NULL, NULL);
ncplane_pixel_geom(stdn, NULL, NULL, &cellpixy, &cellpixx, NULL, NULL);
if(interp(nc, cellpixy, cellpixx)){
goto err;
}
ncinput ni;
do{
notcurses_getc_blocking(nc, &ni);
}while(ni.evtype == NCTYPE_RELEASE);
}while(ni.id != (uint32_t)-1 && ni.evtype != NCTYPE_RELEASE);
notcurses_stop(nc);
return EXIT_SUCCESS;

@ -53,7 +53,7 @@ TEST_CASE("Bitmaps") {
vopts.blitter = NCBLIT_PIXEL;
vopts.flags = NCVISUAL_OPTION_NODEGRADE;
unsigned maxy, maxx;
ncplane_pixelgeom(n_, nullptr, nullptr, nullptr, nullptr, &maxy, &maxx);
ncplane_pixel_geom(n_, nullptr, nullptr, nullptr, nullptr, &maxy, &maxx);
CHECK(0 == ncvisual_resize(ncv, maxy, maxx));
auto n = ncvisual_blit(nc_, ncv, &vopts);
REQUIRE(nn == n);
@ -306,8 +306,8 @@ TEST_CASE("Bitmaps") {
vopts.x = 5;
vopts.scaling = NCSCALE_NONE;
auto ninf = ncvisual_blit(nc_, ncv, &vopts);
ncplane_set_name(ninf, "ninf");
REQUIRE(nullptr != ninf);
ncplane_set_name(ninf, "ninf");
// y of scaled might not be exactly equal to y of inflated since one
// is based around what can be fit into a specific space, whereas the
// other is based on a multiple of the original image size, which might

@ -10,7 +10,7 @@ char* impericize_ncmetric(uintmax_t val, uintmax_t decimal, char* buf,
const char* decisep = localeconv()->decimal_point;
REQUIRE(decisep);
REQUIRE(1 == strlen(decisep));
REQUIRE(ncmetric(val, decimal, buf, omitdec, mult, uprefix));
REQUIRE(ncnmetric(val, INT_MAX, decimal, buf, omitdec, mult, uprefix));
char* commie = buf;
while( (commie = strstr(commie, decisep)) ){
*commie = '.'; // https://dank.qemfd.net/images/16whcc.jpg
@ -89,20 +89,20 @@ TEST_CASE("Metric") {
SUBCASE("Maxints1024") {
char buf[NCPREFIXSTRLEN + 1], gold[NCPREFIXSTRLEN + 1];
// FIXME these will change based on the size of intmax_t and uintmax_t
REQUIRE(ncmetric(((double)(INTMAX_MAX - 1ull)), 1, buf, 0, 1024, 'i'));
REQUIRE(ncbprefix(((double)(INTMAX_MAX - 1ull)), 1, buf, 0));
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - 1ull)) / (1ull << 60));
CHECK(!strcmp(gold, buf));
REQUIRE(ncmetric(((double)(INTMAX_MAX - (1ull << 53))), 1, buf, 0, 1024, 'i'));
REQUIRE(ncbprefix(((double)(INTMAX_MAX - (1ull << 53))), 1, buf, 0));
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - (1ull << 53))) / (1ull << 60));
CHECK(!strcmp(gold, buf));
REQUIRE(ncmetric(INTMAX_MAX + 1ull, 1, buf, 0, 1024, 'i'));
REQUIRE(ncbprefix(INTMAX_MAX + 1ull, 1, buf, 0));
sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX + 1ull)) / (1ull << 60));
CHECK(!strcmp(gold, buf));
impericize_ncmetric(UINTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
CHECK(!strcmp("16.00Ei", buf));
impericize_ncmetric(UINTMAX_MAX, 1, buf, 0, 1024, 'i');
CHECK(!strcmp("16.00Ei", buf));
ncmetric(UINTMAX_MAX - (1ull << 53), 1, buf, 0, 1024, 'i');
ncbprefix(UINTMAX_MAX - (1ull << 53), 1, buf, 0);
sprintf(gold, "%.2fEi", ((double)UINTMAX_MAX - (1ull << 53)) / (1ull << 60));
CHECK(!strcmp(gold, buf));
}
@ -116,7 +116,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 0, 1000, '\0');
ncqprefix(val, 1, buf, 0);
const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%ju%s00%c", goldval, decisep, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -139,7 +139,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 1, 1000, '\0');
ncqprefix(val, 1, buf, 1);
const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%ju%c", goldval, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -162,7 +162,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 0, 1024, 'i');
ncbprefix(val, 1, buf, 0);
const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%ju%s00%ci", goldval, decisep, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -185,7 +185,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 1, 1024, 'i');
ncbprefix(val, 1, buf, 1);
const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%ju%ci", goldval, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -208,7 +208,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 0, 1000, '\0');
ncqprefix(val, 1, buf, 0);
const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)val) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -231,7 +231,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val, 1, buf, 0, 1024, 'i');
ncbprefix(val, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%ci", ((double)val) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -254,7 +254,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val - 1, 1, buf, 0, 1000, '\0');
ncqprefix(val - 1, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val - 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -277,7 +277,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val + 1, 1, buf, 0, 1000, '\0');
ncqprefix(val + 1, 1, buf, 0);
const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val + 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf));
@ -300,7 +300,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1;
size_t i = 0;
do{
ncmetric(val - 1, 1, buf, 0, 1024, 'i');
ncbprefix(val - 1, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%ci", ((double)(val - 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf));

@ -1051,22 +1051,22 @@ TEST_CASE("Plane") {
CHECK(x == 2);
CHECK(1 == ncplane_set_base(n, " ", 0, channels));
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_moverel(n, -1, 0)); // up
CHECK(0 == ncplane_move_rel(n, -1, 0)); // up
ncplane_yx(n, &y, &x);
CHECK(y == 1);
CHECK(x == 2);
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_moverel(n, 2, 0)); // down
CHECK(0 == ncplane_move_rel(n, 2, 0)); // down
ncplane_yx(n, &y, &x);
CHECK(y == 3);
CHECK(x == 2);
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_moverel(n, 0, -1)); // left
CHECK(0 == ncplane_move_rel(n, 0, -1)); // left
ncplane_yx(n, &y, &x);
CHECK(y == 3);
CHECK(x == 1);
CHECK(0 == notcurses_render(nc_));
CHECK(0 == ncplane_moverel(n, 0, 2)); // right
CHECK(0 == ncplane_move_rel(n, 0, 2)); // right
ncplane_yx(n, &y, &x);
CHECK(y == 3);
CHECK(x == 3);

Loading…
Cancel
Save