Merge branch 'master' of github.com:dankamongmen/notcurses

pull/456/head
nick black 5 years ago
commit e276a36264

@ -2,22 +2,35 @@ 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_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
functions continues onto the next line when encountering the end of a row.
This does not apply to e.g. boxes or lines.
* `ncplane_putstr_yx()` now always returns the inverse of the number of
columns advanced on an error (it used to return the positive short count so
long as the error was due to plane geometry, not bad input).
* `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.
* 1.2.5
* Add ncplot, with support for sliding-windowed horizontal histograms.
* gradient, polyfill, ncplane_format() and ncplane_stain() all now return the
number of cells written on success. Failure still sees -1 returned.
* gradient, polyfill, `ncplane_format()` and `ncplane_stain()` all now return
the number of cells written on success. Failure still sees -1 returned.
* `ncvisual_render()` now returns the number of cells emitted on success, as
opposed to 0. Failure still sees -1 returned.
* `ncvisual_render()` now interprets length parameters of -1 to mean "to the
end along this axis", and no longer interprets 0 to mean this. 0 now means
end along this axis", and no longer interprets 0 to mean this. 0 now means
"a length of 0", resulting in a zero-area rendering.
* `notcurses_at_yx()` no longer accepts a `cell*` as its last parameter.
Instead, it accepts a `uint32_t*` and a `uint64_t*`, and writes the
attribute and channels to these parameters. This was done because the
`gcluster` field of the `cell*` was always set to 0, which was surprising
and a source of blunders. The EGC is returned via the `char*` return
value. https://github.com/dankamongmen/notcurses/issues/410
Instead, it accepts a `uint32_t*` and a `uint64_t*`, and writes the
attribute and channels to these parameters. This was done because the
`gcluster` field of the `cell*` was always set to 0, which was surprising
and a source of blunders. The EGC is returned via the `char*` return
value. https://github.com/dankamongmen/notcurses/issues/410
* 1.2.4 2020-03-24
* Add ncmultiselector

@ -18,7 +18,8 @@ option(USE_FFMPEG "Disable FFmpeg image/video support (recommended)" ON)
option(USE_NETWORK "Allow cargo to use the network" OFF)
option(USE_PANDOC "Build man pages and HTML reference with pandoc" ON)
option(USE_PYTHON "Build Python wrappers" ON)
option(USE_RUST "Build Rust wrappers/colloquy (experimental)" OFF)
option(USE_RUST "Build Rust wrappers (experimental)" OFF)
option(USE_TESTS "Build doctest unit tests" ON)
############## END (additional) USER-SELECTABLE OPTIONS ##################
find_package(PkgConfig REQUIRED)
@ -31,7 +32,9 @@ pkg_check_modules(AVUTIL REQUIRED libavutil>=56.0)
pkg_check_modules(SWSCALE REQUIRED libswscale>=5.0)
endif()
find_library(LIBRT rt)
if(${USE_TESTS})
find_package(doctest 2.3.5 REQUIRED)
endif()
# libnotcurses
file(GLOB NCSRCS CONFIGURE_DEPENDS src/lib/*.c)
@ -68,11 +71,13 @@ target_include_directories(notcurses-static
)
target_link_libraries(notcurses
PRIVATE
Threads::Threads
"${TERMINFO_LIBRARIES}"
"${LIBRT}"
)
target_link_libraries(notcurses-static
PRIVATE
Threads::Threads
"${TERMINFO_STATIC_LIBRARIES}"
"${LIBRT}"
)
@ -106,7 +111,6 @@ target_link_libraries(notcurses
"${AVFORMAT_LIBRARIES}"
"${AVUTIL_LIBRARIES}"
"${SWSCALE_LIBRARIES}"
Threads::Threads
)
target_link_libraries(notcurses-static
PRIVATE
@ -114,7 +118,6 @@ target_link_libraries(notcurses-static
"${AVFORMAT_STATIC_LIBRARIES}"
"${AVUTIL_STATIC_LIBRARIES}"
"${SWSCALE_STATIC_LIBRARIES}"
Threads::Threads
)
target_link_directories(notcurses
PUBLIC
@ -330,6 +333,7 @@ foreach(f ${POCSRCS})
add_executable(${fe} ${f})
target_include_directories(${fe}
PRIVATE include "${TERMINFO_INCLUDE_DIRS}"
"${PROJECT_BINARY_DIR}/include"
)
target_link_libraries(${fe}
PRIVATE notcurses++ "${TERMINFO_LIBRARIES}"
@ -528,6 +532,7 @@ target_compile_definitions(notcurses-view
endif()
# Testing
if(${USE_TESTS})
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
include(CTest)
endif()
@ -557,6 +562,7 @@ add_test(
NAME notcurses-tester
COMMAND notcurses-tester -p ${CMAKE_CURRENT_SOURCE_DIR}/data
)
endif()
# pkg-config support
configure_file(tools/notcurses.pc.in
@ -624,13 +630,11 @@ if(${USE_PYTHON})
endif()
endif()
# Rust bindings + colloquy
# Rust bindings
if(${USE_RUST})
file(GLOB LIBNCRSSRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/rust/libnotcurses-sys/src/*.rs ${CMAKE_CURRENT_SOURCE_DIR}/rust/libnotcurses-sys/src/*.rs)
file(GLOB COLLOQUYSRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/colloquy/src/*.rs ${CMAKE_CURRENT_SOURCE_DIR}/src/colloquy/src/*.yml)
set(LIBNOTCURSESSYS ${CMAKE_CURRENT_BINARY_DIR}/rust/debug/liblibnotcurses_sys.rlib)
set(CRATENOTCURSES ${CMAKE_CURRENT_BINARY_DIR}/rust/debug/libnotcurses.rlib)
set(COLLOQUY ${CMAKE_CURRENT_BINARY_DIR}/rust/debug/colloquy)
find_program(CARGO cargo REQUIRED)
# might need --locked here
set(CARGO_ARGS --verbose --release)
@ -643,7 +647,7 @@ if(${USE_RUST})
COMMAND
PKG_CONFIG_PATH=${CMAKE_CURRENT_BINARY_DIR} CARGO_HOME=${CMAKE_CURRENT_BINARY_DIR}/rust CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR}/rust ${CARGO} build ${CARGO_ARGS}
DEPENDS
${COLLOQUYSRC}
${LIBNCRSSRC}
COMMENT "Building rust crate libnotcurses-sys"
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/rust/libnotcurses-sys
@ -667,24 +671,6 @@ if(${USE_RUST})
DEPENDS
${CRATENOTCURSES}
)
add_custom_command(
OUTPUT
${COLLOQUY}
COMMAND
CARGO_HOME=${CMAKE_CURRENT_BINARY_DIR}/rust CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR}/rust ${CARGO} build ${CARGO_ARGS}
DEPENDS
${COLLOQUYSRC} ${CRATENOTCURSES}
COMMENT "Building colloquy"
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/src/colloquy
)
add_custom_target(colloquy ALL
DEPENDS
${COLLOQUY}
)
set_target_properties(colloquy
PROPERTIES LOCATION ${CMAKE_CURRENT_BINARY_DIR}
)
endif()
# Installation
@ -699,11 +685,13 @@ install(FILES
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
if(${USE_FFMPEG})
file(GLOB TESTDATA CONFIGURE_DEPENDS data/*)
install(FILES
${TESTDATA}
DESTINATION ${CMAKE_INSTALL_DATADIR}/notcurses
)
endif()
install(DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/include/"
@ -725,7 +713,9 @@ install(TARGETS notcurses-demo DESTINATION bin)
install(TARGETS notcurses-input DESTINATION bin)
install(TARGETS notcurses-keyplot DESTINATION bin)
install(TARGETS notcurses-ncreel DESTINATION bin)
if(${USE_TESTS})
install(TARGETS notcurses-tester DESTINATION bin)
endif()
install(TARGETS notcurses-tetris DESTINATION bin)
if(${USE_FFMPEG})
install(TARGETS notcurses-view DESTINATION bin)

@ -145,12 +145,12 @@ output of `pkg-config --cflags notcurses`. If using CMake, a support file is
provided, and can be accessed as `notcurses`.
Before calling into notcurses—and usually as one of the first calls of the
program—be sure to call `setlocale(3)` with an appropriate UTF-8 `LC_ALL`
locale. It is usually appropriate to use `setlocale(LC_ALL, "")`, relying on
the user to properly set the `LANG` environment variable. notcurses will
refuse to start if `nl_langinfo(3)` doesn't indicate `ANSI_X3.4-1968` or
`UTF-8`. In addition, it is wise to mask most signals early in the program,
before any threads are spawned (this is particularly critical for `SIGWINCH`).
program—be sure to call `setlocale(3)` with an appropriate UTF-8 locale. It is
usually appropriate to use `setlocale(LC_ALL, "")`, relying on the user to
properly set the `LANG` environment variable. notcurses will refuse to start if
`nl_langinfo(3)` doesn't indicate `ANSI_X3.4-1968` or `UTF-8`. In addition, it
is wise to mask most signals early in the program, before any threads are
spawned (this is particularly critical for `SIGWINCH`).
notcurses requires an available `terminfo(5)` definition appropriate for the
terminal. It is usually appropriate to pass `NULL` in the `termtype` field of a
@ -660,6 +660,30 @@ int ncplane_mergedown(struct ncplane* restrict src, struct ncplane* restrict dst
void ncplane_erase(struct ncplane* n);
```
All planes, including the standard plane, are created with scrolling disabled.
Attempting to print past the end of a line will stop at the plane boundary,
and indicate an error. On a plane 10 columns wide and two rows high, printing
"0123456789" at the origin should succeed, but printing "01234567890" will by
default fail at the eleventh character. In either case, the cursor will be left
at location 0x10; it must be moved before further printing can take place. If
scrolling is enabled, the first row will be filled with 01234546789, the second
row will have 0 written to its first column, and the cursor will end up at 1x1.
Note that it is still an error to manually attempt to move the cursor off-plane,
or to specify off-plane output. Boxes do not scroll; attempting to draw a 2x11
box on our 2x10 plane will result in an error and no output. When scrolling is
enabled, and output takes place while the cursor is past the end of the last
row, the first row is discarded, all other rows are moved up, the last row is
cleared, and output begins at the beginning of the last row. This does not take
place until output is generated (i.e. it is possible to fill a plane when
scrolling is enabled).
```c
// All planes are created with scrolling disabled. Scrolling can be dynamically
// controlled with ncplane_set_scrolling(). Returns true if scrolling was
// previously enabled, or false if it was disabled.
bool ncplane_set_scrolling(struct ncplane* n, bool scrollp);
```
Planes can be freely resized, though they must retain a positive size in
both dimensions. The powerful `ncplane_resize()` allows resizing an `ncplane`,
retaining all or a portion of the plane's existing content, and translating
@ -839,7 +863,14 @@ ncplane_putc(struct ncplane* n, const cell* c){
// Replace the cell at the specified coordinates with the provided 7-bit char
// 'c'. Advance the cursor by 1. On success, returns 1. On failure, returns -1.
// This works whether the underlying char is signed or unsigned.
int ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c);
static inline int
ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c){
cell ce = CELL_INITIALIZER(c, ncplane_attr(n), ncplane_channels(n));
if(!cell_simple_p(&ce)){
return -1;
}
return ncplane_putc_yx(n, y, x, &ce);
}
// Call ncplane_putsimple_yx() at the current cursor location.
static inline int
@ -924,7 +955,8 @@ int ncplane_putwegc_stainable(struct ncplane* n, const wchar_t* gclust, int* sby
// (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 cells
// which were written before the error.
int ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclustarr);
static inline int
ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclusters);
static inline int
ncplane_putstr(struct ncplane* n, const char* gclustarr){

@ -73,9 +73,7 @@ libnotcurses.so.1 libnotcurses1 #MINVER#
ncplane_putegc_stainable@Base 1.2.1
ncplane_putegc_yx@Base 1.2.1
ncplane_putsimple_stainable@Base 1.2.1
ncplane_putsimple_yx@Base 1.2.1
ncplane_putstr_aligned@Base 1.2.1
ncplane_putstr_yx@Base 1.2.1
ncplane_putwegc_stainable@Base 1.2.1
ncplane_reparent@Base 1.2.5
ncplane_resize@Base 1.2.1
@ -95,6 +93,7 @@ libnotcurses.so.1 libnotcurses1 #MINVER#
ncplane_set_fg_palindex@Base 1.2.1
ncplane_set_fg_rgb@Base 1.2.1
ncplane_set_fg_rgb_clipped@Base 1.2.1
ncplane_set_scrolling@Base 1.2.6
ncplane_set_userptr@Base 1.2.1
ncplane_stain@Base 1.2.5
ncplane_styles@Base 1.2.1

@ -17,6 +17,7 @@
<h1><a href="https://nick-black.com/dankwiki/index.php/Notcurses">notcurses</a> man pages (v1.2.5)</h1>
<a href="notcurses.3.html">notcurses(3)</a>—a blingful TUI library<br/>
<h2>Binaries (section 1)</h2>
<a href="colloquy.1.html">colloquy</a>—attractive terminal dialogs<br/>
<a href="notcurses-demo.1.html">notcurses-demo</a>—shows off some notcurses features<br/>
<a href="notcurses-input.1.html">notcurses-input</a>—reads and decodes input events<br/>
<a href="notcurses-keyplot.1.html">notcurses-input</a>—plots input events over time<br/>

@ -0,0 +1,44 @@
% colloquy(1)
% nick black <nickblack@linux.com>
% v1.2.5
# NAME
colloquy - Command line dialogs and widgets
# SYNOPSIS
**colloquy** [**-h|--help**]
# DESCRIPTION
**colloquy** uses notcurses to construct attractive widgets from the command
line and shell scripts. It can be used with any terminal environment, and
supports both keyboards and mice. Available widget types include:
* Message boxes requiring a button press to continue
* Selection of a single item from a list
* Selection of zero or more items from a list
Data to be displayed is provided on the command line, and the user's input
is reported on standard output. If the user aborts, the program returns
non-zero.
**colloquy** is inspired by (and compatible with a subset of) **dialog(1)**,
a similar tool built atop NCURSES.
# OPTIONS
**-h**|**--help**: Display a usage message
# NOTES
Optimal display requires a terminal advertising the **rgb** terminfo(5)
capability, or that the environment variable **COLORTERM** is defined to
**24bit** (and that the terminal honors this variable), along with a
fixed-width font with good coverage of the Unicode Block Drawing Characters.
# SEE ALSO
**dialog(1)**,
**notcurses(3)**

@ -77,6 +77,8 @@ ncplane_box_sized(struct ncplane* n, const cell* ul, const cell* ur,
upper-left corner at the cursor's current position, and its lower-right corner
at **ystop**, **xstop**.
Box- and line-drawing is unaffected by a plane's scrolling status.
# RETURN VALUES
**ncplane_format** returns -1 if either **ystop** or **xstop** is less than the

@ -132,6 +132,8 @@ notcurses_ncplane - operations on notcurses planes
**void ncplane_erase(struct ncplane* n);**
**bool ncplane_set_scrolling(struct ncplane* n, bool scrollp);**
## DESCRIPTION
Ncplanes are the fundamental drawing object of notcurses. All output functions
@ -182,6 +184,26 @@ expressed relative to the standard plane, and returns coordinates relative to
of the rendering region. Only those cells where **src** intersects with **dst**
might see changes. It is an error to merge a plane onto itself.
## Scrolling
All planes, including the standard plane, are created with scrolling disabled.
Control scrolling on a per-plane basis with **ncplane_set_scrolling**.
Attempting to print past the end of a line will stop at the plane boundary, and
indicate an error. On a plane 10 columns wide and two rows high, printing
"0123456789" at the origin should succeed, but printing "01234567890" will by
default fail at the eleventh character. In either case, the cursor will be left
at location 0x10; it must be moved before further printing can take place. If
scrolling is enabled, the first row will be filled with 01234546789, the second
row will have 0 written to its first column, and the cursor will end up at 1x1.
Note that it is still an error to manually attempt to move the cursor
off-plane, or to specify off-plane output. Boxes do not scroll; attempting to
draw a 2x11 box on our 2x10 plane will result in an error and no output. When
scrolling is enabled, and output takes place while the cursor is past the end
of the last row, the first row is discarded, all other rows are moved up, the
last row is cleared, and output begins at the beginning of the last row. This
does not take place until output is generated (i.e. it is possible to fill a
plane when scrolling is enabled).
# RETURN VALUES
**ncplane_new**, **ncplane_bound**, **ncplane_aligned**, and **ncplane_dup**
@ -193,6 +215,9 @@ cannot fail.
**ncplane_below** returns the plane below the specified ncplane. If the provided
plane is the bottommost plane, NULL is returned. It cannot fail.
**ncplane_set_scrolling** returns **true** if scrolling was previously enabled,
and **false** otherwise.
Functions returning **int** return 0 on success, and non-zero on error.
All other functions cannot fail (and return **void**).

@ -18,7 +18,8 @@ ncplane_putc(struct ncplane* n, const cell* c);**
**static inline int
ncplane_putsimple(struct ncplane* n, char c);**
**int ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c);**
**static inline int
ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c);**
**int ncplane_putsimple_stainable(struct ncplane* n, char c);**
@ -42,7 +43,8 @@ ncplane_putwegc_yx(struct ncplane* n, int y, int x, const wchar_t* gclust, int*
**int ncplane_putwegc_stainable(struct ncplane* n, const wchar_t* gclust, int* sbytes);**
**int ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclustarr);**
**static inline int
ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclustarr);**
**static inline int
ncplane_putstr(struct ncplane* n, const char* gclustarr);**

@ -30,7 +30,7 @@ typedef struct ncplot_options {
uint64_t rangex;
// dependent min and max. set both equal to 0 to
// use domain autodiscovery.
int64_t miny, maxy;
uint64_t miny, maxy;
bool labelaxisd; // label dependent axis
bool exponentialy; // is dependent exponential?
bool vertical_indep; // vertical independent variable
@ -41,8 +41,8 @@ typedef struct ncplot_options {
**struct ncplane* ncplot_plane(struct ncplot* n);**
**int ncplot_add_sample(struct ncplot* n, uint64_t x, int64_t y);**
**int ncplot_set_sample(struct ncplot* n, uint64_t x, int64_t y);**
**int ncplot_add_sample(struct ncplot* n, uint64_t x, uint64_t y);**
**int ncplot_set_sample(struct ncplot* n, uint64_t x, uint64_t y);**
**void ncplot_destroy(struct ncplot* n);**

@ -118,13 +118,13 @@ namespace ncpp
return ncplane_pulse (plane, ts, fader, curry) != -1;
}
bool mergedown (Plane* dst = nullptr) {
return ncplane_mergedown(*this, dst ? dst->plane : nullptr);
}
bool mergedown (Plane* dst = nullptr) {
return ncplane_mergedown(*this, dst ? dst->plane : nullptr);
}
bool mergedown (Plane& dst) {
return mergedown(&dst);
}
bool mergedown (Plane& dst) {
return mergedown(&dst);
}
bool gradient (const char* egc, uint32_t attrword, uint64_t ul, uint64_t ur, uint64_t ll, uint64_t lr, int ystop, int xstop) const noexcept
{
@ -539,8 +539,8 @@ namespace ncpp
}
bool box (const Cell &ul, const Cell &ur, const Cell &ll, const Cell &lr,
const Cell &hline, const Cell &vline, int ystop, int xstop,
unsigned ctlword) const noexcept
const Cell &hline, const Cell &vline, int ystop, int xstop,
unsigned ctlword) const noexcept
{
return ncplane_box (plane, ul, ur, ll, lr, hline, vline, ystop, xstop, ctlword) != -1;
}
@ -692,6 +692,11 @@ namespace ncpp
ncplane_set_bg_default (plane);
}
bool set_scrolling (bool scrollp) noexcept
{
return ncplane_set_scrolling (plane, scrollp);
}
void styles_set (CellStyle styles) const noexcept
{
ncplane_styles_set (plane, static_cast<unsigned>(styles));
@ -882,7 +887,7 @@ namespace ncpp
void translate (const Plane *dst, int *y = nullptr, int *x = nullptr) const
{
ncplane_translate(*this, dst ? dst->plane: nullptr, y, x);
ncplane_translate(*this, dst ? dst->plane: nullptr, y, x);
}
void translate (const Plane &dst, int *y = nullptr, int *x = nullptr) noexcept
@ -895,7 +900,7 @@ namespace ncpp
if (src == nullptr)
throw invalid_argument ("'src' must be a valid pointer");
ncplane_translate(*src, dst ? dst->plane : nullptr, y, x);
ncplane_translate(*src, dst ? dst->plane : nullptr, y, x);
}
static void translate (const Plane &src, const Plane &dst, int *y = nullptr, int *x = nullptr) noexcept
@ -951,7 +956,7 @@ namespace ncpp
protected:
explicit Plane (ncplane *_plane, bool _is_stdplane)
: plane (_plane),
is_stdplane (_is_stdplane)
is_stdplane (_is_stdplane)
{
if (_plane == nullptr)
throw invalid_argument ("_plane must be a valid pointer");

@ -0,0 +1,67 @@
#ifndef __NCPP_PLOT_HH
#define __NCPP_PLOT_HH
#include <notcurses/notcurses.h>
#include "Root.hh"
#include "NCAlign.hh"
namespace ncpp
{
class Plane;
class NCPP_API_EXPORT Plot : public Root
{
public:
static plot_options default_options;
public:
explicit Plot (Plane *plane, const plot_options *opts = nullptr)
: Plot (reinterpret_cast<ncplane*>(plane), opts)
{}
explicit Plot (Plane const* plane, const plot_options *opts = nullptr)
: Plot (const_cast<Plane*>(plane), opts)
{}
explicit Plot (Plane &plane, const plot_options *opts = nullptr)
: Plot (reinterpret_cast<ncplane*>(&plane), opts)
{}
explicit Plot (Plane const& plane, const plot_options *opts = nullptr)
: Plot (const_cast<Plane*>(&plane), opts)
{}
explicit Plot (ncplane *plane, const plot_options *opts = nullptr)
{
if (plane == nullptr)
throw invalid_argument ("'plane' must be a valid pointer");
plot = ncplot_create (plane, opts == nullptr ? &default_options : opts);
if (plot == nullptr)
throw init_error ("notcurses failed to create a new plot");
}
~Plot ()
{
if (!is_notcurses_stopped ())
ncplot_destroy (plot);
}
int add_sample(uint64_t x, uint64_t y)
{
return ncplot_add_sample (plot, x, y) >= 0;
}
int set_sample(uint64_t x, uint64_t y)
{
return ncplot_set_sample (plot, x, y) >= 0;
}
Plane* get_plane () const noexcept;
private:
ncplot *plot;
};
}
#endif

File diff suppressed because it is too large Load Diff

@ -123,7 +123,6 @@ int ncplane_move_yx(struct ncplane* n, int y, int x);
void ncplane_yx(struct ncplane* n, int* y, int* x);
void ncplane_dim_yx(const struct ncplane* n, int* rows, int* cols);
int ncplane_putc_yx(struct ncplane* n, int y, int x, const cell* c);
int ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c);
int ncplane_move_top(struct ncplane* n);
int ncplane_move_bottom(struct ncplane* n);
int ncplane_move_below(struct ncplane* n, struct ncplane* below);
@ -193,7 +192,6 @@ int ncplane_pulse(struct ncplane* n, const struct timespec* ts, fadecb fader, vo
int ncplane_putwc_yx(struct ncplane* n, int y, int x, wchar_t w);
int ncplane_putwc(struct ncplane* n, wchar_t w);
int ncplane_putegc_yx(struct ncplane* n, int y, int x, const char* gclust, int* sbytes);
int ncplane_putstr_yx(struct ncplane* n, int y, int x, const char* gclustarr);
int ncplane_putstr_aligned(struct ncplane* n, int y, ncalign_e align, const char* s);
void cell_init(cell* c);
int cell_load(struct ncplane* n, cell* c, const char* gcluster);
@ -422,16 +420,17 @@ typedef struct ncplot_options {
uint64_t minchannel;
ncgridgeom_e gridtype;
uint64_t rangex;
int64_t miny, maxy;
uint64_t miny, maxy;
bool labelaxisd;
bool exponentialy;
bool vertical_indep;
} ncplot_options;
struct ncplot* ncplot_create(struct ncplane* n, const ncplot_options* opts);
struct ncplane* ncplot_plane(struct ncplot* n);
int ncplot_add_sample(struct ncplot* n, uint64_t x, int64_t y);
int ncplot_set_sample(struct ncplot* n, uint64_t x, int64_t y);
int ncplot_add_sample(struct ncplot* n, uint64_t x, uint64_t y);
int ncplot_set_sample(struct ncplot* n, uint64_t x, uint64_t y);
void ncplot_destroy(struct ncplot* n);
bool ncplane_set_scrolling(struct ncplane* n, bool scrollp);
""")
if __name__ == "__main__":

@ -2,9 +2,25 @@ extern crate libnotcurses_sys as ffi;
pub fn getc_blocking(_n: *mut ffi::notcurses, _ni: &mut ffi::ncinput) -> u32 {
unsafe {
let mut sigmask: ffi::sigset_t = std::mem::zeroed();
ffi::sigemptyset(&mut sigmask);
return ffi::notcurses_getc(_n, std::ptr::null(), &mut sigmask, _ni);
let mut sigmask: ffi::sigset_t = std::mem::zeroed();
ffi::sigemptyset(&mut sigmask);
return ffi::notcurses_getc(_n, std::ptr::null(), &mut sigmask, _ni);
}
}
pub fn ncplane_putstr(_n: *mut ffi::ncplane, _str: &str) -> i32 {
unsafe {
return ffi::ncplane_putstr_yx(_n, -1, -1, std::ffi::CString::new(_str).expect("Bad string").as_ptr());
}
}
pub fn render(_n: *mut ffi::notcurses) -> std::result::Result<(), std::io::Error> {
unsafe {
let r = ffi::notcurses_render(_n);
if r != 0 {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "error rendering"));
}
Ok(())
}
}

@ -1,410 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bindgen"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cexpr"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clang-sys"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "colloquy"
version = "0.1.0"
dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libnotcurses-sys 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"notcurses 1.2.4",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hermit-abi"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc-stdhandle"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libnotcurses-sys"
version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bindgen 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "notcurses"
version = "1.2.4"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libc-stdhandle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libnotcurses-sys 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pkg-config"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "yaml-rust"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum bindgen 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1c85344eb535a31b62f0af37be84441ba9e7f0f4111eb0530f43d15e513fe57"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
"checksum hermit-abi 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum libc-stdhandle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dac2473dc28934c5e0b82250dab231c9d3b94160d91fe9ff483323b05797551"
"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
"checksum libnotcurses-sys 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69cd13c04e971783d60cc48e307d2dfd47f6cad8a1519d0c2439316db7eb31f8"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"

@ -1,19 +0,0 @@
[package]
name = "colloquy"
version = "0.1.0"
authors = ["nick black <dankamongmen@gmail.com>"]
edition = "2018"
repository = "https://github.com/dankamongmen/notcurses"
license = "Apache-2.0"
description = "Notcurses-based utility for command-line TUI widgets"
homepage = "https://nick-black.com/dankwiki/index.php/Notcurses"
[dependencies]
libc = ">= 0.2.66"
notcurses = ">= 1.2.5"
libnotcurses-sys = ">= 1.2.5"
[dependencies.clap]
version = ">= 2.33.0"
default-features = false
features = ["yaml", "color", "suggestions"]

@ -1,31 +0,0 @@
name: colloquy
version: "0.1.0"
about: Attractive Notcurses UI widgets from the shell
author: Nick Black <dankamongmen@gmail.com>
args:
- verbose:
long: verbose
short: v
help: Verbose mode
# - file:
# long: file
# short: f
# help: Read configuration options from this file
# takes_value: true
- title:
long: title
short: t
help: Set the title text
- msgbox:
long: msgbox
help: Display arbitrary text with a single button to accept it
requires: text
- text:
help: The contents of the widget
index: 1
- height:
help: The height of the widget, 0 for screen height
index: 2
- width:
help: The width of the widget, 0 for screen width
index: 3

@ -1,45 +0,0 @@
extern crate notcurses;
extern crate libnotcurses_sys as ffi;
extern {
fn libc_stdout() -> *mut ffi::_IO_FILE;
}
fn main() {
use clap::{load_yaml, App};
let yaml = load_yaml!("cli.yml");
let matches = App::from_yaml(yaml).get_matches();
unsafe{
let _ = libc::setlocale(libc::LC_ALL, std::ffi::CString::new("").unwrap().as_ptr());
let opts: ffi::notcurses_options = ffi::notcurses_options {
inhibit_alternate_screen: true,
loglevel: 0,
termtype: std::ptr::null(),
retain_cursor: false,
suppress_banner: false,
no_winch_sighandler: false,
no_quit_sighandlers: false,
renderfp: std::ptr::null_mut(),
margin_t: 4,
margin_r: 4,
margin_b: 4,
margin_l: 4,
};
let nc = ffi::notcurses_init(&opts, libc_stdout());
let stdplane = ffi::notcurses_stdplane(nc);
let mut dimy = 0;
let mut dimx = 0;
ffi::ncplane_dim_yx(stdplane, &mut dimy, &mut dimx);
if matches.is_present("msgbox") {
ffi::ncplane_new(nc, dimy, dimx, 0, 0, std::ptr::null_mut());
}else{
eprintln!("Needed a widget type");
ffi::notcurses_stop(nc);
std::process::exit(1);
}
let mut ni: ffi::ncinput = std::mem::zeroed();
notcurses::getc_blocking(nc, &mut ni);
ffi::notcurses_stop(nc);
}
}

@ -72,7 +72,14 @@ struct timespec demodelay = {
#ifndef DFSG_BUILD
#ifdef USE_FFMPEG
#define NONFREE(name, fxn) { name, fxn, }
#else
#endif
#else
#define DFSG(name, fxn) { NULL, NULL, }
#endif
#ifndef DFSG
#define DFSG(name, fxn) { name, fxn, }
#endif
#ifndef NONFREE
#define NONFREE(name, fxn) { NULL, NULL, }
@ -99,7 +106,7 @@ static struct {
{ "grid", grid_demo, },
{ "highcon", highcontrast_demo, },
{ "intro", intro, },
NONFREE("jungle", jungle_demo),
DFSG("jungle", jungle_demo),
{ NULL, NULL, },
NONFREE("luigi", luigi_demo),
{ NULL, NULL, },

@ -454,6 +454,7 @@ int witherworm_demo(struct notcurses* nc){
size_t i;
const size_t screens = sizeof(steps) / sizeof(*steps);
struct ncplane* n = notcurses_stdplane(nc);
ncplane_set_scrolling(n, true);
ncplane_erase(n);
for(i = 0 ; i < screens ; ++i){
wchar_t key = NCKEY_INVALID;
@ -481,12 +482,15 @@ int witherworm_demo(struct notcurses* nc){
s = strs + random() % ((sizeof(strs) / sizeof(*strs)) - 1);
size_t idx = 0;
ncplane_cursor_yx(n, &y, &x);
// fprintf(stderr, "%02d %s\n", y, *s);
while((*s)[idx]){ // each multibyte char of string
if(ncplane_set_fg_rgb(n, channel_r(rgb), channel_g(rgb), channel_b(rgb))){
return -1;
}
if(y >= maxy || x >= maxx){
if(x >= maxx){
x = 0;
++y;
}
if(y >= maxy){
break;
}
wchar_t wcs;
@ -503,7 +507,7 @@ int witherworm_demo(struct notcurses* nc){
int ulen = 0;
int r;
if(wcwidth(wcs) <= maxx - x){
if((r = ncplane_putegc(n, &(*s)[idx], &ulen)) < 0){
if((r = ncplane_putegc(n, &(*s)[idx], &ulen)) <= 0){
if(ulen < 0){
return -1;
}
@ -520,7 +524,7 @@ int witherworm_demo(struct notcurses* nc){
++egcs_out;
}
rgb += step;
}while(y < maxy && x < maxx);
}while(y < maxy);
struct ncplane* math = mathplane(nc);
if(math == NULL){
return -1;
@ -565,7 +569,7 @@ int witherworm_demo(struct notcurses* nc){
}
}while(key < 0);
pthread_cancel(tid);
void* result;
void* result = NULL;
pthread_join(tid, &result);
ncplane_destroy(mess);
ncplane_destroy(math);
@ -580,5 +584,6 @@ int witherworm_demo(struct notcurses* nc){
return 1;
}
}
ncplane_set_scrolling(n, false);
return 0;
}

@ -41,13 +41,14 @@ perframecb(struct notcurses* nc, struct ncvisual* ncv __attribute__ ((unused)),
return -1;
}
*(struct ncplane**)vnewplane = n;
uint64_t channels = 0;
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
ncplane_set_base(n, channels, 0, " ");
ncplane_set_bg_alpha(n, CELL_ALPHA_BLEND);
ncplane_set_scrolling(n, true);
}
ncplane_dim_yx(n, &dimy, &dimx);
uint64_t channels = 0;
channels_set_fg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
channels_set_bg_alpha(&channels, CELL_ALPHA_TRANSPARENT);
ncplane_set_base(n, channels, 0, " ");
ncplane_set_bg_alpha(n, CELL_ALPHA_BLEND);
// fg/bg rgbs are set within loop
int x = dimx - (frameno * 2);
int r = startr;
@ -79,7 +80,7 @@ perframecb(struct notcurses* nc, struct ncvisual* ncv __attribute__ ((unused)),
if(ncplane_set_bg_rgb(n, (l + 1) * 0x2, 0x20, (l + 1) * 0x2)){
return -1;
}
if(ncplane_printf_yx(n, l, x, "%*.*s", len, len, leg[l] + stroff) != (int)len){
if(ncplane_printf_yx(n, l, x, "%*.*s", len, len, leg[l] + stroff) != len){
return -1;
}
}

@ -68,14 +68,15 @@ int main(void){
planes.emplace_back(6, plotlen, 31, 1, nullptr);
struct ncplot_options popts{};
for(auto i = 0u ; i < plots.size() ; ++i){
if(i == plots.size() - 1){
popts.labelaxisd = true;
}
popts.labelaxisd = (i % 2 == 0);
popts.minchannel = popts.maxchannel = 0;
channels_set_fg_rgb(&popts.maxchannel, random() % 256, random() % 256, random() % 256);
channels_set_fg_rgb(&popts.minchannel, random() % 256, random() % 256, random() % 256);
popts.gridtype = static_cast<ncgridgeom_e>(i);
plots[i] = ncplot_create(planes[i], &popts);
if(!plots[i]){
return EXIT_FAILURE;
}
}
char32_t r;
ncinput ni;

@ -72,6 +72,7 @@ typedef struct ncplane {
void* userptr; // slot for the user to stick some opaque pointer
cell basecell; // cell written anywhere that fb[i].gcluster == 0
struct notcurses* nc; // notcurses object of which we are a part
bool scrolling; // is scrolling enabled? always disabled by default
} ncplane;
typedef struct ncvisual {
@ -160,7 +161,7 @@ typedef struct ncplot {
// domain minimum and maximum. if detectdomain is true, these are
// progressively enlarged/shrunk to fit the sample set. if not, samples
// outside these bounds are counted, but the displayed range covers only this.
int64_t miny, maxy;
uint64_t miny, maxy;
// circular buffer, with the oldest element at slotstart, and slotcount
// elements. slotcount is max(columns, rangex).
int64_t* slots;

@ -6,6 +6,95 @@ ncplane* ncvisual_plane(ncvisual* ncv){
return ncv->ncp;
}
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p(bool bgr, unsigned char alpha){
if(!bgr && alpha < 192){
return true;
}
return false;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit(ncplane* nc, int placey, int placex, int linesize, const void* data,
int begy, int begx, int leny, int lenx, bool bgr){
const int bpp = 32;
const int rpos = bgr ? 2 : 0;
const int bpos = bgr ? 0 : 2;
int dimy, dimx, x, y;
int visy = begy;
int total = 0; // number of cells written
ncplane_dim_yx(nc, &dimy, &dimx);
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char* dat = data;
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 2){
if(ncplane_cursor_move_yx(nc, y, placex)){
return -1;
}
int visx = begx;
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, ++visx){
const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT);
const unsigned char* rgbbase_down = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT);
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell* c = ncplane_cell_ref_yx(nc, y, x);
// use the default for the background, as that's the only way it's
// effective in that case anyway
c->channels = 0;
c->attrword = 0;
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) || ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) && ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
}else if(ffmpeg_trans_p(bgr, rgbbase_up[3])){ // down has the color
if(cell_load(nc, c, "\u2584") <= 0){ // lower half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
}else{ // up has the color
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
}
}else{
if(memcmp(rgbbase_up, rgbbase_down, 3) == 0){
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, " ") <= 0){ // only need the background
return -1;
}
}else{
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
}
}
++total;
}
}
return total;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, true);
}
int ncblit_rgba(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, false);
}
void ncvisual_destroy(ncvisual* ncv){
if(ncv){
#ifdef USE_FFMPEG
@ -354,95 +443,6 @@ ncvisual* ncvisual_open_plane(notcurses* nc, const char* filename,
return ncv;
}
// alpha comes to us 0--255, but we have only 3 alpha values to map them to.
// settled on experimentally.
static inline bool
ffmpeg_trans_p(bool bgr, unsigned char alpha){
if(!bgr && alpha < 192){
return true;
}
return false;
}
// RGBA/BGRx blitter. For incoming BGRx (no transparency), bgr == true.
static inline int
tria_blit(ncplane* nc, int placey, int placex, int linesize, const void* data,
int begy, int begx, int leny, int lenx, bool bgr){
const int bpp = 32;
const int rpos = bgr ? 2 : 0;
const int bpos = bgr ? 0 : 2;
int dimy, dimx, x, y;
int visy = begy;
int total = 0; // number of cells written
ncplane_dim_yx(nc, &dimy, &dimx);
// FIXME not going to necessarily be safe on all architectures hrmmm
const unsigned char* dat = data;
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 2){
if(ncplane_cursor_move_yx(nc, y, placex)){
return -1;
}
int visx = begx;
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, ++visx){
const unsigned char* rgbbase_up = dat + (linesize * visy) + (visx * bpp / CHAR_BIT);
const unsigned char* rgbbase_down = dat + (linesize * (visy + 1)) + (visx * bpp / CHAR_BIT);
//fprintf(stderr, "[%04d/%04d] bpp: %d lsize: %d %02x %02x %02x %02x\n", y, x, bpp, linesize, rgbbase_up[0], rgbbase_up[1], rgbbase_up[2], rgbbase_up[3]);
cell* c = ncplane_cell_ref_yx(nc, y, x);
// use the default for the background, as that's the only way it's
// effective in that case anyway
c->channels = 0;
c->attrword = 0;
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) || ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_bg_alpha(c, CELL_ALPHA_TRANSPARENT);
if(ffmpeg_trans_p(bgr, rgbbase_up[3]) && ffmpeg_trans_p(bgr, rgbbase_down[3])){
cell_set_fg_alpha(c, CELL_ALPHA_TRANSPARENT);
}else if(ffmpeg_trans_p(bgr, rgbbase_up[3])){ // down has the color
if(cell_load(nc, c, "\u2584") <= 0){ // lower half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
}else{ // up has the color
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
}
}else{
if(memcmp(rgbbase_up, rgbbase_down, 3) == 0){
cell_set_fg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, " ") <= 0){ // only need the background
return -1;
}
}else{
cell_set_fg_rgb(c, rgbbase_up[rpos], rgbbase_up[1], rgbbase_up[bpos]);
cell_set_bg_rgb(c, rgbbase_down[rpos], rgbbase_down[1], rgbbase_down[bpos]);
if(cell_load(nc, c, "\u2580") <= 0){ // upper half block
return -1;
}
}
}
++total;
}
}
return total;
}
// Blit a flat array 'data' of BGRx 32-bit values to the ncplane 'nc', offset
// from the upper left by 'placey' and 'placex'. Each row ought occupy
// 'linesize' bytes (this might be greater than lenx * 4 due to padding). A
// subregion of the input can be specified with 'begy'x'begx' and 'leny'x'lenx'.
int ncblit_bgrx(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, true);
}
int ncblit_rgba(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, int leny, int lenx){
return tria_blit(nc, placey, placex, linesize, data,
begy, begx, leny, lenx, false);
}
int ncvisual_render(const ncvisual* ncv, int begy, int begx, int leny, int lenx){
//fprintf(stderr, "render %dx%d+%dx%d\n", begy, begx, leny, lenx);
if(begy < 0 || begx < 0 || lenx < -1 || leny < -1){
@ -610,6 +610,7 @@ char* ncvisual_subtitle(const ncvisual* ncv){
int ncvisual_init(int loglevel){
(void)loglevel;
return 0;
return 0; // allow success here
}
#endif

@ -282,6 +282,7 @@ ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
return NULL;
}
memset(p->fb, 0, fbsize);
p->scrolling = false;
p->userptr = NULL;
p->leny = rows;
p->lenx = cols;
@ -340,8 +341,7 @@ ncplane* ncplane_aligned(ncplane* n, int rows, int cols, int yoff,
return ncplane_create(n->nc, NULL, rows, cols, yoff, ncplane_align(n, align, cols), opaque);
}
static inline int
ncplane_cursor_move_yx_locked(ncplane* n, int y, int x){
inline int ncplane_cursor_move_yx(ncplane* n, int y, int x){
if(x >= n->lenx){
return -1;
}else if(x < 0){
@ -380,7 +380,7 @@ ncplane* ncplane_dup(ncplane* n, void* opaque){
if(egcpool_dup(&newn->pool, &n->pool)){
ncplane_destroy(newn);
}else{
ncplane_cursor_move_yx_locked(newn, y, x); // FIXME what about error?
ncplane_cursor_move_yx(newn, y, x);
n->attrword = attr;
n->channels = chan;
ncplane_move_above_unsafe(newn, n);
@ -1248,17 +1248,6 @@ const char* cell_extended_gcluster(const struct ncplane* n, const cell* c){
return extended_gcluster(n, c);
}
static void
advance_cursor(ncplane* n, int cols){
if(cursor_invalid_p(n)){
return; // stuck!
}
if((n->x += cols) >= n->lenx){
++n->y;
n->x = 0;
}
}
// 'n' ends up above 'above'
int ncplane_move_above_unsafe(ncplane* restrict n, ncplane* restrict above){
if(n->z == above){
@ -1319,10 +1308,6 @@ int ncplane_move_bottom(ncplane* n){
return 0;
}
int ncplane_cursor_move_yx(ncplane* n, int y, int x){
return ncplane_cursor_move_yx_locked(n, y, x);
}
void ncplane_cursor_yx(const ncplane* n, int* y, int* x){
if(y){
*y = n->y;
@ -1332,11 +1317,6 @@ void ncplane_cursor_yx(const ncplane* n, int* y, int* x){
}
}
static inline bool
ncplane_cursor_stuck(const ncplane* n){
return (n->x >= n->lenx && n->y >= n->leny);
}
static inline void
cell_obliterate(ncplane* n, cell* c){
cell_release(n, c);
@ -1344,11 +1324,18 @@ cell_obliterate(ncplane* n, cell* c){
}
int ncplane_putc_yx(ncplane* n, int y, int x, const cell* c){
if(ncplane_cursor_move_yx_locked(n, y, x)){
return -1;
}
// if scrolling is enabled, check *before ncplane_cursor_move_yx()* whether
// we're past the end of the line, and move to the next line if so.
bool wide = cell_double_wide_p(c);
if(wide && (n->x + 1 == n->lenx)){
if(x == -1 && y == -1 && n->x + wide >= n->lenx){
if(!n->scrolling){
return -1;
}
n->x = 0;
++n->y;
// FIXME if new n->y >= n->leny, scroll everything up a line and reset n->y
}
if(ncplane_cursor_move_yx(n, y, x)){
return -1;
}
// A wide character obliterates anything to its immediate right (and marks
@ -1388,18 +1375,10 @@ int ncplane_putc_yx(ncplane* n, int y, int x, const cell* c){
cell_release(n, candidate);
}
}
advance_cursor(n, cols);
n->x += cols;
return cols;
}
int ncplane_putsimple_yx(struct ncplane* n, int y, int x, char c){
cell ce = CELL_INITIALIZER(c, ncplane_attr(n), ncplane_channels(n));
if(!cell_simple_p(&ce)){
return -1;
}
return ncplane_putc_yx(n, y, x, &ce);
}
int ncplane_putegc_yx(struct ncplane* n, int y, int x, const char* gclust, int* sbytes){
cell c = CELL_TRIVIAL_INITIALIZER;
int primed = cell_prime(n, &c, gclust, n->attrword, n->channels);
@ -1488,34 +1467,6 @@ int cell_load(ncplane* n, cell* c, const char* gcluster){
return bytes;
}
int ncplane_putstr_yx(ncplane* n, int y, int x, const char* gclusters){
int ret = 0;
// FIXME speed up this blissfully naive solution
while(*gclusters){
// FIXME can we not dispense with this cell, and print directly in?
cell c;
memset(&c, 0, sizeof(c));
int wcs = cell_load(n, &c, gclusters);
int cols = ncplane_putegc_yx(n, y, x, gclusters, &wcs);
if(cols < 0){
if(wcs < 0){
return -ret;
}
break;
}
if(wcs == 0){
break;
}
ncplane_cursor_yx(n, &y, &x);
gclusters += wcs;
ret += wcs;
if(ncplane_cursor_stuck(n)){
break;
}
}
return ret;
}
unsigned notcurses_supported_styles(const notcurses* nc){
unsigned styles = 0;
styles |= nc->standout ? NCSTYLE_STANDOUT : 0;
@ -1688,7 +1639,7 @@ int ncplane_vline_interp(ncplane* n, const cell* c, int len,
bgdef = true;
}
for(ret = 0 ; ret < len ; ++ret){
if(ncplane_cursor_move_yx_locked(n, ypos + ret, xpos)){
if(ncplane_cursor_move_yx(n, ypos + ret, xpos)){
return -1;
}
r1 += deltr;
@ -1744,7 +1695,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
}
if(!(ctlword & NCBOXMASK_TOP)){ // draw top border, if called for
if(xstop - xoff >= 2){
if(ncplane_cursor_move_yx_locked(n, yoff, xoff + 1)){
if(ncplane_cursor_move_yx(n, yoff, xoff + 1)){
return -1;
}
if(!(ctlword & NCBOXGRAD_TOP)){ // cell styling, hl
@ -1760,7 +1711,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
}
edges = !(ctlword & NCBOXMASK_TOP) + !(ctlword & NCBOXMASK_RIGHT);
if(edges >= box_corner_needs(ctlword)){
if(ncplane_cursor_move_yx_locked(n, yoff, xstop)){
if(ncplane_cursor_move_yx(n, yoff, xstop)){
return -1;
}
if(ncplane_putc(n, ur) < 0){
@ -1771,7 +1722,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
// middle rows (vertical lines)
if(yoff < ystop){
if(!(ctlword & NCBOXMASK_LEFT)){
if(ncplane_cursor_move_yx_locked(n, yoff, xoff)){
if(ncplane_cursor_move_yx(n, yoff, xoff)){
return -1;
}
if((ctlword & NCBOXGRAD_LEFT)){ // grad styling, ul->ll
@ -1785,7 +1736,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
}
}
if(!(ctlword & NCBOXMASK_RIGHT)){
if(ncplane_cursor_move_yx_locked(n, yoff, xstop)){
if(ncplane_cursor_move_yx(n, yoff, xstop)){
return -1;
}
if((ctlword & NCBOXGRAD_RIGHT)){ // grad styling, ur->lr
@ -1803,7 +1754,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
yoff = ystop;
edges = !(ctlword & NCBOXMASK_BOTTOM) + !(ctlword & NCBOXMASK_LEFT);
if(edges >= box_corner_needs(ctlword)){
if(ncplane_cursor_move_yx_locked(n, yoff, xoff)){
if(ncplane_cursor_move_yx(n, yoff, xoff)){
return -1;
}
if(ncplane_putc(n, ll) < 0){
@ -1812,7 +1763,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
}
if(!(ctlword & NCBOXMASK_BOTTOM)){
if(xstop - xoff >= 2){
if(ncplane_cursor_move_yx_locked(n, yoff, xoff + 1)){
if(ncplane_cursor_move_yx(n, yoff, xoff + 1)){
return -1;
}
if(!(ctlword & NCBOXGRAD_BOTTOM)){ // cell styling, hl
@ -1828,7 +1779,7 @@ int ncplane_box(ncplane* n, const cell* ul, const cell* ur,
}
edges = !(ctlword & NCBOXMASK_BOTTOM) + !(ctlword & NCBOXMASK_RIGHT);
if(edges >= box_corner_needs(ctlword)){
if(ncplane_cursor_move_yx_locked(n, yoff, xstop)){
if(ncplane_cursor_move_yx(n, yoff, xstop)){
return -1;
}
if(ncplane_putc(n, lr) < 0){
@ -2015,3 +1966,9 @@ ncplane* ncplane_reparent(ncplane* n, ncplane* newparent){
}
return n;
}
bool ncplane_set_scrolling(ncplane* n, bool scrollp){
bool old = n->scrolling;
n->scrolling = scrollp;
return old;
}

@ -4,13 +4,77 @@ static const struct {
ncgridgeom_e geom;
const wchar_t* egcs;
} geomdata[] = {
{ .geom = NCPLOT_1x1, .egcs = L"", },
{ .geom = NCPLOT_2x1, .egcs = L"▄█", },
{ .geom = NCPLOT_1x1x4, .egcs = L"▒░▓█", },
{ .geom = NCPLOT_4x1, .egcs = L"▂▄▆█", },
{ .geom = NCPLOT_8x1, .egcs = L"▁▂▃▄▅▆▇█", },
{ .geom = NCPLOT_1x1, .egcs = L" ", },
{ .geom = NCPLOT_2x1, .egcs = L" ▄█", },
{ .geom = NCPLOT_1x1x4, .egcs = L" ▒░▓█", },
{ .geom = NCPLOT_4x1, .egcs = L" ▂▄▆█", },
{ .geom = NCPLOT_8x1, .egcs = L" ▁▂▃▄▅▆▇█", },
};
static int
redraw_plot(ncplot* n){
ncplane_erase(ncplot_plane(n));
int dimy, dimx;
ncplane_dim_yx(ncplot_plane(n), &dimy, &dimx);
// each transition is worth this much change in value
const size_t states = wcslen(geomdata[n->gridtype].egcs);
// FIXME can we not rid ourselves of this meddlesome double?
double interval = n->maxy < n->miny ? 0 : (n->maxy - n->miny) / ((double)dimy * states);
int idx = n->slotstart;
const int startx = n->labelaxisd ? PREFIXSTRLEN : 0;
if(n->labelaxisd){
// show the *top* of each interval range
for(int y = 0 ; y < dimy ; ++y){
char buf[PREFIXSTRLEN + 1];
ncmetric(interval * states * (y + 1) * 100, 100, buf, 0, 1000, '\0');
ncplane_putstr_yx(ncplot_plane(n), dimy - y - 1, PREFIXSTRLEN - strlen(buf), buf);
}
}
if(interval){
for(uint64_t x = startx ; x < n->slotcount + startx ; ++x){
if(x >= (unsigned)dimx){
break;
}
uint64_t gval = n->slots[idx]; // clip the value at the limits of the graph
if(gval < n->miny){
gval = n->miny;
}
if(gval > n->maxy){
gval = n->maxy;
}
// starting from the least-significant row, progress in the more significant
// direction, drawing egcs from the grid specification, aborting early if
// we can't draw anything in a given cell.
double intervalbase = n->miny;
for(int y = 0 ; y < dimy ; ++y){
// if we've got at least one interval's worth on the number of positions
// times the number of intervals per position plus the starting offset,
// we're going to print *something*
if(intervalbase >= gval){
break;
}
size_t egcidx = (gval - intervalbase) / interval;
if(egcidx >= states){
egcidx = states - 1;
}
if(ncplane_putwc_yx(ncplot_plane(n), dimy - y - 1, x, geomdata[n->gridtype].egcs[egcidx]) <= 0){
return -1;
}
intervalbase += (states * interval);
}
idx = (idx + 1) % n->slotcount;
}
}
if(ncplane_cursor_move_yx(ncplot_plane(n), 0, 0)){
return -1;
}
if(ncplane_stain(ncplot_plane(n), dimy - 1, dimx - 1, n->maxchannel,
n->maxchannel, n->minchannel, n->minchannel) <= 0){
return -1;
}
return 0;
}
ncplot* ncplot_create(ncplane* n, const ncplot_options* opts){
// if miny == maxy, they both must be equal to 0
if(opts->miny == opts->maxy && opts->miny){
@ -56,10 +120,14 @@ ncplot* ncplot_create(ncplane* n, const ncplot_options* opts){
ret->vertical_indep = opts->vertical_indep;
ret->gridtype = opts->gridtype;
ret->exponentialy = opts->exponentialy;
ret->detectdomain = opts->miny == opts->maxy;
if( (ret->detectdomain = (opts->miny == opts->maxy)) ){
ret->maxy = 0;
ret->miny = ~(uint64_t)0ull;
}
ret->windowbase = 0;
ret->slotstart = 0;
ret->slotx = 0;
redraw_plot(ret);
return ret;
}
free(ret);
@ -76,7 +144,7 @@ ncplane* ncplot_plane(ncplot* n){
// return -1 if the value is outside of that range.
static inline int
update_domain(ncplot* n, uint64_t x){
const int64_t val = n->slots[x % n->slotcount];
const uint64_t val = n->slots[x % n->slotcount];
if(n->detectdomain){
if(val > n->maxy){
n->maxy = val;
@ -127,8 +195,8 @@ window_slide(ncplot* n, uint64_t x){
// x must be within n's window
static inline void
update_sample(ncplot* n, uint64_t x, int64_t y, bool reset){
uint64_t idx = x/*(n->slotstart + delta)*/ % n->slotcount;
update_sample(ncplot* n, uint64_t x, uint64_t y, bool reset){
uint64_t idx = x % n->slotcount;
if(reset){
n->slots[idx] = y;
}else{
@ -136,74 +204,11 @@ update_sample(ncplot* n, uint64_t x, int64_t y, bool reset){
}
}
static int
redraw_plot(ncplot* n){
ncplane_erase(ncplot_plane(n)); // FIXME shouldn't need this
int dimy, dimx;
ncplane_dim_yx(ncplot_plane(n), &dimy, &dimx);
// each transition is worth this much change in value
const size_t states = wcslen(geomdata[n->gridtype].egcs);
double interval = (n->maxy - n->miny + 1) / ((double)dimy * states); // FIXME
int idx = n->slotstart;
const int startx = n->labelaxisd ? PREFIXSTRLEN : 0;
if(n->labelaxisd){
for(int y = 0 ; y < dimy ; ++y){
char buf[PREFIXSTRLEN + 1];
ncmetric(interval * states * y, 1, buf, 0, 1000, '\0');
ncplane_putstr_yx(ncplot_plane(n), dimy - y - 1, PREFIXSTRLEN - strlen(buf), buf);
}
}
for(uint64_t x = startx ; x < n->slotcount + startx ; ++x){
if(x >= (unsigned)dimx){
break;
}
int64_t gval = n->slots[idx]; // clip the value at the limits of the graph
if(gval < n->miny){
gval = n->miny;
}
if(gval > n->maxy){
gval = n->maxy;
}
// starting from the least-significant row, progress in the more significant
// direction, drawing egcs from the grid specification, aborting early if
// we can't draw anything in a given cell.
for(int y = 0 ; y < dimy ; ++y){
// if we've got at least one interval's worth on the number of positions
// times the number of intervals per position plus the starting offset,
// we're going to print *something*
if(n->miny + (interval * states) * y + interval > gval){
break;
}
size_t egcidx = (gval - n->miny) - (y * interval * states) - 1;
if(egcidx >= states){
egcidx = states - 1;
}
if(ncplane_putwc_yx(ncplot_plane(n), dimy - y - 1, x, geomdata[n->gridtype].egcs[egcidx]) <= 0){
return -1;
}
// FIXME this ought fall out naturally. that it does not indicates, i
// think, an error above...
if(egcidx != states - 1){
break;
}
}
idx = (idx + 1) % n->slotcount;
}
if(ncplane_cursor_move_yx(ncplot_plane(n), 0, 0)){
return -1;
}
if(ncplane_stain(ncplot_plane(n), dimy - 1, dimx - 1, n->maxchannel,
n->maxchannel, n->minchannel, n->minchannel) <= 0){
return -1;
}
return 0;
}
// Add to or set the value corresponding to this x. If x is beyond the current
// x window, the x window is advanced to include x, and values passing beyond
// the window are lost. The first call will place the initial window. The plot
// will be redrawn, but notcurses_render() is not called.
int ncplot_add_sample(ncplot* n, uint64_t x, int64_t y){
int ncplot_add_sample(ncplot* n, uint64_t x, uint64_t y){
if(window_slide(n, x)){
return -1;
}
@ -214,7 +219,7 @@ int ncplot_add_sample(ncplot* n, uint64_t x, int64_t y){
return redraw_plot(n);
}
int ncplot_set_sample(ncplot* n, uint64_t x, int64_t y){
int ncplot_set_sample(ncplot* n, uint64_t x, uint64_t y){
if(window_slide(n, x)){
return -1;
}

@ -63,6 +63,7 @@ int main(void){
std::unique_ptr<Plane> nstd(nc.get_stdplane());
int y, dimy, dimx;
nc.get_term_dim(&dimy, &dimx);
nstd->set_scrolling(true);
do{
nstd->putstr(c);
nstd->get_cursor_yx(&y, nullptr);

@ -118,17 +118,6 @@ int main(void){
int averr;
struct ncvisual* ncv = ncplane_visual_open(n, "../data/ebolavirus_wide-0723bc3f01c644976b4df7e146a1d795aaf9d55e.jpg", &averr);
if(!ncv){
goto err;
}
if(!ncvisual_decode(ncv, &averr)){
goto err;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
goto err;
}
uint64_t channels = 0;
channels_set_fg(&channels, 0x88aa00);
channels_set_bg(&channels, 0x000088);
@ -144,18 +133,6 @@ int main(void){
run_menu(nc, top);
ncplane_erase(n);
ncvisual_destroy(ncv);
ncv = ncplane_visual_open(n, "../data/aidsrobots.jpeg", &averr);
if(!ncv){
goto err;
}
if(!ncvisual_decode(ncv, &averr)){
goto err;
}
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
goto err;
}
mopts.bottom = true;
struct ncmenu* bottom = ncmenu_create(nc, &mopts);
@ -167,7 +144,6 @@ int main(void){
}
run_menu(nc, bottom);
ncvisual_destroy(ncv);
if(notcurses_stop(nc)){
return EXIT_FAILURE;
}

@ -3,6 +3,7 @@
#include <locale.h>
#include <stdlib.h>
#include <notcurses/notcurses.h>
#include "version.h"
// http://theboomerbible.com/tbb112.html
static struct mselector_item items[] = {
@ -81,6 +82,7 @@ int main(void){
channels_set_bg_alpha(&sopts.bgchannels, CELL_ALPHA_BLEND);
struct ncplane* n = notcurses_stdplane(nc);
#ifdef USE_FFMPEG
int averr;
struct ncvisual* ncv = ncplane_visual_open(n, "../data/covid19.jpg", &averr);
if(!ncv){
@ -92,6 +94,7 @@ int main(void){
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
goto err;
}
#endif
ncplane_set_fg(n, 0x40f040);
ncplane_putstr_aligned(n, 0, NCALIGN_RIGHT, "multiselect widget demo");

@ -3,6 +3,7 @@
#include <locale.h>
#include <stdlib.h>
#include <notcurses/notcurses.h>
#include "version.h"
static struct selector_item items[] = {
{ "first", "this is the first option", },
@ -80,6 +81,7 @@ int main(void){
channels_set_bg_alpha(&sopts.bgchannels, CELL_ALPHA_BLEND);
struct ncplane* n = notcurses_stdplane(nc);
#ifdef USE_FFMPEG
int averr;
struct ncvisual* ncv = ncplane_visual_open(n, "../data/changes.jpg", &averr);
if(!ncv){
@ -91,7 +93,7 @@ int main(void){
if(ncvisual_render(ncv, 0, 0, -1, -1) <= 0){
goto err;
}
#endif
ncplane_set_fg(n, 0x40f040);
ncplane_putstr_aligned(n, 0, NCALIGN_RIGHT, "selector widget demo");

@ -1,4 +1,5 @@
void DrawBackground(const std::string& s) { // drawn to the standard plane
#ifdef USE_FFMPEG
int averr;
try{
backg_ = std::make_unique<ncpp::Visual>(s.c_str(), &averr, 0, 0, ncpp::NCScale::Stretch);
@ -12,6 +13,9 @@ void DrawBackground(const std::string& s) { // drawn to the standard plane
throw TetrisNotcursesErr("render(): " + s);
}
backg_->get_plane()->greyscale();
#else
(void)s;
#endif
}
void DrawBoard() { // draw all fixed components of the game

@ -54,8 +54,7 @@ public:
#include "stain.h"
#include "lock.h"
#include "movedown.h"
#include "moveleft.h"
#include "moveright.h"
#include "movelateral.h"
#include "rotate.h"
private:

@ -1,8 +1,9 @@
void MoveLeft() {
void MoveLateral(int direction) { // pass in -1 for left, 1 for right
int shift = 2 * direction;
const std::lock_guard<std::mutex> lock(mtx_);
int y, x;
if(PrepForMove(&y, &x)){
if(!curpiece_->move(y, x - 2)){
if(!curpiece_->move(y, x + shift)){
throw TetrisNotcursesErr("move()");
}
if(InvalidMove()){
@ -10,10 +11,18 @@ void MoveLeft() {
throw TetrisNotcursesErr("move()");
}
}else{
x -= 2;
x += shift;
if(!nc_.render()){
throw TetrisNotcursesErr("render()");
}
}
}
}
inline void MoveLeft() {
MoveLateral(-1);
}
inline void MoveRight() {
MoveLateral(1);
}

@ -1,19 +0,0 @@
void MoveRight() {
const std::lock_guard<std::mutex> lock(mtx_);
int y, x;
if(PrepForMove(&y, &x)){
if(!curpiece_->move(y, x + 2)){
throw TetrisNotcursesErr("move()");
}
if(InvalidMove()){
if(!curpiece_->move(y, x)){
throw TetrisNotcursesErr("move()");
}
}else{
x += 2;
if(!nc_.render()){
throw TetrisNotcursesErr("render()");
}
}
}
}

@ -40,6 +40,7 @@ TEST_CASE("Fade") {
c.gcluster = '*';
cell_set_fg_rgb(&c, 0xff, 0xff, 0xff);
unsigned rgb = 0xffffffu;
CHECK(!ncplane_set_scrolling(n_, true));
for(int y = 0 ; y < dimy ; ++y){
for(int x = 0 ; x < dimx ; ++x){
rgb -= 32;

@ -211,6 +211,7 @@ TEST_CASE("NCPlane") {
L"🍺🚬🌿💉💊🔫💣🤜🤛🐌🐎🐑🐒🐔🐗🐘🐙🐚"
"🐛🐜🐝🐞🐟🐠🐡🐢🐣🐤🐥🐦🐧🐨🐩🐫🐬🐭🐮"
"🐯🐰🐱🐲🐳🐴🐵🐶🐷🐹🐺🐻🐼🦉🐊🦕🦖🐬🐙🦠🦀";
CHECK(!ncplane_set_scrolling(n_, true));
int wrote = ncplane_putwstr(n_, e);
CHECK(0 < wrote);
int x, y;
@ -539,20 +540,20 @@ TEST_CASE("NCPlane") {
ncplane_styles_set(n_, 0);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
REQUIRE(0 < ncplane_putstr(n_, STR1));
cell testcell = CELL_TRIVIAL_INITIALIZER;
REQUIRE(0 == ncplane_at_cursor(n_, &testcell)); // want nothing at the cursor
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.attrword);
CHECK(0 == testcell.channels);
int dimy, dimx;
ncplane_dim_yx(n_, &dimy, &dimx);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - strlen(STR2)));
REQUIRE(0 < ncplane_putstr(n_, STR2));
int y, x;
ncplane_cursor_yx(n_, &y, &x);
REQUIRE(2 == y);
REQUIRE(0 == x);
REQUIRE(0 < ncplane_putstr(n_, STR3));
cell testcell = CELL_TRIVIAL_INITIALIZER;
REQUIRE(0 == ncplane_at_cursor(n_, &testcell)); // want nothing at the cursor
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.attrword);
CHECK(0 == testcell.channels);
REQUIRE(1 == y);
REQUIRE(dimx == x);
REQUIRE(0 == ncplane_putstr(n_, STR3));
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want first char of STR1
CHECK(STR1[0] == testcell.gcluster);
@ -575,20 +576,20 @@ TEST_CASE("NCPlane") {
ncplane_styles_set(n_, 0);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
REQUIRE(0 < ncplane_putstr(n_, STR1));
cell testcell = CELL_TRIVIAL_INITIALIZER;
ncplane_at_cursor(n_, &testcell); // should be nothing at the cursor
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.attrword);
CHECK(0 == testcell.channels);
int dimy, dimx;
ncplane_dim_yx(n_, &dimy, &dimx);
REQUIRE(0 == ncplane_cursor_move_yx(n_, 1, dimx - mbstowcs(NULL, STR2, 0)));
REQUIRE(0 < ncplane_putstr(n_, STR2));
int y, x;
ncplane_cursor_yx(n_, &y, &x);
REQUIRE(2 == y);
REQUIRE(0 == x);
REQUIRE(0 < ncplane_putstr(n_, STR3));
cell testcell = CELL_TRIVIAL_INITIALIZER;
ncplane_at_cursor(n_, &testcell); // should be nothing at the cursor
CHECK(0 == testcell.gcluster);
CHECK(0 == testcell.attrword);
CHECK(0 == testcell.channels);
REQUIRE(1 == y);
REQUIRE(dimx == x);
REQUIRE(0 == ncplane_putstr(n_, STR3));
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
REQUIRE(0 < ncplane_at_cursor(n_, &testcell)); // want first char of STR1
CHECK(!strcmp("Σ", cell_extended_gcluster(n_, &testcell)));
@ -916,7 +917,7 @@ TEST_CASE("NCPlane") {
int dimx, dimy;
ncplane_dim_yx(n_, &dimy, &dimx);
CHECK(0 == ncplane_rounded_box_sized(ncp, 0, 0, 3, 4, 0));
CHECK(0 < ncplane_putegc_yx(ncp, 1, 1, "\xf0\x9f\xa6\x82", NULL));
CHECK(2 == ncplane_putegc_yx(ncp, 1, 1, "\xf0\x9f\xa6\x82", NULL)); // scorpion
CHECK(0 == notcurses_render(nc_));
cell c = CELL_TRIVIAL_INITIALIZER;
REQUIRE(0 < ncplane_at_yx(ncp, 1, 0, &c));

@ -0,0 +1,120 @@
#include "main.h"
#include <array>
#include <cstdlib>
#include "internal.h"
TEST_CASE("Scrolling") {
if(getenv("TERM") == nullptr){
return;
}
notcurses_options nopts{};
nopts.inhibit_alternate_screen = true;
nopts.suppress_banner = true;
FILE* outfp_ = fopen("/dev/tty", "wb");
REQUIRE(outfp_);
struct notcurses* nc_ = notcurses_init(&nopts, outfp_);
REQUIRE(nc_);
struct ncplane* n_ = notcurses_stdplane(nc_);
REQUIRE(n_);
// verify that the standard plane has scrolling disabled initially, and that
// we can enable it at runtime.
SUBCASE("ScollingDisabledStdplane"){
CHECK(!ncplane_set_scrolling(n_, true));
CHECK(ncplane_set_scrolling(n_, false));
}
SUBCASE("ScrollingStr"){
struct ncplane* n = ncplane_new(nc_, 2, 20, 1, 1, nullptr);
REQUIRE(n);
// verify that the new plane was started without scrolling
CHECK(!ncplane_set_scrolling(n, false));
// try to write 40 EGCs; it ought fail
CHECK(-20 == ncplane_putstr(n, "0123456789012345678901234567890123456789"));
int y, x;
ncplane_cursor_yx(n, &y, &x);
CHECK(0 == y);
CHECK(20 == x);
CHECK(0 == ncplane_cursor_move_yx(n, 0, 0));
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
// try to write 40 EGCs; it ought succeed
CHECK(40 == ncplane_putstr(n, "0123456789012345678901234567890123456789"));
ncplane_cursor_yx(n, &y, &x);
CHECK(1 == y);
CHECK(20 == x);
CHECK(0 == notcurses_render(nc_));
}
// even when scrolling is enabled, you aren't allowed to move the cursor
// off-plane, or initiate output there
SUBCASE("NoScrollingManually"){
struct ncplane* n = ncplane_new(nc_, 2, 20, 1, 1, nullptr);
REQUIRE(n);
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
CHECK(0 > ncplane_cursor_move_yx(n, 0, 20));
CHECK(0 > ncplane_cursor_move_yx(n, 1, 20));
CHECK(0 > ncplane_cursor_move_yx(n, 2, 2));
CHECK(0 > ncplane_putsimple_yx(n, 0, 20, 'c'));
CHECK(0 > ncplane_putsimple_yx(n, 1, 20, 'c'));
CHECK(0 > ncplane_putsimple_yx(n, 2, 0, 'c'));
}
// verify that two strings, each the length of the plane, can be output when
// scrolling is enabled (the second ought get an error without scrolling)
SUBCASE("ScrollingSplitStr"){
struct ncplane* n = ncplane_new(nc_, 2, 20, 1, 1, nullptr);
REQUIRE(n);
CHECK(20 == ncplane_putstr(n, "01234567890123456789"));
int y, x;
ncplane_cursor_yx(n, &y, &x);
CHECK(0 == y);
CHECK(20 == x);
CHECK(0 == ncplane_putstr(n, "01234567890123456789"));
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
CHECK(20 == ncplane_putstr(n, "01234567890123456789"));
ncplane_cursor_yx(n, &y, &x);
CHECK(1 == y);
CHECK(20 == x);
CHECK(0 == notcurses_render(nc_));
}
// verify that a single string the size of the plane can be output when
// scrolling is enabled (it ought be an error without scrolling)
SUBCASE("ScrollingEGC"){
const char* out = "0123456789012345678901234567890123456789";
struct ncplane* n = ncplane_new(nc_, 2, 20, 1, 1, nullptr);
REQUIRE(n);
// verify that the new plane was started without scrolling
CHECK(!ncplane_set_scrolling(n, false));
// try to write 40 EGCs; the last 20 ought fail
for(const char* c = out ; *c ; ++c){
int ret = ncplane_putsimple(n, *c);
if(c - out < 20){
CHECK(1 == ret);
}else{
CHECK(0 > ret);
}
}
int y, x;
ncplane_cursor_yx(n, &y, &x);
CHECK(0 == y);
CHECK(20 == x);
CHECK(0 == ncplane_cursor_move_yx(n, 0, 0));
CHECK(!ncplane_set_scrolling(n, true)); // enable scrolling
// try to write 40 EGCs; all ought succeed
for(const char* c = out ; *c ; ++c){
CHECK(1 == ncplane_putsimple(n, *c));
}
ncplane_cursor_yx(n, &y, &x);
CHECK(1 == y);
CHECK(20 == x);
CHECK(0 == notcurses_render(nc_));
}
// FIXME add one verifying boxes don't exceed the right side
// FIXME add one where we go past the end of the plane
CHECK(0 == notcurses_stop(nc_));
CHECK(0 == fclose(outfp_));
}

@ -0,0 +1,50 @@
Name: notcurses
Version: 1.2.5
Release: 1
Summary: Character graphics and TUI library
License: ASL 2.0
Source0: https://github.com/dankamongmen/%{name}/archive/v%{version}.tar.gz
Source1: https://github.com/dankamongmen/%{name}/releases/v%{version}/v%{version}.tar.gz.asc
Source2: https://dank.qemfd.net/dankamongmen.gpg
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.
%prep
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%setup
%build
%cmake -DUSE_FFMPEG=off -DUSE_TEST=off .
%make_build
%install
%make_install
%files
/usr/bin/notcurses-demo
/usr/bin/notcurses-input
/usr/bin/notcurses-keyplot
/usr/bin/notcurses-ncreel
/usr/bin/notcurses-pydemo
/usr/bin/notcurses-tester
/usr/bin/notcurses-tetris
/usr/bin/notcurses-view
/usr/include/notcurses/nckeys.h
/usr/include/notcurses/notcurses.h
/usr/lib/x86_64-linux-gnu/libnotcurses.so.{version}
/usr/lib/x86_64-linux-gnu/libnotcurses.so.1
/usr/lib/x86_64-linux-gnu/libnotcurses.so
/usr/lib/x86_64-linux-gnu/cmake/notcurses/notcursesConfig.cmake
/usr/lib/x86_64-linux-gnu/cmake/notcurses/notcursesConfigVersion.cmake
/usr/lib/x86_64-linux-gnu/libnotcurses.a
/usr/lib/x86_64-linux-gnu/pkgconfig
/usr/lib/x86_64-linux-gnu/pkgconfig/notcurses.pc
%license LICENSE
%changelog
* Tue, Apr 07 2020 Nick Black <dankamongmen@gmail.com> - 1.2.5-1
- Initial Fedora packaging
Loading…
Cancel
Save