mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-06 03:20:26 +00:00
Merge branch 'master' of github.com:dankamongmen/notcurses
This commit is contained in:
commit
e276a36264
29
CHANGELOG.md
29
CHANGELOG.md
@ -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)
|
||||
|
48
README.md
48
README.md
@ -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){
|
||||
|
3
debian/libnotcurses1.symbols
vendored
3
debian/libnotcurses1.symbols
vendored
@ -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/>
|
||||
|
44
doc/man/man1/colloquy.1.md
Normal file
44
doc/man/man1/colloquy.1.md
Normal file
@ -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");
|
||||
|
67
include/ncpp/Plot.hh
Normal file
67
include/ncpp/Plot.hh
Normal file
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
|
410
src/colloquy/Cargo.lock
generated
410
src/colloquy/Cargo.lock
generated
@ -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;
|
||||
|
181
src/lib/libav.c
181
src/lib/libav.c
@ -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;
|
||||
}
|
||||
|
153
src/lib/plot.c
153
src/lib/plot.c
@ -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));
|
||||
|
120
tests/scrolling.cpp
Normal file
120
tests/scrolling.cpp
Normal file
@ -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_));
|
||||
|
||||
}
|
50
tools/notcurses.spec
Normal file
50
tools/notcurses.spec
Normal file
@ -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…
Reference in New Issue
Block a user