mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-10-31 15:20:13 +00:00
Rust wrapper work (#454)
* packaging: s/libtinfo/Terminfo/g * rust: add stddim_yx() * rust: check for valid init in unit tests * rust: serialize up tests * constify notcurses_term_dim_yx() * rust: add dim wrappers * remove notcurses_resize() from public API #367 * call notcurses_resize() from notcurses_refresh() #367
This commit is contained in:
parent
e276a36264
commit
c2a645e9af
10
CHANGELOG.md
10
CHANGELOG.md
@ -2,8 +2,8 @@ This document attempts to list user-visible changes and any major internal
|
||||
rearrangements of Notcurses.
|
||||
|
||||
* 1.2.6 (not yet released)
|
||||
* `ncplane_putsimple_yx()` and `ncplane_putstr_yx()` has been exported as a
|
||||
static inline function.
|
||||
* `ncplane_putsimple_yx()` and `ncplane_putstr_yx()` have been exported as
|
||||
static inline functions.
|
||||
* `ncplane_set_scrolling()` has been added, allowing control over whether a
|
||||
plane scrolls. All planes, including the standard plane, do not scroll by
|
||||
default. If scrolling is enabled, text output via the `*put*` family of
|
||||
@ -15,6 +15,12 @@ rearrangements of Notcurses.
|
||||
* `ncplot_add_sample()` and `ncplot_set_sample()` have been changed to accept
|
||||
a `uint64_t` rather than `int64_t`, since negative samples do not
|
||||
currently make sense. Plots were made more accurate in general.
|
||||
* `notcurses_term_dim_yx()` now accepts a `const struct notcurses*`.
|
||||
* `notcurses_resize()` is no longer exported. It was never necessary to call
|
||||
this in response to a resize, despite confusing documentation that could
|
||||
have been read to suggest otherwise. If you're in a long block on input, and
|
||||
get an `NCKEY_RESIZE`, just call `notcurses_refresh()` (which now calls
|
||||
`notcurses_resize()` internally, as `notcurses_render()` always has).
|
||||
|
||||
* 1.2.5
|
||||
* Add ncplot, with support for sliding-windowed horizontal histograms.
|
||||
|
12
README.md
12
README.md
@ -296,22 +296,18 @@ Utility functions operating on the toplevel `notcurses` object include:
|
||||
// Return the topmost ncplane, of which there is always at least one.
|
||||
struct ncplane* notcurses_top(struct notcurses* n);
|
||||
|
||||
// Refresh our idea of the terminal's dimensions, reshaping the standard plane
|
||||
// if necessary, without a fresh render. References to ncplanes (and the
|
||||
// egcpools underlying cells) remain valid following a resize operation.
|
||||
int notcurses_resize(struct notcurses* n, int* restrict y, int* restrict x);
|
||||
|
||||
// Return our current idea of the terminal dimensions in rows and cols.
|
||||
static inline void
|
||||
notcurses_term_dim_yx(const struct notcurses* n, int* restrict rows,
|
||||
int* restrict cols){
|
||||
ncplane_dim_yx(notcurses_stdplane(n), rows, cols);
|
||||
ncplane_dim_yx(notcurses_stdplane_const(n), rows, cols);
|
||||
}
|
||||
|
||||
// Refresh the physical screen to match what was last rendered (i.e., without
|
||||
// reflecting any changes since the last call to notcurses_render()). This is
|
||||
// primarily useful if the screen is externally corrupted.
|
||||
int notcurses_refresh(struct notcurses* n);
|
||||
// primarily useful if the screen is externally corrupted, or if an
|
||||
// NCKEY_RESIZE event has been read and you're not ready to render.
|
||||
int notcurses_refresh(struct notcurses* n, int* restrict y, int* restrict x);
|
||||
|
||||
// Returns a 16-bit bitmask in the LSBs of supported curses-style attributes
|
||||
// (NCSTYLE_UNDERLINE, NCSTYLE_BOLD, etc.) The attribute is only
|
||||
|
10
debian/control
vendored
10
debian/control
vendored
@ -40,7 +40,7 @@ Depends:
|
||||
Description: Character graphics and TUI library (C++ development)
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
.
|
||||
These files are necessary for C++ development using notcurses.
|
||||
|
||||
@ -52,7 +52,7 @@ Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Character graphics and TUI library (C++ wrappers)
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
.
|
||||
These files underlie the C++ wrappers for notcurses.
|
||||
|
||||
@ -101,7 +101,7 @@ Depends:
|
||||
Description: Character graphics and TUI library demos
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
.
|
||||
These utilities from the notcurses project include notcurses-demo
|
||||
(a demonstration of various libnotcurses capabilities) and
|
||||
@ -117,7 +117,7 @@ Depends: ncurses-term, ${misc:Depends}
|
||||
Description: Multimedia used by notcurses-bin
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
.
|
||||
This package contains multimedia used by notcurses-demo
|
||||
and notcurses-tester from the notcurses-bin package.
|
||||
@ -131,6 +131,6 @@ Provides: ${python3:Provides}
|
||||
Description: Character graphics and TUI library (Python)
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
.
|
||||
These files are necessary for Python development using notcurses.
|
||||
|
@ -41,8 +41,8 @@
|
||||
<a href="notcurses_output.3.html">notcurses_output</a>—drawing text on <tt>ncplane</tt>s<br/>
|
||||
<a href="notcurses_palette.3.html">notcurses_palette</a>—operations on notcurses palettes<br/>
|
||||
<a href="notcurses_plot.3.html">notcurses_palette</a>—drawing histograms and lineplots<br/>
|
||||
<a href="notcurses_refresh.3.html">notcurses_refresh</a>—refresh an externally-damaged display<br/>
|
||||
<a href="notcurses_render.3.html">notcurses_render</a>—sync the physical display<br/>
|
||||
<a href="notcurses_resize.3.html">notcurses_resize</a>—resize the standard plane based off screen size<br/>
|
||||
<a href="notcurses_selector.3.html">notcurses_selector</a>—high-level widget for selecting one item from a set<br/>
|
||||
<a href="notcurses_multiselector.3.html">notcurses_multiselector</a>—high-level widget for selecting items from a set<br/>
|
||||
<a href="notcurses_stats.3.html">notcurses_stats</a>—notcurses runtime statistics<br/>
|
||||
|
@ -146,8 +146,8 @@ previous action.
|
||||
**notcurses_palette(3)**,
|
||||
**notcurses_plot(3)**,
|
||||
**notcurses_reel(3)**,
|
||||
**notcurses_refresh(3)**,
|
||||
**notcurses_render(3)**,
|
||||
**notcurses_resize(3)**,
|
||||
**notcurses_selector(3)**,
|
||||
**notcurses_stats(3)**,
|
||||
**notcurses_stdplane(3)**, **notcurses_stop(3)**,
|
||||
|
@ -92,8 +92,8 @@ a handler for this signal. The handler causes notcurses to update its idea of
|
||||
the terminal's size using **TIOCGWINSZ** (see **ioctl_tty(2)**), and generates an
|
||||
**NCKEY_RESIZE** input event (see **notcurses_input(3)**. This signal handler can be
|
||||
inhibited by setting **no_winch_sighandler** to **true**. If this is done, the
|
||||
caller should probably watch for the signal, and invoke **notcurses_resize()**
|
||||
upon its receipt.
|
||||
caller should probably watch for the signal, and invoke **notcurses_refresh(3)**
|
||||
or **notcurses_render(3)** upon its receipt.
|
||||
|
||||
A resize event does not invalidate any references returned earlier by
|
||||
notcurses. The content of any new screen area is undefined until the next call
|
||||
@ -109,7 +109,7 @@ Thus, in the absence of **no_winch_sighandler**, **SIGWINCH** results in:
|
||||
* a **TIOCGWINSZ** **ioctl** to retrieve the new screen size
|
||||
* queuing of a **NCKEY_RESIZE** input event (if there is space in the queue)
|
||||
|
||||
Upon the next call to **notcurses_render(3)** or **notcurses_resize(3)**, the
|
||||
Upon the next call to **notcurses_render(3)** or **notcurses_refresh(3)**, the
|
||||
standard plane (see **notcurses_stdplane(3)**) will be resized to the new
|
||||
screen size. The next **notcurses_render(3)** call will function as expected
|
||||
across the new screen geometry.
|
||||
@ -123,5 +123,5 @@ across the new screen geometry.
|
||||
# SEE ALSO
|
||||
|
||||
**getenv(3)**, **termios(3)**, **notcurses(3)**, **notcurses_input(3)**,
|
||||
**notcurses_ncplane(3)**, **notcurses_render(3)**, **notcurses_resize(3)**,
|
||||
**notcurses_ncplane(3)**, **notcurses_refresh(3)**, **notcurses_render(3)**,
|
||||
**notcurses_stop(3)**, **terminfo(5)**, **signal(7)**
|
||||
|
@ -91,7 +91,7 @@ found in **<notcurses.h>**. For more details, consult **terminfo(5)**.
|
||||
Unless the **SIGWINCH** handler has been inhibited (see **notcurses_init(3)**),
|
||||
notcurses will automatically catch screen resizes, and synthesize an
|
||||
**NCKEY_RESIZE** event. Upon receiving this event, the user may call
|
||||
**notcurses_resize(3)** to force an immediate reflow, or just wait until the
|
||||
**notcurses_refresh(3)** to force an immediate reflow, or just wait until the
|
||||
next call to **notcurses_render(3)**, when notcurses will pick up the resize
|
||||
itself. If the **SIGWINCH** handler is inhibited, **NCKEY_RESIZE** is never
|
||||
generated.
|
||||
@ -139,8 +139,8 @@ registers as **NCKEY_ENTER**. This will likely change in the future.
|
||||
**poll(2)**,
|
||||
**cfmakeraw(3)**,
|
||||
**notcurses(3)**,
|
||||
**notcurses_refresh(3)**,
|
||||
**notcurses_render(3)**,
|
||||
**notcurses_resize(3)**,
|
||||
**termios(3)**,
|
||||
**terminfo(5)**,
|
||||
**ascii(7)**,
|
||||
|
66
doc/man/man3/notcurses_refresh.3.md
Normal file
66
doc/man/man3/notcurses_refresh.3.md
Normal file
@ -0,0 +1,66 @@
|
||||
% notcurses_refresh(3)
|
||||
% nick black <nickblack@linux.com>
|
||||
% v1.2.5
|
||||
|
||||
# NAME
|
||||
|
||||
notcurses_refresh - redraw an externally-damaged display
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
**#include <notcurses.h>**
|
||||
|
||||
**int notcurses_refresh(const struct notcurses* nc, int* restrict rows, int* restrict cols);**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**notcurses_refresh** clears the screen, homes the cursor, checks the current
|
||||
terminal geometry, and repaints the most recently rendered frame. It can be
|
||||
called concurrently with all other Notcurses functions save
|
||||
**notcurses_render**. **notcurses_refresh** ought be called when the screen is
|
||||
externally damaged (as occurs when another program writes to the terminal, or
|
||||
if your program writes to the terminal using standard I/O). It is necessary to
|
||||
use **notcurses_refresh** in such a case (as opposed to simply calling
|
||||
**notcurses_render**), since **notcurses_render** optimizes its output by only
|
||||
writing internally-damaged cells. Notcurses has no way of knowing about
|
||||
external corruption; by tradition, Ctrl+L is bound to **notcurses_refresh**,
|
||||
and the user is responsible for requesting a hard redraw.
|
||||
|
||||
A secondary use of this function is when the program is blocking on input (and
|
||||
perhaps not ready to render), and receives an **NCKEY_RESIZE** event (see
|
||||
**notcurses_input**). In this case, **notcurses_refresh** will acquire the new
|
||||
screen parameters, and repaint what it can. If you're prepared to call
|
||||
**notcurses_render**, it's better to do that in this case, and thus avoid
|
||||
unnecessary screen redrawing.
|
||||
|
||||
If **rows** and/or **cols** is not NULL, they receive the new geometry.
|
||||
|
||||
# NOTES
|
||||
|
||||
If your program **is** in a render loop (i.e. rendering as quickly as
|
||||
possible, or at least at the refresh rate), there's not much point in
|
||||
erecting the machinery to trigger **notcurses_refresh** based off
|
||||
**NCKEY_RESIZE**. The latter is generated based upon receipt of the **SIGWINCH**
|
||||
signal, which is fundamentally racy with regards to the rest of the program.
|
||||
If your program truly relies on timely invocation of **notcurses_refresh**,
|
||||
it's a broken program. If you don't rely on it in a causal fashion, then just
|
||||
wait for the upcoming render.
|
||||
|
||||
Highest performance in a rendering loop would actually call for disabling
|
||||
Notcurses's **SIGWINCH** handling in the call to **notcurses_init**, so that no
|
||||
time is spent handling a signal you're not going to use.
|
||||
|
||||
# RETURN VALUES
|
||||
|
||||
Returns 0 on success, and -1 on failure. The causes for failure include system
|
||||
error, programming error, closing of output, or allocation failure. None
|
||||
of these are particularly good things, and the most reasonable response to a
|
||||
**notcurses_refresh** failure is either to ignore it, or to weep and exit.
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
**notcurses_init(3)**,
|
||||
**notcurses_input(3)**,
|
||||
**notcurses_render(3)**,
|
||||
**termios(3)**,
|
||||
**signal(7)**
|
@ -20,8 +20,8 @@ notcurses_render - sync the physical display to the virtual ncplanes
|
||||
ncplanes. It is necessary to call **notcurses_render** to generate any visible
|
||||
output; the various notcurses_output(3) calls only draw to the virtual
|
||||
ncplanes. Most of the notcurses statistics are updated as a result of a
|
||||
render (see notcurses_stats(3)), and **notcurses_resize(3)** is called
|
||||
internally *following* the render.
|
||||
render (see notcurses_stats(3)), and screen geometry is refreshed (similarly to
|
||||
**notcurses_refresh**) *following* the render.
|
||||
|
||||
While **notcurses_render** is called, you **must not call any other functions
|
||||
on the same notcurses context**, with the one exception of **notcurses_getc**
|
||||
@ -35,7 +35,7 @@ color, and style for each cell of the physical terminal. Writing the scene
|
||||
requires synthesizing a set of UTF-8-encoded characters and escape codes
|
||||
appropriate for the terminal (relying on terminfo(5)), and writing this
|
||||
sequence to the output **FILE**. If the **renderfp** value was not NULL in the
|
||||
original call to notcurses_init(3), the frame will be written to that **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
|
||||
@ -85,5 +85,5 @@ purposes of color blending.
|
||||
# SEE ALSO
|
||||
|
||||
**notcurses(3)**, **notcurses_cell(3)**, **notcurses_ncplane(3)**,
|
||||
**notcurses_output(3)**, **notcurses_resize(3)**, **notcurses_stats(3)**,
|
||||
**notcurses_output(3)**, **notcurses_refresh(3)**, **notcurses_stats(3)**,
|
||||
**console_codes(4)**, **utf-8(7)**
|
||||
|
@ -1,64 +0,0 @@
|
||||
% notcurses_resize(3)
|
||||
% nick black <nickblack@linux.com>
|
||||
% v1.2.5
|
||||
|
||||
# NAME
|
||||
|
||||
notcurses_resize - resizeialize a notcurses instance
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
**#include <notcurses.h>**
|
||||
|
||||
**int notcurses_resize(const struct notcurses* nc, int* rows, int* cols);**
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**notcurses_resize** causes notcurses to retrieve the screen's current size
|
||||
using **termios(3)**. If it has changed, notcurses will resize the standard
|
||||
plane appropriately. Like any other **ncplane_resize(3)** operation, lost
|
||||
space will be culled from the standard plane, while new space will be
|
||||
populated by the standard plane's base cell. Other planes are unaffected.
|
||||
**notcurses_resize** does *not* result in a rendering operation.
|
||||
|
||||
**notcurses_render(3)** calls this function following a render+raster cycle. It
|
||||
is thus not necessary to call it yourself unless both of the following are
|
||||
true:
|
||||
|
||||
* Your program is in an event loop rather than a rendering loop (i.e. it calls **notcurses_render(3)** only based on external events), and
|
||||
* Your program makes use of the standard plane, or the standard plane's dimensions.
|
||||
|
||||
If this is the case, you might call **notcurses_resize** based on an
|
||||
**NCKEY_RESIZE** event on the input channel (see **notcurses_input(3)**),
|
||||
so that you can write to the standard plane using its new size prior to a
|
||||
render. If you have no changes, and just want to render what you have (with
|
||||
more or less now visible), it is sufficient to simply call **notcurses_render(3)**.
|
||||
|
||||
If **rows** and/or **cols** is not NULL, they receive the new geometry.
|
||||
|
||||
# NOTES
|
||||
|
||||
If your program **is** in a render loop (i.e. rendering as quickly as
|
||||
possible, or at least at the refresh rate), there's not much point in
|
||||
erecting the machinery to trigger **notcurses_resize** based off
|
||||
**NCKEY_RESIZE**. The latter is generated based upon receipt of the **SIGWINCH**
|
||||
signal, which is fundamentally racy with regards to the rest of the program.
|
||||
If your program truly relies on timely invocation of **notcurses_resize()**,
|
||||
it's a broken program. If you don't rely on it in a causal fashion, then just
|
||||
wait for the upcoming render.
|
||||
|
||||
Highest performance in a rendering loop would actually call for disabling
|
||||
notcurses SIGWINCH handling in the call to **notcurses_init(3)**, so that no
|
||||
time is spent handling a signal you're not going to use.
|
||||
|
||||
# RETURN VALUES
|
||||
|
||||
Returns 0 on success, and -1 on failure. The causes for failure include system
|
||||
error, programming error, closing of output, or allocation failure. None
|
||||
of these are particularly good things, and the most reasonable response to a
|
||||
**notcurses_resize** failure is probably to weep.
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
**notcurses_init(3)**, **notcurses_input(3)**, **notcurses_ncplane(3)**,
|
||||
**notcurses_render(3)**, **termios(3)**, **signal(7)**
|
@ -145,16 +145,6 @@ namespace ncpp
|
||||
return notcurses_render (nc) == 0;
|
||||
}
|
||||
|
||||
bool resize (int *rows, int *cols) const noexcept
|
||||
{
|
||||
return notcurses_resize (nc, rows, cols) == 0;
|
||||
}
|
||||
|
||||
bool resize (int &rows, int &cols) const noexcept
|
||||
{
|
||||
return resize (&rows, &cols) == 0;
|
||||
}
|
||||
|
||||
void get_term_dim (int *rows, int *cols) const noexcept
|
||||
{
|
||||
notcurses_term_dim_yx (nc, rows, cols);
|
||||
@ -165,9 +155,14 @@ namespace ncpp
|
||||
get_term_dim (&rows, &cols);
|
||||
}
|
||||
|
||||
bool refresh () const noexcept
|
||||
bool refresh (int* rows, int* cols) const noexcept
|
||||
{
|
||||
return notcurses_refresh (nc) == 0;
|
||||
return notcurses_refresh (nc, rows, cols) == 0;
|
||||
}
|
||||
|
||||
bool refresh (int& rows, int& cols) const noexcept
|
||||
{
|
||||
return refresh (&rows, &cols) == 0;
|
||||
}
|
||||
|
||||
int get_palette_size () const noexcept
|
||||
|
@ -666,15 +666,11 @@ API int notcurses_mouse_enable(struct notcurses* n);
|
||||
// Disable mouse events. Any events in the input queue can still be delivered.
|
||||
API int notcurses_mouse_disable(struct notcurses* n);
|
||||
|
||||
// Refresh our idea of the terminal's dimensions, reshaping the standard plane
|
||||
// if necessary, without a fresh render. References to ncplanes (and the
|
||||
// egcpools underlying cells) remain valid following a resize operation.
|
||||
API int notcurses_resize(struct notcurses* n, int* RESTRICT y, int* RESTRICT x);
|
||||
|
||||
// Refresh the physical screen to match what was last rendered (i.e., without
|
||||
// reflecting any changes since the last call to notcurses_render()). This is
|
||||
// primarily useful if the screen is externally corrupted.
|
||||
API int notcurses_refresh(struct notcurses* n);
|
||||
// primarily useful if the screen is externally corrupted, or if an
|
||||
// NCKEY_RESIZE event has been read and you're not ready to render.
|
||||
API int notcurses_refresh(struct notcurses* n, int* RESTRICT y, int* RESTRICT x);
|
||||
|
||||
// Return the dimensions of this ncplane.
|
||||
API void ncplane_dim_yx(const struct ncplane* n, int* RESTRICT y, int* RESTRICT x);
|
||||
@ -709,8 +705,8 @@ ncplane_dim_x(const struct ncplane* n){
|
||||
|
||||
// Return our current idea of the terminal dimensions in rows and cols.
|
||||
static inline void
|
||||
notcurses_term_dim_yx(struct notcurses* n, int* RESTRICT rows, int* RESTRICT cols){
|
||||
ncplane_dim_yx(notcurses_stdplane(n), rows, cols);
|
||||
notcurses_term_dim_yx(const struct notcurses* n, int* RESTRICT rows, int* RESTRICT cols){
|
||||
ncplane_dim_yx(notcurses_stdplane_const(n), rows, cols);
|
||||
}
|
||||
|
||||
// Retrieve the contents of the specified cell as last rendered. The EGC is
|
||||
|
@ -97,8 +97,7 @@ int ncplane_set_base(struct ncplane* ncp, uint64_t channels, uint32_t attrword,
|
||||
int ncplane_base(struct ncplane* ncp, cell* c);
|
||||
struct ncplane* notcurses_top(struct notcurses* n);
|
||||
void notcurses_drop_planes(struct notcurses* nc);
|
||||
int notcurses_refresh(struct notcurses* n);
|
||||
int notcurses_resize(struct notcurses* n, int* y, int* x);
|
||||
int notcurses_refresh(struct notcurses* n, int* restrict y, int* restrict x);
|
||||
struct ncplane* ncplane_new(struct notcurses* nc, int rows, int cols, int yoff, int xoff, void* opaque);
|
||||
struct ncplane* ncplane_bound(struct ncplane* n, int rows, int cols, int yoff, int xoff, void* opaque);
|
||||
struct ncplane* ncplane_reparent(struct ncplane* n, struct ncplane* newparent);
|
||||
|
@ -14,3 +14,8 @@ homepage = "https://nick-black.com/dankwiki/index.php/Notcurses"
|
||||
libnotcurses-sys = "^1.2.5"
|
||||
libc = "0.2.66"
|
||||
libc-stdhandle = ">= 0.1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
all_asserts = ">= 1.0.0"
|
||||
serial_test = "*"
|
||||
serial_test_derive = "*"
|
||||
|
@ -14,6 +14,22 @@ pub fn ncplane_putstr(_n: *mut ffi::ncplane, _str: &str) -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ncplane_dim_y(_n: *const ffi::ncplane) -> i32 {
|
||||
unsafe {
|
||||
let mut y = 0;
|
||||
ffi::ncplane_dim_yx(_n, &mut y, std::ptr::null_mut());
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ncplane_dim_x(_n: *const ffi::ncplane) -> i32 {
|
||||
unsafe {
|
||||
let mut x = 0;
|
||||
ffi::ncplane_dim_yx(_n, std::ptr::null_mut(), &mut x);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(_n: *mut ffi::notcurses) -> std::result::Result<(), std::io::Error> {
|
||||
unsafe {
|
||||
let r = ffi::notcurses_render(_n);
|
||||
@ -24,15 +40,32 @@ pub fn render(_n: *mut ffi::notcurses) -> std::result::Result<(), std::io::Error
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stddim_yx(_n: *mut ffi::notcurses, _dimy: &mut i32, _dimx: &mut i32) -> *mut ffi::ncplane {
|
||||
unsafe {
|
||||
let stdplane = ffi::notcurses_stdplane(_n);
|
||||
ffi::ncplane_dim_yx(stdplane, _dimy, _dimx);
|
||||
return stdplane;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dim_yx(_n: *const ffi::notcurses, _dimy: &mut i32, _dimx: &mut i32) {
|
||||
unsafe {
|
||||
ffi::ncplane_dim_yx(ffi::notcurses_stdplane_const(_n), _dimy, _dimx);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use all_asserts;
|
||||
use serial_test_derive::serial; // serialize tests w/ ffi::notcurses_init()
|
||||
|
||||
extern {
|
||||
static stdout: *mut ffi::_IO_FILE;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn create_context() {
|
||||
unsafe {
|
||||
let _ = libc::setlocale(libc::LC_ALL, std::ffi::CString::new("").unwrap().as_ptr());
|
||||
@ -51,7 +84,33 @@ mod tests {
|
||||
margin_l: 0,
|
||||
};
|
||||
let nc = ffi::notcurses_init(&opts, stdout);
|
||||
ffi::notcurses_stop(nc);
|
||||
assert_ne!(std::ptr::null(), nc);
|
||||
let mut dimy = 0;
|
||||
let mut dimx = 0;
|
||||
dim_yx(nc, &mut dimy, &mut dimx);
|
||||
all_asserts::assert_lt!(0, dimy);
|
||||
all_asserts::assert_lt!(0, dimx);
|
||||
assert_eq!(0, ffi::notcurses_stop(nc));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn stdplane_dims() {
|
||||
unsafe {
|
||||
let _ = libc::setlocale(libc::LC_ALL, std::ffi::CString::new("").unwrap().as_ptr());
|
||||
let nc = ffi::notcurses_init(std::ptr::null(), stdout);
|
||||
assert_ne!(std::ptr::null(), nc);
|
||||
let mut dimsy = 0;
|
||||
let mut dimsx = 0;
|
||||
let _stdplane = stddim_yx(nc, &mut dimsy, &mut dimsx);
|
||||
all_asserts::assert_lt!(0, dimsy);
|
||||
all_asserts::assert_lt!(0, dimsx);
|
||||
let dimy = ncplane_dim_y(_stdplane);
|
||||
let dimx = ncplane_dim_x(_stdplane);
|
||||
assert_eq!(dimy, dimsy);
|
||||
assert_eq!(dimx, dimsx);
|
||||
assert_eq!(0, ffi::notcurses_stop(nc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ chunli_draw(struct notcurses* nc, const char* ext, int count, const cell* b){
|
||||
timespec_div(&demodelay, 10, &iterdelay);
|
||||
for(int i = 0 ; i < count ; ++i){
|
||||
int averr;
|
||||
notcurses_resize(nc, &dimy, &dimx);
|
||||
notcurses_refresh(nc, &dimy, &dimx);
|
||||
snprintf(file, sizeof(file), "chunli%d.%s", i + 1, ext);
|
||||
chuns[i].path = find_data(file);
|
||||
chuns[i].ncv = ncvisual_open_plane(nc, chuns[i].path, &averr, 0, 0, NCSCALE_NONE);
|
||||
@ -54,7 +54,7 @@ int chunli_demo(struct notcurses* nc){
|
||||
struct timespec iterdelay;
|
||||
timespec_div(&demodelay, 10, &iterdelay);
|
||||
int averr, dimx, dimy;
|
||||
notcurses_resize(nc, &dimy, &dimx);
|
||||
notcurses_refresh(nc, &dimy, &dimx);
|
||||
cell b = CELL_TRIVIAL_INITIALIZER;
|
||||
cell_set_fg_alpha(&b, CELL_ALPHA_TRANSPARENT);
|
||||
cell_set_bg_alpha(&b, CELL_ALPHA_TRANSPARENT);
|
||||
|
@ -111,7 +111,7 @@ ultramegaok_demo(void* vnc){
|
||||
}
|
||||
if(id == 'L' && ni.ctrl){
|
||||
lock_demo_render();
|
||||
notcurses_refresh(nc);
|
||||
notcurses_refresh(nc, NULL, NULL);
|
||||
unlock_demo_render();
|
||||
continue;
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ ncreel_demo_core(struct notcurses* nc, int efdr, int efdw){
|
||||
case NCKEY_UP: ncreel_prev(pr); break;
|
||||
case NCKEY_DOWN: ncreel_next(pr); break;
|
||||
case NCKEY_DEL: kill_active_tablet(pr, &tctxs); break;
|
||||
case NCKEY_RESIZE: notcurses_resize(nc, &dimy, NULL); break;
|
||||
case NCKEY_RESIZE: notcurses_render(nc); break;
|
||||
default: ncplane_printf_yx(w, 3, 2, "Unknown keycode (0x%x)\n", rw); break;
|
||||
}
|
||||
if(newtablet){
|
||||
@ -376,6 +376,7 @@ ncreel_demo_core(struct notcurses* nc, int efdr, int efdw){
|
||||
if(timespec_subtract_ns(&cur, &deadline) >= 0){
|
||||
break;
|
||||
}
|
||||
dimy = ncplane_dim_y(w);
|
||||
}while(!aborted);
|
||||
while(tctxs){
|
||||
kill_tablet(&tctxs);
|
||||
|
@ -577,7 +577,7 @@ int witherworm_demo(struct notcurses* nc){
|
||||
return 1;
|
||||
}
|
||||
if(key == NCKEY_RESIZE){
|
||||
notcurses_resize(nc, &maxy, &maxx);
|
||||
DEMO_RENDER(nc);
|
||||
}
|
||||
}while(key == NCKEY_RESIZE);
|
||||
if(key == 'q'){
|
||||
|
@ -18,7 +18,7 @@ static int dimy, dimx;
|
||||
const char* nckeystr(char32_t spkey){
|
||||
switch(spkey){ // FIXME
|
||||
case NCKEY_RESIZE:
|
||||
NotCurses::get_instance ().resize(&dimy, &dimx);
|
||||
NotCurses::get_instance().refresh(&dimy, &dimx);
|
||||
return "resize event";
|
||||
case NCKEY_INVALID: return "invalid";
|
||||
case NCKEY_LEFT: return "left";
|
||||
|
@ -620,6 +620,12 @@ cell_duplicate_far(egcpool* tpool, cell* targ, const ncplane* splane, const cell
|
||||
return ulen;
|
||||
}
|
||||
|
||||
int ncplane_resize_internal(ncplane* n, int keepy, int keepx,
|
||||
int keepleny, int keeplenx, int yoff, int xoff,
|
||||
int ylen, int xlen);
|
||||
|
||||
int update_term_dimensions(int fd, int* rows, int* cols);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -216,8 +216,7 @@ void ncplane_dim_yx(const ncplane* n, int* rows, int* cols){
|
||||
|
||||
// anyone calling this needs ensure the ncplane's framebuffer is updated
|
||||
// to reflect changes in geometry.
|
||||
static int
|
||||
update_term_dimensions(int fd, int* rows, int* cols){
|
||||
int update_term_dimensions(int fd, int* rows, int* cols){
|
||||
struct winsize ws;
|
||||
int i = ioctl(fd, TIOCGWINSZ, &ws);
|
||||
if(i < 0){
|
||||
@ -391,9 +390,8 @@ ncplane* ncplane_dup(ncplane* n, void* opaque){
|
||||
}
|
||||
|
||||
// can be used on stdscr, unlike ncplane_resize() which prohibits it.
|
||||
static int
|
||||
ncplane_resize_internal(ncplane* n, int keepy, int keepx, int keepleny,
|
||||
int keeplenx, int yoff, int xoff, int ylen, int xlen){
|
||||
int ncplane_resize_internal(ncplane* n, int keepy, int keepx, int keepleny,
|
||||
int keeplenx, int yoff, int xoff, int ylen, int xlen){
|
||||
if(keepleny < 0 || keeplenx < 0){ // can't retain negative size
|
||||
//fprintf(stderr, "Can't retain negative size %dx%d\n", keepleny, keeplenx);
|
||||
return -1;
|
||||
@ -494,48 +492,6 @@ int ncplane_resize(ncplane* n, int keepy, int keepx, int keepleny,
|
||||
yoff, xoff, ylen, xlen);
|
||||
}
|
||||
|
||||
// Call this when the screen size changes. Acquires the new size, and copies
|
||||
// what can be copied from the old stdscr. Assumes that the screen is always
|
||||
// anchored in the same place.
|
||||
int notcurses_resize(notcurses* n, int* rows, int* cols){
|
||||
int r, c;
|
||||
if(rows == NULL){
|
||||
rows = &r;
|
||||
}
|
||||
if(cols == NULL){
|
||||
cols = &c;
|
||||
}
|
||||
int oldrows = n->stdscr->leny;
|
||||
int oldcols = n->stdscr->lenx;
|
||||
if(update_term_dimensions(n->ttyfd, rows, cols)){
|
||||
return -1;
|
||||
}
|
||||
// FIXME can we emerge from the previous call with rows/cols <= 0?
|
||||
*rows -= n->margin_t + n->margin_b;
|
||||
if(*rows <= 0){
|
||||
*rows = 1;
|
||||
}
|
||||
*cols -= n->margin_l + n->margin_r;
|
||||
if(*cols <= 0){
|
||||
*cols = 1;
|
||||
}
|
||||
if(*rows == oldrows && *cols == oldcols){
|
||||
return 0; // no change
|
||||
}
|
||||
int keepy = *rows;
|
||||
if(keepy > oldrows){
|
||||
keepy = oldrows;
|
||||
}
|
||||
int keepx = *cols;
|
||||
if(keepx > oldcols){
|
||||
keepx = oldcols;
|
||||
}
|
||||
if(ncplane_resize_internal(n->stdscr, 0, 0, keepy, keepx, 0, 0, *rows, *cols)){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// find the pointer on the z-index referencing the specified plane. writing to
|
||||
// this pointer will remove the plane (and everything below it) from the stack.
|
||||
static ncplane**
|
||||
|
@ -4,6 +4,47 @@
|
||||
#include <sys/poll.h>
|
||||
#include "internal.h"
|
||||
|
||||
// Check whether the terminal geometry has changed, and if so, copies what can
|
||||
// be copied from the old stdscr. Assumes that the screen is always anchored in
|
||||
// the same place.
|
||||
int notcurses_resize(notcurses* n, int* restrict rows, int* restrict cols){
|
||||
int r, c;
|
||||
if(rows == NULL){
|
||||
rows = &r;
|
||||
}
|
||||
if(cols == NULL){
|
||||
cols = &c;
|
||||
}
|
||||
int oldrows = n->stdscr->leny;
|
||||
int oldcols = n->stdscr->lenx;
|
||||
if(update_term_dimensions(n->ttyfd, rows, cols)){
|
||||
return -1;
|
||||
}
|
||||
*rows -= n->margin_t + n->margin_b;
|
||||
if(*rows <= 0){
|
||||
*rows = 1;
|
||||
}
|
||||
*cols -= n->margin_l + n->margin_r;
|
||||
if(*cols <= 0){
|
||||
*cols = 1;
|
||||
}
|
||||
if(*rows == oldrows && *cols == oldcols){
|
||||
return 0; // no change
|
||||
}
|
||||
int keepy = *rows;
|
||||
if(keepy > oldrows){
|
||||
keepy = oldrows;
|
||||
}
|
||||
int keepx = *cols;
|
||||
if(keepx > oldcols){
|
||||
keepx = oldcols;
|
||||
}
|
||||
if(ncplane_resize_internal(n->stdscr, 0, 0, keepy, keepx, 0, 0, *rows, *cols)){
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
blocking_write(int fd, const char* buf, size_t buflen){
|
||||
//fprintf(stderr, "writing %zu to %d...\n", buflen, fd);
|
||||
@ -998,8 +1039,13 @@ home_cursor(notcurses* nc, bool flush){
|
||||
return -1;
|
||||
}
|
||||
|
||||
int notcurses_refresh(notcurses* nc){
|
||||
// FIXME need reflow in the event we've been resized
|
||||
int notcurses_refresh(notcurses* nc, int* restrict dimy, int* restrict dimx){
|
||||
if(notcurses_resize(nc, dimy, dimx)){
|
||||
return -1;
|
||||
}
|
||||
if(nc->lfdimx == 0 || nc->lfdimy == 0){
|
||||
return 0;
|
||||
}
|
||||
if(home_cursor(nc, true)){
|
||||
return -1;
|
||||
}
|
||||
@ -1024,6 +1070,8 @@ int notcurses_render(notcurses* nc){
|
||||
struct timespec start, done;
|
||||
int ret;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
int dimy, dimx;
|
||||
notcurses_resize(nc, &dimy, &dimx);
|
||||
int bytes = -1;
|
||||
const size_t crenderlen = sizeof(struct crender) * nc->stdscr->leny * nc->stdscr->lenx;
|
||||
struct crender* crender = malloc(crenderlen);
|
||||
@ -1032,8 +1080,6 @@ int notcurses_render(notcurses* nc){
|
||||
bytes = notcurses_rasterize(nc, crender);
|
||||
}
|
||||
free(crender);
|
||||
int dimy, dimx;
|
||||
notcurses_resize(nc, &dimy, &dimx);
|
||||
clock_gettime(CLOCK_MONOTONIC, &done);
|
||||
update_render_stats(&done, &start, &nc->stats, bytes);
|
||||
ret = bytes >= 0 ? 0 : -1;
|
||||
|
@ -2,7 +2,7 @@ int main(void) {
|
||||
if(setlocale(LC_ALL, "") == nullptr){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
srand(time(NULL));
|
||||
srand(time(nullptr));
|
||||
std::atomic_bool gameover = false;
|
||||
notcurses_options ncopts{};
|
||||
ncpp::NotCurses nc(ncopts);
|
||||
@ -19,7 +19,7 @@ int main(void) {
|
||||
case NCKEY_LEFT: case 'h': t.MoveLeft(); break;
|
||||
case NCKEY_RIGHT: case 'l': t.MoveRight(); break;
|
||||
case NCKEY_DOWN: case 'j': t.MoveDown(); break;
|
||||
case 'L': if(ni.ctrl){ notcurses_refresh(nc); } break;
|
||||
case 'L': if(ni.ctrl){ notcurses_refresh(nc, nullptr, nullptr); } break;
|
||||
case 'z': t.RotateCcw(); break;
|
||||
case 'x': t.RotateCw(); break;
|
||||
default:
|
||||
|
@ -198,10 +198,10 @@ int main(int argc, char** argv){
|
||||
break;
|
||||
}else if(ie == NCKey::Resize){
|
||||
--i; // rerun with the new size
|
||||
if(!nc.resize(&dimy, &dimx)){
|
||||
if(!nc.refresh(&dimy, &dimx)){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(!ncv->get_plane ()->resize(dimy, dimx)){
|
||||
if(!ncv->get_plane()->resize(dimy, dimx)){
|
||||
nc.stop();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ TEST_CASE("NotcursesBase") {
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("ResizeSameSize") {
|
||||
SUBCASE("RefreshSameSize") {
|
||||
int x, y;
|
||||
notcurses_term_dim_yx(nc_, &y, &x);
|
||||
int newx, newy;
|
||||
CHECK(0 == notcurses_resize(nc_, &newy, &newx));
|
||||
CHECK(0 == notcurses_refresh(nc_, &newy, &newx));
|
||||
CHECK(newx == x);
|
||||
CHECK(newy == y);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ BuildRequires: gnupg2 cmake make gcc-c++ ncurses-devel pandoc python3-devel
|
||||
%description
|
||||
notcurses facilitates the creation of modern TUI programs,
|
||||
making full use of Unicode and 24-bit direct color. It presents
|
||||
an API similar to that of Curses, and rides atop libtinfo.
|
||||
an API similar to that of Curses, and rides atop Terminfo.
|
||||
|
||||
%prep
|
||||
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
|
||||
|
Loading…
Reference in New Issue
Block a user