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 without an obvious replacement is the `renderfp` field of
`notcurses_options`, for which I make no apology. If you've been avoiding `notcurses_options`, for which I make no apology. If you've been avoiding
deprecated functionality, ABI3 ought require small changes, if any. 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) * 2.4.9 (not yet released)
* Added `ncnmetric()`, which uses `snprintf()` internally. `ncmetric()` * 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 `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 former, passing 0 as the event mask. This can be used to get mouse
movement buttons and focus events, which were previously unavailable. 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 * `ncvisual_geom()` has been introduced, using the `ncvgeom` struct
introduced for direct mode. This allows complete statement of geometry introduced for direct mode. This allows complete statement of geometry
for an `ncvisual`. It replaces `ncvisual_blitter_geom()`, which has been 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 * `notcurses_detected_terminal()` and `ncdirect_detected_terminal()` now
both return a heap-allocated string, which will contain the terminal 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. 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 * Documented `ncplane_move_yx()` in `notcurses_plane.3`, and removed the
false comment that "passing -1 as a coordinate will hold that axis false comment that "passing -1 as a coordinate will hold that axis
constant" from `USAGE.md` and `notcurses.h`. This has never been true. 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. // must be freed by the caller.
int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen); int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen);
// Write the last rendered frame, in its entirety, to 'fp'. If // Write the last rendered frame, in its entirety, to 'fp'. If a frame has
// notcurses_render() has not yet been called, nothing will be written. // 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); int ncpile_render_to_file(struct ncplane* p, FILE* fp);
// Retrieve the contents of the specified cell as last rendered. The EGC is // 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 // Move this plane relative to its current location. Negative values move up
// and left, respectively. Pass 0 to hold an axis constant. // and left, respectively. Pass 0 to hold an axis constant.
__attribute__ ((nonnull (1))) static inline int __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; int oy, ox;
ncplane_yx(n, &oy, &ox); ncplane_yx(n, &oy, &ox);
return ncplane_move_yx(n, oy + y, ox + x); 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', // ('celldimy', 'celldimx'), and the maximum displayable bitmap ('maxbmapy',
// 'maxbmapx'). If bitmaps are not supported, 'maxbmapy' and 'maxbmapx' will // 'maxbmapx'). If bitmaps are not supported, 'maxbmapy' and 'maxbmapx' will
// be 0. Any of the geometry arguments may be NULL. // be 0. Any of the geometry arguments may be NULL.
void ncplane_pixelgeom(struct ncplane* n, void ncplane_pixel_geom(struct ncplane* n,
unsigned* restrict pxy, unsigned* restrict pxx, unsigned* restrict pxy, unsigned* restrict pxx,
unsigned* restrict celldimy, unsigned* restrict celldimx, unsigned* restrict celldimy, unsigned* restrict celldimx,
unsigned* restrict maxbmapy, unsigned* restrict maxbmapx); unsigned* restrict maxbmapy, unsigned* restrict maxbmapx);
// provided a coordinate relative to the origin of 'src', map it to the same // 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' // 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 ```c
// Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or bottom. // Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or bottom.
void ncplane_move_top(struct ncplane* n); __attribute__ ((nonnull (1)))
void ncplane_move_bottom(struct ncplane* n); 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 // 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 // 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 writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0 uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes uint64_t failed_writeouts; // aborted writes
uint64_t render_bytes; // bytes emitted to ttyfp uint64_t raster_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame int64_t raster_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max 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+raster for a frame int64_t render_min_ns; // min ns spent in render for a frame
uint64_t raster_ns; // nanoseconds spent rasterizing uint64_t raster_ns; // nanoseconds spent rasterizing
int64_t raster_max_ns; // max ns spent in raster for a frame 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 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 sprixelemissions; // sprixel draw count
uint64_t sprixelelisions; // sprixel elision count uint64_t sprixelelisions; // sprixel elision count
uint64_t sprixelbytes; // sprixel bytes emitted 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_errors; // errors processing control sequences/utf8
uint64_t input_events; // characters returned to userspace
uint64_t hpa_gratuitous; // unnecessary hpas issued uint64_t hpa_gratuitous; // unnecessary hpas issued
// current state -- these can decrease // 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 by examining the output of **notcurses-info(1)**. If the **kbd** property
is indicated, you're using the Kitty protocol. 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 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. 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) #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***);** **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 range 1e24 (one septillion) through 1e-24, sufficing for all possible values of
a 64-bit **uintmax_t**. a 64-bit **uintmax_t**.
**val** is the value being output, having been scaled by **decimal**. ***val*** is the value being output, having been scaled by ***decimal***.
**decimal** will typically be 1; to represent values less than 1, **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 should be larger than ***val***. The output will be written to ***buf***, which
must be at least: must be at least:
* **NCPREFIXSTRLEN** + 1 bytes for a 1000-based value * **NCPREFIXSTRLEN** + 1 bytes for a 1000-based value
* **NCIPREFIXSTRLEN** + 1 bytes for a 1024-based value * **NCIPREFIXSTRLEN** + 1 bytes for a 1024-based value
* **NCBPREFIXSTRLEN** + 1 bytes for a 1024-based value with an 'i' suffix * **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: 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 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 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)**). 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. will be used as a suffix following any metric suffix.
The maximum number of columns is not directly related to the maximum number of 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 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 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 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 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 **C**. This minimal form can occur if ***omitdec*** is non-zero and a
single-column value such as 5 is passed for **val**. single-column value such as 5 is passed for ***val***.
Three more defines are provided to simplify formatted fixed-width output using Three more defines are provided to simplify formatted fixed-width output using
the results of **ncmetric**. Each of these macros accepts a character buffer 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 # 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. filled in with the formatted output.
# EXAMPLES # 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 # BUGS
@ -143,4 +146,5 @@ This function is difficult to understand.
**localeconv(3)**, **localeconv(3)**,
**notcurses(3)**, **notcurses(3)**,
**notcurses_output(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_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***);** **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***);** **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***);** **void ncplane_move_family_top(struct ncplane* ***n***);**
@ -225,7 +225,7 @@ typedef struct ncplane_options {
**int ncplane_rotate_ccw(struct ncplane* ***n***);** **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***);** **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 ## 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 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). the size of a cell in pixels (these ought be the same across planes).
**maxbmapy** and **maxbmapx** describe the largest bitmap which can be **maxbmapy** and **maxbmapx** describe the largest bitmap which can be
@ -505,9 +505,6 @@ All other functions cannot fail (and return **void**).
# NOTES # NOTES
**ncplane_new** is defined as a deprecated wrapper around **ncplane_create**.
It should not be used in new code.
# BUGS # BUGS
**ncplane_at_yx** doesn't yet account for bitmap-based graphics (see **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 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 requires synthesizing a set of UTF-8-encoded characters and escape codes
appropriate for the terminal (relying on terminfo(5)), and writing this 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 sequence to the output **FILE**.
original call to **notcurses_init**, the frame will be written to that **FILE**
as well. This write does not affect statistics.
Each cell can be rendered in isolation, though synthesis of the stream carries Each cell can be rendered in isolation, though synthesis of the stream carries
dependencies between cells. dependencies between cells.

@ -17,9 +17,9 @@ typedef struct ncstats {
uint64_t writeouts; // successful ncpile_rasterize() runs uint64_t writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0 uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes uint64_t failed_writeouts; // aborted writes
uint64_t render_bytes; // bytes emitted to ttyfp uint64_t raster_bytes; // bytes emitted to ttyfp
int64_t render_max_bytes; // max bytes emitted for a frame int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame int64_t raster_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max ns spent for a frame int64_t render_max_ns; // max ns spent for a frame
int64_t render_min_ns; // min 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, should **notcurses_render(3)** fail while writing out a frame to the terminal,
it counts as a failed render. 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 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 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 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 instead directly into the memory-mapped framebuffer (see **mmap(2)**). Bytes
used for framebuffer graphics are thus independent of bytes written to the used for framebuffer graphics are thus independent of bytes written to the
terminal. This explains why **sprixelbytes** may be surprising given the terminal. This explains why **sprixelbytes** may be surprising given the
value of **render_bytes**. value of **raster_bytes**.
# RETURN VALUES # 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 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 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) API int ncdirect_set_bg_rgb(struct ncdirect* nc, unsigned rgb)
__attribute__ ((nonnull (1))); __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) API int ncdirect_set_fg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
API int ncdirect_set_bg_palindex(struct ncdirect* nc, int pidx) API int ncdirect_set_bg_palindex(struct ncdirect* nc, int pidx)
__attribute__ ((nonnull (1))); __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 // Returns the number of simultaneous colors claimed to be supported, or 1 if
// there is no color support. Note that several terminal emulators advertise // there is no color support. Note that several terminal emulators advertise
// more colors than they actually support, downsampling internally. // 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); 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) API int ncdirect_set_fg_default(struct ncdirect* nc)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
API int ncdirect_set_bg_default(struct ncdirect* nc) API int ncdirect_set_bg_default(struct ncdirect* nc)
__attribute__ ((nonnull (1))); __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. // Get the current number of columns/rows.
API unsigned ncdirect_dim_x(struct ncdirect* nc) __attribute__ ((nonnull (1))); API unsigned ncdirect_dim_x(struct ncdirect* nc) __attribute__ ((nonnull (1)));
API unsigned ncdirect_dim_y(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 // (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
// indicated as supported if the terminal can support it together with color. // indicated as supported if the terminal can support it together with color.
// For more information, see the "ncv" capability in terminfo(5). // 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))); __attribute__ ((nonnull (1)));
// ncplane_styles_*() analogues // ncplane_styles_*() analogues
@ -211,17 +145,9 @@ API int ncdirect_on_styles(struct ncdirect* n, unsigned stylebits)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
API int ncdirect_off_styles(struct ncdirect* n, unsigned stylebits) API int ncdirect_off_styles(struct ncdirect* n, unsigned stylebits)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
API unsigned ncdirect_styles(const struct ncdirect* n) API uint16_t ncdirect_styles(const struct ncdirect* n)
__attribute__ ((nonnull (1))); __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. // 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) API int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));

@ -95,11 +95,6 @@ typedef enum {
NCSCALE_SCALE_HIRES, NCSCALE_SCALE_HIRES,
} ncscale_e; } 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 // 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, // (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| // 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. // *|validbytes| and *|validwidth| reflect the entire string.
API int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth); 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. // Returns a heap-allocated copy of the user name under which we are running.
API ALLOC char* notcurses_accountname(void); API ALLOC char* notcurses_accountname(void);
@ -716,7 +718,7 @@ nccell_set_styles(nccell* c, unsigned stylebits){
} }
// Extract the style bits from the nccell. // Extract the style bits from the nccell.
static inline unsigned static inline uint16_t
nccell_styles(const nccell* c){ nccell_styles(const nccell* c){
return c->stylemask; return c->stylemask;
} }
@ -923,7 +925,6 @@ typedef struct notcurses_options {
// the environment variable TERM is used. Failure to open the terminal // the environment variable TERM is used. Failure to open the terminal
// definition will result in failure to initialize notcurses. // definition will result in failure to initialize notcurses.
const char* termtype; 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 // Progressively higher log levels result in more logging to stderr. By
// default, nothing is printed to stderr once fullscreen service begins. // default, nothing is printed to stderr once fullscreen service begins.
ncloglevel_e loglevel; 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) API int notcurses_leave_alternate_screen(struct notcurses* nc)
__attribute__ ((nonnull (1))); __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'. // Return the topmost plane of the pile containing 'n'.
API struct ncplane* ncpile_top(struct ncplane* n) API struct ncplane* ncpile_top(struct ncplane* n)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
@ -1001,8 +1008,14 @@ API int ncpile_rasterize(struct ncplane* n)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
// Renders and rasterizes the standard pile in one shot. Blocking call. // Renders and rasterizes the standard pile in one shot. Blocking call.
API int notcurses_render(struct notcurses* nc) static inline int
__attribute__ ((nonnull (1))); 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 // Perform the rendering and rasterization portion of ncpile_render() and
// ncpile_rasterize(), but do not write the resulting buffer out to the // 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) API int ncpile_render_to_buffer(struct ncplane* p, char** buf, size_t* buflen)
__attribute__ ((nonnull (1, 2, 3))); __attribute__ ((nonnull (1, 2, 3)));
// Write the last rendered frame, in its entirety, to 'fp'. If // Write the last rendered frame, in its entirety, to 'fp'. If a frame has
// notcurses_render() has not yet been called, nothing will be written. // not yet been rendered, nothing will be written.
API int ncpile_render_to_file(struct ncplane* p, FILE* fp) API int ncpile_render_to_file(struct ncplane* p, FILE* fp)
__attribute__ ((nonnull (1, 2))); __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 // '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 // limit on bitmap size, 'maxbmapy' and 'maxbmapx' will be 0. Any of the
// geometry arguments may be NULL. // 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 pxy, unsigned* RESTRICT pxx,
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx, unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx) unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx)
@ -1420,7 +1433,7 @@ typedef struct nccapabilities {
// (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only // (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
// indicated as supported if the terminal can support it together with color. // indicated as supported if the terminal can support it together with color.
// For more information, see the "ncv" capability in terminfo(5). // 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)); __attribute__ ((nonnull (1))) __attribute__ ((pure));
// Returns the number of simultaneous colors claimed to be supported, or 1 if // 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 writeouts; // successful ncpile_rasterize() runs
uint64_t failed_renders; // aborted renders, should be 0 uint64_t failed_renders; // aborted renders, should be 0
uint64_t failed_writeouts; // aborted writes uint64_t failed_writeouts; // aborted writes
// FIXME these next three all ought be "writeout" or "raster" uint64_t raster_bytes; // bytes emitted to ttyfp
uint64_t render_bytes; // bytes emitted to ttyfp int64_t raster_max_bytes; // max bytes emitted for a frame
int64_t render_max_bytes; // max bytes emitted for a frame int64_t raster_min_bytes; // min bytes emitted for a frame
int64_t render_min_bytes; // min bytes emitted for a frame
uint64_t render_ns; // nanoseconds spent rendering uint64_t render_ns; // nanoseconds spent rendering
int64_t render_max_ns; // max ns spent in render 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 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 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_max_ns; // max ns spent writing out a frame
int64_t writeout_min_ns; // min 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 defaultelisions; // default color was emitted
uint64_t defaultemissions; // default color was elided uint64_t defaultemissions; // default color was elided
uint64_t refreshes; // refresh requests (non-optimized redraw) 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 sprixelemissions; // sprixel draw count
uint64_t sprixelelisions; // sprixel elision count uint64_t sprixelelisions; // sprixel elision count
uint64_t sprixelbytes; // sprixel bytes emitted 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_errors; // errors processing control sequences/utf8
uint64_t input_events; // characters returned to userspace uint64_t input_events; // characters returned to userspace
uint64_t hpa_gratuitous; // unnecessary hpas issued 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; } ncstats;
// Allocate an ncstats object. Use this rather than allocating your own, since // 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 // Move this plane relative to its current location. Negative values move up
// and left, respectively. Pass 0 to hold an axis constant. // and left, respectively. Pass 0 to hold an axis constant.
__attribute__ ((nonnull (1))) static inline int __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; int oy, ox;
ncplane_yx(n, &oy, &ox); ncplane_yx(n, &oy, &ox);
return ncplane_move_yx(n, oy + y, ox + x); 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) struct ncplane* RESTRICT below)
__attribute__ ((nonnull (1))); __attribute__ ((nonnull (1)));
// Splice ncplane 'n' out of the z-buffer, and reinsert it at the top or // Splice ncplane 'n' out of the z-buffer; reinsert it at the top or bottom.
// bottom. FIXME these both become static inline wrappers around __attribute__ ((nonnull (1)))
// ncplane_move_below() and ncplane_move_above() in ABI3. static inline void
API void ncplane_move_top(struct ncplane* n) ncplane_move_top(struct ncplane* n){
__attribute__ ((nonnull (1))); ncplane_move_below(n, NULL);
API void ncplane_move_bottom(struct ncplane* n) }
__attribute__ ((nonnull (1)));
__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 // 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 // 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. // (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 // On error, a non-positive number is returned, indicating the number of columns
// which were written before the error. // 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 static inline int
ncplane_putstr(struct ncplane* n, const char* gclustarr){ ncplane_putstr(struct ncplane* n, const char* gclustarr){
return ncplane_putstr_yx(n, -1, -1, gclustarr); return ncplane_putstr_yx(n, -1, -1, gclustarr);
} }
API int ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align, static inline int
const char* s); 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 // 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. // 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. // 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 // 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. // (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 // 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. // 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 static inline int
ncplane_putnstr(struct ncplane* n, size_t s, const char* gclustarr){ ncplane_putnstr(struct ncplane* n, size_t s, const char* gclustarr){
return ncplane_putnstr_yx(n, -1, -1, s, 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. // 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 // FIXME do this as a loop over ncplane_putegc_yx and save the big allocation+copy
static inline int static inline int
@ -2687,16 +2770,30 @@ nccells_load_box(struct ncplane* n, uint32_t styles, uint64_t channels,
return -1; 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 static inline int
nccells_ascii_box(struct ncplane* n, uint16_t attr, uint64_t channels, nccells_ascii_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){ 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); 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 static inline int
nccells_light_box(struct ncplane* n, uint16_t attr, uint64_t channels, nccells_light_box(struct ncplane* n, uint16_t attr, uint64_t channels,
nccell* ul, nccell* ur, nccell* ll, nccell* lr, nccell* hl, nccell* vl){ 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); 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 static inline int
ncplane_double_box(struct ncplane* n, uint16_t styles, uint64_t channels, ncplane_double_box(struct ncplane* n, uint16_t styles, uint64_t channels,
unsigned ylen, unsigned xlen, unsigned ctlword){ 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) uint32_t pixel)
__attribute__ ((nonnull (1))); __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 // 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. // 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 // 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); API struct ncplane* nctablet_plane(struct nctablet* t);
// Takes an arbitrarily large number, and prints it into a fixed-size buffer by // 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 // adding the necessary SI suffix. Usually, pass a |NC[IB]?PREFIXSTRLEN+1|-sized
// buffer to generate up to |[IB]PREFIXCOLUMNS| columns' worth of EGCs. The // 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 // characteristic can occupy up through |mult-1| characters (3 for 1000, 4 for
// 1024). The mantissa can occupy either zero or two characters. // 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 // Floating-point is never used, because an IEEE758 double can only losslessly
// represent integers through 2^53-1. // 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. // an 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
// 2^-63 is 0.000000000000000000108, 1.08a(tto). // 2^-63 is 0.000000000000000000108, 1.08a(tto).
// val: value to print // val: value to print
// s: maximum output size; see snprintf(3)
// decimal: scaling. '1' if none has taken place. // decimal: scaling. '1' if none has taken place.
// buf: buffer in which string will be generated // buf: buffer in which string will be generated
// omitdec: inhibit printing of all-0 decimal portions // 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). // only printed if suffix is actually printed (input >= mult).
// //
// You are encouraged to consult notcurses_metric(3). // 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, API const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
char* buf, int omitdec, uintmax_t mult, char* buf, int omitdec, uintmax_t mult,
int uprefix) 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 // 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 // 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) // 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 // mult == 1024 (digital information) ncmetric(). NCBPREFIXSTRLEN is the maximum
// number of columns used by a mult == 1024 call making use of the 'i' suffix. // 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 // 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. // Mega, kilo, gigafoo. Use PREFIXSTRLEN + 1 and PREFIXCOLUMNS.
static inline const char* static inline const char*
ncqprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){ 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. // Mibi, kebi, gibibytes sans 'i' suffix. Use IPREFIXSTRLEN + 1.
static inline const char* static inline const char*
nciprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){ 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. // Mibi, kebi, gibibytes. Use BPREFIXSTRLEN + 1 and BPREFIXCOLUMNS.
static inline const char* static inline const char*
ncbprefix(uintmax_t val, uintmax_t decimal, char* buf, int omitdec){ 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 // 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) API void notcurses_debug(const struct notcurses* nc, FILE* debugfp)
__attribute__ ((nonnull (1, 2))); __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 API
#undef ALLOC #undef ALLOC

@ -524,7 +524,7 @@ class NcPlane:
"""Return Y dimension of this NcPlane.""" """Return Y dimension of this NcPlane."""
raise NotImplementedError('Stub') 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 """Retrieve pixel geometry for the display region, each cell
and the maximum displayable bitmap.""" and the maximum displayable bitmap."""
raise NotImplementedError('Stub') raise NotImplementedError('Stub')

@ -110,10 +110,10 @@ NcPlane_dim_y(NcPlaneObject *self, PyObject *Py_UNUSED(args))
} }
static PyObject * 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; 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); 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_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_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.")}, {"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.")}, {"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'.")}, {"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 { typedef struct siginfo_t {
int aieeee; int aieeee;
} siginfo_t; } 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 sigset_t int
#define nl_langinfo(x) "UTF-8" #define nl_langinfo(x) "UTF-8"
#define ppoll(w, x, y, z) WSAPoll((w), (x), (y)) #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; return -1;
} }
unsigned cdimy, cdimx; 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)){ if(ncvisual_resize(wmv, cdimy * SHIPHEIGHT, cdimx * SHIPWIDTH)){
ncvisual_destroy(wmv); ncvisual_destroy(wmv);
return -1; return -1;

@ -377,7 +377,7 @@ summary_json(FILE* f, const char* spec, int rows, int cols){
continue; continue;
} }
ret |= (fprintf(f, "\"%s\":{\"bytes\":\"%"PRIu64"\",\"frames\":\"%"PRIu64"\",\"ns\":\"%"PRIu64"\"}%s", 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); results[i].stats.renders, results[i].timens, i < strlen(spec) - 1 ? "," : "") < 0);
} }
ret |= (fprintf(f, "}}}\n") < 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){ for(size_t i = 0 ; i < strlen(spec) ; ++i){
nsdelta += results[i].timens; nsdelta += results[i].timens;
ncqprefix(results[i].timens, NANOSECS_IN_SEC, timebuf, 0); 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; uint64_t divisor = results[i].stats.render_ns + results[i].stats.writeout_ns + results[i].stats.raster_ns;
if(divisor){ if(divisor){
ncqprefix((uintmax_t)results[i].stats.writeouts * NANOSECS_IN_SEC * 1000 / 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; failed = true;
} }
totalframes += results[i].stats.renders; totalframes += results[i].stats.renders;
totalbytes += results[i].stats.render_bytes; totalbytes += results[i].stats.raster_bytes;
totalrenderns += results[i].stats.render_ns; totalrenderns += results[i].stats.render_ns;
totalwriteoutns += results[i].stats.writeout_ns; totalwriteoutns += results[i].stats.writeout_ns;
} }

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

@ -65,29 +65,6 @@ fetch_env_vars(struct notcurses* nc, fetched_info* fi){
return 0; 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 static int
fetch_bsd_cpuinfo(fetched_info* fi){ fetch_bsd_cpuinfo(fetched_info* fi){
#if defined(__linux__) || defined(__gnu_hurd__) || defined(__MINGW64__) #if defined(__linux__) || defined(__gnu_hurd__) || defined(__MINGW64__)
@ -110,6 +87,32 @@ fetch_bsd_cpuinfo(fetched_info* fi){
return 0; 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 static int
fetch_cpu_info(fetched_info* fi){ fetch_cpu_info(fetched_info* fi){
FILE* cpuinfo = fopen("/proc/cpuinfo", "re"); FILE* cpuinfo = fopen("/proc/cpuinfo", "re");
@ -197,6 +200,7 @@ fetch_x_props(fetched_info* fi){
return 0; return 0;
} }
#ifdef __linux__
// Given a filename, check for its existence in the directories specified by // Given a filename, check for its existence in the directories specified by
// https://specifications.freedesktop.org/icon-theme-spec/latest/ar01s03.html. // https://specifications.freedesktop.org/icon-theme-spec/latest/ar01s03.html.
// Returns NULL if no such file can be found. Return value is heap-allocated. // 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); strcat(p, spec);
return p; return p;
} }
#endif
// FIXME deal more forgivingly with quotation marks // FIXME deal more forgivingly with quotation marks
static const distro_info* static const distro_info*
linux_ncneofetch(fetched_info* fi){ 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"); FILE* osinfo = fopen("/etc/os-release", "re");
if(osinfo == NULL){ if(osinfo == NULL){
return NULL; return NULL;
@ -266,7 +295,6 @@ linux_ncneofetch(fetched_info* fi){
if(distro == NULL){ if(distro == NULL){
return NULL; return NULL;
} }
const distro_info* dinfo = NULL;
for(dinfo = distros ; dinfo->name ; ++dinfo){ for(dinfo = distros ; dinfo->name ; ++dinfo){
if(strcmp(dinfo->name, distro) == 0){ if(strcmp(dinfo->name, distro) == 0){
break; break;
@ -276,6 +304,9 @@ linux_ncneofetch(fetched_info* fi){
fi->neologo = get_neofetch_art(distro); fi->neologo = get_neofetch_art(distro);
} }
free(distro); free(distro);
#else
(void)fi;
#endif
return dinfo; return dinfo;
} }
@ -309,7 +340,14 @@ get_kernel(fetched_info* fi){
} }
fprintf(stderr, "Unknown operating system via uname: %s\n", uts.sysname); fprintf(stderr, "Unknown operating system via uname: %s\n", uts.sysname);
#else #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; return NCNEO_WINDOWS;
#endif #endif
return NCNEO_UNKNOWN; return NCNEO_UNKNOWN;
@ -440,7 +478,7 @@ infoplane_notcurses(struct notcurses* nc, const fetched_info* fi, int planeheigh
size_t oldlenp = sizeof(ram); size_t oldlenp = sizeof(ram);
if(sysctlbyname("hw.memsize", &ram, &oldlenp, NULL, 0) == 0){ if(sysctlbyname("hw.memsize", &ram, &oldlenp, NULL, 0) == 0){
char tram[NCBPREFIXSTRLEN + 1]; char tram[NCBPREFIXSTRLEN + 1];
bprefix(ram, 1, tram, 1); ncbprefix(ram, 1, tram, 1);
ncplane_printf_aligned(infop, 2, NCALIGN_LEFT, " RAM: %sB", tram); ncplane_printf_aligned(infop, 2, NCALIGN_LEFT, " RAM: %sB", tram);
} }
#endif #endif
@ -664,6 +702,8 @@ ncneofetch(struct notcurses* nc){
} }
if(kern == NCNEO_LINUX){ if(kern == NCNEO_LINUX){
fetch_cpu_info(&fi); fetch_cpu_info(&fi);
}else if(kern == NCNEO_WINDOWS){
fetch_windows_cpuinfo(&fi);
}else{ }else{
fetch_bsd_cpuinfo(&fi); fetch_bsd_cpuinfo(&fi);
} }

@ -331,7 +331,7 @@ unicodedumper(struct ncplane* n, const char* indent){
static int static int
display_logo(struct ncplane* n, const char* path){ display_logo(struct ncplane* n, const char* path){
unsigned cpixy, cpixx; 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); struct ncvisual* ncv = ncvisual_from_file(path);
if(ncv == NULL){ if(ncv == NULL){
return -1; return -1;

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

@ -2,12 +2,6 @@
int loglevel = NCLOGLEVEL_SILENT; 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){ void notcurses_debug(const notcurses* nc, FILE* debugfp){
fbuf f; fbuf f;
if(fbuf_init_small(&f)){ if(fbuf_init_small(&f)){

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

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

@ -502,11 +502,11 @@ mouse_click(inputctx* ictx, unsigned release, char follow){
logwarn("dropping click in margins %ld/%ld\n", y, x); logwarn("dropping click in margins %ld/%ld\n", y, x);
return; 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); logwarn("dropping click in margins %ld/%ld\n", y, x);
return; 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); logwarn("dropping click in margins %ld/%ld\n", y, x);
return; 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); 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){ int get_cursor_location(inputctx* ictx, const char* u7, unsigned* y, unsigned* x){
pthread_mutex_lock(&ictx->clock); pthread_mutex_lock(&ictx->clock);
while(ictx->cvalid == 0){ 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_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_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 update_write_stats(const struct timespec* time1, const struct timespec* time0, ncstats* stats, int bytes);
void sigwinch_handler(int signo); void sigwinch_handler(int signo);

@ -116,8 +116,3 @@ const char* ncnmetric(uintmax_t val, size_t s, uintmax_t decimal,
} }
return buf; 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; 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[] = static const char NOTCURSES_VERSION[] =
NOTCURSES_VERSION_MAJOR "." NOTCURSES_VERSION_MAJOR "."
NOTCURSES_VERSION_MINOR "." NOTCURSES_VERSION_MINOR "."
@ -605,20 +576,6 @@ ncplane* ncpile_create(notcurses* nc, const struct ncplane_options* nopts){
return ncplane_new_internal(nc, NULL, 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){ void ncplane_home(ncplane* n){
n->x = 0; n->x = 0;
n->y = 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' // 'n' ends up above 'above'
int ncplane_move_above(ncplane* restrict n, ncplane* restrict above){ int ncplane_move_above(ncplane* restrict n, ncplane* restrict above){
if(n == above){ if(n == above){ // probably gets optimized out =/
return -1; return -1;
} }
ncpile* p = ncplane_pile(n);
if(above == NULL){ 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; return 0;
} }
if(ncplane_pile(n) != ncplane_pile(above)){ // can't move among piles
return -1;
}
if(n->below != above){ if(n->below != above){
if(p != ncplane_pile(above)){ // can't move among piles
return -1;
}
// splice out 'n' // splice out 'n'
if(n->below){ if(n->below){
n->below->above = n->above; n->below->above = n->above;
}else{ }else{
ncplane_pile(n)->bottom = n->above; p->bottom = n->above;
} }
if(n->above){ if(n->above){
n->above->below = n->below; n->above->below = n->below;
}else{ }else{
ncplane_pile(n)->top = n->below; p->top = n->below;
} }
if( (n->above = above->above) ){ if( (n->above = above->above) ){
above->above->below = n; above->above->below = n;
}else{ }else{
ncplane_pile(n)->top = n; p->top = n;
} }
above->above = n; above->above = n;
n->below = above; n->below = above;
@ -1416,33 +1385,45 @@ int ncplane_move_above(ncplane* restrict n, ncplane* restrict above){
return 0; 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){ int ncplane_move_below(ncplane* restrict n, ncplane* restrict below){
if(n == below){ if(n == below){ // probably gets optimized out =/
return -1; return -1;
} }
ncpile* p = ncplane_pile(n);
if(below == NULL){ 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; return 0;
} }
if(ncplane_pile(n) != ncplane_pile(below)){ // can't move among piles
return -1;
}
if(n->above != below){ if(n->above != below){
if(p != ncplane_pile(below)){ // can't move among piles
return -1;
}
if(n->below){ if(n->below){
n->below->above = n->above; n->below->above = n->above;
}else{ }else{
ncplane_pile(n)->bottom = n->above; p->bottom = n->above;
} }
if(n->above){ if(n->above){
n->above->below = n->below; n->above->below = n->below;
}else{ }else{
ncplane_pile(n)->top = n->below; p->top = n->below;
} }
if( (n->below = below->below) ){ if( (n->below = below->below) ){
below->below->above = n; below->below->above = n;
}else{ }else{
ncplane_pile(n)->bottom = n; p->bottom = n;
} }
below->below = n; below->below = n;
n->above = below; n->above = below;
@ -1450,36 +1431,6 @@ int ncplane_move_below(ncplane* restrict n, ncplane* restrict below){
return 0; 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 // if above is NULL, we're moving to the bottom
int ncplane_move_family_above(ncplane* restrict n, ncplane* restrict bpoint){ int ncplane_move_family_above(ncplane* restrict n, ncplane* restrict bpoint){
ncplane* above = ncplane_above(n); ncplane* above = ncplane_above(n);
@ -1584,7 +1535,7 @@ void scroll_down(ncplane* n){
for(struct ncplane* c = n->blist ; c ; c = c->bnext){ for(struct ncplane* c = n->blist ; c ; c = c->bnext){
if(!c->fixedbound){ if(!c->fixedbound){
if(ncplanes_intersect_p(n, c)){ 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; 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 nccell_load(ncplane* n, nccell* c, const char* gcluster){
int cols; int cols;
int bytes = utf8_egc_len(gcluster, &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){ 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; return -1;
} }
const nccell* src = &n->fb[nfbcellidx(n, n->y, n->x)]; 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; return 0;
} }
unsigned notcurses_supported_styles(const notcurses* nc){ uint16_t notcurses_supported_styles(const notcurses* nc){
return term_supported_styles(&nc->tcache); return term_supported_styles(&nc->tcache);
} }
@ -1821,28 +1768,16 @@ void ncplane_set_styles(ncplane* n, unsigned stylebits){
n->stylemask = (stylebits & NCSTYLE_MASK); n->stylemask = (stylebits & NCSTYLE_MASK);
} }
void ncplane_styles_set(ncplane* n, unsigned stylebits){ // deprecated
ncplane_set_styles(n, stylebits);
}
// turn on any specified stylebits // turn on any specified stylebits
void ncplane_on_styles(ncplane* n, unsigned stylebits){ void ncplane_on_styles(ncplane* n, unsigned stylebits){
n->stylemask |= (stylebits & NCSTYLE_MASK); n->stylemask |= (stylebits & NCSTYLE_MASK);
} }
void ncplane_styles_on(ncplane* n, unsigned stylebits){ // deprecated
ncplane_on_styles(n, stylebits);
}
// turn off any specified stylebits // turn off any specified stylebits
void ncplane_off_styles(ncplane* n, unsigned stylebits){ void ncplane_off_styles(ncplane* n, unsigned stylebits){
n->stylemask &= ~(stylebits & NCSTYLE_MASK); 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? // 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 // well, for one, we don't need the huge allocation FIXME
char* ncplane_vprintf_prep(const char* format, va_list ap){ 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; 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, int ncplane_hline_interp(ncplane* n, const nccell* c, unsigned len,
uint64_t c1, uint64_t c2){ uint64_t c1, uint64_t c2){
if(len <= 0){ if(len <= 0){
@ -2370,10 +2312,6 @@ ncpalette* ncpalette_new(notcurses* nc){
return p; return p;
} }
ncpalette* palette256_new(notcurses* nc){
return ncpalette_new(nc);
}
int ncpalette_use(notcurses* nc, const ncpalette* p){ int ncpalette_use(notcurses* nc, const ncpalette* p){
int ret = -1; int ret = -1;
if(!notcurses_canchangecolor(nc)){ if(!notcurses_canchangecolor(nc)){
@ -2389,18 +2327,10 @@ int ncpalette_use(notcurses* nc, const ncpalette* p){
return ret; return ret;
} }
int palette256_use(notcurses* nc, const ncpalette* p){
return ncpalette_use(nc, p);
}
void ncpalette_free(ncpalette* p){ void ncpalette_free(ncpalette* p){
free(p); free(p);
} }
void palette256_free(ncpalette* p){
ncpalette_free(p);
}
bool ncplane_translate_abs(const ncplane* n, int* restrict y, int* restrict x){ bool ncplane_translate_abs(const ncplane* n, int* restrict y, int* restrict x){
ncplane_translate(ncplane_stdplane_const(n), n, y, x); ncplane_translate(ncplane_stdplane_const(n), n, y, x);
if(y){ if(y){
@ -3006,32 +2936,6 @@ char* ncplane_contents(ncplane* nc, int begy, int begx, unsigned leny, unsigned
return ret; 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 // 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 // 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 // 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); 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){ int ncplane_putwstr_stained(ncplane* n, const wchar_t* gclustarr){
mbstate_t ps = {}; mbstate_t ps = {};
const wchar_t** wset = &gclustarr; const wchar_t** wset = &gclustarr;
@ -3115,36 +2980,6 @@ int ncplane_putwstr_stained(ncplane* n, const wchar_t* gclustarr){
return r; 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, int notcurses_ucs32_to_utf8(const uint32_t* ucs32, unsigned ucs32count,
unsigned char* resultbuf, size_t buflen){ unsigned char* resultbuf, size_t buflen){
if(u32_to_u8(ucs32, ucs32count, resultbuf, &buflen) == NULL){ 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; return buflen;
} }
int ncstrwidth(const char* mbs){
return ncstrwidth_valid(mbs, NULL, NULL);
}
int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){ int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){
int cols = 0; // number of columns consumed thus far int cols;
if(validwidth == NULL){ if(validwidth == NULL){
validwidth = &cols; validwidth = &cols;
} }
int bytes = 0; // number of bytes consumed thus far *validwidth = 0;
int bytes;
if(validbytes == NULL){ if(validbytes == NULL){
validbytes = &bytes; validbytes = &bytes;
} }
*validbytes = 0;
do{ do{
int thesecols, thesebytes; int thesecols, thesebytes;
thesebytes = utf8_egc_len(egcs, &thesecols); thesebytes = utf8_egc_len(egcs, &thesecols);
@ -3179,9 +3012,10 @@ int ncstrwidth_valid(const char* egcs, int* validbytes, int* validwidth){
return *validwidth; return *validwidth;
} }
void ncplane_pixelgeom(const ncplane* n, unsigned* RESTRICT pxy, unsigned* RESTRICT pxx, void ncplane_pixel_geom(const ncplane* n,
unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx, unsigned* RESTRICT pxy, unsigned* RESTRICT pxx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx){ unsigned* RESTRICT celldimy, unsigned* RESTRICT celldimx,
unsigned* RESTRICT maxbmapy, unsigned* RESTRICT maxbmapx){
notcurses* nc = ncplane_notcurses(n); notcurses* nc = ncplane_notcurses(n);
if(celldimy){ if(celldimy){
*celldimy = nc->tcache.cellpixy; *celldimy = nc->tcache.cellpixy;

@ -127,12 +127,12 @@ int redraw_pixelplot_##T(nc##X##plot* ncp){ \
char buf[NCPREFIXSTRLEN + 1]; \ char buf[NCPREFIXSTRLEN + 1]; \
if(ncp->plot.exponentiali){ \ if(ncp->plot.exponentiali){ \
if(y == dimy - 1){ /* we cheat on the top row to exactly match maxy */ \ 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{ \ }else{ \
ncmetric(pow(interval, (y + 1) * states) * 100, 100, buf, 0, 1000, '\0'); \ ncqprefix(pow(interval, (y + 1) * states) * 100, 100, buf, 0); \
} \ } \
}else{ \ }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)){ \ if(y == dimy - 1 && strlen(ncp->plot.title)){ \
ncplane_printf_yx(ncp->plot.ncp, dimy - y - 1, 0, "%*.*s %s", \ 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]; \ char buf[NCPREFIXSTRLEN + 1]; \
if(ncp->plot.exponentiali){ \ if(ncp->plot.exponentiali){ \
if(y == dimy - 1){ /* we cheat on the top row to exactly match maxy */ \ 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{ \ }else{ \
ncmetric(pow(interval, (y + 1) * states) * 100, 100, buf, 0, 1000, '\0'); \ ncqprefix(pow(interval, (y + 1) * states) * 100, 100, buf, 0); \
} \ } \
}else{ \ }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)){ \ 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); \ 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; return t->cbp;
} }
ncplane* nctablet_ncplane(nctablet* t){ // deprecated
return nctablet_plane(t);
}
ncplane* ncreel_plane(ncreel* nr){ ncplane* ncreel_plane(ncreel* nr){
return nr->p; return nr->p;
} }

@ -122,11 +122,6 @@ void nccell_release(ncplane* n, nccell* c){
pool_release(&n->pool, 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. // Duplicate one cell onto another when they share a plane. Convenience wrapper.
int nccell_duplicate(ncplane* n, nccell* targ, const nccell* c){ int nccell_duplicate(ncplane* n, nccell* targ, const nccell* c){
if(cell_duplicate_far(&n->pool, targ, n, c) < 0){ 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; 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. // Emit fchannel with RGB changed to contrast effectively against bchannel.
static uint32_t static uint32_t
highcontrast(const tinfo* ti, uint32_t bchannel){ highcontrast(const tinfo* ti, uint32_t bchannel){
@ -1458,10 +1448,6 @@ int ncpile_render_to_file(ncplane* n, FILE* fp){
return ret; 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 // We execute the painter's algorithm, starting from our topmost plane. The
// damagevector should be all zeros on input. On success, it will reflect // 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 // 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 // accepts -1 as an indication of failure
clock_gettime(CLOCK_MONOTONIC, &writedone); clock_gettime(CLOCK_MONOTONIC, &writedone);
pthread_mutex_lock(&nc->stats.lock); 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_raster_stats(&rasterdone, &start, &nc->stats.s);
update_write_stats(&writedone, &rasterdone, &nc->stats.s, bytes); update_write_stats(&writedone, &rasterdone, &nc->stats.s, bytes);
pthread_mutex_unlock(&nc->stats.lock); pthread_mutex_unlock(&nc->stats.lock);
@ -1556,18 +1542,6 @@ int ncpile_render(ncplane* n){
return 0; 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. // 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){ int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
if(ncpile_render(p)){ 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); fbuf_reset(&nc->rstate.f);
int bytes = notcurses_rasterize_inner(nc, ncplane_pile(p), &nc->rstate.f, &useasu); int bytes = notcurses_rasterize_inner(nc, ncplane_pile(p), &nc->rstate.f, &useasu);
pthread_mutex_lock(&nc->stats.lock); 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); pthread_mutex_unlock(&nc->stats.lock);
if(bytes < 0){ if(bytes < 0){
return -1; return -1;
@ -1589,10 +1563,6 @@ int ncpile_render_to_buffer(ncplane* p, char** buf, size_t* buflen){
return 0; 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 // 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. // result is not tied to the ncplane, and persists across erases / destruction.
static inline char* 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. // negative 'bytes' are ignored as failures. call only while holding statlock.
// we don't increment failed_renders here because 'bytes' < 0 actually indicates // we don't increment failed_rasters here because 'bytes' < 0 actually indicates
// a rasterization failure -- we can't fail in rendering anymore. // a rasterization failure -- we can't fail in rastering anymore.
void update_render_bytes(ncstats* stats, int bytes){ void update_raster_bytes(ncstats* stats, int bytes){
if(bytes >= 0){ if(bytes >= 0){
stats->render_bytes += bytes; stats->raster_bytes += bytes;
if(bytes > stats->render_max_bytes){ if(bytes > stats->raster_max_bytes){
stats->render_max_bytes = bytes; stats->raster_max_bytes = bytes;
} }
if(bytes < stats->render_min_bytes){ if(bytes < stats->raster_min_bytes){
stats->render_min_bytes = bytes; stats->raster_min_bytes = bytes;
} }
} }
} }
@ -76,7 +76,7 @@ void reset_stats(ncstats* stats){
unsigned planes = stats->planes; unsigned planes = stats->planes;
memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats));
stats->render_min_ns = 1ull << 62u; 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->raster_min_ns = 1ull << 62u;
stats->writeout_min_ns = 1ull << 62u; stats->writeout_min_ns = 1ull << 62u;
stats->fbbytes = fbbytes; 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){ if(nc->stats.s.render_min_ns < stash->render_min_ns){
stash->render_min_ns = nc->stats.s.render_min_ns; stash->render_min_ns = nc->stats.s.render_min_ns;
} }
if(nc->stats.s.render_min_bytes < stash->render_min_bytes){ if(nc->stats.s.raster_min_bytes < stash->raster_min_bytes){
stash->render_min_bytes = nc->stats.s.render_min_bytes; stash->raster_min_bytes = nc->stats.s.raster_min_bytes;
} }
if(nc->stats.s.raster_min_ns < stash->raster_min_ns){ if(nc->stats.s.raster_min_ns < stash->raster_min_ns){
stash->raster_min_ns = nc->stats.s.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){ if(nc->stats.s.render_max_ns > stash->render_max_ns){
stash->render_max_ns = nc->stats.s.render_max_ns; stash->render_max_ns = nc->stats.s.render_max_ns;
} }
if(nc->stats.s.render_max_bytes > stash->render_max_bytes){ if(nc->stats.s.raster_max_bytes > stash->raster_max_bytes){
stash->render_max_bytes = nc->stats.s.render_max_bytes; stash->raster_max_bytes = nc->stats.s.raster_max_bytes;
} }
if(nc->stats.s.raster_max_ns > stash->raster_max_ns){ if(nc->stats.s.raster_max_ns > stash->raster_max_ns){
stash->raster_max_ns = nc->stats.s.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->writeout_ns += nc->stats.s.writeout_ns;
stash->raster_ns += nc->stats.s.raster_ns; stash->raster_ns += nc->stats.s.raster_ns;
stash->render_ns += nc->stats.s.render_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_renders += nc->stats.s.failed_renders;
stash->failed_writeouts += nc->stats.s.failed_writeouts; stash->failed_writeouts += nc->stats.s.failed_writeouts;
stash->renders += nc->stats.s.renders; stash->renders += nc->stats.s.renders;
@ -199,11 +199,11 @@ void summarize_stats(notcurses* nc){
totalbuf, minbuf, avgbuf, maxbuf); totalbuf, minbuf, avgbuf, maxbuf);
} }
if(stats->renders || stats->input_events){ if(stats->renders || stats->input_events){
ncbprefix(stats->render_bytes, 1, totalbuf, 1), ncbprefix(stats->raster_bytes, 1, totalbuf, 1),
ncbprefix(stats->render_bytes ? stats->render_min_bytes : 0, ncbprefix(stats->raster_bytes ? stats->raster_min_bytes : 0,
1, minbuf, 1), 1, minbuf, 1),
ncbprefix(stats->renders ? stats->render_bytes / stats->renders : 0, 1, avgbuf, 1); ncbprefix(stats->renders ? stats->raster_bytes / stats->renders : 0, 1, avgbuf, 1);
ncbprefix(stats->render_max_bytes, 1, maxbuf, 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, fprintf(stderr, "%s%sB (%sB min, %sB avg, %sB max) %"PRIu64" input%s Ghpa: %"PRIu64 NL,
clreol, totalbuf, minbuf, avgbuf, maxbuf, clreol, totalbuf, minbuf, avgbuf, maxbuf,
stats->input_events, stats->input_events,
@ -240,7 +240,7 @@ void summarize_stats(notcurses* nc){
(stats->sprixelemissions + stats->sprixelelisions) == 0 ? 0 : (stats->sprixelemissions + stats->sprixelelisions) == 0 ? 0 :
(stats->sprixelelisions * 100.0) / (stats->sprixelemissions + stats->sprixelelisions), (stats->sprixelelisions * 100.0) / (stats->sprixelemissions + stats->sprixelelisions),
totalbuf, 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->appsync_updates,
stats->writeouts ? stats->appsync_updates * 100.0 / stats->writeouts : 0); 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"); logpanic("failed opening Windows ConPTY\n");
return -1; return -1;
} }
if(cursor_y && cursor_x){ unsigned ucy, ucx;
locate_cursor(ti, cursor_y, cursor_x); if(locate_cursor(ti, &ucy, &ucx) == 0){
*cursor_y = ucy;
*cursor_x = ucx;
} }
#elif defined(__linux__) #elif defined(__linux__)
ti->linux_fb_fd = -1; ti->linux_fb_fd = -1;

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

@ -70,11 +70,6 @@ ncplane* ncvisual_subtitle_plane(ncplane* parent, const ncvisual* ncv){
return visual_implementation.visual_subtitle(parent, 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, int ncvisual_blit_internal(ncvisual* ncv, int rows, int cols, ncplane* n,
const struct blitset* bset, const blitterargs* barg){ const struct blitset* bset, const blitterargs* barg){
if(!(barg->flags & NCVISUAL_OPTION_NOINTERPOLATE)){ 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; *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 // 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| // 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 // 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; 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, ncvisual* ncvisual_from_plane(const ncplane* n, ncblitter_e blit,
int begy, int begx, int begy, int begx,
unsigned leny, unsigned lenx){ unsigned leny, unsigned lenx){
@ -1345,10 +1291,3 @@ bool notcurses_canopen_videos(const notcurses* nc __attribute__ ((unused))){
} }
return visual_implementation.canopen_videos; 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 = { notcurses_options NotCurses::default_notcurses_options = {
/* termtype */ nullptr, /* termtype */ nullptr,
/* renderfp */ nullptr,
/* loglevel */ NCLogLevel::Silent, /* loglevel */ NCLogLevel::Silent,
/* margin_t */ 0, /* margin_t */ 0,
/* margin_r */ 0, /* margin_r */ 0,

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

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

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

@ -53,7 +53,7 @@ TEST_CASE("Bitmaps") {
vopts.blitter = NCBLIT_PIXEL; vopts.blitter = NCBLIT_PIXEL;
vopts.flags = NCVISUAL_OPTION_NODEGRADE; vopts.flags = NCVISUAL_OPTION_NODEGRADE;
unsigned maxy, maxx; 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)); CHECK(0 == ncvisual_resize(ncv, maxy, maxx));
auto n = ncvisual_blit(nc_, ncv, &vopts); auto n = ncvisual_blit(nc_, ncv, &vopts);
REQUIRE(nn == n); REQUIRE(nn == n);
@ -306,8 +306,8 @@ TEST_CASE("Bitmaps") {
vopts.x = 5; vopts.x = 5;
vopts.scaling = NCSCALE_NONE; vopts.scaling = NCSCALE_NONE;
auto ninf = ncvisual_blit(nc_, ncv, &vopts); auto ninf = ncvisual_blit(nc_, ncv, &vopts);
ncplane_set_name(ninf, "ninf");
REQUIRE(nullptr != ninf); REQUIRE(nullptr != ninf);
ncplane_set_name(ninf, "ninf");
// y of scaled might not be exactly equal to y of inflated since one // 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 // 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 // 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; const char* decisep = localeconv()->decimal_point;
REQUIRE(decisep); REQUIRE(decisep);
REQUIRE(1 == strlen(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; char* commie = buf;
while( (commie = strstr(commie, decisep)) ){ while( (commie = strstr(commie, decisep)) ){
*commie = '.'; // https://dank.qemfd.net/images/16whcc.jpg *commie = '.'; // https://dank.qemfd.net/images/16whcc.jpg
@ -89,20 +89,20 @@ TEST_CASE("Metric") {
SUBCASE("Maxints1024") { SUBCASE("Maxints1024") {
char buf[NCPREFIXSTRLEN + 1], gold[NCPREFIXSTRLEN + 1]; char buf[NCPREFIXSTRLEN + 1], gold[NCPREFIXSTRLEN + 1];
// FIXME these will change based on the size of intmax_t and uintmax_t // 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)); sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - 1ull)) / (1ull << 60));
CHECK(!strcmp(gold, buf)); 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)); sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX - (1ull << 53))) / (1ull << 60));
CHECK(!strcmp(gold, buf)); 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)); sprintf(gold, "%.2fEi", ((double)(INTMAX_MAX + 1ull)) / (1ull << 60));
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
impericize_ncmetric(UINTMAX_MAX - 1, 1, buf, 0, 1024, 'i'); impericize_ncmetric(UINTMAX_MAX - 1, 1, buf, 0, 1024, 'i');
CHECK(!strcmp("16.00Ei", buf)); CHECK(!strcmp("16.00Ei", buf));
impericize_ncmetric(UINTMAX_MAX, 1, buf, 0, 1024, 'i'); impericize_ncmetric(UINTMAX_MAX, 1, buf, 0, 1024, 'i');
CHECK(!strcmp("16.00Ei", buf)); 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)); sprintf(gold, "%.2fEi", ((double)UINTMAX_MAX - (1ull << 53)) / (1ull << 60));
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
} }
@ -116,7 +116,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 0, 1000, '\0'); ncqprefix(val, 1, buf, 0);
const int sidx = i / 3; const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%ju%s00%c", goldval, decisep, suffixes[sidx]); snprintf(gold, sizeof(gold), "%ju%s00%c", goldval, decisep, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -139,7 +139,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 1, 1000, '\0'); ncqprefix(val, 1, buf, 1);
const int sidx = i / 3; const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%ju%c", goldval, suffixes[sidx]); snprintf(gold, sizeof(gold), "%ju%c", goldval, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -162,7 +162,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 0, 1024, 'i'); ncbprefix(val, 1, buf, 0);
const int sidx = i / 10; const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%ju%s00%ci", goldval, decisep, suffixes[sidx]); snprintf(gold, sizeof(gold), "%ju%s00%ci", goldval, decisep, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -185,7 +185,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 1, 1024, 'i'); ncbprefix(val, 1, buf, 1);
const int sidx = i / 10; const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%ju%ci", goldval, suffixes[sidx]); snprintf(gold, sizeof(gold), "%ju%ci", goldval, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -208,7 +208,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 0, 1000, '\0'); ncqprefix(val, 1, buf, 0);
const int sidx = i / 10; const int sidx = i / 10;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)val) / vfloor, suffixes[sidx]); snprintf(gold, sizeof(gold), "%.2f%c", ((double)val) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -231,7 +231,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val, 1, buf, 0, 1024, 'i'); ncbprefix(val, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0; const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%ci", ((double)val) / vfloor, suffixes[sidx]); snprintf(gold, sizeof(gold), "%.2f%ci", ((double)val) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -254,7 +254,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val - 1, 1, buf, 0, 1000, '\0'); ncqprefix(val - 1, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0; const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val - 1)) / vfloor, suffixes[sidx]); snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val - 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -277,7 +277,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val + 1, 1, buf, 0, 1000, '\0'); ncqprefix(val + 1, 1, buf, 0);
const int sidx = i / 3; const int sidx = i / 3;
snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val + 1)) / vfloor, suffixes[sidx]); snprintf(gold, sizeof(gold), "%.2f%c", ((double)(val + 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));
@ -300,7 +300,7 @@ TEST_CASE("Metric") {
uintmax_t val = 1; uintmax_t val = 1;
size_t i = 0; size_t i = 0;
do{ do{
ncmetric(val - 1, 1, buf, 0, 1024, 'i'); ncbprefix(val - 1, 1, buf, 0);
const int sidx = i ? (i - 1) / 3 : 0; const int sidx = i ? (i - 1) / 3 : 0;
snprintf(gold, sizeof(gold), "%.2f%ci", ((double)(val - 1)) / vfloor, suffixes[sidx]); snprintf(gold, sizeof(gold), "%.2f%ci", ((double)(val - 1)) / vfloor, suffixes[sidx]);
CHECK(!strcmp(gold, buf)); CHECK(!strcmp(gold, buf));

@ -1051,22 +1051,22 @@ TEST_CASE("Plane") {
CHECK(x == 2); CHECK(x == 2);
CHECK(1 == ncplane_set_base(n, " ", 0, channels)); CHECK(1 == ncplane_set_base(n, " ", 0, channels));
CHECK(0 == notcurses_render(nc_)); 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); ncplane_yx(n, &y, &x);
CHECK(y == 1); CHECK(y == 1);
CHECK(x == 2); CHECK(x == 2);
CHECK(0 == notcurses_render(nc_)); 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); ncplane_yx(n, &y, &x);
CHECK(y == 3); CHECK(y == 3);
CHECK(x == 2); CHECK(x == 2);
CHECK(0 == notcurses_render(nc_)); 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); ncplane_yx(n, &y, &x);
CHECK(y == 3); CHECK(y == 3);
CHECK(x == 1); CHECK(x == 1);
CHECK(0 == notcurses_render(nc_)); 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); ncplane_yx(n, &y, &x);
CHECK(y == 3); CHECK(y == 3);
CHECK(x == 3); CHECK(x == 3);

Loading…
Cancel
Save