mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 09:09:03 -04:00
[rust-split] delete rust directory #2171
- remove references to rust from `.drone.yml` and `.github/workflow/*.yml`
This commit is contained in:
parent
4060368c23
commit
9b5f5f3827
@ -21,10 +21,6 @@ steps:
|
||||
- LDFLAGS=-L/usr/local/lib CFLAGS=-I/usr/local/include python3 setup.py sdist build install
|
||||
- env LD_LIBRARY_PATH=/usr/local/lib ./notcurses-pydemo > /dev/null
|
||||
- env LD_LIBRARY_PATH=/usr/local/lib ./ncdirect-pydemo > /dev/null
|
||||
- cd ../rust
|
||||
- rustc --version
|
||||
- cargo build
|
||||
- cargo t_all
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
@ -43,10 +39,6 @@ steps:
|
||||
- ctest --output-on-failure
|
||||
- make install
|
||||
- ldconfig
|
||||
- cd ../rust
|
||||
- rustc --version
|
||||
- cargo build
|
||||
- cargo t_all
|
||||
- cd ../cffi
|
||||
- LDFLAGS=-L/usr/local/lib CFLAGS=-I/usr/local/include python3 setup.py sdist build install
|
||||
- cd ../python
|
||||
|
11
.github/workflows/macos_test.yml
vendored
11
.github/workflows/macos_test.yml
vendored
@ -27,8 +27,7 @@ jobs:
|
||||
libunistring \
|
||||
ncurses \
|
||||
pandoc \
|
||||
readline \
|
||||
rust
|
||||
readline
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@ -69,11 +68,3 @@ jobs:
|
||||
python3 setup.py build
|
||||
#sudo python3 setup.py install
|
||||
#python3 examples/000-print-version.py
|
||||
|
||||
- name: rust wrappers
|
||||
run: |
|
||||
export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
|
||||
cd rust
|
||||
rustc --version
|
||||
cargo build
|
||||
cargo t_all
|
||||
|
7
.github/workflows/ubuntu_test.yml
vendored
7
.github/workflows/ubuntu_test.yml
vendored
@ -81,10 +81,3 @@ jobs:
|
||||
python3 setup.py build
|
||||
sudo python3 setup.py install
|
||||
python3 examples/000-print-version.py
|
||||
|
||||
- name: rust wrappers
|
||||
run: |
|
||||
cd rust
|
||||
rustc --version
|
||||
cargo build
|
||||
cargo t_all
|
||||
|
8
.github/workflows/windows_test.yml
vendored
8
.github/workflows/windows_test.yml
vendored
@ -85,11 +85,3 @@ jobs:
|
||||
#python3 setup.py install
|
||||
#notcurses-pydemo > /dev/null
|
||||
#ncdirect-pydemo > /dev/null
|
||||
|
||||
- name: rust wrappers
|
||||
run: |
|
||||
cd rust
|
||||
#rustc --version
|
||||
#cargo build
|
||||
#cargo t_all
|
||||
#mingw-w64-ucrt-x86_64-rust
|
||||
|
@ -1,14 +0,0 @@
|
||||
[alias]
|
||||
d = "doc --no-deps"
|
||||
do = "doc --no-deps --open"
|
||||
|
||||
re = "run --example"
|
||||
rre = "run --release --example"
|
||||
|
||||
rqe = "run --quiet --example "
|
||||
req = "rqe"
|
||||
|
||||
# TEST
|
||||
# fix IO errors: https://github.com/dankamongmen/notcurses/issues/766
|
||||
t = "test -- --test-threads 1 --nocapture"
|
||||
t_all = "test --no-fail-fast -- --test-threads 1 --nocapture"
|
@ -1,48 +0,0 @@
|
||||
[package]
|
||||
name = "libnotcurses-sys"
|
||||
version = "2.4.1"
|
||||
authors = [
|
||||
"nick black <dankamongmen@gmail.com>",
|
||||
"José Luis Cruz <joseluis@andamira.net>"
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
description = "Low-level Rust bindings for the notcurses C library."
|
||||
documentation = "https://dankamongmen.github.io/notcurses/rustdoc/libnotcurses_sys/"
|
||||
repository = "https://github.com/dankamongmen/notcurses"
|
||||
homepage = "https://nick-black.com/dankwiki/index.php/Notcurses"
|
||||
readme = "./README.md"
|
||||
links = "notcurses"
|
||||
build = "build/build.rs"
|
||||
categories = [
|
||||
"external-ffi-bindings",
|
||||
"command-line-interface",
|
||||
"visualization",
|
||||
"multimedia",
|
||||
"rendering",
|
||||
]
|
||||
keywords = ["tui", "cli", "terminal", "ncurses", "ffi"]
|
||||
include = ["build/", "examples/", "src/", "LICENSE-*", "README.md"]
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "^0.2.80", default-features = false }
|
||||
cty = "^0.2.1"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "^0.57"
|
||||
pkg-config = "^0.3.18"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "^0.5.0"
|
||||
serial_test_derive = "^0.5.0"
|
||||
|
||||
rand = "^0.8"
|
||||
|
||||
# https://doc.rust-lang.org/cargo/reference/profiles.html
|
||||
[profile.dev]
|
||||
#
|
||||
[profile.release]
|
||||
# opt-level = 0 # [0-*3 | s | z]
|
||||
# lto = "fat" # [*fat | thin]
|
||||
# debug = 1 # [*0/false | 1 | 2/true]
|
||||
# debug-assertions = true # [*false | true]
|
@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -1,25 +0,0 @@
|
||||
Copyright 2020-2021 José Luis Cruz and Nick Black
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
105
rust/README.md
105
rust/README.md
@ -1,105 +0,0 @@
|
||||
[](https://crates.io/crates/libnotcurses-sys)
|
||||
[](https://dankamongmen.github.io/notcurses/rustdoc/libnotcurses_sys/)
|
||||
[](https://blog.rust-lang.org/2020/11/19/Rust-1.48.html)
|
||||
|
||||
`libnotcurses-sys` is a low-level Rust wrapper for the
|
||||
[notcurses C library](https://www.github.com/dankamongmen/notcurses/)
|
||||
|
||||
This library is built with several layers of zero-overhead abstractions
|
||||
over the C functions and pointers accessed through FFI.
|
||||
|
||||
# How to use this library
|
||||
|
||||
There are basically two ways: The [**Rust way**](#1-the-rust-way),
|
||||
and the [**C way**](#2-the-c-way). (Or a mix of both).
|
||||
|
||||
## 1. The Rust way
|
||||
|
||||
Where you use the more safely wrapped types, with its methods and constructors,
|
||||
and painless error handling, like this:
|
||||
|
||||
```rust
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?;
|
||||
let plane = nc.stdplane();
|
||||
plane.putstr("hello world")?;
|
||||
nc.render()?;
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
Although you still have to manually call the `stop()` method for `Nc`
|
||||
and `NcDirect` objects, and the `destroy()` method for the rest of types that
|
||||
allocate, (like `NcPlane`, `NcMenu`…) at the end of their scope, since the Drop
|
||||
trait is not implemented for any wrapping type in libnotcurses-sys.
|
||||
|
||||
But they do implement methods and use `NcResult` as the return type,
|
||||
for handling errors in the way we are used to in Rust.
|
||||
|
||||
For the types that don't allocate, most are based on primitives like `i32`,
|
||||
`u32`, `u64`… without a name in the C library. In Rust they are type aliased
|
||||
(e.g.: `NcChannel`, `NcChannelPair`, `NcRgb`, `NcColor`…), to
|
||||
leverage type checking, and they implement methods through traits
|
||||
(e.g. `NcChannelMethods` must be in scope to use the `NcChannel` methods.
|
||||
|
||||
## 2. The C way
|
||||
|
||||
You can always use the C API functions directly if you prefer,
|
||||
in a very similar way as the C library is used.
|
||||
|
||||
It requires the use of unsafe, since most functions are wrapped directly
|
||||
by `bindgen` marked as such.
|
||||
|
||||
Error handling is done this way by checking the returned `NcIntResult`,
|
||||
or in case of receiving a pointer, by comparing it to `null_mut()`.
|
||||
|
||||
### Example
|
||||
|
||||
```rust
|
||||
use core::ptr::{null, null_mut};
|
||||
use std::process::exit;
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() {
|
||||
let options = ffi::notcurses_options {
|
||||
termtype: null(),
|
||||
loglevel: 0,
|
||||
margin_t: 0,
|
||||
margin_r: 0,
|
||||
margin_b: 0,
|
||||
margin_l: 0,
|
||||
flags: NCOPTION_NO_ALTERNATE_SCREEN,
|
||||
};
|
||||
unsafe {
|
||||
let nc = notcurses_init(&options, null_mut());
|
||||
if nc == null_mut() {
|
||||
exit(1);
|
||||
}
|
||||
let plane = notcurses_stdplane(nc);
|
||||
let cols = ncplane_putstr(&mut *plane, "hello world");
|
||||
if cols < NCRESULT_OK {
|
||||
notcurses_stop(nc);
|
||||
exit(cols.abs());
|
||||
}
|
||||
if notcurses_stop(nc) < NCRESULT_OK {
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### The `notcurses` C API docs
|
||||
|
||||
- [API reference (man pages)](https://notcurses.com/)
|
||||
- [Wiki Page](https://nick-black.com/dankwiki/index.php/Notcurses)
|
||||
- [The Book Guide (pdf)](https://nick-black.com/htp-notcurses.pdf)
|
||||
- [USAGE.md](https://github.com/dankamongmen/notcurses/blob/master/USAGE.md)
|
||||
- [HACKING.md](https://github.com/dankamongmen/notcurses/blob/master/doc/HACKING.md)
|
||||
- [Doxygen Documentation](https://nick-black.com/notcurses/html/index.html)
|
||||
- [FOSDEM 2021 presentation](https://fosdem.org/2021/schedule/event/notcurses/)
|
||||
|
@ -1,99 +0,0 @@
|
||||
extern crate bindgen;
|
||||
extern crate pkg_config;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// largely taken from https://rust-lang.github.io/rust-bindgen/tutorial-3.html
|
||||
fn main() {
|
||||
let plib = pkg_config::Config::new()
|
||||
.atleast_version("2.4.1")
|
||||
.probe("notcurses")
|
||||
.unwrap();
|
||||
|
||||
// Tell cargo to invalidate the built crate whenever the wrapper changes
|
||||
println!("cargo:rerun-if-changed=build/wrapper.h");
|
||||
|
||||
// The bindgen::Builder is the main entry point to bindgen, and lets you
|
||||
// build up options for the resulting bindings.
|
||||
//
|
||||
// https://docs.rs/bindgen/*/bindgen/struct.Builder.html
|
||||
//
|
||||
// allow .blacklist_function instead of .blocklist_function for now,
|
||||
// until we update bindgen to >= 0.58.
|
||||
#[allow(deprecated)]
|
||||
let mut builder = bindgen::Builder::default()
|
||||
.use_core()
|
||||
.ctypes_prefix("cty")
|
||||
.clang_arg("-D_XOPEN_SOURCE")
|
||||
// The input header we would like to generate builder for.
|
||||
.header("build/wrapper.h")
|
||||
// generate comments, also from headers and not just doc comments (///)
|
||||
.generate_comments(true)
|
||||
.clang_arg("-fretain-comments-from-system-headers")
|
||||
.clang_arg("-fparse-all-comments")
|
||||
// Remove warnings about improper_ctypes
|
||||
.blacklist_function("strtold")
|
||||
.blacklist_function("wcstold")
|
||||
.blacklist_function("socketpair")
|
||||
// only import functions from notcurses public API
|
||||
.blacklist_function("[^ns].*")
|
||||
.blacklist_function("n[^co].*")
|
||||
.blacklist_function("s[^i].*") // allow sig*
|
||||
// clean more unneeded types
|
||||
.blacklist_item("B[0-9]+")
|
||||
.blacklist_item("_BITS.*")
|
||||
.blacklist_item("_POSIX.*")
|
||||
.blacklist_item("__[A-Z].*")
|
||||
.blacklist_item("[ADHJ-MQ-Z].*")
|
||||
.blacklist_item("IN.*")
|
||||
.blacklist_item("IP[^R].*")
|
||||
.blacklist_item("ip.*")
|
||||
.blacklist_item("m.*")
|
||||
.blacklist_item("PF.*")
|
||||
.blacklist_item("MSG_.*")
|
||||
.blacklist_item("N[^C].*")
|
||||
.blacklist_type("_bindgen.*")
|
||||
// https://github.com/dankamongmen/notcurses/pull/1937
|
||||
// https://github.com/rust-lang/rust-bindgen/issues/1651
|
||||
.layout_tests(false)
|
||||
// Don't derive the Copy trait on types with destructors.
|
||||
.no_copy("ncdirect")
|
||||
.no_copy("ncdplot")
|
||||
.no_copy("ncfdplane")
|
||||
.no_copy("ncmenu")
|
||||
.no_copy("ncmultiselector")
|
||||
.no_copy("ncplane")
|
||||
.no_copy("ncreader")
|
||||
.no_copy("ncreel")
|
||||
.no_copy("ncselector")
|
||||
.no_copy("ncuplot")
|
||||
.no_copy("ncvisual")
|
||||
.no_copy("notcurses")
|
||||
// try to derive more traits
|
||||
.derive_default(true)
|
||||
.derive_hash(true)
|
||||
.derive_partialord(true)
|
||||
.derive_ord(true)
|
||||
.derive_partialeq(true)
|
||||
.derive_eq(true)
|
||||
// Tell cargo to invalidate the built crate whenever any of the
|
||||
// included header files changed.
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks));
|
||||
|
||||
for d in plib.include_paths {
|
||||
builder = builder.clang_arg(format!("-I{}", d.to_string_lossy()));
|
||||
}
|
||||
|
||||
// Finish the builder and generate the builder.
|
||||
let bindings = builder
|
||||
.generate()
|
||||
// Unwrap the Result and panic on failure.
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
// Write the bindings to the $OUT_DIR/bindings.rs file.
|
||||
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
bindings
|
||||
.write_to_file(out_path.join("bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
#include <notcurses/notcurses.h>
|
||||
#include <notcurses/direct.h>
|
@ -1,22 +0,0 @@
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let dm = NcDirect::new()?;
|
||||
|
||||
let (t_rows, t_cols) = dm.dim_yx();
|
||||
println!("Terminal rows={0}, cols={1}", t_rows, t_cols);
|
||||
|
||||
println!(
|
||||
"Can display UTF-8: {0}
|
||||
Can open images: {1}
|
||||
Supports Pixels: {2:?}
|
||||
Palette size: {3:?}
|
||||
",
|
||||
dm.canutf8(),
|
||||
dm.canopen_images(),
|
||||
dm.check_pixel_support(),
|
||||
dm.palette_size(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
//! Example 'direct-cursor'
|
||||
//!
|
||||
//! Explore cursor functions in direct mode
|
||||
//!
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let ncd = NcDirect::new()?;
|
||||
|
||||
let cols = ncd.dim_x();
|
||||
let rows = ncd.dim_y();
|
||||
println!("terminal size (rows, cols): {}, {}", rows, cols);
|
||||
|
||||
let mut channels =
|
||||
NcChannels::combine(NcChannel::from_rgb(0xAA2244), NcChannel::from_rgb(0x112233));
|
||||
ncd.putstr(channels, "The current coordinates are")?;
|
||||
|
||||
for _n in 0..40 {
|
||||
ncd.flush()?;
|
||||
sleep![0, 30];
|
||||
channels.set_fg_rgb8(
|
||||
rng.gen_range(0x66..=0xEE),
|
||||
rng.gen_range(0x66..=0xEE),
|
||||
rng.gen_range(0x66..=0xEE),
|
||||
);
|
||||
channels.set_bg_rgb8(
|
||||
rng.gen_range(0..=0x9),
|
||||
rng.gen_range(0..=0x9),
|
||||
rng.gen_range(0..=0x9),
|
||||
);
|
||||
ncd.putstr(channels, ".")?;
|
||||
}
|
||||
|
||||
let (cy, cx) = ncd.cursor_yx()?;
|
||||
ncd.putstr(channels, &format!(" ({},{})\n", cy, cx))?;
|
||||
sleep![1];
|
||||
|
||||
let sentence = vec![
|
||||
"And", "now", "I", "will", "clear", "the", "screen", ".", ".", ".",
|
||||
];
|
||||
for word in sentence {
|
||||
channels.set_fg_rgb(channels.fg_rgb().wrapping_sub(0x050505));
|
||||
channels.set_bg_rgb(channels.bg_rgb().wrapping_add(0x090909));
|
||||
ncd.putstr(channels, &format!["{} ", word])?;
|
||||
ncd.flush()?;
|
||||
sleep![0, 150];
|
||||
}
|
||||
sleep![0, 300];
|
||||
channels.set_fg_rgb(0xFFFFFF);
|
||||
channels.set_bg_default();
|
||||
ncd.putstr(channels, "\nbye!\n\n")?;
|
||||
ncd.flush()?;
|
||||
sleep![0, 600];
|
||||
ncd.clear()?;
|
||||
Ok(())
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//! Example 'direct-image'
|
||||
//!
|
||||
//! Explore image rendering in direct mode
|
||||
//!
|
||||
//! NOTE: This example uses the C style with functions.
|
||||
|
||||
use core::ptr::{null, null_mut};
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let ncd = ncdirect_init(null(), null_mut(), 0);
|
||||
|
||||
render_image(&mut *ncd, NCBLIT_1x1);
|
||||
render_image(&mut *ncd, NCBLIT_2x1);
|
||||
render_image(&mut *ncd, NCBLIT_BRAILLE);
|
||||
|
||||
ncdirect_stop(ncd);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_image(ncd: &mut NcDirect, blit: NcBlitter) {
|
||||
unsafe {
|
||||
if ncdirect_render_image(
|
||||
ncd,
|
||||
cstring!["image-16x16.png"],
|
||||
NCALIGN_CENTER,
|
||||
blit,
|
||||
NCSCALE_NONE,
|
||||
) != 0
|
||||
{
|
||||
panic!(
|
||||
"ERROR: ncdirect_render_image(). Make sure you \
|
||||
are running this example from the examples folder"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
//! Example 'direct-image'
|
||||
//!
|
||||
//! Explore image rendering in direct mode
|
||||
//!
|
||||
//! NOTE: This example uses the Rust style with methods.
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut dm = NcDirect::new()?;
|
||||
|
||||
render_image(&mut dm, NCBLIT_1x1)?;
|
||||
render_image(&mut dm, NCBLIT_2x1)?;
|
||||
render_image(&mut dm, NCBLIT_BRAILLE)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_image(dm: &mut NcDirect, blit: NcBlitter) -> NcResult<()> {
|
||||
if let Err(nc_error) = dm.render_image("image-16x16.png", NCALIGN_CENTER, blit, NCSCALE_NONE) {
|
||||
return Err(NcError::with_msg(
|
||||
nc_error.int,
|
||||
"ERROR: dmirect_render_image(). Make sure you \
|
||||
are running this example from the examples folder",
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let nc = Nc::without_altscreen()?;
|
||||
|
||||
let (t_rows, t_cols) = nc.term_dim_yx();
|
||||
println!("Terminal rows={0}, cols={1}", t_rows, t_cols);
|
||||
|
||||
println!(
|
||||
"Can display UTF-8: {0}
|
||||
Can display braille characters: {1}
|
||||
Can display sextant characters: {2}
|
||||
Can display quadrant characters: {3}
|
||||
Can display half block characters: {4}
|
||||
Can open images: {5}
|
||||
Can open videos: {6}
|
||||
Supports Pixels: {7:?}
|
||||
Supports True Color: {8}
|
||||
Supports fading: {9}
|
||||
Supports changing the palette: {10}
|
||||
Palette size: {11:?}
|
||||
",
|
||||
nc.canutf8(),
|
||||
nc.canbraille(),
|
||||
nc.cansextant(),
|
||||
nc.canquadrant(),
|
||||
nc.canhalfblock(),
|
||||
nc.canopen_images(),
|
||||
nc.canopen_videos(),
|
||||
nc.check_pixel_support(),
|
||||
nc.cantruecolor(),
|
||||
nc.canfade(),
|
||||
nc.canchangecolor(),
|
||||
nc.palette_size(),
|
||||
);
|
||||
|
||||
let pixelgeom = nc.stdplane().pixelgeom();
|
||||
println!("{:#?}", pixelgeom);
|
||||
|
||||
nc.render()?;
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
//! Input
|
||||
//!
|
||||
//! https://github.com/dankamongmen/notcurses/blob/master/USAGE.md#input
|
||||
//!
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::with_flags(
|
||||
NCOPTION_SUPPRESS_BANNERS | NCOPTION_NO_WINCH_SIGHANDLER | NCOPTION_NO_QUIT_SIGHANDLERS,
|
||||
)?;
|
||||
|
||||
println!("Exit with F1\n");
|
||||
|
||||
let mut input = NcInput::new_empty();
|
||||
|
||||
loop {
|
||||
let key = notcurses_getc_nblock(&mut nc, &mut input);
|
||||
|
||||
if key as i32 != -1 {
|
||||
println!("'{0}' ({1:x})\n{2:?}", key, key as u32, input);
|
||||
}
|
||||
|
||||
nrs![&mut nc, 0, 10];
|
||||
|
||||
match key {
|
||||
NCKEY_F01 => break,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
println!("\nExiting...");
|
||||
|
||||
nrs![&mut nc, 1];
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::new()?;
|
||||
|
||||
// get the terminal size in character rows & columns
|
||||
let (t_rows, t_cols) = nc.term_dim_yx();
|
||||
|
||||
// the standard plane has the same size
|
||||
let mut stdplane = nc.stdplane();
|
||||
assert_eq![(t_rows, t_cols), stdplane.dim_yx()];
|
||||
|
||||
// set the standard plane's base cell's foreground and background colors
|
||||
let channels = NcChannels::from_rgb(0x88aa00, 0x222288);
|
||||
stdplane.set_base("x", 0, channels)?;
|
||||
nrs![&mut nc, 0, 500];
|
||||
|
||||
// add a green plane to the stdplane's pile
|
||||
let plane_green = NcPlane::new_bound(&mut stdplane, 0, 0, 16, 30)?;
|
||||
plane_green.set_base("·", 0, NcChannels::from_rgb(0x224411, 0x229922))?;
|
||||
nrs![&mut nc, 0, 800];
|
||||
|
||||
// add a smaller red plane, a bit displaced to the bottom right
|
||||
let plane_red = NcPlane::new_bound(&mut stdplane, 8, 12, 10, 20)?;
|
||||
plane_red.set_base("~", 0, NcChannels::from_rgb(0xaadd2b, 0x882222))?;
|
||||
nrs![&mut nc, 0, 800];
|
||||
|
||||
// write something
|
||||
plane_green.putstr("PLANE 11111")?;
|
||||
plane_red.putstr("PLANE 22222")?;
|
||||
nrs![&mut nc, 0, 800];
|
||||
|
||||
// move the green plane down
|
||||
for _ in 0..16 {
|
||||
plane_green.move_rel(1, 1)?;
|
||||
nrs![&mut nc, 0, 30];
|
||||
}
|
||||
// and up
|
||||
for _ in 0..20 {
|
||||
plane_green.move_rel(-1, -1)?;
|
||||
nrs![&mut nc, 0, 35];
|
||||
}
|
||||
|
||||
// move the red plane right
|
||||
for _ in 0..26 {
|
||||
plane_red.move_rel(0, 1)?;
|
||||
nrs![&mut nc, 0, 40];
|
||||
}
|
||||
sleep![1];
|
||||
|
||||
// resize the red plane
|
||||
plane_red.resize_simple(14, 24)?;
|
||||
nrs![&mut nc, 0, 300];
|
||||
plane_red.move_rel(-2, -2)?;
|
||||
nrs![&mut nc, 0, 300];
|
||||
plane_red.resize_simple(8, 16)?;
|
||||
|
||||
// TODO…
|
||||
|
||||
nrs![&mut nc, 3];
|
||||
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 435 B |
@ -1,48 +0,0 @@
|
||||
//! https://github.com/dankamongmen/notcurses/issues/1832
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
const W: u32 = 32;
|
||||
const H: u32 = 32;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::new()?;
|
||||
|
||||
// create a white rectangle visual for the background
|
||||
let buffer1 = vec![255; H as usize * W as usize * 3];
|
||||
let mut bg_plane = NcPlane::new(&mut nc, 0, 0, H, W)?;
|
||||
let v = NcVisual::from_rgb_packed(buffer1.as_slice(), H, W * 3, W, 255)?;
|
||||
let vo = NcVisualOptions::with_plane(
|
||||
&mut bg_plane,
|
||||
NCSCALE_NONE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NCBLIT_PIXEL,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
// create a blue plane for the foreground
|
||||
let fg_plane = NcPlane::new_bound(&mut bg_plane, 1, 1, 2, 16)?;
|
||||
fg_plane.set_base(" ", 0, NcChannels::from_rgb(0x88aa00, 0x222288))?;
|
||||
|
||||
let mut counter = 0;
|
||||
for _ in 0..3 {
|
||||
let _ = fg_plane.putstr_yx(0, 0, &format!["counter: {}", &counter]);
|
||||
counter += 1;
|
||||
|
||||
v.render(nc, &vo)?;
|
||||
bg_plane.render()?;
|
||||
bg_plane.rasterize()?;
|
||||
sleep![1];
|
||||
}
|
||||
|
||||
v.destroy();
|
||||
bg_plane.destroy()?;
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
//! pixel-cell example
|
||||
//!
|
||||
//! Shows how to get the size of a cell in pixels
|
||||
//!
|
||||
//! It works on the following terminals:
|
||||
//! - kitty
|
||||
//! - xterm (invoked with `xterm -ti vt340`)
|
||||
//! - alacritty (WIP: https://github.com/ayosec/alacritty/tree/graphics)
|
||||
|
||||
use rand::{distributions::Uniform, Rng};
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::new()?;
|
||||
|
||||
if nc.check_pixel_support() == NCPIXEL_NONE {
|
||||
nc.stop()?;
|
||||
return Err(NcError::new_msg("Current terminal doesn't support pixels."));
|
||||
}
|
||||
|
||||
let mut stdplane = nc.stdplane();
|
||||
let pg = stdplane.pixelgeom();
|
||||
|
||||
// print visual delimiters around our pixelized cell
|
||||
println!("0▗│▖\n│─ ─\n2▝│▘");
|
||||
println!("a cell is {}x{} pixels", pg.cell_y, pg.cell_x);
|
||||
println!("\ninterpolated not-interpolated not-interpolated interpolated");
|
||||
println!(" SCALE SCALE RESIZE RESIZE");
|
||||
|
||||
// fill the buffer with random color pixels
|
||||
let mut rng = rand::thread_rng();
|
||||
let range = Uniform::from(50..=180);
|
||||
let mut buffer = Vec::<u8>::with_capacity((pg.cell_y * pg.cell_x * 4) as usize);
|
||||
#[allow(unused_parens)]
|
||||
for _byte in (0..={ pg.cell_y * pg.cell_x }) {
|
||||
buffer.push(rng.sample(&range));
|
||||
buffer.push(rng.sample(&range));
|
||||
buffer.push(rng.sample(&range));
|
||||
buffer.push(255);
|
||||
}
|
||||
|
||||
// show the newly created ncvisual delimited with the box drawing characters
|
||||
let v1 = NcVisual::from_rgba(buffer.as_slice(), pg.cell_y, pg.cell_x * 4, pg.cell_x)?;
|
||||
let voptions =
|
||||
NcVisualOptions::without_plane(1, 2, 0, 0, pg.cell_y, pg.cell_x, NCBLIT_PIXEL, 0, 0);
|
||||
v1.render(&mut nc, &voptions)?;
|
||||
nrs![&mut nc, 1];
|
||||
|
||||
// show the ncvisual, scaled with interpolated values
|
||||
let mut vplane2 = NcPlane::new_bound(&mut stdplane, 7, 4, 5, 4)?;
|
||||
let voptions2 = NcVisualOptions::with_plane(
|
||||
&mut vplane2,
|
||||
NCSCALE_SCALE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
pg.cell_y,
|
||||
pg.cell_x,
|
||||
NCBLIT_PIXEL,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
v1.render(&mut nc, &voptions2)?;
|
||||
nrs![&mut nc, 0, 250];
|
||||
|
||||
// show the ncvisual, scaled without using interpolation
|
||||
let mut vplane3 = NcPlane::new_bound(&mut stdplane, 7, 19, 5, 4)?;
|
||||
let voptions3 = NcVisualOptions::with_plane(
|
||||
&mut vplane3,
|
||||
NCSCALE_SCALE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
pg.cell_y,
|
||||
pg.cell_x,
|
||||
NCBLIT_PIXEL,
|
||||
NCVISUAL_OPTION_NOINTERPOLATE,
|
||||
0,
|
||||
);
|
||||
v1.render(&mut nc, &voptions3)?;
|
||||
nrs![&mut nc, 0, 250];
|
||||
|
||||
// resize the ncvisual (doesn't use interpolation)
|
||||
let voptions4 =
|
||||
NcVisualOptions::without_plane(7, 39, 0, 0, pg.cell_y, pg.cell_x, NCBLIT_PIXEL, 0, 0);
|
||||
v1.resize_noninterpolative(pg.cell_y * 4, pg.cell_x * 4)?;
|
||||
v1.render(&mut nc, &voptions4)?;
|
||||
nrs![&mut nc, 0, 250];
|
||||
|
||||
// resize the ncvisual (uses interpolation)
|
||||
let v5 = NcVisual::from_rgba(buffer.as_slice(), pg.cell_y, pg.cell_x * 4, pg.cell_x)?;
|
||||
let voptions5 =
|
||||
NcVisualOptions::without_plane(7, 56, 0, 0, pg.cell_y, pg.cell_x, NCBLIT_PIXEL, 0, 0);
|
||||
v5.resize(pg.cell_y * 4, pg.cell_x * 4)?;
|
||||
v5.render(&mut nc, &voptions5)?;
|
||||
nrs![&mut nc, 0, 250];
|
||||
|
||||
sleep![2];
|
||||
|
||||
v1.destroy();
|
||||
v5.destroy();
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
//! based on the proof of concept at ../../src/poc/cjkscroll.c
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::new()?;
|
||||
|
||||
let plane = nc.stdplane();
|
||||
plane.set_scrolling(true);
|
||||
|
||||
let mut wc = '\u{4e00}'; // 一
|
||||
|
||||
loop {
|
||||
plane.putchar(wc)?;
|
||||
wc = core::char::from_u32(wc as u32 + 1).expect("invalid char");
|
||||
|
||||
// 龣
|
||||
if wc == '\u{9fa5}' {
|
||||
wc = '\u{4e00}';
|
||||
}
|
||||
nrs![&mut nc, 0, 0, 30];
|
||||
}
|
||||
|
||||
// nc.stop()?;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
//! based on the proof of concept at ../../src/poc/direct.c
|
||||
|
||||
use core::convert::TryInto;
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let dm = NcDirect::new()?;
|
||||
|
||||
let dimy = dm.dim_y() as i32;
|
||||
let dimx = dm.dim_x() as i32;
|
||||
for _ in 0..dimy {
|
||||
for _ in 0..dimx {
|
||||
printf!("X");
|
||||
}
|
||||
}
|
||||
dm.flush()?;
|
||||
|
||||
dm.set_fg_rgb(0xff8080)?;
|
||||
printf!(" erp erp \n");
|
||||
dm.set_fg_rgb(0x80ff80)?;
|
||||
printf!(" erp erp \n");
|
||||
dm.set_fg_rgb(0xff8080)?;
|
||||
printf!(" erp erp \n");
|
||||
dm.cursor_right(dimx / 2)?;
|
||||
dm.cursor_up(dimy / 2)?;
|
||||
printf!(" erperperp! \n");
|
||||
|
||||
let (mut y, x);
|
||||
|
||||
if let Ok((_y, _x)) = dm.cursor_yx() {
|
||||
y = _y;
|
||||
x = _x;
|
||||
printf!("\n\tRead cursor position: y: %d x: %d\n", y, x);
|
||||
|
||||
y += 2;
|
||||
while y > 3 {
|
||||
let up = if y >= 3 { 3 } else { y };
|
||||
dm.cursor_up(up.try_into().unwrap_or(0))?;
|
||||
dm.flush()?;
|
||||
y -= up;
|
||||
|
||||
let newy;
|
||||
if let Ok((_y, _)) = dm.cursor_yx() {
|
||||
newy = _y;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if newy != y {
|
||||
eprintln!("Expected {}, got {}", y, newy);
|
||||
break;
|
||||
}
|
||||
printf!("\n\tRead cursor position: y: %d x: %d\n", newy, x);
|
||||
y += 2;
|
||||
}
|
||||
} else {
|
||||
return Err(NcError::with_msg(-10, "Couldn't read cursor position."));
|
||||
}
|
||||
|
||||
dm.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
//! based on the proof of concept at ../../src/poc/kittyzapper.c
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let dm = NcDirect::new()?;
|
||||
|
||||
dm.set_fg_rgb8(100, 100, 100)?;
|
||||
dm.set_bg_rgb8(0xff, 0xff, 0xff)?;
|
||||
printf!("a");
|
||||
dm.set_bg_rgb8(0, 0, 0)?;
|
||||
printf!("b");
|
||||
printf!(" ");
|
||||
printf!(" ");
|
||||
dm.set_bg_rgb8(0, 0, 1)?;
|
||||
printf!("c");
|
||||
printf!(" ");
|
||||
printf!(" ");
|
||||
dm.set_bg_rgb8(0xff, 0xff, 0xff)?;
|
||||
printf!("d");
|
||||
printf!("\n");
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
//! based on the proof of concept at ../../src/poc/menu.c
|
||||
|
||||
// FIXME: has bugs, doesn't work well
|
||||
// probably related to the arrays or the strings...
|
||||
|
||||
use libnotcurses_sys::*;
|
||||
use widgets::*;
|
||||
|
||||
fn main() -> NcResult<()> {
|
||||
let mut nc = Nc::new()?;
|
||||
nc.mouse_enable()?;
|
||||
|
||||
let mut demo_items = [
|
||||
NcMenuItem::new("Restart", NcInput::with_ctrl('r')),
|
||||
NcMenuItem::new("Disabled", NcInput::with_ctrl('d')),
|
||||
];
|
||||
let mut file_items = [
|
||||
NcMenuItem::new("New", NcInput::with_ctrl('n')),
|
||||
NcMenuItem::new("Open", NcInput::with_ctrl('o')),
|
||||
NcMenuItem::new("Close", NcInput::with_ctrl('c')),
|
||||
NcMenuItem::new_empty(),
|
||||
NcMenuItem::new("Quit", NcInput::with_ctrl('q')),
|
||||
];
|
||||
|
||||
let mut help_items = [NcMenuItem::new("About", NcInput::with_ctrl('a'))];
|
||||
|
||||
let mut sections = [
|
||||
NcMenuSection::new("Schwarzgerät", &mut demo_items, NcInput::with_alt('ä')),
|
||||
NcMenuSection::new("File", &mut file_items, NcInput::with_alt('f')),
|
||||
NcMenuSection::new_separator(),
|
||||
// DEBUG: remove alt modifier for now.
|
||||
NcMenuSection::new("Help", &mut help_items, NcInput::new('h')),
|
||||
];
|
||||
|
||||
let mut mopts = NcMenuOptions::new(&mut sections);
|
||||
mopts.header_channels_mut().set_fg_rgb(0x00ff00);
|
||||
mopts.header_channels_mut().set_bg_rgb(0x440000);
|
||||
mopts.section_channels_mut().set_fg_rgb(0xb0d700);
|
||||
mopts.section_channels_mut().set_bg_rgb(0x002000);
|
||||
|
||||
let stdplane = nc.stdplane();
|
||||
let (dim_y, _dim_x) = stdplane.dim_yx();
|
||||
|
||||
let menu_top = NcMenu::new(stdplane, mopts)?;
|
||||
menu_top.item_set_status("Schwarzgerät", "Disabled", false)?;
|
||||
menu_top.item_set_status("Schwarzgerät", "Restart", false)?;
|
||||
|
||||
stdplane.set_base("x", 0, NcChannels::from_rgb(0x88aa00, 0x000088))?;
|
||||
|
||||
nc.render()?;
|
||||
|
||||
stdplane.set_fg_rgb(0x00dddd);
|
||||
stdplane.putstr_aligned(
|
||||
dim_y - 1,
|
||||
NCALIGN_RIGHT,
|
||||
" -=+ menu poc. press q to exit +=-",
|
||||
)?;
|
||||
|
||||
run_menu(&mut nc, menu_top)?;
|
||||
|
||||
stdplane.erase(); // is this needed?
|
||||
|
||||
// BUG FIXME: this doesn't show over the menu (at row 0)
|
||||
stdplane.putstr_aligned(0, NCALIGN_RIGHT, " -=+ menu poc. press q to exit +=-")?;
|
||||
stdplane.putstr_aligned(1, NCALIGN_CENTER, " -=+ menu poc. press q to exit +=-")?;
|
||||
stdplane.putstr_aligned(2, NCALIGN_LEFT, " -=+ menu poc. press q to exit +=-")?;
|
||||
|
||||
mopts.flags |= NCMENU_OPTION_BOTTOM;
|
||||
let menu_bottom = NcMenu::new(stdplane, mopts)?;
|
||||
|
||||
run_menu(&mut nc, menu_bottom)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_menu(nc: &mut Nc, menu: &mut NcMenu) -> NcResult<()> {
|
||||
// yellow rectangle
|
||||
let planeopts = NcPlaneOptions::new_aligned(10, NCALIGN_CENTER, 3, 40);
|
||||
let stdplane = nc.stdplane();
|
||||
let selplane = NcPlane::with_options_bound(stdplane, planeopts)?;
|
||||
selplane.set_fg_rgb(0);
|
||||
selplane.set_bg_rgb(0xdddddd);
|
||||
let mut channels = 0;
|
||||
channels.set_fg_rgb(0x000088);
|
||||
channels.set_bg_rgb(0x88aa00);
|
||||
selplane.set_base(" ", 0, channels)?;
|
||||
|
||||
let mut ni = NcInput::new_empty();
|
||||
let mut keypress: char;
|
||||
nc.render()?;
|
||||
|
||||
loop {
|
||||
stdplane.erase();
|
||||
selplane.erase();
|
||||
|
||||
keypress = nc.getc_blocking(Some(&mut ni))?;
|
||||
|
||||
// DEBUG
|
||||
stdplane.putstr_yx(2, 0, &format!["{:?}", ni])?;
|
||||
nc.render()?;
|
||||
|
||||
// BUG FIXME: always returns false:
|
||||
if !menu.offer_input(ni) {
|
||||
match keypress {
|
||||
'q' => {
|
||||
menu.destroy()?;
|
||||
selplane.destroy()?;
|
||||
nc.stop()?;
|
||||
return Ok(());
|
||||
}
|
||||
NCKEY_ENTER => {
|
||||
if let Some(selection) = menu.selected(Some(&mut ni)) {
|
||||
match selection.as_ref() {
|
||||
"Quit" => {
|
||||
menu.destroy()?;
|
||||
selplane.destroy()?;
|
||||
nc.stop()?;
|
||||
return Ok(());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let mut selni = NcInput::new_empty();
|
||||
if let Some(selitem) = menu.selected(Some(&mut selni)) {
|
||||
selplane.putstr_aligned(1, NCALIGN_CENTER, &selitem)?;
|
||||
} else {
|
||||
// DEBUG
|
||||
selplane.putstr_aligned(1, NCALIGN_CENTER, "nothing opened")?;
|
||||
}
|
||||
nc.render()?;
|
||||
}
|
||||
}
|
@ -1,850 +0,0 @@
|
||||
//! A selection of the [ffi] bindings intended to be used directly.
|
||||
//!
|
||||
//! The full list of bindings is under the [ffi] submodule.
|
||||
//!
|
||||
//! The current module publicly re-exports bindgen generated structs, functions,
|
||||
//! and constants, for their direct usage.
|
||||
|
||||
// BUG ISSUES:
|
||||
// https://github.com/rust-lang/rust-bindgen/issues/1470
|
||||
#[allow(clippy::all)]
|
||||
// https://github.com/rust-lang/rust-bindgen/issues/1651
|
||||
#[allow(unknown_lints, deref_nullptr)]
|
||||
pub mod ffi {
|
||||
//! Rust FFI bindings, automatically generated with bindgen.
|
||||
//!
|
||||
//! Almost all of the notcurses API functions are reexported to the public
|
||||
//! API, while structs, enums and constants are type aliased or wrapped up.
|
||||
//!
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
}
|
||||
|
||||
// Miscellaneous ---------------------------------------------------------------
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncstrwidth,
|
||||
};
|
||||
|
||||
// blitset ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// blitset,
|
||||
|
||||
// cell ------------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// cell,
|
||||
//
|
||||
// // constants
|
||||
// NCALPHA_BLEND,
|
||||
// NCALPHA_HIGHCONTRAST,
|
||||
// NCALPHA_OPAQUE,
|
||||
// NCALPHA_TRANSPARENT,
|
||||
// NC_BGDEFAULT_MASK,
|
||||
// NC_BG_ALPHA_MASK,
|
||||
// NC_BG_PALETTE,
|
||||
// NC_BG_RGB_MASK,
|
||||
// NC_FGDEFAULT_MASK,
|
||||
// NC_FG_ALPHA_MASK,
|
||||
// NC_FG_PALETTE,
|
||||
// NC_FG_RGB_MASK,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
nccell_duplicate,
|
||||
nccell_extended_gcluster,
|
||||
nccell_load,
|
||||
nccell_release,
|
||||
nccells_double_box,
|
||||
nccells_rounded_box,
|
||||
};
|
||||
|
||||
// channel ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // constants
|
||||
// CHANNEL_ALPHA_MASK,
|
||||
|
||||
// ncalign ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // type definitions
|
||||
// ncalign_e,
|
||||
//
|
||||
// // constants
|
||||
// ncalign_e_NCALIGN_CENTER,
|
||||
// ncalign_e_NCALIGN_LEFT,
|
||||
// ncalign_e_NCALIGN_RIGHT,
|
||||
// ncalign_e_NCALIGN_UNALIGNED,
|
||||
|
||||
// ncblitter -------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // type definitions
|
||||
// ncblitter_e,
|
||||
//
|
||||
// // constants
|
||||
// ncblitter_e_NCBLIT_1x1,
|
||||
// ncblitter_e_NCBLIT_2x1,
|
||||
// ncblitter_e_NCBLIT_2x2,
|
||||
// ncblitter_e_NCBLIT_3x2,
|
||||
// ncblitter_e_NCBLIT_4x1,
|
||||
// ncblitter_e_NCBLIT_8x1,
|
||||
// ncblitter_e_NCBLIT_BRAILLE,
|
||||
// ncblitter_e_NCBLIT_DEFAULT,
|
||||
// ncblitter_e_NCBLIT_PIXEL,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
ncblit_bgrx,
|
||||
ncblit_rgb_loose,
|
||||
ncblit_rgb_packed,
|
||||
// functions
|
||||
ncblit_rgba,
|
||||
};
|
||||
|
||||
// ncbox -----------------------------------------------------------------------
|
||||
|
||||
// // constants
|
||||
// NCBOXCORNER_MASK,
|
||||
// NCBOXCORNER_SHIFT,
|
||||
// NCBOXGRAD_BOTTOM,
|
||||
// NCBOXGRAD_LEFT,
|
||||
// NCBOXGRAD_RIGHT,
|
||||
// NCBOXGRAD_TOP,
|
||||
// NCBOXMASK_BOTTOM,
|
||||
// NCBOXMASK_LEFT,
|
||||
// NCBOXMASK_RIGHT,
|
||||
// NCBOXMASK_TOP,
|
||||
|
||||
// nccapabilit* ----------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// nccapabilities,
|
||||
//
|
||||
// // functions
|
||||
// nccapability_canchangecolor,
|
||||
|
||||
// ncdirect --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncdirect,
|
||||
//
|
||||
// // functions
|
||||
// ncdirect_canbraille,
|
||||
// ncdirect_canopen_videos
|
||||
// ncdirect_canchangecolor,
|
||||
// ncdirect_canfade,
|
||||
// ncdirect_canhalfblock,
|
||||
// ncdirect_canquadrant,
|
||||
// ncdirect_cantruecolor,
|
||||
// ncdirect_capabilities,
|
||||
// ncdirect_hline_interp,
|
||||
// ncdirect_vline_interp,
|
||||
//
|
||||
// // constants
|
||||
// NCDIRECT_OPTION_INHIBIT_CBREAK,
|
||||
// NCDIRECT_OPTION_INHIBIT_SETLOCALE,
|
||||
// NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS,
|
||||
// NCDIRECT_OPTION_VERBOSE
|
||||
// NCDIRECT_OPTION_VERY_VERBOSE
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncdirect_box,
|
||||
ncdirect_canget_cursor,
|
||||
ncdirect_canopen_images,
|
||||
ncdirect_canutf8,
|
||||
ncdirect_check_pixel_support,
|
||||
ncdirect_clear,
|
||||
ncdirect_core_init,
|
||||
ncdirect_cursor_disable,
|
||||
ncdirect_cursor_down,
|
||||
ncdirect_cursor_enable,
|
||||
ncdirect_cursor_left,
|
||||
ncdirect_cursor_move_yx,
|
||||
ncdirect_cursor_pop,
|
||||
ncdirect_cursor_push,
|
||||
ncdirect_cursor_right,
|
||||
ncdirect_cursor_up,
|
||||
ncdirect_cursor_yx,
|
||||
ncdirect_detected_terminal,
|
||||
ncdirect_dim_x,
|
||||
ncdirect_dim_y,
|
||||
ncdirect_double_box,
|
||||
ncdirect_flush,
|
||||
ncdirect_get,
|
||||
ncdirect_init,
|
||||
ncdirect_inputready_fd,
|
||||
ncdirect_off_styles,
|
||||
ncdirect_on_styles,
|
||||
ncdirect_palette_size,
|
||||
//W ncdirect_printf_aligned,
|
||||
ncdirect_putstr,
|
||||
ncdirect_raster_frame,
|
||||
ncdirect_readline,
|
||||
ncdirect_render_frame,
|
||||
ncdirect_render_image,
|
||||
ncdirect_rounded_box,
|
||||
ncdirect_set_bg_default,
|
||||
ncdirect_set_bg_palindex,
|
||||
ncdirect_set_bg_rgb,
|
||||
ncdirect_set_fg_default,
|
||||
ncdirect_set_fg_palindex,
|
||||
ncdirect_set_fg_rgb,
|
||||
ncdirect_set_styles,
|
||||
ncdirect_stop,
|
||||
ncdirect_stream,
|
||||
ncdirect_styles,
|
||||
ncdirect_supported_styles,
|
||||
};
|
||||
|
||||
// ncdirectf --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // type alias
|
||||
// ncdirectf,
|
||||
//
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
ncdirectf_free,
|
||||
// functions
|
||||
ncdirectf_from_file,
|
||||
ncdirectf_geom,
|
||||
ncdirectf_render,
|
||||
};
|
||||
|
||||
// ncfadectx -------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncfadectx,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncfadectx_free,
|
||||
ncfadectx_iterations,
|
||||
ncfadectx_setup,
|
||||
};
|
||||
|
||||
// ncinput ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncinput,
|
||||
|
||||
// ncloglevel ------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // type definitions
|
||||
// ncloglevel_e,
|
||||
//
|
||||
// // constants
|
||||
// ncloglevel_e_NCLOGLEVEL_DEBUG,
|
||||
// ncloglevel_e_NCLOGLEVEL_ERROR,
|
||||
// ncloglevel_e_NCLOGLEVEL_FATAL,
|
||||
// ncloglevel_e_NCLOGLEVEL_INFO,
|
||||
// ncloglevel_e_NCLOGLEVEL_PANIC,
|
||||
// ncloglevel_e_NCLOGLEVEL_SILENT,
|
||||
// ncloglevel_e_NCLOGLEVEL_TRACE,
|
||||
// ncloglevel_e_NCLOGLEVEL_VERBOSE,
|
||||
// ncloglevel_e_NCLOGLEVEL_WARNING,
|
||||
|
||||
// ncfdplane -------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncfdplane,
|
||||
// ncfdplane_options,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncfdplane_create,
|
||||
ncfdplane_destroy,
|
||||
ncfdplane_plane,
|
||||
};
|
||||
|
||||
// ncmenu ----------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncmenu,
|
||||
// ncmenu_item,
|
||||
// ncmenu_options,
|
||||
// ncmenu_section,
|
||||
//
|
||||
// // constants
|
||||
// NCMENU_OPTION_BOTTOM,
|
||||
// NCMENU_OPTION_HIDING,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncmenu_create,
|
||||
ncmenu_destroy,
|
||||
ncmenu_item_set_status,
|
||||
ncmenu_mouse_selected,
|
||||
ncmenu_nextitem,
|
||||
ncmenu_nextsection,
|
||||
ncmenu_offer_input,
|
||||
ncmenu_plane,
|
||||
ncmenu_previtem,
|
||||
ncmenu_prevsection,
|
||||
ncmenu_rollup,
|
||||
ncmenu_selected,
|
||||
ncmenu_unroll,
|
||||
};
|
||||
|
||||
// ncmetric --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // functions
|
||||
// ncmetric
|
||||
//
|
||||
// // constants
|
||||
// PREFIXCOLUMNS,
|
||||
// PREFIXSTRLEN,
|
||||
// BPREFIXCOLUMNS,
|
||||
// BPREFIXSTRLEN,
|
||||
// IPREFIXCOLUMNS,
|
||||
// IPREFIXSTRLEN,
|
||||
|
||||
// ncmultiselector -------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncmultiselector,
|
||||
// ncmselector_item,
|
||||
// ncmultiselector_options,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncmultiselector_create,
|
||||
ncmultiselector_destroy,
|
||||
ncmultiselector_offer_input,
|
||||
ncmultiselector_plane,
|
||||
ncmultiselector_selected,
|
||||
};
|
||||
|
||||
// ncpile ----------------------------------------------------------------------
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncpile_bottom,
|
||||
ncpile_create,
|
||||
ncpile_rasterize,
|
||||
ncpile_render,
|
||||
ncpile_top,
|
||||
};
|
||||
|
||||
// ncplane ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncplane,
|
||||
// ncplane_options,
|
||||
//
|
||||
// // functions
|
||||
// ncplane_channels,
|
||||
// ncplane_gradient,
|
||||
// ncplane_set_bchannel,
|
||||
// ncplane_set_fchannel,
|
||||
// ncplane_set_channels,
|
||||
//
|
||||
// // constants
|
||||
// NCPLANE_OPTION_HORALIGNED,
|
||||
// NCPLANE_OPTION_MARGINALIZED,
|
||||
// NCPLANE_OPTION_VERALIGNED,
|
||||
//
|
||||
// // type alias
|
||||
// ncdirectv,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncplane_above,
|
||||
ncplane_abs_x,
|
||||
ncplane_abs_y,
|
||||
ncplane_abs_yx,
|
||||
ncplane_as_rgba,
|
||||
ncplane_at_cursor,
|
||||
ncplane_at_cursor_cell,
|
||||
ncplane_at_yx,
|
||||
ncplane_at_yx_cell,
|
||||
ncplane_base,
|
||||
ncplane_below,
|
||||
ncplane_box,
|
||||
ncplane_center_abs,
|
||||
ncplane_contents,
|
||||
ncplane_create,
|
||||
ncplane_cursor_move_yx,
|
||||
ncplane_cursor_yx,
|
||||
ncplane_destroy,
|
||||
ncplane_dim_yx,
|
||||
ncplane_dup,
|
||||
ncplane_erase,
|
||||
ncplane_erase_region,
|
||||
ncplane_fadein,
|
||||
ncplane_fadein_iteration,
|
||||
ncplane_fadeout,
|
||||
ncplane_fadeout_iteration,
|
||||
ncplane_format,
|
||||
ncplane_greyscale,
|
||||
ncplane_highgradient,
|
||||
ncplane_highgradient_sized,
|
||||
ncplane_hline_interp,
|
||||
ncplane_home,
|
||||
ncplane_mergedown,
|
||||
ncplane_mergedown_simple,
|
||||
ncplane_move_above,
|
||||
ncplane_move_below,
|
||||
ncplane_move_bottom,
|
||||
ncplane_move_top,
|
||||
ncplane_move_yx,
|
||||
ncplane_notcurses,
|
||||
ncplane_notcurses_const,
|
||||
ncplane_off_styles,
|
||||
ncplane_on_styles,
|
||||
ncplane_parent,
|
||||
ncplane_parent_const,
|
||||
ncplane_pixelgeom,
|
||||
ncplane_polyfill_yx,
|
||||
ncplane_pulse,
|
||||
ncplane_putc_yx,
|
||||
ncplane_putchar_stained,
|
||||
ncplane_putegc_stained,
|
||||
ncplane_putegc_yx,
|
||||
ncplane_putnstr_aligned,
|
||||
ncplane_putnstr_yx,
|
||||
ncplane_putstr_aligned,
|
||||
ncplane_putstr_stained,
|
||||
ncplane_putstr_yx,
|
||||
ncplane_puttext,
|
||||
ncplane_putwegc_stained,
|
||||
ncplane_putwstr_stained,
|
||||
ncplane_qrcode,
|
||||
ncplane_reparent,
|
||||
ncplane_reparent_family,
|
||||
ncplane_resize,
|
||||
ncplane_resize_marginalized,
|
||||
ncplane_resize_maximize,
|
||||
ncplane_resize_realign,
|
||||
ncplane_resizecb,
|
||||
ncplane_rotate_ccw,
|
||||
ncplane_rotate_cw,
|
||||
ncplane_scrolling_p,
|
||||
ncplane_set_base,
|
||||
ncplane_set_base_cell,
|
||||
ncplane_set_bg_alpha,
|
||||
ncplane_set_bg_default,
|
||||
ncplane_set_bg_palindex,
|
||||
ncplane_set_bg_rgb,
|
||||
ncplane_set_bg_rgb8,
|
||||
ncplane_set_bg_rgb8_clipped,
|
||||
ncplane_set_fg_alpha,
|
||||
ncplane_set_fg_default,
|
||||
ncplane_set_fg_palindex,
|
||||
ncplane_set_fg_rgb,
|
||||
ncplane_set_fg_rgb8,
|
||||
ncplane_set_fg_rgb8_clipped,
|
||||
ncplane_set_resizecb,
|
||||
ncplane_set_scrolling,
|
||||
ncplane_set_styles,
|
||||
ncplane_set_userptr,
|
||||
ncplane_stain,
|
||||
ncplane_styles,
|
||||
ncplane_styles_off,
|
||||
ncplane_styles_on,
|
||||
ncplane_styles_set,
|
||||
ncplane_translate,
|
||||
ncplane_translate_abs,
|
||||
ncplane_userptr,
|
||||
ncplane_vline_interp,
|
||||
ncplane_vprintf_aligned,
|
||||
ncplane_vprintf_stained,
|
||||
ncplane_vprintf_yx,
|
||||
ncplane_x,
|
||||
ncplane_y,
|
||||
ncplane_yx,
|
||||
};
|
||||
|
||||
// ncplot ----------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncdplot, // f64
|
||||
// ncuplot, // u64
|
||||
// ncplot_options,
|
||||
//
|
||||
// // constants
|
||||
// NCPLOT_OPTION_DETECTMAXONLY,
|
||||
// NCPLOT_OPTION_EXPONENTIALD,
|
||||
// NCPLOT_OPTION_LABELTICKSD,
|
||||
// NCPLOT_OPTION_NODEGRADE,
|
||||
// NCPLOT_OPTION_VERTICALI,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncdplot_add_sample,
|
||||
ncdplot_create,
|
||||
ncdplot_destroy,
|
||||
ncdplot_plane,
|
||||
ncdplot_sample,
|
||||
ncdplot_set_sample,
|
||||
|
||||
ncuplot_add_sample,
|
||||
ncuplot_create,
|
||||
ncuplot_destroy,
|
||||
ncuplot_plane,
|
||||
ncuplot_sample,
|
||||
ncuplot_set_sample,
|
||||
};
|
||||
|
||||
// ncreader --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncreader,
|
||||
// ncreader_options,
|
||||
//
|
||||
// // constants
|
||||
// NCREADER_OPTION_CURSOR,
|
||||
// NCREADER_OPTION_HORSCROLL,
|
||||
// NCREADER_OPTION_NOCMDKEYS,
|
||||
// NCREADER_OPTION_VERSCROLL,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncreader_clear,
|
||||
ncreader_contents,
|
||||
ncreader_create,
|
||||
ncreader_destroy,
|
||||
ncreader_move_down,
|
||||
ncreader_move_left,
|
||||
ncreader_move_right,
|
||||
ncreader_move_up,
|
||||
ncreader_offer_input,
|
||||
ncreader_plane,
|
||||
ncreader_write_egc,
|
||||
};
|
||||
|
||||
// ncprogbar -------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncprogbar,
|
||||
// ncprogbar_options,
|
||||
//
|
||||
// // constants
|
||||
// NCPROGBAR_OPTION_RETROGRADE,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncprogbar_create,
|
||||
ncprogbar_destroy,
|
||||
ncprogbar_plane,
|
||||
ncprogbar_progress,
|
||||
ncprogbar_set_progress,
|
||||
};
|
||||
|
||||
// ncreel ----------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncreel,
|
||||
// ncreel_options,
|
||||
//
|
||||
// // constants
|
||||
// NCREEL_OPTION_CIRCULAR,
|
||||
// NCREEL_OPTION_INFINITESCROLL,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncreel_add,
|
||||
ncreel_create,
|
||||
ncreel_del,
|
||||
ncreel_destroy,
|
||||
ncreel_focused,
|
||||
ncreel_next,
|
||||
ncreel_offer_input,
|
||||
ncreel_plane,
|
||||
ncreel_prev,
|
||||
ncreel_redraw,
|
||||
ncreel_tabletcount,
|
||||
};
|
||||
|
||||
// ncscale ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // type definitions
|
||||
// ncscale_e,
|
||||
//
|
||||
// // constants
|
||||
// ncscale_e_NCSCALE_NONE,
|
||||
// ncscale_e_NCSCALE_SCALE,
|
||||
// ncscale_e_NCSCALE_STRETCH,
|
||||
// ncscale_e_NCSCALE_NONE_HIRES,
|
||||
// ncscale_e_NCSCALE_SCALE_HIRES,
|
||||
|
||||
// ncselector ------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncselector,
|
||||
// ncselector_item,
|
||||
// ncselector_options,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncselector_additem,
|
||||
ncselector_create,
|
||||
ncselector_delitem,
|
||||
ncselector_destroy,
|
||||
ncselector_nextitem,
|
||||
ncselector_offer_input,
|
||||
ncselector_plane,
|
||||
ncselector_previtem,
|
||||
ncselector_selected,
|
||||
};
|
||||
|
||||
// ncstats ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncstats,
|
||||
|
||||
// ncstyle ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // constants
|
||||
// NCSTYLE_MASK,
|
||||
// NCSTYLE_ITALIC,
|
||||
// NCSTYLE_UNDERLINE,
|
||||
// NCSTYLE_UNDERCURL,
|
||||
// NCSTYLE_BOLD,
|
||||
// NCSTYLE_STRUCK,
|
||||
// NCSTYLE_NONE,
|
||||
|
||||
// nctablet --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// nctablet,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
nctablet_plane,
|
||||
nctablet_userptr,
|
||||
};
|
||||
|
||||
// nctree ----------------------------------------------------------------------
|
||||
//
|
||||
// // structs
|
||||
// nctree,
|
||||
// nctree_item,
|
||||
// nctree_options,
|
||||
//
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
nctree_create,
|
||||
nctree_destroy,
|
||||
nctree_focused,
|
||||
nctree_goto,
|
||||
nctree_next,
|
||||
nctree_offer_input,
|
||||
nctree_plane,
|
||||
nctree_prev,
|
||||
nctree_redraw,
|
||||
};
|
||||
|
||||
// ncvgeom ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncvgeom
|
||||
|
||||
// ncvisual --------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncvisual,
|
||||
// ncvisual_options,
|
||||
//
|
||||
// // constants
|
||||
// NCVISUAL_OPTION_ADDALPHA,
|
||||
// NCVISUAL_OPTION_BLEND,
|
||||
// NCVISUAL_OPTION_CHILDPLANE
|
||||
// NCVISUAL_OPTION_HORALIGNED
|
||||
// NCVISUAL_OPTION_NODEGRADE,
|
||||
// NCVISUAL_OPTION_NOINTERPOLATE
|
||||
// NCVISUAL_OPTION_VERALIGNED,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncvisual_at_yx,
|
||||
ncvisual_blitter_geom,
|
||||
ncvisual_decode,
|
||||
ncvisual_decode_loop,
|
||||
ncvisual_destroy,
|
||||
ncvisual_from_bgra,
|
||||
ncvisual_from_file,
|
||||
ncvisual_from_plane,
|
||||
ncvisual_from_rgb_loose,
|
||||
ncvisual_from_rgb_packed,
|
||||
ncvisual_from_rgba,
|
||||
ncvisual_media_defblitter,
|
||||
ncvisual_polyfill_yx,
|
||||
ncvisual_render,
|
||||
ncvisual_resize,
|
||||
ncvisual_resize_noninterpolative,
|
||||
ncvisual_rotate,
|
||||
ncvisual_set_yx,
|
||||
ncvisual_simple_streamer,
|
||||
ncvisual_stream,
|
||||
ncvisual_subtitle,
|
||||
};
|
||||
|
||||
// notcurses -------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// notcurses,
|
||||
// notcurses_options,
|
||||
//
|
||||
// // constants
|
||||
// NCOPTION_INHIBIT_SETLOCALE,
|
||||
// NCOPTION_NO_ALTERNATE_SCREEN,
|
||||
// NCOPTION_NO_CLEAR_BITMAPS
|
||||
// NCOPTION_NO_FONT_CHANGES,
|
||||
// NCOPTION_NO_QUIT_SIGHANDLERS,
|
||||
// NCOPTION_NO_WINCH_SIGHANDLER,
|
||||
// NCOPTION_PRESERVE_CURSOR,
|
||||
// NCOPTION_SUPPRESS_BANNERS,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
notcurses_at_yx,
|
||||
notcurses_bottom,
|
||||
notcurses_canbraille,
|
||||
notcurses_canchangecolor,
|
||||
notcurses_canfade,
|
||||
notcurses_canhalfblock,
|
||||
notcurses_canopen_images,
|
||||
notcurses_canopen_videos,
|
||||
notcurses_canquadrant,
|
||||
notcurses_cansextant,
|
||||
notcurses_cantruecolor,
|
||||
notcurses_canutf8,
|
||||
notcurses_check_pixel_support,
|
||||
notcurses_core_init,
|
||||
notcurses_cursor_disable,
|
||||
notcurses_cursor_enable,
|
||||
notcurses_cursor_yx,
|
||||
notcurses_debug,
|
||||
notcurses_detected_terminal,
|
||||
notcurses_drop_planes,
|
||||
notcurses_get,
|
||||
notcurses_init,
|
||||
notcurses_inputready_fd,
|
||||
notcurses_lex_blitter,
|
||||
notcurses_lex_margins,
|
||||
notcurses_lex_scalemode,
|
||||
notcurses_linesigs_disable,
|
||||
notcurses_linesigs_enable,
|
||||
notcurses_mouse_disable,
|
||||
notcurses_mouse_enable,
|
||||
notcurses_palette_size,
|
||||
notcurses_refresh,
|
||||
notcurses_render,
|
||||
notcurses_render_to_buffer,
|
||||
notcurses_render_to_file,
|
||||
notcurses_stats,
|
||||
notcurses_stats_alloc,
|
||||
notcurses_stats_reset,
|
||||
notcurses_stdplane,
|
||||
notcurses_stdplane_const,
|
||||
notcurses_stop,
|
||||
notcurses_str_blitter,
|
||||
notcurses_str_scalemode,
|
||||
notcurses_supported_styles,
|
||||
notcurses_top,
|
||||
notcurses_ucs32_to_utf8,
|
||||
notcurses_version,
|
||||
notcurses_version_components,
|
||||
};
|
||||
|
||||
// palette ---------------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // structs
|
||||
// ncpalette,
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::{
|
||||
// functions
|
||||
ncpalette_free,
|
||||
ncpalette_new,
|
||||
ncpalette_use,
|
||||
|
||||
// constants
|
||||
NCPALETTESIZE,
|
||||
};
|
||||
|
||||
// fade callback ---------------------------------------------------------------
|
||||
//
|
||||
// already wrapped:
|
||||
//
|
||||
// // types
|
||||
// fadecb,
|
@ -1,75 +0,0 @@
|
||||
//! `NcBoxMask`
|
||||
|
||||
/// Controls the drawing of borders, gradients and corners.
|
||||
///
|
||||
/// NcBoxMax is defined in the least significant byte, where bits [3, 0] are
|
||||
/// are a border mask, and bits [7, 4] are a gradient mask.
|
||||
///
|
||||
/// The drawing of the corners is defined in the second byte,
|
||||
/// see [`NCBOXCORNER_MASK`].
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// NCBOXMASK_TOP 0x0001 0b00000001
|
||||
/// NCBOXMASK_RIGHT 0x0002 0b00000010
|
||||
/// NCBOXMASK_BOTTOM 0x0004 0b00000100
|
||||
/// NCBOXMASK_LEFT 0x0008 0b00001000
|
||||
///
|
||||
/// NCBOXGRAD_TOP 0x0010 0b00010000
|
||||
/// NCBOXGRAD_RIGHT 0x0020 0b00100000
|
||||
/// NCBOXGRAD_BOTTOM 0x0040 0b01000000
|
||||
/// NCBOXGRAD_LEFT 0x0080 0b10000000
|
||||
///
|
||||
/// NCBOXCORNER_MASK 0x0300 0b00000111_00000000
|
||||
///
|
||||
/// NCBOXCORNER_SHIFT 8
|
||||
/// ```
|
||||
///
|
||||
/// ## Bit masks
|
||||
///
|
||||
/// - [NCBOXMASK_TOP]
|
||||
/// - [NCBOXMASK_RIGHT]
|
||||
/// - [NCBOXMASK_BOTTOM]
|
||||
/// - [NCBOXMASK_LEFT]
|
||||
///
|
||||
/// - [NCBOXGRAD_TOP]
|
||||
/// - [NCBOXGRAD_RIGHT]
|
||||
/// - [NCBOXGRAD_BOTTOM]
|
||||
/// - [NCBOXGRAD_LEFT]
|
||||
///
|
||||
/// - [NCBOXCORNER_MASK]
|
||||
/// - [NCBOXCORNER_SHIFT]
|
||||
///
|
||||
pub type NcBoxMask = u32;
|
||||
|
||||
/// [NcBoxMask] top gradient mask.
|
||||
pub const NCBOXGRAD_TOP: NcBoxMask = crate::bindings::ffi::NCBOXGRAD_TOP;
|
||||
/// [NcBoxMask] right gradient mask.
|
||||
pub const NCBOXGRAD_RIGHT: NcBoxMask = crate::bindings::ffi::NCBOXGRAD_RIGHT;
|
||||
/// [NcBoxMask] bottom gradient mask.
|
||||
pub const NCBOXGRAD_BOTTOM: NcBoxMask = crate::bindings::ffi::NCBOXGRAD_BOTTOM;
|
||||
/// [NcBoxMask] left gradient mask.
|
||||
pub const NCBOXGRAD_LEFT: NcBoxMask = crate::bindings::ffi::NCBOXGRAD_LEFT;
|
||||
|
||||
/// [NcBoxMask] top border mask.
|
||||
pub const NCBOXMASK_TOP: NcBoxMask = crate::bindings::ffi::NCBOXMASK_TOP;
|
||||
/// [NcBoxMask] right border mask.
|
||||
pub const NCBOXMASK_RIGHT: NcBoxMask = crate::bindings::ffi::NCBOXMASK_RIGHT;
|
||||
/// [NcBoxMask] bottom border mask.
|
||||
pub const NCBOXMASK_BOTTOM: NcBoxMask = crate::bindings::ffi::NCBOXMASK_BOTTOM;
|
||||
/// [NcBoxMask] left border mask.
|
||||
pub const NCBOXMASK_LEFT: NcBoxMask = crate::bindings::ffi::NCBOXMASK_LEFT;
|
||||
|
||||
/// [NcBoxMask] corner mask to control the drawing of boxes corners.
|
||||
///
|
||||
/// By default, vertexes are drawn whether their connecting edges are drawn
|
||||
/// or not. The value of the bits control this, and are interpreted as the
|
||||
/// number of connecting edges necessary to draw a given corner.
|
||||
///
|
||||
/// At 0 (the default), corners are always drawn. At 3, corners are never drawn
|
||||
/// (since at most 2 edges can touch a box's corner).
|
||||
pub const NCBOXCORNER_MASK: NcBoxMask = crate::bindings::ffi::NCBOXCORNER_MASK;
|
||||
|
||||
/// The number of bits [NCBOXCORNER_MASK] is shifted in [NcBoxMask].
|
||||
pub const NCBOXCORNER_SHIFT: NcBoxMask = crate::bindings::ffi::NCBOXCORNER_SHIFT;
|
@ -1,26 +0,0 @@
|
||||
//! `NcCapabilities`
|
||||
|
||||
use crate::NcPalette;
|
||||
|
||||
use core::mem::size_of;
|
||||
|
||||
/// Capabilities, derived from terminfo, environment variables, and queries.
|
||||
pub type NcCapabilities = crate::bindings::ffi::nccapabilities;
|
||||
|
||||
/// Can we set the "hardware" palette?
|
||||
///
|
||||
/// Requires the "ccc" terminfo capability, and that the number of colors
|
||||
/// supported is at least the size of our `NcPalette` structure.
|
||||
#[inline]
|
||||
pub fn nccapability_canchangecolor(caps: &NcCapabilities) -> bool {
|
||||
if !caps.can_change_colors {
|
||||
return false;
|
||||
}
|
||||
// CHECK this does the same as:
|
||||
// if(caps.colors < sizeof(p->chans) / sizeof(*p->chans)){
|
||||
//
|
||||
if (caps.colors as usize) < size_of::<NcPalette>() / size_of::<u32>() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
@ -1,471 +0,0 @@
|
||||
//! `NcCell` methods and associated functions.
|
||||
|
||||
use crate::{
|
||||
cstring, error, nccell_load, NcAlphaBits, NcCell, NcChannels, NcComponent, NcEgcBackstop,
|
||||
NcPaletteIndex, NcPlane, NcResult, NcRgb, NcStyle, NCRESULT_ERR,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)] // for the doc comments
|
||||
use crate::NcChannel;
|
||||
|
||||
/// # NcCell constructors
|
||||
impl NcCell {
|
||||
/// New `NcCell`, expects a 7-bit [`char`].
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub const fn from_char7b(ch: char) -> Self {
|
||||
NcCell {
|
||||
gcluster: (ch as u32).to_le(),
|
||||
gcluster_backstop: 0 as NcEgcBackstop,
|
||||
width: 0_u8,
|
||||
stylemask: 0 as NcStyle,
|
||||
channels: 0 as NcChannels,
|
||||
}
|
||||
}
|
||||
|
||||
/// New `NcCell`, expects an [`NcPlane`] and a [`char`].
|
||||
#[inline]
|
||||
pub fn from_char(ch: char, plane: &mut NcPlane) -> Self {
|
||||
let mut cell = Self::new();
|
||||
let result = unsafe { nccell_load(plane, &mut cell, cstring![ch.to_string()]) };
|
||||
// TEMP solution for:
|
||||
// https://github.com/dankamongmen/notcurses/pull/1937/checks?check_run_id=3093152924#step:11:339
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
debug_assert_ne![NCRESULT_ERR, result];
|
||||
cell
|
||||
}
|
||||
|
||||
/// New `NcCell`, expects an [`NcPlane`] and a &[`str`].
|
||||
#[inline]
|
||||
pub fn from_str(plane: &mut NcPlane, string: &str) -> Self {
|
||||
let mut cell = Self::new();
|
||||
let result = unsafe { nccell_load(plane, &mut cell, cstring![string]) };
|
||||
debug_assert_ne![NCRESULT_ERR, result];
|
||||
cell
|
||||
}
|
||||
|
||||
/// New empty `NcCell`.
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
Self::from_char7b(0 as char)
|
||||
}
|
||||
|
||||
/// Breaks the UTF-8 string in `egc` down, setting up this `NcCell`,
|
||||
/// and returns the number of bytes copied out of `egc`.
|
||||
///
|
||||
/// The styling of the cell is left untouched, but any resources are released.
|
||||
/// *C style function: [nccell_load()][crate::nccell_load].*
|
||||
pub fn load(plane: &mut NcPlane, cell: &mut NcCell, egc: &str) -> NcResult<u32> {
|
||||
let bytes = unsafe { crate::nccell_load(plane, cell, cstring![egc]) };
|
||||
error![
|
||||
bytes,
|
||||
&format!["NcCell.load(NcPlane, NcCell, {:?})", egc],
|
||||
bytes as u32
|
||||
]
|
||||
}
|
||||
|
||||
/// Same as [load][NcCell#method.load], plus blasts the styling with
|
||||
/// `style` and `channels`.
|
||||
///
|
||||
/// - Breaks the UTF-8 string in `gcluster` down, setting up this NcCell.
|
||||
/// - Returns the number of bytes copied out of `gcluster`.
|
||||
/// - Any resources are released.
|
||||
/// - Blasts the styling with `style` and `channels`.
|
||||
///
|
||||
/// *C style function: [nccell_prime()][crate::nccell_prime].*
|
||||
pub fn prime(
|
||||
plane: &mut NcPlane,
|
||||
cell: &mut NcCell,
|
||||
gcluster: &str,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
) -> NcResult<u32> {
|
||||
let bytes = crate::nccell_prime(plane, cell, gcluster, style, channels);
|
||||
error![bytes, "", bytes as u32]
|
||||
}
|
||||
|
||||
/// Duplicate this `NcCell` into another one.
|
||||
///
|
||||
/// Both must be or will be bound to `common_plane`.
|
||||
///
|
||||
/// *C style function: [nccell_duplicate()][crate::nccell_duplicate].*
|
||||
pub fn duplicate(&self, target: &mut NcCell, common_plane: &mut NcPlane) -> NcResult<()> {
|
||||
error![unsafe { crate::nccell_duplicate(common_plane, target, self) }]
|
||||
}
|
||||
|
||||
/// Initializes (zeroes out) this `NcCell`.
|
||||
///
|
||||
/// *C style function: [nccell_init()][crate::nccell_init].*
|
||||
#[inline]
|
||||
pub fn init(&mut self) {
|
||||
crate::nccell_init(self);
|
||||
}
|
||||
|
||||
/// Releases resources held by the current cell in the [NcPlane] `plane`.
|
||||
///
|
||||
/// *C style function: [nccell_release()][crate::nccell_release].*
|
||||
pub fn release(&mut self, plane: &mut NcPlane) {
|
||||
unsafe {
|
||||
crate::nccell_release(plane, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/// ## NcCell methods: bg|fg `NcChannel`s manipulation.
|
||||
impl NcCell {
|
||||
/// Returns the [`NcChannels`] of this `NcCell`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn channels(&mut self, plane: &mut NcPlane) -> NcChannels {
|
||||
let (mut _styles, mut channels) = (0, 0);
|
||||
let _char = crate::nccell_extract(plane, self, &mut _styles, &mut channels);
|
||||
channels
|
||||
}
|
||||
|
||||
/// Extracts the background [`NcAlphaBits`] (shifted to LSBs).
|
||||
///
|
||||
/// *C style function: [nccell_bg_alpha()][crate::nccell_bg_alpha].*
|
||||
pub fn bg_alpha(&self) -> NcAlphaBits {
|
||||
crate::nccell_bg_alpha(self)
|
||||
}
|
||||
|
||||
/// Is the background [`NcChannel`] using the "default background color"?
|
||||
///
|
||||
/// *C style function: [nccell_bg_default_p()][crate::nccell_bg_default_p].*
|
||||
pub fn bg_default_p(&self) -> bool {
|
||||
crate::nccell_bg_default_p(self)
|
||||
}
|
||||
|
||||
/// Gets the [`NcPaletteIndex`] of the background [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [nccell_bg_palindex()][crate::nccell_bg_palindex].*
|
||||
pub fn bg_palindex(&self) -> NcPaletteIndex {
|
||||
crate::nccell_bg_palindex(self)
|
||||
}
|
||||
|
||||
/// Is the background [`NcChannel`] using an [`NcPaletteIndex`] indexed
|
||||
/// [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *C style function: [nccell_bg_palindex_p()][crate::nccell_bg_palindex_p].*
|
||||
pub fn bg_palindex_p(&self) -> bool {
|
||||
crate::nccell_bg_palindex_p(self)
|
||||
}
|
||||
|
||||
/// Gets the background [`NcRgb`] (shifted to LSBs).
|
||||
///
|
||||
/// *C style function: [nccell_bg_rgb()][crate::nccell_bg_rgb].*
|
||||
pub fn bg_rgb(&self) -> NcRgb {
|
||||
crate::nccell_bg_rgb(self)
|
||||
}
|
||||
|
||||
/// Gets the background RGB [`NcComponent`]s.
|
||||
///
|
||||
/// *C style function: [nccell_bg_rgb8()][crate::nccell_bg_rgb8].*
|
||||
pub fn bg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::nccell_bg_rgb8(self, &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Extracts the foreground [`NcAlphaBits`] (shifted to LSBs).
|
||||
///
|
||||
/// *C style function: [nccell_fg_alpha()][crate::nccell_fg_alpha].*
|
||||
pub fn fg_alpha(&self) -> NcAlphaBits {
|
||||
crate::nccell_fg_alpha(self)
|
||||
}
|
||||
|
||||
/// Is the foreground [`NcChannel`] using the "default foreground color"?
|
||||
///
|
||||
/// *C style function: [nccell_fg_default_p()][crate::nccell_fg_default_p].*
|
||||
pub fn fg_default_p(&self) -> bool {
|
||||
crate::nccell_fg_default_p(self)
|
||||
}
|
||||
|
||||
/// Gets the [`NcPaletteIndex`] of the foreground [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [nccell_fg_palindex()][crate::nccell_fg_palindex].*
|
||||
pub fn fg_palindex(&self) -> NcPaletteIndex {
|
||||
crate::nccell_fg_palindex(self)
|
||||
}
|
||||
|
||||
/// Is the foreground [`NcChannel`] using an [`NcPaletteIndex`] indexed
|
||||
/// [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *C style function: [nccell_fg_palindex_p()][crate::nccell_fg_palindex_p].*
|
||||
pub fn fg_palindex_p(&self) -> bool {
|
||||
crate::nccell_fg_palindex_p(self)
|
||||
}
|
||||
|
||||
/// Gets the foreground [`NcRgb`] (shifted to LSBs).
|
||||
///
|
||||
/// *C style function: [nccell_fg_rgb()][crate::nccell_fg_rgb].*
|
||||
pub fn fg_rgb(&self) -> NcRgb {
|
||||
crate::nccell_fg_rgb(self)
|
||||
}
|
||||
|
||||
/// Gets the foreground RGB [`NcComponent`]s.
|
||||
///
|
||||
/// *C style function: [nccell_fg_rgb8()][crate::nccell_fg_rgb8].*
|
||||
pub fn fg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::nccell_fg_rgb8(self, &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the background [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [nccell_set_bg_alpha()][crate::nccell_set_bg_alpha].*
|
||||
pub fn set_bg_alpha(&mut self, alpha: NcAlphaBits) {
|
||||
crate::nccell_set_bg_alpha(self, alpha);
|
||||
}
|
||||
|
||||
/// Indicates to use the "default color" for the background [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [nccell_set_bg_default()][crate::nccell_set_bg_default].*
|
||||
pub fn set_bg_default(&mut self) {
|
||||
crate::nccell_set_bg_default(self);
|
||||
}
|
||||
|
||||
/// Sets the background [`NcPaletteIndex`].
|
||||
///
|
||||
/// Also sets [NCALPHA_BG_PALETTE][crate::NCALPHA_BG_PALETTE] and
|
||||
/// [NCALPHA_OPAQUE][crate::NCALPHA_OPAQUE], and clears out
|
||||
/// [NCALPHA_BGDEFAULT_MASK][crate::NCALPHA_BGDEFAULT_MASK].
|
||||
///
|
||||
/// *C style function: [nccell_set_bg_palindex()][crate::nccell_set_bg_palindex].*
|
||||
pub fn set_bg_palindex(&mut self, index: NcPaletteIndex) {
|
||||
crate::nccell_set_bg_palindex(self, index);
|
||||
}
|
||||
|
||||
/// Sets the background [`NcRgb`] and marks it as not using the default color.
|
||||
///
|
||||
/// *C style function: [nccell_set_bg_rgb()][crate::nccell_set_bg_rgb].*
|
||||
pub fn set_bg_rgb(&mut self, rgb: NcRgb) {
|
||||
crate::nccell_set_bg_rgb(self, rgb);
|
||||
}
|
||||
|
||||
/// Sets the background RGB [`NcComponent`]s, and marks it as not using
|
||||
/// the "default color".
|
||||
///
|
||||
/// *C style function: [nccell_set_bg_rgb8()][crate::nccell_set_bg_rgb8].*
|
||||
pub fn set_bg_rgb8(&mut self, red: NcComponent, green: NcComponent, blue: NcComponent) {
|
||||
crate::nccell_set_bg_rgb8(self, red, green, blue);
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [nccell_set_fg_alpha()][crate::nccell_set_fg_alpha].*
|
||||
pub fn set_fg_alpha(&mut self, alpha: NcAlphaBits) {
|
||||
crate::nccell_set_fg_alpha(self, alpha);
|
||||
}
|
||||
|
||||
/// Indicates to use the "default color" for the foreground [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [nccell_set_fg_default()][crate::nccell_set_fg_default].*
|
||||
pub fn set_fg_default(&mut self) {
|
||||
crate::nccell_set_fg_default(self);
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcPaletteIndex`].
|
||||
///
|
||||
/// Also sets [NCALPHA_FG_PALETTE][crate::NCALPHA_FG_PALETTE] and
|
||||
/// [NCALPHA_OPAQUE][crate::NCALPHA_OPAQUE], and clears out
|
||||
/// [NCALPHA_BGDEFAULT_MASK][crate::NCALPHA_BGDEFAULT_MASK].
|
||||
///
|
||||
/// *C style function: [nccell_set_fg_palindex()][crate::nccell_set_fg_palindex].*
|
||||
pub fn set_fg_palindex(&mut self, index: NcPaletteIndex) {
|
||||
crate::nccell_set_fg_palindex(self, index);
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcRgb`] and marks it as not using the default color.
|
||||
///
|
||||
/// *C style function: [nccell_set_fg_rgb()][crate::nccell_set_fg_rgb].*
|
||||
pub fn set_fg_rgb(&mut self, rgb: NcRgb) {
|
||||
crate::nccell_set_fg_rgb(self, rgb);
|
||||
}
|
||||
|
||||
/// Sets the foreground RGB [`NcComponent`]s, and marks it as not using
|
||||
/// the "default color".
|
||||
///
|
||||
/// *C style function: [nccell_set_fg_rgb8()][crate::nccell_set_fg_rgb8].*
|
||||
pub fn set_fg_rgb8(&mut self, red: NcComponent, green: NcComponent, blue: NcComponent) {
|
||||
crate::nccell_set_fg_rgb8(self, red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcCell` methods: other components
|
||||
impl NcCell {
|
||||
/// Returns true if the two cells have distinct `EGC`s, attributes,
|
||||
/// or [`NcChannel`]s.
|
||||
///
|
||||
/// The actual egcpool index needn't be the same--indeed, the planes
|
||||
/// needn't even be the same. Only the expanded `EGC` must be bit-equal.
|
||||
///
|
||||
/// *C style function: [nccellcmp()][crate::nccellcmp].*
|
||||
pub fn compare(plane1: &NcPlane, cell1: &NcCell, plane2: &NcPlane, cell2: &NcCell) -> bool {
|
||||
crate::nccellcmp(plane1, cell1, plane2, cell2)
|
||||
}
|
||||
|
||||
/// Saves the [`NcStyle`] and the [`NcChannels`], and returns the `EGC`.
|
||||
/// (These are the three elements of an `NcCell`).
|
||||
///
|
||||
/// *C style function: [nccell_fg_alpha()][crate::nccell_fg_alpha].*
|
||||
pub fn extract(
|
||||
&mut self,
|
||||
plane: &mut NcPlane,
|
||||
styles: &mut NcStyle,
|
||||
channels: &mut NcChannels,
|
||||
) -> String {
|
||||
crate::nccell_extract(plane, self, styles, channels)
|
||||
}
|
||||
|
||||
/// Returns the `EGC` of the `NcCell`.
|
||||
///
|
||||
/// See also: [extended_gcluster][NcCell#method.extended_gcluster] method.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn egc(&mut self, plane: &mut NcPlane) -> String {
|
||||
let (mut _styles, mut _channels) = (0, 0);
|
||||
crate::nccell_extract(plane, self, &mut _styles, &mut _channels)
|
||||
}
|
||||
|
||||
/// Returns the [`NcStyle`] bits.
|
||||
///
|
||||
/// *C style function: [nccell_styles()][crate::nccell_styles].*
|
||||
pub fn styles(&mut self) -> NcStyle {
|
||||
crate::nccell_styles(self)
|
||||
}
|
||||
|
||||
/// Removes the specified [`NcStyle`] bits.
|
||||
///
|
||||
/// *C style function: [nccell_off_styles()][crate::nccell_off_styles].*
|
||||
pub fn styles_off(&mut self, stylebits: NcStyle) {
|
||||
crate::nccell_off_styles(self, stylebits)
|
||||
}
|
||||
|
||||
/// Adds the specified [`NcStyle`] bits.
|
||||
///
|
||||
/// *C style function: [nccell_on_styles()][crate::nccell_on_styles].*
|
||||
pub fn styles_on(&mut self, stylebits: NcStyle) {
|
||||
crate::nccell_on_styles(self, stylebits)
|
||||
}
|
||||
|
||||
/// Sets just the specified [`NcStyle`] bits.
|
||||
///
|
||||
/// *C style function: [nccell_set_styles()][crate::nccell_set_styles].*
|
||||
pub fn styles_set(&mut self, stylebits: NcStyle) {
|
||||
crate::nccell_set_styles(self, stylebits)
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcCell` methods: text
|
||||
impl NcCell {
|
||||
// /// Returns a pointer to the `EGC` of this NcCell in the [NcPlane] `plane`.
|
||||
// ///
|
||||
// /// This pointer can be invalidated by any further operation on the referred
|
||||
// /// plane, so… watch out!
|
||||
// ///
|
||||
// /// *C style function: [nccell_extended_gcluster()][crate::nccell_wide_left_p].*
|
||||
// pub fn extended_gcluster(&self, plane: &NcPlane) -> u32 {
|
||||
// let egcpointer = unsafe { crate::nccell_extended_gcluster(plane, self) };
|
||||
// egcpointer
|
||||
// }
|
||||
|
||||
/// Copies the UTF8-encoded `EGC` out of this NcCell,
|
||||
/// whether simple or complex.
|
||||
///
|
||||
/// The result is not tied to the [NcPlane],
|
||||
/// and persists across erases and destruction.
|
||||
///
|
||||
/// *C style function: [nccell_strdup()][crate::nccell_strdup].*
|
||||
pub fn strdup(&self, plane: &NcPlane) -> String {
|
||||
crate::nccell_strdup(plane, self)
|
||||
}
|
||||
|
||||
/// Does this NcCell contain a wide codepoint?
|
||||
///
|
||||
/// *C style function: [nccell_double_wide_p()][crate::nccell_double_wide_p].*
|
||||
pub fn double_wide_p(&self) -> bool {
|
||||
crate::nccell_double_wide_p(self)
|
||||
}
|
||||
|
||||
/// Is this the left half of a wide character?
|
||||
///
|
||||
/// *C style function: [nccell_wide_left_p()][crate::nccell_wide_left_p].*
|
||||
pub fn wide_left_p(&self) -> bool {
|
||||
crate::nccell_wide_right_p(self)
|
||||
}
|
||||
|
||||
/// Is this the right side of a wide character?
|
||||
///
|
||||
/// *C style function: [nccell_wide_right_p()][crate::nccell_wide_right_p].*
|
||||
pub fn wide_right_p(&self) -> bool {
|
||||
crate::nccell_wide_right_p(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcCell` methods: boxes
|
||||
impl NcCell {
|
||||
/// Loads up six cells with the `EGC`s necessary to draw a box.
|
||||
///
|
||||
/// On error, any [`NcCell`]s this function might have loaded before the error
|
||||
/// are [release][NcCell#method.release]d.
|
||||
/// There must be at least six `EGC`s in `gcluster`.
|
||||
///
|
||||
/// *C style function: [nccells_load_box()][crate::nccells_load_box].*
|
||||
pub fn load_box(
|
||||
plane: &mut NcPlane,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
ul: &mut NcCell,
|
||||
ur: &mut NcCell,
|
||||
ll: &mut NcCell,
|
||||
lr: &mut NcCell,
|
||||
hl: &mut NcCell,
|
||||
vl: &mut NcCell,
|
||||
gcluster: &str,
|
||||
) -> NcResult<()> {
|
||||
error![crate::nccells_load_box(
|
||||
plane, style, channels, ul, ur, ll, lr, hl, vl, gcluster
|
||||
)]
|
||||
}
|
||||
|
||||
/// NcCell.[load_box()][NcCell#method.box] with the double box-drawing characters.
|
||||
///
|
||||
/// *C style function: [nccells_double_box()][crate::nccells_double_box].*
|
||||
pub fn double_box(
|
||||
plane: &mut NcPlane,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
ul: &mut NcCell,
|
||||
ur: &mut NcCell,
|
||||
ll: &mut NcCell,
|
||||
lr: &mut NcCell,
|
||||
hl: &mut NcCell,
|
||||
vl: &mut NcCell,
|
||||
) -> NcResult<()> {
|
||||
error![unsafe {
|
||||
crate::nccells_double_box(plane, style as u32, channels, ul, ur, ll, lr, hl, vl)
|
||||
}]
|
||||
}
|
||||
|
||||
/// NcCell.[load_box()][NcCell#method.box] with the rounded box-drawing characters.
|
||||
///
|
||||
/// *C style function: [nccells_rounded_box()][crate::nccells_double_box].*
|
||||
pub fn rounded_box(
|
||||
plane: &mut NcPlane,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
ul: &mut NcCell,
|
||||
ur: &mut NcCell,
|
||||
ll: &mut NcCell,
|
||||
lr: &mut NcCell,
|
||||
hl: &mut NcCell,
|
||||
vl: &mut NcCell,
|
||||
) -> NcResult<()> {
|
||||
error![unsafe {
|
||||
crate::nccells_rounded_box(plane, style as u32, channels, ul, ur, ll, lr, hl, vl)
|
||||
}]
|
||||
}
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
//! `NcCell`
|
||||
|
||||
// functions already exported by bindgen : 7
|
||||
// -----------------------------------------
|
||||
// (W) wrap: 4
|
||||
// (#) test: 0
|
||||
// ------------------------------------------
|
||||
//… nccell_extended_gcluster
|
||||
//… nccell_load
|
||||
//W nccells_double_box
|
||||
//W nccells_rounded_box
|
||||
//W nccell_duplicate
|
||||
//W nccell_release
|
||||
//
|
||||
// functions manually reimplemented: 46
|
||||
// ------------------------------------------
|
||||
// (X) wont: 2
|
||||
// (+) done: 38
|
||||
// (W) wrap: 40
|
||||
// (#) test: 26
|
||||
// ------------------------------------------
|
||||
//W# nccell_bg_alpha
|
||||
//W# nccell_bg_default_p
|
||||
//W# nccell_bg_palindex
|
||||
//W# nccell_bg_palindex_p
|
||||
//W# nccell_bg_rgb
|
||||
//W# nccell_bg_rgb8
|
||||
// + nccell_cols
|
||||
//W+ nccell_double_wide_p
|
||||
//W+ nccell_extract
|
||||
//W# nccell_fchannel
|
||||
//W# nccell_fg_alpha
|
||||
//W# nccell_fg_default_p
|
||||
//W# nccell_fg_palindex
|
||||
//W# nccell_fg_palindex_p
|
||||
//W# nccell_fg_rgb
|
||||
//W# nccell_fg_rgb8
|
||||
//W+ nccell_init
|
||||
//…… nccell_load_char
|
||||
// nccell_load_egc32
|
||||
//W+ nccell_off_styles
|
||||
//W+ nccell_on_styles
|
||||
//W+ nccell_prime
|
||||
//W# nccell_set_bchannel
|
||||
//W# nccell_set_bg_alpha
|
||||
//W# nccell_set_bg_default
|
||||
//W# nccell_set_bg_palindex
|
||||
//W# nccell_set_bg_rgb
|
||||
//W# nccell_set_bg_rgb8
|
||||
// X nccell_set_bg_rgb8_clipped // unneeded
|
||||
//W# nccell_set_fchannel
|
||||
//W# nccell_set_fg_alpha
|
||||
//W# nccell_set_fg_default
|
||||
//W# nccell_set_fg_palindex
|
||||
//W# nccell_set_fg_rgb
|
||||
//W# nccell_set_fg_rgb8
|
||||
// X nccell_set_fg_rgb8_clipped // unneeded
|
||||
//W+ nccell_set_styles
|
||||
//W+ nccell_strdup
|
||||
//W+ nccell_styles
|
||||
//W+ nccell_wide_left_p
|
||||
//W+ nccell_wide_right_p
|
||||
//W+ nccellcmp
|
||||
// nccells_ascii_box
|
||||
// nccells_heavy_box
|
||||
// nccells_light_box
|
||||
//W+ nccells_load_box
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
pub use reimplemented::*;
|
||||
|
||||
#[allow(unused_imports)] // TEMP
|
||||
use crate::{NcChannel, NcPlane};
|
||||
|
||||
// NcCell
|
||||
/// A coordinate on an [`NcPlane`][crate::NcPlane] storing 128 bits of data.
|
||||
///
|
||||
/// # Methods & Associated Functions
|
||||
///
|
||||
/// - [Constructors & Destructors](#nccell-constructors-and-destructors)
|
||||
///
|
||||
/// - [bg|fg `NcChannel`s manipulation](#nccell-methods-bgfg-ncchannels-manipulation)
|
||||
/// - [Other components](#nccell-methods-other-components)
|
||||
/// - [Text](#nccell-methods-text)
|
||||
///
|
||||
/// # Description
|
||||
///
|
||||
/// An `NcCell` corresponds to a single character cell on some `NcPlane`,
|
||||
/// which can be occupied by a single `EGC` grapheme cluster (some root
|
||||
/// spacing glyph, along with possible combining characters, which might span
|
||||
/// multiple columns).
|
||||
///
|
||||
/// An NcCell is bounded to an `NcPlane`, but the cell doesn't store anything
|
||||
/// about the plane.
|
||||
///
|
||||
/// At any `NcCell`, we can have a theoretically arbitrarily long UTF-8 string,
|
||||
/// a foreground color, a background color, and an [`NcStyle`] attribute set.
|
||||
///
|
||||
/// Valid grapheme cluster contents include:
|
||||
///
|
||||
/// - A NUL terminator,
|
||||
/// - A single [control character](https://en.wikipedia.org/wiki/Control_character),
|
||||
/// followed by a NUL terminator,
|
||||
/// - At most one [spacing
|
||||
/// character](https://en.wikipedia.org/wiki/Graphic_character#Spacing_character),
|
||||
/// followed by zero or more nonspacing characters, followed by a NUL terminator.
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// NcCell: 128 bits structure comprised of the following 5 elements:
|
||||
///
|
||||
/// GCLUSTER|GCLUSTER|GCLUSTER|GCLUSTER 1. `EGC`
|
||||
/// 00000000║WWWWWWWW║11111111|11111111 2. NcEgcBackstop + 3. width + 4. NcStyle
|
||||
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB 5. NcChannels
|
||||
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB "
|
||||
///
|
||||
/// 1. (32b) Extended Grapheme Cluster, presented either as:
|
||||
///
|
||||
/// 1.1. An EGC of up to 4 bytes:
|
||||
/// UUUUUUUU|UUUUUUUU|UUUUUUUU|UUUUUUUU
|
||||
///
|
||||
/// 1.2. A `0x01` in the first byte, plus 3 bytes with a 24b address to an egcpool:
|
||||
/// 00000001|IIIIIIII|IIIIIIII|IIIIIIII
|
||||
///
|
||||
/// 2. (8b) Backstop (zero)
|
||||
/// 00000000
|
||||
///
|
||||
/// 3. (8b) column width
|
||||
/// WWWWWWWW
|
||||
///
|
||||
/// 4. (16b) NcStyle
|
||||
/// 11111111 11111111
|
||||
///
|
||||
/// 5. (64b) NcChannels
|
||||
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB║~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
|
||||
/// ```
|
||||
///
|
||||
/// `type in C: cell (struct)`
|
||||
///
|
||||
/// # More NcCell Information
|
||||
///
|
||||
/// ## Size
|
||||
///
|
||||
/// Multi-column characters can only have a single style/color throughout.
|
||||
/// [`wcwidth()`](https://www.man7.org/linux/man-pages/man3/wcwidth.3.html)
|
||||
/// is not reliable. It's just quoting whether or not the `EGC`
|
||||
/// contains a "Wide Asian" double-width character.
|
||||
/// This is set for some things, like most emoji, and not set for
|
||||
/// other things, like cuneiform.
|
||||
///
|
||||
/// Each cell occupies 16 static bytes (128 bits). The surface is thus ~1.6MB
|
||||
/// for a (pretty large) 500x200 terminal. At 80x43, it's less than 64KB.
|
||||
/// Dynamic requirements (the egcpool) can add up to 16MB to an ncplane, but
|
||||
/// such large pools are unlikely in common use.
|
||||
///
|
||||
/// ## Alpha Compositing
|
||||
///
|
||||
/// We implement some small alpha compositing. Foreground and background both
|
||||
/// have two bits of inverted alpha. The actual grapheme written to a cell is
|
||||
/// the topmost non-zero grapheme.
|
||||
///
|
||||
/// - If its alpha is 00 ([`NCALPHA_OPAQUE`][crate::NCALPHA_OPAQUE])
|
||||
/// its foreground color is used unchanged.
|
||||
///
|
||||
/// - If its alpha is 10 ([`NCALPHA_TRANSPARENT`][crate::NCALPHA_TRANSPARENT])
|
||||
/// its foreground color is derived
|
||||
/// entirely from cells underneath it.
|
||||
///
|
||||
/// - If its alpha is 01 ([`NCALPHA_BLEND`][crate::NCALPHA_BLEND])
|
||||
/// the result will be a composite.
|
||||
///
|
||||
/// Likewise for the background. If the bottom of a coordinate's zbuffer is
|
||||
/// reached with a cumulative alpha of zero, the default is used. In this way,
|
||||
/// a terminal configured with transparent background can be supported through
|
||||
/// multiple occluding ncplanes.
|
||||
///
|
||||
/// A foreground alpha of 11
|
||||
/// ([`NCALPHA_HIGHCONTRAST`][crate::NCALPHA_HIGHCONTRAST])
|
||||
/// requests high-contrast text (relative to the computed background).
|
||||
/// A background alpha of 11 is currently forbidden.
|
||||
///
|
||||
/// ## Precedence
|
||||
///
|
||||
/// - Default color takes precedence over palette or RGB, and cannot be used with
|
||||
/// transparency.
|
||||
/// - Indexed palette takes precedence over RGB. It cannot meaningfully set
|
||||
/// transparency, but it can be mixed into a cascading color.
|
||||
/// - RGB is used if neither default terminal colors nor palette indexing are in
|
||||
/// play, and fully supports all transparency options.
|
||||
///
|
||||
/// ## Column width *(WIP)*
|
||||
///
|
||||
/// See [USAGE.md](https://github.com/dankamongmen/notcurses/blob/master/USAGE.md)
|
||||
///
|
||||
/// We store the column width in this field. for a multicolumn EGC of N
|
||||
/// columns, there will be N nccells, and each has a width of N...for now.
|
||||
/// eventually, such an EGC will set more than one subsequent cell to
|
||||
/// WIDE_RIGHT, and this won't be necessary. it can then be used as a
|
||||
/// bytecount. see #1203. FIXME iff width >= 2, the cell is part of a
|
||||
/// multicolumn glyph. whether a cell is the left or right side of the glyph
|
||||
/// can be determined by checking whether ->gcluster is zero.
|
||||
///
|
||||
pub type NcCell = crate::bindings::ffi::nccell;
|
||||
|
||||
// RETHINK:
|
||||
//
|
||||
// NcEgc
|
||||
//
|
||||
// /// Extended Grapheme Cluster. A unicode string of length 1.
|
||||
// ///
|
||||
// /// This 32 bit char, together with the associated plane's associated egcpool,
|
||||
// /// completely define this cell's `NcEgc`. Unless the `NcEgc` requires more than
|
||||
// /// four bytes to encode as UTF-8, it will be inlined here:
|
||||
// ///
|
||||
// /// ## Diagram 1
|
||||
// ///
|
||||
// /// ```txt
|
||||
// /// UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
|
||||
// /// extended grapheme cluster <= 4bytes
|
||||
// /// ```
|
||||
// ///
|
||||
// /// `type in C: uint32_t`
|
||||
// ///
|
||||
// /// If more than four bytes are required, it will be spilled into the egcpool.
|
||||
// /// In either case, there's a NUL-terminated string available without copying,
|
||||
// /// because (1) the egcpool is all NUL-terminated sequences and (2) the fifth
|
||||
// /// byte of this struct (the GClusterBackStop field, see below) is
|
||||
// /// guaranteed to be zero, as are any unused bytes in gcluster.
|
||||
// ///
|
||||
// /// A spilled `NcEgc` is indicated by the value `0x01iiiiii`. This cannot alias a
|
||||
// /// true supra-ASCII NcEgc, because UTF-8 only encodes bytes <= 0x80 when they
|
||||
// /// are single-byte ASCII-derived values. The `iiiiii` is interpreted as a 24-bit
|
||||
// /// index into the egcpool (which may thus be up to 16MB):
|
||||
// ///
|
||||
// /// ## Diagram 2
|
||||
// ///
|
||||
// /// ```txt
|
||||
// /// 00000001 iiiiiiii iiiiiiii iiiiiiii
|
||||
// /// sign 24bit index to egcpool
|
||||
// /// ```
|
||||
// /// `type in C: uint32_t`
|
||||
// ///
|
||||
// /// The cost of this scheme is that the character 0x01 (`SOH`) cannot be encoded
|
||||
// /// in a cell, and therefore it must not be allowed through the API.
|
||||
// ///
|
||||
// /// -----
|
||||
// /// Note that even if the `NcEgc` is <= 4 bytes and inlined, is still interpreted as
|
||||
// /// a NUL-terminated char * (technically, &cell->gcluster is treated as a char*).
|
||||
// /// If it is more than 4 bytes, cell->gcluster has a first byte of 0x01,
|
||||
// /// and the remaining 24 bits are an index into the plane's egcpool,
|
||||
// /// which is carved into NUL-terminated chunks of arbitrary length.
|
||||
// ///
|
||||
// /// ## Links
|
||||
// ///
|
||||
// /// - [Grapheme Cluster
|
||||
// /// Boundaries](https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
|
||||
// ///
|
||||
// ///
|
||||
// FIXME: should be an utf-8 string len 1 of type &str.
|
||||
// pub type NcEgc = String;
|
||||
// pub type NcEgc<'a> = &'a str;
|
||||
|
||||
// NcEgcBackStop
|
||||
/// An `u8` always at zero, part of the [`NcCell`] struct
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// 00000000
|
||||
/// ```
|
||||
///
|
||||
/// `type in C: uint_8t`
|
||||
///
|
||||
pub type NcEgcBackstop = u8;
|
||||
|
||||
// NcStyle
|
||||
///
|
||||
/// An `u16` of `NCSTYLE_*` boolean styling attribute flags
|
||||
///
|
||||
/// ## Attributes
|
||||
///
|
||||
/// - [`NCSTYLE_MASK`]
|
||||
/// - [`NCSTYLE_ITALIC`]
|
||||
/// - [`NCSTYLE_UNDERLINE`]
|
||||
/// - [`NCSTYLE_UNDERCURL`]
|
||||
/// - [`NCSTYLE_STRUCK`]
|
||||
/// - [`NCSTYLE_BOLD`]
|
||||
/// - [`NCSTYLE_NONE`]
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// 11111111 11111111
|
||||
/// ```
|
||||
///
|
||||
/// `type in C: uint16_t`
|
||||
///
|
||||
pub type NcStyle = u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_MASK: u16 = crate::bindings::ffi::NCSTYLE_MASK as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_ITALIC: u16 = crate::bindings::ffi::NCSTYLE_ITALIC as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_UNDERLINE: u16 = crate::bindings::ffi::NCSTYLE_UNDERLINE as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_UNDERCURL: u16 = crate::bindings::ffi::NCSTYLE_UNDERCURL as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_STRUCK: u16 = crate::bindings::ffi::NCSTYLE_STRUCK as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_BOLD: u16 = crate::bindings::ffi::NCSTYLE_BOLD as u16;
|
||||
|
||||
///
|
||||
pub const NCSTYLE_NONE: u16 = crate::bindings::ffi::NCSTYLE_NONE as u16;
|
||||
|
||||
/// Enables the [`NcStyle`] methods.
|
||||
pub trait NcStyleMethods {
|
||||
fn add(&mut self, other_style: NcStyle);
|
||||
fn has(&self, other: NcStyle) -> bool;
|
||||
fn to_vec(&self) -> Vec<NcStyle>;
|
||||
}
|
||||
|
||||
impl NcStyleMethods for NcStyle {
|
||||
/// Returns a `Vec` with all the styles contained in the current style.
|
||||
fn to_vec(&self) -> Vec<NcStyle> {
|
||||
let mut v = vec![];
|
||||
let styles = [
|
||||
NCSTYLE_ITALIC,
|
||||
NCSTYLE_UNDERLINE,
|
||||
NCSTYLE_UNDERCURL,
|
||||
NCSTYLE_STRUCK,
|
||||
NCSTYLE_BOLD,
|
||||
NCSTYLE_NONE,
|
||||
];
|
||||
for s in &styles {
|
||||
if self.has(*s) {
|
||||
v.push(*s)
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
/// Returns true if the current style has included the `other_style`.
|
||||
fn has(&self, other_style: NcStyle) -> bool {
|
||||
(self & other_style) == other_style
|
||||
}
|
||||
|
||||
/// Adds the `other_style` to the current style.
|
||||
fn add(&mut self, other_style: NcStyle) {
|
||||
*self |= other_style
|
||||
}
|
||||
}
|
@ -1,532 +0,0 @@
|
||||
//! `cell*_*` reimplemented functions.
|
||||
|
||||
use libc::strcmp;
|
||||
|
||||
use crate::{
|
||||
cstring, nccell_release, rstring, NcAlphaBits, NcCell, NcChannel, NcChannels, NcComponent,
|
||||
NcIntResult, NcPaletteIndex, NcPlane, NcRgb, NcStyle, NCALPHA_BGDEFAULT_MASK,
|
||||
NCALPHA_BG_PALETTE, NCALPHA_FGDEFAULT_MASK, NCALPHA_FG_PALETTE, NCALPHA_OPAQUE, NCRESULT_ERR,
|
||||
NCRESULT_OK, NCSTYLE_MASK,
|
||||
};
|
||||
|
||||
// Alpha -----------------------------------------------------------------------
|
||||
|
||||
/// Extracts the foreground [`NcAlphaBits`] from an [`NcCell`] (shifted to LSBs).
|
||||
///
|
||||
/// *Method: NcCell.[fg_alpha()][NcCell#method.fg_alpha].*
|
||||
#[inline]
|
||||
pub fn nccell_fg_alpha(cell: &NcCell) -> NcAlphaBits {
|
||||
crate::ncchannels_fg_alpha(cell.channels)
|
||||
}
|
||||
|
||||
/// Extracts the background [`NcAlphaBits`] from an [`NcCell`] (shifted to LSBs).
|
||||
///
|
||||
/// *Method: NcCell.[bg_alpha()][NcCell#method.bg_alpha].*
|
||||
#[inline]
|
||||
pub fn nccell_bg_alpha(cell: &NcCell) -> NcAlphaBits {
|
||||
crate::ncchannels_bg_alpha(cell.channels)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcAlphaBits`] of an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[set_fg_alpha()][NcCell#method.set_fg_alpha].*
|
||||
#[inline]
|
||||
pub fn nccell_set_fg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
|
||||
crate::ncchannels_set_fg_alpha(&mut cell.channels, alpha);
|
||||
}
|
||||
|
||||
/// Sets the background [`NcAlphaBits`] of an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[set_bg_alpha()][NcCell#method.set_bg_alpha].*
|
||||
#[inline]
|
||||
pub fn nccell_set_bg_alpha(cell: &mut NcCell, alpha: NcAlphaBits) {
|
||||
crate::ncchannels_set_bg_alpha(&mut cell.channels, alpha);
|
||||
}
|
||||
|
||||
// NcComponent ---------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [`NcComponent`]s of an [`NcCell`],
|
||||
/// and returns the [`NcChannel`] (which can have some extra bits set).
|
||||
///
|
||||
/// *Method: NcCell.[fg_rgb8()][NcCell#method.fg_rgb8].*
|
||||
#[inline]
|
||||
pub fn nccell_fg_rgb8(
|
||||
cell: &NcCell,
|
||||
red: &mut NcComponent,
|
||||
green: &mut NcComponent,
|
||||
blue: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
crate::ncchannels_fg_rgb8(cell.channels, red, green, blue)
|
||||
}
|
||||
|
||||
/// Gets the background [`NcComponent`]s of an [`NcCell`],
|
||||
/// and returns the [`NcChannel`] (which can have some extra bits set).
|
||||
///
|
||||
/// *Method: NcCell.[bg_rgb8()][NcCell#method.bg_rgb8].*
|
||||
#[inline]
|
||||
pub fn nccell_bg_rgb8(
|
||||
cell: &NcCell,
|
||||
red: &mut NcComponent,
|
||||
green: &mut NcComponent,
|
||||
blue: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
crate::ncchannels_bg_rgb8(cell.channels, red, green, blue)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcComponent`]s of the [`NcCell`],
|
||||
/// and marks it as not using the "default color".
|
||||
///
|
||||
/// *Method: NcCell.[set_fg_rgb8()][NcCell#method.set_fg_rgb8].*
|
||||
#[inline]
|
||||
pub fn nccell_set_fg_rgb8(
|
||||
cell: &mut NcCell,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) {
|
||||
crate::ncchannels_set_fg_rgb8(&mut cell.channels, red, green, blue);
|
||||
}
|
||||
|
||||
/// Sets the background [`NcComponent`]s of the [`NcCell`],
|
||||
/// and marks it as not using the "default color".
|
||||
///
|
||||
/// *Method: NcCell.[set_bg_rgb8()][NcCell#method.set_bg_rgb8].*
|
||||
#[inline]
|
||||
pub fn nccell_set_bg_rgb8(
|
||||
cell: &mut NcCell,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) {
|
||||
crate::ncchannels_set_bg_rgb8(&mut cell.channels, red, green, blue);
|
||||
}
|
||||
|
||||
// NcRgb -----------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [`NcRgb`] from an [`NcCell`] (shifted to LSBs).
|
||||
///
|
||||
/// *Method: NcCell.[fg_rgb()][NcCell#method.fg_rgb].*
|
||||
#[inline]
|
||||
pub fn nccell_fg_rgb(cell: &NcCell) -> NcRgb {
|
||||
crate::ncchannels_fg_rgb(cell.channels)
|
||||
}
|
||||
|
||||
/// Gets the background [`NcRgb`] from an [`NcCell`] (shifted to LSBs).
|
||||
///
|
||||
/// *Method: NcCell.[bg_rgb()][NcCell#method.bg_rgb].*
|
||||
#[inline]
|
||||
pub fn nccell_bg_rgb(cell: &NcCell) -> NcRgb {
|
||||
crate::ncchannels_bg_rgb(cell.channels)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcRgb`] of an [`NcCell`],
|
||||
/// and marks it as not using the default color.
|
||||
///
|
||||
/// *Method: NcCell.[set_fg_rgb()][NcCell#method.set_fg_rgb].*
|
||||
#[inline]
|
||||
pub fn nccell_set_fg_rgb(cell: &mut NcCell, rgb: NcRgb) {
|
||||
crate::ncchannels_set_fg_rgb(&mut cell.channels, rgb);
|
||||
}
|
||||
|
||||
/// Sets the background [`NcRgb`] of an [`NcCell`],
|
||||
/// and marks it as not using the default color.
|
||||
///
|
||||
/// *Method: NcCell.[set_bg_rgb()][NcCell#method.set_bg_rgb].*
|
||||
#[inline]
|
||||
pub fn nccell_set_bg_rgb(cell: &mut NcCell, rgb: NcRgb) {
|
||||
crate::ncchannels_set_bg_rgb(&mut cell.channels, rgb);
|
||||
}
|
||||
|
||||
// Default ---------------------------------------------------------------------
|
||||
|
||||
/// Indicates to use the "default color" for the foreground [`NcChannel`]
|
||||
/// of an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[set_fg_default()][NcCell#method.set_fg_default].*
|
||||
#[inline]
|
||||
pub fn nccell_set_fg_default(cell: &mut NcCell) {
|
||||
crate::ncchannels_set_fg_default(&mut cell.channels);
|
||||
}
|
||||
|
||||
/// Indicates to use the "default color" for the background [`NcChannel`]
|
||||
/// of an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[set_bg_default()][NcCell#method.set_bg_default].*
|
||||
#[inline]
|
||||
pub fn nccell_set_bg_default(cell: &mut NcCell) {
|
||||
crate::ncchannels_set_bg_default(&mut cell.channels);
|
||||
}
|
||||
|
||||
/// Is the foreground [`NcChannel`] of this [`NcCell`] using the
|
||||
/// "default foreground color"?
|
||||
///
|
||||
/// *Method: NcCell.[fg_default_p()][NcCell#method.fg_default_p].*
|
||||
#[inline]
|
||||
pub fn nccell_fg_default_p(cell: &NcCell) -> bool {
|
||||
crate::ncchannels_fg_default_p(cell.channels)
|
||||
}
|
||||
|
||||
/// Is the background [`NcChannel`] of this [`NcCell`] using the
|
||||
/// "default background color"?
|
||||
///
|
||||
/// The "default background color" must generally be used to take advantage of
|
||||
/// terminal-effected transparency.
|
||||
///
|
||||
/// *Method: NcCell.[bg_default_p()][NcCell#method.bg_default_p].*
|
||||
#[inline]
|
||||
pub fn nccell_bg_default_p(cell: &NcCell) -> bool {
|
||||
crate::ncchannels_bg_default_p(cell.channels)
|
||||
}
|
||||
|
||||
// Palette ---------------------------------------------------------------------
|
||||
|
||||
/// Is the foreground [`NcChannel`] of this [`NcCell`] using an
|
||||
/// [`NcPaletteIndex`] indexed [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *Method: NcCell.[fg_palindex_p()][NcCell#method.fg_palindex_p].*
|
||||
#[inline]
|
||||
pub fn nccell_fg_palindex_p(cell: &NcCell) -> bool {
|
||||
crate::ncchannels_fg_palindex_p(cell.channels)
|
||||
}
|
||||
|
||||
/// Is the background [`NcChannel`] of this [`NcCell`] using an
|
||||
/// [`NcPaletteIndex`] indexed [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *Method: NcCell.[bg_palindex_p()][NcCell#method.bg_palindex_p].*
|
||||
#[inline]
|
||||
pub fn nccell_bg_palindex_p(cell: &NcCell) -> bool {
|
||||
crate::ncchannels_bg_palindex_p(cell.channels)
|
||||
}
|
||||
|
||||
/// Gets the [`NcPaletteIndex`] of the foreground [`NcChannel`] of the [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[fg_palindex()][NcCell#method.fg_palindex].*
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub const fn nccell_fg_palindex(cell: &NcCell) -> NcPaletteIndex {
|
||||
((cell.channels & 0xff00000000 as NcChannels) >> 32) as NcPaletteIndex
|
||||
}
|
||||
|
||||
/// Gets the [`NcPaletteIndex`] of the background [`NcChannel`] of the [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[bg_palindex()][NcCell#method.bg_palindex].*
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub const fn nccell_bg_palindex(cell: &NcCell) -> NcPaletteIndex {
|
||||
(cell.channels & 0xff) as NcPaletteIndex
|
||||
}
|
||||
|
||||
/// Sets an [`NcCell`]'s foreground [`NcPaletteIndex`].
|
||||
///
|
||||
/// Also sets [NCALPHA_FG_PALETTE] and [NCALPHA_OPAQUE],
|
||||
/// and clears out [NCALPHA_FGDEFAULT_MASK].
|
||||
///
|
||||
/// *Method: NcCell.[set_fg_palindex()][NcCell#method.set_fg_palindex].*
|
||||
//
|
||||
// NOTE: unlike the original C function, this one can't fail
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub fn nccell_set_fg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
|
||||
cell.channels |= NCALPHA_FGDEFAULT_MASK;
|
||||
cell.channels |= NCALPHA_FG_PALETTE;
|
||||
nccell_set_fg_alpha(cell, NCALPHA_OPAQUE);
|
||||
cell.channels &= 0xff000000ffffffff as NcChannels;
|
||||
cell.channels |= (index as NcChannels) << 32;
|
||||
}
|
||||
|
||||
/// Sets an [`NcCell`]'s background [`NcPaletteIndex`].
|
||||
///
|
||||
/// Also sets [`NCALPHA_BG_PALETTE`] and [`NCALPHA_OPAQUE`],
|
||||
/// and clears out [`NCALPHA_BGDEFAULT_MASK`].
|
||||
///
|
||||
/// *Method: NcCell.[set_bg_palindex()][NcCell#method.set_bg_palindex].*
|
||||
//
|
||||
// NOTE: unlike the original C function, this one can't fail
|
||||
#[inline]
|
||||
pub fn nccell_set_bg_palindex(cell: &mut NcCell, index: NcPaletteIndex) {
|
||||
cell.channels |= NCALPHA_BGDEFAULT_MASK as NcChannels;
|
||||
cell.channels |= NCALPHA_BG_PALETTE as NcChannels;
|
||||
nccell_set_bg_alpha(cell, NCALPHA_OPAQUE);
|
||||
cell.channels &= 0xffffffffff000000;
|
||||
cell.channels |= index as NcChannels;
|
||||
}
|
||||
|
||||
// Styles ----------------------------------------------------------------------
|
||||
|
||||
/// Extracts the [`NcStyle`] bits from an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[cell_styles()][NcCell#method.cell_styles].*
|
||||
#[inline]
|
||||
pub const fn nccell_styles(cell: &NcCell) -> NcStyle {
|
||||
cell.stylemask
|
||||
}
|
||||
|
||||
/// Adds the specified [`NcStyle`] bits to an [`NcCell`]'s existing spec.,
|
||||
/// whether they're actively supported or not.
|
||||
///
|
||||
/// *Method: NcCell.[styles_on()][NcCell#method.styles_on].*
|
||||
#[inline]
|
||||
pub fn nccell_on_styles(cell: &mut NcCell, stylebits: NcStyle) {
|
||||
cell.stylemask |= stylebits & NCSTYLE_MASK as u16;
|
||||
}
|
||||
|
||||
/// Removes the specified [`NcStyle`] bits from an [`NcCell`]'s existing spec.
|
||||
///
|
||||
/// *Method: NcCell.[styles_off()][NcCell#method.styles_off].*
|
||||
#[inline]
|
||||
pub fn nccell_off_styles(cell: &mut NcCell, stylebits: NcStyle) {
|
||||
cell.stylemask &= !(stylebits & NCSTYLE_MASK as u16);
|
||||
}
|
||||
|
||||
/// Sets *just* the specified [`NcStyle`] bits for an [`NcCell`],
|
||||
/// whether they're actively supported or not.
|
||||
///
|
||||
/// *Method: NcCell.[styles_set()][NcCell#method.styles_set].*
|
||||
#[inline]
|
||||
pub fn nccell_set_styles(cell: &mut NcCell, stylebits: NcStyle) {
|
||||
cell.stylemask = stylebits & NCSTYLE_MASK as u16;
|
||||
}
|
||||
|
||||
// Chars -----------------------------------------------------------------------
|
||||
|
||||
/// Returns the number of columns occupied by 'c'. see ncstrwidth() for an
|
||||
/// equivalent for multiple EGCs.
|
||||
#[inline]
|
||||
pub const fn nccell_cols(cell: &NcCell) -> u8 {
|
||||
if cell.width != 0 {
|
||||
cell.width
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn nccell_width(plane: &NcPlane, cell: &NcCell) -> NcIntResult {
|
||||
unsafe { crate::ffi::nccell_width(plane, cell) }
|
||||
}
|
||||
|
||||
/// Does the [`NcCell`] contain an East Asian Wide codepoint?
|
||||
///
|
||||
/// *Method: NcCell.[double_wide_p()][NcCell#method.double_wide_p].*
|
||||
#[inline]
|
||||
pub const fn nccell_double_wide_p(cell: &NcCell) -> bool {
|
||||
cell.width > 0
|
||||
}
|
||||
|
||||
/// Is this the right half of a wide character?
|
||||
///
|
||||
/// *Method: NcCell.[wide_right_p()][NcCell#method.wide_right_p].*
|
||||
#[inline]
|
||||
pub const fn nccell_wide_right_p(cell: &NcCell) -> bool {
|
||||
nccell_double_wide_p(cell) && cell.gcluster == 0
|
||||
}
|
||||
|
||||
/// Is this the left half of a wide character?
|
||||
///
|
||||
/// *Method: NcCell.[wide_left_p()][NcCell#method.wide_left_p].*
|
||||
#[inline]
|
||||
pub const fn nccell_wide_left_p(cell: &NcCell) -> bool {
|
||||
nccell_double_wide_p(cell) && cell.gcluster != 0
|
||||
}
|
||||
|
||||
// /// Loads a 7-bit `EGC` character into the [`NcCell`].
|
||||
// ///
|
||||
// /// *Method: NcCell.[load_char()][NcCell#method.load_char].*
|
||||
// //
|
||||
// // TODO:CHECK is this necessary at all?
|
||||
// #[inline]
|
||||
// pub fn nccell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: char) /* -> i32 */
|
||||
// {
|
||||
// let _ = unsafe { crate::nccell_load(plane, cell, ch) };
|
||||
// }
|
||||
// nccell_load_char(struct ncplane* n, nccell* c, char ch){
|
||||
// char gcluster[2];
|
||||
// gcluster[0] = ch;
|
||||
// gcluster[1] = '\0';
|
||||
// let _ = nccell_load(n, c, gcluster);
|
||||
// }
|
||||
|
||||
// /// Loads a UTF-8 grapheme cluster of up to 4 bytes into the cell `c`.
|
||||
// ///
|
||||
// /// *Method: NcCell.[load_egc32()][NcCell#method.load_egc32].*
|
||||
// //
|
||||
// // TODO
|
||||
// #[inline]
|
||||
// pub fn nccell_load_egc32(plane: &mut NcPlane, cell: &mut NcCell, egc: &str) -> NcIntResult {
|
||||
// char gcluster[sizeof(egc) + 1];
|
||||
// egc = egc.to_le();
|
||||
// memcpy(gcluster, &egc, sizeof(egc));
|
||||
// gcluster[4] = '\0';
|
||||
// return nccell_load(n, c, gcluster);
|
||||
// }
|
||||
// // Load a UTF-8 encoded EGC of up to 4 bytes into the nccell 'c'. Returns the
|
||||
// // number of bytes used, or -1 on error.
|
||||
// static inline int
|
||||
// nccell_load_egc32(struct ncplane* n, nccell* c, uint32_t egc){
|
||||
// char gcluster[sizeof(egc) + 1];
|
||||
// egc = htole(egc);
|
||||
// memcpy(gcluster, &egc, sizeof(egc));
|
||||
// gcluster[4] = '\0';
|
||||
// return nccell_load(n, c, gcluster);
|
||||
// }
|
||||
|
||||
/// Copies the UTF8-encoded `EGC` out of the [`NcCell`], whether simple or complex.
|
||||
///
|
||||
/// The result is not tied to the [NcPlane],
|
||||
/// and persists across erases and destruction.
|
||||
///
|
||||
/// *Method: NcCell.[strdup()][NcCell#method.strdup].*
|
||||
#[inline]
|
||||
pub fn nccell_strdup(plane: &NcPlane, cell: &NcCell) -> String {
|
||||
rstring![libc::strdup(crate::nccell_extended_gcluster(plane, cell))].into()
|
||||
}
|
||||
|
||||
// Misc. -----------------------------------------------------------------------
|
||||
|
||||
/// Saves the [`NcStyle`] and the [`NcChannels`],
|
||||
/// and returns the `EGC`, of an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[extract()][NcCell#method.extract].*
|
||||
#[inline]
|
||||
pub fn nccell_extract(
|
||||
plane: &NcPlane,
|
||||
cell: &NcCell,
|
||||
stylemask: &mut NcStyle,
|
||||
channels: &mut NcChannels,
|
||||
) -> String {
|
||||
if *stylemask != 0 {
|
||||
*stylemask = cell.stylemask;
|
||||
}
|
||||
if *channels != 0 {
|
||||
*channels = cell.channels;
|
||||
}
|
||||
nccell_strdup(plane, cell)
|
||||
}
|
||||
|
||||
/// Returns true if the two cells are distinct `EGC`s, attributes, or channels.
|
||||
///
|
||||
/// The actual egcpool index needn't be the same--indeed, the planes needn't even
|
||||
/// be the same. Only the expanded EGC must be equal. The EGC must be bit-equal;
|
||||
///
|
||||
/// *Method: NcCell.[compare()][NcCell#method.compare].*
|
||||
//
|
||||
// NOTE: FIXME: it would probably be better to test whether they're Unicode-equal
|
||||
#[inline]
|
||||
pub fn nccellcmp(plane1: &NcPlane, cell1: &NcCell, plane2: &NcPlane, cell2: &NcCell) -> bool {
|
||||
if cell1.stylemask != cell2.stylemask {
|
||||
return true;
|
||||
}
|
||||
if cell1.channels != cell2.channels {
|
||||
return true;
|
||||
}
|
||||
unsafe {
|
||||
strcmp(
|
||||
crate::nccell_extended_gcluster(plane1, cell1),
|
||||
crate::nccell_extended_gcluster(plane2, cell2),
|
||||
) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes (zeroes out) an [`NcCell`].
|
||||
///
|
||||
/// *Method: NcCell.[init()][NcCell#method.init].*
|
||||
#[inline]
|
||||
pub fn nccell_init(cell: &mut NcCell) {
|
||||
*cell = unsafe { core::mem::zeroed() }
|
||||
}
|
||||
|
||||
/// Same as [`nccell_load`][crate::nccell_load], plus blasts the styling with
|
||||
/// `style` and `channels`.
|
||||
///
|
||||
/// - Breaks the UTF-8 string in `gcluster` down, setting up the cell `cell`.
|
||||
/// - Returns the number of bytes copied out of `gcluster`, or -1 on failure.
|
||||
/// - The styling of the cell is left untouched, but any resources are released.
|
||||
/// - Blasts the styling with `style` and `channels`.
|
||||
///
|
||||
/// *Method: NcCell.[prime()][NcCell#method.prime].*
|
||||
pub fn nccell_prime(
|
||||
plane: &mut NcPlane,
|
||||
cell: &mut NcCell,
|
||||
gcluster: &str,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
) -> NcIntResult {
|
||||
cell.stylemask = style;
|
||||
cell.channels = channels;
|
||||
unsafe { crate::nccell_load(plane, cell, cstring![gcluster]) }
|
||||
}
|
||||
|
||||
/// Loads up six cells with the `EGC`s necessary to draw a box.
|
||||
///
|
||||
/// Returns [`NCRESULT_OK`] on success or [`NCRESULT_ERR`] on error.
|
||||
///
|
||||
/// On error, any [`NcCell`]s this function might have loaded before the error
|
||||
/// are [nccell_release]d. There must be at least six `EGC`s in `gcluster`.
|
||||
///
|
||||
/// *Method: NcCell.[load_box()][NcCell#method.load_box].*
|
||||
pub fn nccells_load_box(
|
||||
plane: &mut NcPlane,
|
||||
style: NcStyle,
|
||||
channels: NcChannels,
|
||||
ul: &mut NcCell,
|
||||
ur: &mut NcCell,
|
||||
ll: &mut NcCell,
|
||||
lr: &mut NcCell,
|
||||
hl: &mut NcCell,
|
||||
vl: &mut NcCell,
|
||||
gcluster: &str,
|
||||
) -> NcIntResult {
|
||||
assert![gcluster.len() >= 6]; // DEBUG
|
||||
|
||||
// TODO: CHECK: mutable copy for pointer arithmetics:
|
||||
let mut gclu = cstring![gcluster];
|
||||
|
||||
let mut ulen: NcIntResult;
|
||||
|
||||
ulen = nccell_prime(plane, ul, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
gclu = unsafe { gclu.offset(ulen as isize) };
|
||||
ulen = nccell_prime(plane, ur, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
gclu = unsafe { gclu.offset(ulen as isize) };
|
||||
ulen = nccell_prime(plane, ll, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
gclu = unsafe { gclu.offset(ulen as isize) };
|
||||
ulen = nccell_prime(plane, lr, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
gclu = unsafe { gclu.offset(ulen as isize) };
|
||||
ulen = nccell_prime(plane, hl, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
let _gclu = unsafe { gclu.offset(ulen as isize) };
|
||||
ulen = nccell_prime(plane, vl, gcluster, style, channels);
|
||||
|
||||
if ulen > 0 {
|
||||
return NCRESULT_OK;
|
||||
}
|
||||
unsafe {
|
||||
nccell_release(plane, hl);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
nccell_release(plane, lr);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
nccell_release(plane, ll);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
nccell_release(plane, ur);
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
nccell_release(plane, ul);
|
||||
}
|
||||
}
|
||||
NCRESULT_ERR
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
//! Test `NcCell` methods and associated functions.
|
||||
|
||||
use crate::{Nc, NcCell, NcPlane};
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn constructors() -> crate::NcResult<()> {
|
||||
let _c1 = NcCell::new();
|
||||
let _c2 = NcCell::from_char7b('C');
|
||||
|
||||
let nc = Nc::new()?;
|
||||
let plane = NcPlane::new(nc, 0, 0, 10, 10)?;
|
||||
let _c3 = NcCell::from_char('௵', plane);
|
||||
nc.stop()?;
|
||||
Ok(())
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
//! `NcCell` tests
|
||||
|
||||
#[cfg(test)]
|
||||
mod methods;
|
||||
|
||||
#[cfg(test)]
|
||||
mod reimplemented;
|
@ -1,103 +0,0 @@
|
||||
//! Test `cell*_*` reimplemented functions
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::NcCell;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn rgb() {
|
||||
// rgb
|
||||
|
||||
let mut c1 = NcCell::new();
|
||||
assert_eq![0, crate::nccell_fg_rgb(&c1)];
|
||||
assert_eq![0, crate::nccell_bg_rgb(&c1)];
|
||||
|
||||
crate::nccell_set_fg_rgb(&mut c1, 0x99112233);
|
||||
assert_eq![0x112233, crate::nccell_fg_rgb(&c1)];
|
||||
crate::nccell_set_bg_rgb(&mut c1, 0x99445566);
|
||||
assert_eq![0x445566, crate::nccell_bg_rgb(&c1)];
|
||||
|
||||
// rgb8
|
||||
|
||||
let mut c2 = NcCell::new();
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
|
||||
crate::nccell_set_fg_rgb8(&mut c2, 0x11, 0x22, 0x33);
|
||||
let fchannel = crate::nccell_fg_rgb8(&c2, &mut r, &mut g, &mut b);
|
||||
assert_eq!((0x11, 0x22, 0x33), (r, g, b));
|
||||
assert_eq![0x112233, fchannel & !crate::NCALPHA_BGDEFAULT_MASK];
|
||||
|
||||
crate::nccell_set_bg_rgb8(&mut c2, 0x44, 0x55, 0x66);
|
||||
let bchannel = crate::nccell_bg_rgb8(&c2, &mut r, &mut g, &mut b);
|
||||
assert_eq!((0x44, 0x55, 0x66), (r, g, b));
|
||||
assert_eq![0x445566, bchannel & !crate::NCALPHA_BGDEFAULT_MASK];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn alpha() {
|
||||
let mut c1 = NcCell::new();
|
||||
assert_eq![0, crate::nccell_fg_alpha(&c1)];
|
||||
assert_eq![0, crate::nccell_bg_alpha(&c1)];
|
||||
|
||||
crate::nccell_set_fg_alpha(&mut c1, crate::NCALPHA_TRANSPARENT);
|
||||
assert_eq![crate::NCALPHA_TRANSPARENT, crate::nccell_fg_alpha(&c1)];
|
||||
|
||||
crate::nccell_set_bg_alpha(&mut c1, crate::NCALPHA_BLEND);
|
||||
assert_eq![crate::NCALPHA_BLEND, crate::nccell_bg_alpha(&c1)];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn default() {
|
||||
let mut c1 = NcCell::new();
|
||||
assert_eq![true, crate::nccell_fg_default_p(&c1)];
|
||||
assert_eq![true, crate::nccell_bg_default_p(&c1)];
|
||||
|
||||
// rgb
|
||||
crate::nccell_set_fg_rgb(&mut c1, 0x112233);
|
||||
crate::nccell_set_bg_rgb(&mut c1, 0x445566);
|
||||
assert_eq![false, crate::nccell_fg_default_p(&c1)];
|
||||
assert_eq![false, crate::nccell_bg_default_p(&c1)];
|
||||
|
||||
// reset
|
||||
crate::nccell_set_fg_default(&mut c1);
|
||||
crate::nccell_set_bg_default(&mut c1);
|
||||
assert_eq![true, crate::nccell_fg_default_p(&c1)];
|
||||
assert_eq![true, crate::nccell_bg_default_p(&c1)];
|
||||
|
||||
// rgb8
|
||||
crate::nccell_set_fg_rgb8(&mut c1, 0x11, 0x22, 0x33);
|
||||
crate::nccell_set_bg_rgb8(&mut c1, 0x44, 0x55, 0x66);
|
||||
assert_eq![false, crate::nccell_fg_default_p(&c1)];
|
||||
assert_eq![false, crate::nccell_bg_default_p(&c1)];
|
||||
|
||||
// reset
|
||||
crate::nccell_set_fg_default(&mut c1);
|
||||
crate::nccell_set_bg_default(&mut c1);
|
||||
|
||||
// palette
|
||||
crate::nccell_set_fg_palindex(&mut c1, 5);
|
||||
crate::nccell_set_bg_palindex(&mut c1, 6);
|
||||
assert_eq![false, crate::nccell_fg_default_p(&c1)];
|
||||
assert_eq![false, crate::nccell_bg_default_p(&c1)];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn palette() {
|
||||
let mut c1 = NcCell::new();
|
||||
assert_eq![false, crate::nccell_fg_palindex_p(&c1)];
|
||||
assert_eq![false, crate::nccell_bg_palindex_p(&c1)];
|
||||
assert_eq![0, crate::nccell_fg_palindex(&c1)];
|
||||
assert_eq![0, crate::nccell_bg_palindex(&c1)];
|
||||
|
||||
crate::nccell_set_fg_palindex(&mut c1, 5);
|
||||
crate::nccell_set_bg_palindex(&mut c1, 6);
|
||||
assert_eq![true, crate::nccell_fg_palindex_p(&c1)];
|
||||
assert_eq![true, crate::nccell_bg_palindex_p(&c1)];
|
||||
|
||||
assert_eq![5, crate::nccell_fg_palindex(&c1)];
|
||||
assert_eq![6, crate::nccell_bg_palindex(&c1)];
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
//! `NcChannel*` methods and associated functions.
|
||||
#![allow(clippy::unnecessary_cast)]
|
||||
|
||||
use crate::{NcAlphaBits, NcChannel, NcChannels, NcComponent, NcPaletteIndex, NcRgb};
|
||||
|
||||
/// Enables the [`NcChannel`] methods.
|
||||
pub trait NcChannelMethods {
|
||||
// constructors
|
||||
fn new() -> Self;
|
||||
fn default() -> Self;
|
||||
fn from_rgb(rgb: NcRgb) -> Self;
|
||||
fn from_rgb_alpha(rgb: NcRgb, alpha: NcAlphaBits) -> Self;
|
||||
fn from_rgb8(r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn from_rgb8_alpha(r: NcComponent, g: NcComponent, b: NcComponent, alpha: NcAlphaBits) -> Self;
|
||||
|
||||
// methods
|
||||
fn fcombine(&self, bchannel: NcChannel) -> NcChannels;
|
||||
fn bcombine(&self, fchannel: NcChannel) -> NcChannels;
|
||||
|
||||
fn alpha(&self) -> NcAlphaBits;
|
||||
fn set_alpha(&mut self, alpha: NcAlphaBits) -> Self;
|
||||
|
||||
fn rgb(&self) -> NcRgb;
|
||||
fn set(&mut self, rgb: NcRgb) -> Self;
|
||||
|
||||
fn rgb8(&self) -> (NcComponent, NcComponent, NcComponent);
|
||||
fn set_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn r(&self) -> NcComponent;
|
||||
fn g(&self) -> NcComponent;
|
||||
fn b(&self) -> NcComponent;
|
||||
fn set_r(&mut self, r: NcComponent) -> Self;
|
||||
fn set_g(&mut self, g: NcComponent) -> Self;
|
||||
fn set_b(&mut self, b: NcComponent) -> Self;
|
||||
|
||||
fn default_p(&self) -> bool;
|
||||
fn set_default(&mut self) -> Self;
|
||||
fn set_not_default(&mut self) -> Self;
|
||||
|
||||
fn palindex_p(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Enables the [`NcChannels`] methods.
|
||||
pub trait NcChannelsMethods {
|
||||
// constructors
|
||||
fn new() -> Self;
|
||||
fn with_default() -> Self;
|
||||
fn from_rgb(fg_rgb: NcRgb, bg_rgb: NcRgb) -> Self;
|
||||
fn from_rgb_both(rgb: NcRgb) -> Self;
|
||||
fn from_rgb_alpha(
|
||||
fg_rgb: NcRgb,
|
||||
fg_alpha: NcAlphaBits,
|
||||
bg_rgb: NcRgb,
|
||||
bg_alpha: NcAlphaBits,
|
||||
) -> Self;
|
||||
fn from_rgb_alpha_both(rgb: NcRgb, alpha: NcAlphaBits) -> Self;
|
||||
fn from_rgb8(
|
||||
fg_r: NcComponent,
|
||||
fg_g: NcComponent,
|
||||
fg_b: NcComponent,
|
||||
bg_r: NcComponent,
|
||||
bg_g: NcComponent,
|
||||
bg_b: NcComponent,
|
||||
) -> Self;
|
||||
fn from_rgb8_both(r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn from_rgb8_alpha(
|
||||
fg_r: NcComponent,
|
||||
fg_g: NcComponent,
|
||||
fg_b: NcComponent,
|
||||
fg_alpha: NcAlphaBits,
|
||||
bg_r: NcComponent,
|
||||
bg_g: NcComponent,
|
||||
bg_b: NcComponent,
|
||||
bg_alpha: NcAlphaBits,
|
||||
) -> Self;
|
||||
fn from_rgb8_alpha_both(
|
||||
r: NcComponent,
|
||||
g: NcComponent,
|
||||
b: NcComponent,
|
||||
alpha: NcAlphaBits,
|
||||
) -> Self;
|
||||
|
||||
// methods
|
||||
fn combine(fchannel: NcChannel, bchannel: NcChannel) -> Self;
|
||||
|
||||
fn fchannel(&self) -> NcChannel;
|
||||
fn bchannel(&self) -> NcChannel;
|
||||
fn set_fchannel(&mut self, fchannel: NcChannel) -> Self;
|
||||
fn set_bchannel(&mut self, bchannel: NcChannel) -> Self;
|
||||
|
||||
fn fg_alpha(&self) -> NcAlphaBits;
|
||||
fn bg_alpha(&self) -> NcAlphaBits;
|
||||
fn set_fg_alpha(&mut self, alpha: NcAlphaBits);
|
||||
fn set_bg_alpha(&mut self, alpha: NcAlphaBits);
|
||||
|
||||
fn fg_rgb(&self) -> NcRgb;
|
||||
fn bg_rgb(&self) -> NcRgb;
|
||||
fn set_fg_rgb(&mut self, alpha: NcAlphaBits) -> Self;
|
||||
fn set_bg_rgb(&mut self, alpha: NcAlphaBits) -> Self;
|
||||
|
||||
fn fg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent);
|
||||
fn bg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent);
|
||||
fn set_fg_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn set_bg_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn fg_r(&self) -> NcComponent;
|
||||
fn fg_g(&self) -> NcComponent;
|
||||
fn fg_b(&self) -> NcComponent;
|
||||
fn bg_r(&self) -> NcComponent;
|
||||
fn bg_g(&self) -> NcComponent;
|
||||
fn bg_b(&self) -> NcComponent;
|
||||
fn fg_set_r(&mut self, r: NcComponent) -> Self;
|
||||
fn fg_set_g(&mut self, g: NcComponent) -> Self;
|
||||
fn fg_set_b(&mut self, b: NcComponent) -> Self;
|
||||
fn bg_set_r(&mut self, r: NcComponent) -> Self;
|
||||
fn bg_set_g(&mut self, g: NcComponent) -> Self;
|
||||
fn bg_set_b(&mut self, b: NcComponent) -> Self;
|
||||
|
||||
fn fg_default_p(&self) -> bool;
|
||||
fn bg_default_p(&self) -> bool;
|
||||
fn set_fg_default(&mut self) -> Self;
|
||||
fn set_fg_not_default(&mut self) -> Self;
|
||||
fn set_bg_default(&mut self) -> Self;
|
||||
fn set_bg_not_default(&mut self) -> Self;
|
||||
fn set_default(&mut self) -> Self;
|
||||
fn set_not_default(&mut self) -> Self;
|
||||
|
||||
fn fg_palindex_p(&self) -> bool;
|
||||
fn bg_palindex_p(&self) -> bool;
|
||||
fn set_fg_palindex(&mut self, index: NcPaletteIndex) -> Self;
|
||||
fn set_bg_palindex(&mut self, index: NcPaletteIndex) -> Self;
|
||||
}
|
||||
|
||||
// NcChannel -------------------------------------------------------------------
|
||||
|
||||
/// # NcChannel Methods
|
||||
impl NcChannelMethods for NcChannel {
|
||||
// Constructors
|
||||
|
||||
/// New `NcChannel`, set to black and NOT using the "default color".
|
||||
fn new() -> Self {
|
||||
0 as NcChannel | crate::NCALPHA_BGDEFAULT_MASK
|
||||
}
|
||||
|
||||
/// New `NcChannel`, set to black and using the "default color".
|
||||
fn default() -> Self {
|
||||
0 as NcChannel
|
||||
}
|
||||
|
||||
/// New `NcChannel`, expects [`NcRgb`].
|
||||
fn from_rgb(rgb: NcRgb) -> Self {
|
||||
Self::new().set(rgb)
|
||||
}
|
||||
|
||||
/// New `NcChannel`, expects [`NcRgb`] & [`NcAlphaBits`].
|
||||
fn from_rgb_alpha(rgb: NcRgb, alpha: NcAlphaBits) -> Self {
|
||||
Self::new().set(rgb).set_alpha(alpha)
|
||||
}
|
||||
|
||||
/// New `NcChannel`, expects three RGB [`NcComponent`] components.
|
||||
fn from_rgb8(r: NcComponent, g: NcComponent, b: NcComponent) -> Self {
|
||||
Self::new().set_rgb8(r, g, b)
|
||||
}
|
||||
|
||||
/// New `NcChannel`, expects three RGB [`NcComponent`] components & [`NcAlphaBits`].
|
||||
fn from_rgb8_alpha(r: NcComponent, g: NcComponent, b: NcComponent, alpha: NcAlphaBits) -> Self {
|
||||
Self::new().set_rgb8(r, g, b).set_alpha(alpha)
|
||||
}
|
||||
|
||||
// Combine
|
||||
|
||||
/// Combines this [`NcChannel`] as foreground, with another as background
|
||||
/// into an [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_combine()][crate::ncchannels_combine].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn fcombine(&self, bchannel: NcChannel) -> NcChannels {
|
||||
crate::ncchannels_combine(*self, bchannel)
|
||||
}
|
||||
|
||||
/// Combines this [`NcChannel`] as background, with another as foreground
|
||||
/// into an [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_combine()][crate::ncchannels_combine].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn bcombine(&self, fchannel: NcChannel) -> NcChannels {
|
||||
crate::ncchannels_combine(fchannel, *self)
|
||||
}
|
||||
|
||||
// Alpha
|
||||
|
||||
/// Gets the [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channel_alpha()][crate::ncchannel_alpha].*
|
||||
fn alpha(&self) -> NcAlphaBits {
|
||||
crate::ncchannel_alpha(*self)
|
||||
}
|
||||
|
||||
/// Sets the [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channel_set_alpha()][crate::ncchannel_set_alpha].*
|
||||
fn set_alpha(&mut self, alpha: NcAlphaBits) -> Self {
|
||||
crate::ncchannel_set_alpha(self, alpha);
|
||||
*self
|
||||
}
|
||||
|
||||
// NcRgb
|
||||
|
||||
/// Gets the [`NcRgb`].
|
||||
///
|
||||
/// *C style function: [channel_rgb()][crate::ncchannel_rgb].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn rgb(&self) -> NcRgb {
|
||||
crate::ncchannel_rgb(*self)
|
||||
}
|
||||
|
||||
/// Sets the [`NcRgb`], and marks the NcChannel as NOT using the
|
||||
/// "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// *C style function: [channel_set()][crate::ncchannel_set].*
|
||||
fn set(&mut self, rgb: NcRgb) -> Self {
|
||||
crate::ncchannel_set(self, rgb);
|
||||
*self
|
||||
}
|
||||
|
||||
// NcComponent
|
||||
|
||||
/// Gets the three [`NcComponent`]s.
|
||||
///
|
||||
/// *C style function: [channel_rgb8()][crate::ncchannel_rgb8].*
|
||||
fn rgb8(&self) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::ncchannel_rgb8(*self, &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the three [`NcComponent`]s, and
|
||||
/// marks the NcChannel as NOT using the "default color".
|
||||
///
|
||||
/// *C style function: [channel_set_rgb8()][crate::ncchannel_set_rgb8].*
|
||||
fn set_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self {
|
||||
crate::ncchannel_set_rgb8(self, r, g, b);
|
||||
*self
|
||||
}
|
||||
|
||||
/// Gets the red [`NcComponent`].
|
||||
///
|
||||
/// *C style function: [channel_r()][crate::ncchannel_r].*
|
||||
fn r(&self) -> NcComponent {
|
||||
crate::ncchannel_r(*self)
|
||||
}
|
||||
|
||||
/// Gets the green [`NcComponent`].
|
||||
///
|
||||
/// *C style function: [channel_g()][crate::ncchannel_g].*
|
||||
fn g(&self) -> NcComponent {
|
||||
crate::ncchannel_g(*self)
|
||||
}
|
||||
|
||||
/// Gets the blue [`NcComponent`].
|
||||
///
|
||||
/// *C style function: [channel_b()][crate::ncchannel_b].*
|
||||
fn b(&self) -> NcComponent {
|
||||
crate::ncchannel_b(*self)
|
||||
}
|
||||
|
||||
/// Sets the red [`NcComponent`], and returns the new `NcChannel`.
|
||||
///
|
||||
/// *C style function: [channel_set_r()][crate::ncchannel_set_r].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_r(&mut self, r: NcComponent) -> Self {
|
||||
crate::ncchannel_set_r(self, r)
|
||||
}
|
||||
|
||||
/// Sets the green [`NcComponent`], and returns the new `NcChannel`.
|
||||
///
|
||||
/// *C style function: [channel_set_g()][crate::ncchannel_set_g].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_g(&mut self, g: NcComponent) -> Self {
|
||||
crate::ncchannel_set_g(self, g)
|
||||
}
|
||||
|
||||
/// Sets the blue [`NcComponent`], and returns the new `NcChannel`.
|
||||
///
|
||||
/// *C style function: [channel_set_b()][crate::ncchannel_set_b].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_b(&mut self, b: NcComponent) -> Self {
|
||||
crate::ncchannel_set_b(self, b)
|
||||
}
|
||||
|
||||
// default color
|
||||
|
||||
/// Is this `NcChannel` using the "default color" rather than RGB/palette-indexed?
|
||||
///
|
||||
/// *C style function: [channel_default_p()][crate::ncchannel_default_p].*
|
||||
fn default_p(&self) -> bool {
|
||||
crate::ncchannel_default_p(*self)
|
||||
}
|
||||
|
||||
/// Marks this `NcChannel` as using its "default color",
|
||||
/// which also marks it opaque.
|
||||
///
|
||||
/// *C style function: [channel_set_default()][crate::ncchannel_set_default].*
|
||||
fn set_default(&mut self) -> Self {
|
||||
crate::ncchannel_set_default(self)
|
||||
}
|
||||
|
||||
/// Marks this `NcChannel` as *not* using its "default color".
|
||||
///
|
||||
/// The following methods also marks the channel as NOT using the "default color":
|
||||
/// - [new()][NcChannel#method.new]
|
||||
/// - [set()][NcChannel#method.set]
|
||||
/// - [set_rgb8()][NcChannel#method.set_rgb8]
|
||||
///
|
||||
/// *C style function: [channel_set_not_default()][crate::ncchannel_set_not_default].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_not_default(&mut self) -> Self {
|
||||
crate::ncchannel_set_not_default(self)
|
||||
}
|
||||
|
||||
// NcPaletteIndex
|
||||
|
||||
/// Is this NcChannel using palette-indexed color rather than RGB?
|
||||
///
|
||||
/// *C style function: [channel_set_default()][crate::ncchannel_set_default].*
|
||||
fn palindex_p(&self) -> bool {
|
||||
crate::ncchannel_palindex_p(*self)
|
||||
}
|
||||
}
|
||||
|
||||
// NcChannels ---------------------------------------------------------------
|
||||
|
||||
/// # NcChannels Methods
|
||||
impl NcChannelsMethods for NcChannels {
|
||||
// Constructors
|
||||
|
||||
/// New `NcChannels`, set to black and NOT using the "default color".
|
||||
fn new() -> Self {
|
||||
Self::combine(
|
||||
0 as NcChannel | crate::NCALPHA_BGDEFAULT_MASK,
|
||||
0 as NcChannel | crate::NCALPHA_BGDEFAULT_MASK,
|
||||
)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, set to black and using the "default color".
|
||||
fn with_default() -> Self {
|
||||
Self::combine(0 as NcChannel, 0 as NcChannel)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects two separate [`NcRgb`]s for the foreground
|
||||
/// and background channels.
|
||||
fn from_rgb(fg_rgb: NcRgb, bg_rgb: NcRgb) -> Self {
|
||||
Self::combine(NcChannel::from_rgb(fg_rgb), NcChannel::from_rgb(bg_rgb))
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects a single [`NcRgb`] for both foreground
|
||||
/// and background channels.
|
||||
fn from_rgb_both(rgb: NcRgb) -> Self {
|
||||
let channel = NcChannel::new().set(rgb);
|
||||
Self::combine(channel, channel)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects two separate [`NcRgb`] & [`NcAlphaBits`] for the
|
||||
/// foreground and background channels.
|
||||
fn from_rgb_alpha(
|
||||
fg_rgb: NcRgb,
|
||||
fg_alpha: NcAlphaBits,
|
||||
bg_rgb: NcRgb,
|
||||
bg_alpha: NcAlphaBits,
|
||||
) -> Self {
|
||||
Self::combine(
|
||||
NcChannel::from_rgb(fg_rgb).set_alpha(fg_alpha),
|
||||
NcChannel::from_rgb(bg_rgb).set_alpha(bg_alpha),
|
||||
)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects [`NcRgb`] & [`NcAlphaBits`] for both
|
||||
/// channels.
|
||||
fn from_rgb_alpha_both(rgb: NcRgb, alpha: NcAlphaBits) -> Self {
|
||||
let channel = NcChannel::new().set(rgb).set_alpha(alpha);
|
||||
Self::combine(channel, channel)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects three RGB [`NcComponent`] components
|
||||
/// for each channel.
|
||||
fn from_rgb8(
|
||||
fg_r: NcComponent,
|
||||
fg_g: NcComponent,
|
||||
fg_b: NcComponent,
|
||||
bg_r: NcComponent,
|
||||
bg_g: NcComponent,
|
||||
bg_b: NcComponent,
|
||||
) -> Self {
|
||||
Self::combine(
|
||||
NcChannel::from_rgb8(fg_r, fg_g, fg_b),
|
||||
NcChannel::from_rgb8(bg_r, bg_g, bg_b),
|
||||
)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects three RGB [`NcComponent`] components for
|
||||
/// both the foreground and background channels.
|
||||
fn from_rgb8_both(r: NcComponent, g: NcComponent, b: NcComponent) -> Self {
|
||||
let channel = NcChannel::new().set_rgb8(r, g, b);
|
||||
Self::combine(channel, channel)
|
||||
}
|
||||
|
||||
/// New `NcChannels`, expects three RGB [`NcComponent`]s and
|
||||
/// [`NcAlphaBits`], for both the foreground and background channels.
|
||||
fn from_rgb8_alpha(
|
||||
fg_r: NcComponent,
|
||||
fg_g: NcComponent,
|
||||
fg_b: NcComponent,
|
||||
fg_alpha: NcAlphaBits,
|
||||
bg_r: NcComponent,
|
||||
bg_g: NcComponent,
|
||||
bg_b: NcComponent,
|
||||
bg_alpha: NcAlphaBits,
|
||||
) -> Self {
|
||||
Self::combine(
|
||||
NcChannel::from_rgb8_alpha(fg_r, fg_g, fg_b, fg_alpha),
|
||||
NcChannel::from_rgb8_alpha(bg_r, bg_g, bg_b, bg_alpha),
|
||||
)
|
||||
}
|
||||
|
||||
/// New `NcChannel`, expects three RGB [`NcComponent`]s.
|
||||
fn from_rgb8_alpha_both(
|
||||
r: NcComponent,
|
||||
g: NcComponent,
|
||||
b: NcComponent,
|
||||
alpha: NcAlphaBits,
|
||||
) -> Self {
|
||||
let channel = NcChannel::new().set_rgb8(r, g, b).set_alpha(alpha);
|
||||
Self::combine(channel, channel)
|
||||
}
|
||||
|
||||
// Combine
|
||||
|
||||
/// Combines two [`NcChannel`]s into an [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_combine()][crate::ncchannels_combine].*
|
||||
fn combine(fchannel: NcChannel, bchannel: NcChannel) -> Self {
|
||||
crate::ncchannels_combine(fchannel, bchannel)
|
||||
}
|
||||
|
||||
// NcChannel
|
||||
|
||||
/// Extracts the foreground [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [channels_fchannel()][crate::ncchannels_fchannel].*
|
||||
fn fchannel(&self) -> NcChannel {
|
||||
crate::ncchannels_fchannel(*self)
|
||||
}
|
||||
|
||||
/// Extracts the background [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [channels_bchannel()][crate::ncchannels_bchannel].*
|
||||
fn bchannel(&self) -> NcChannel {
|
||||
crate::ncchannels_bchannel(*self)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [channels_set_fchannel()][crate::ncchannels_set_fchannel].*
|
||||
fn set_fchannel(&mut self, fchannel: NcChannel) -> Self {
|
||||
crate::ncchannels_set_fchannel(self, fchannel)
|
||||
}
|
||||
|
||||
/// Sets the background [`NcChannel`].
|
||||
///
|
||||
/// *C style function: [channels_set_bchannel()][crate::ncchannels_set_bchannel].*
|
||||
fn set_bchannel(&mut self, bchannel: NcChannel) -> Self {
|
||||
crate::ncchannels_set_bchannel(self, bchannel)
|
||||
}
|
||||
|
||||
// Alpha
|
||||
|
||||
/// Gets the foreground [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channels_fg_alpha()][crate::ncchannels_fg_alpha].*
|
||||
fn fg_alpha(&self) -> NcAlphaBits {
|
||||
crate::ncchannels_fg_alpha(*self)
|
||||
}
|
||||
|
||||
/// Gets the background [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channels_bg_alpha()][crate::ncchannels_bg_alpha].*
|
||||
fn bg_alpha(&self) -> NcAlphaBits {
|
||||
crate::ncchannels_bg_alpha(*self)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channels_set_fg_alpha()][crate::ncchannels_set_fg_alpha].*
|
||||
fn set_fg_alpha(&mut self, alpha: NcAlphaBits) {
|
||||
crate::ncchannels_set_fg_alpha(self, alpha)
|
||||
}
|
||||
|
||||
/// Sets the background [`NcAlphaBits`].
|
||||
///
|
||||
/// *C style function: [channels_set_bg_alpha()][crate::ncchannels_set_bg_alpha].*
|
||||
fn set_bg_alpha(&mut self, alpha: NcAlphaBits) {
|
||||
crate::ncchannels_set_bg_alpha(self, alpha)
|
||||
}
|
||||
|
||||
// NcRgb
|
||||
|
||||
/// Gets the foreground [`NcRgb`].
|
||||
///
|
||||
/// *C style function: [channels_fg_rgb()][crate::ncchannels_fg_rgb].*
|
||||
fn fg_rgb(&self) -> NcRgb {
|
||||
crate::ncchannels_fg_rgb(*self)
|
||||
}
|
||||
|
||||
/// Gets the background [`NcRgb`].
|
||||
///
|
||||
/// *C style function: [channels_bg_rgb()][crate::ncchannels_bg_rgb].*
|
||||
fn bg_rgb(&self) -> NcRgb {
|
||||
crate::ncchannels_bg_rgb(*self)
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcRgb`].
|
||||
///
|
||||
/// *C style function: [channels_set_fg_rgb()][crate::ncchannels_set_fg_rgb].*
|
||||
fn set_fg_rgb(&mut self, rgb: NcRgb) -> Self {
|
||||
crate::ncchannels_set_fg_rgb(self, rgb);
|
||||
*self
|
||||
}
|
||||
|
||||
/// Sets the background [`NcRgb`].
|
||||
///
|
||||
/// *C style function: [channels_set_bg_rgb()][crate::ncchannels_set_bg_rgb].*
|
||||
fn set_bg_rgb(&mut self, rgb: NcRgb) -> Self {
|
||||
crate::ncchannels_set_bg_rgb(self, rgb);
|
||||
*self
|
||||
}
|
||||
|
||||
// NcComponent
|
||||
|
||||
/// Gets the three foreground RGB [`NcComponent`]s (r, g, b).
|
||||
///
|
||||
/// *C style function: [channels_fg_rgb8()][crate::ncchannels_fg_rgb8].*
|
||||
fn fg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::ncchannels_fg_rgb8(*self, &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Gets the three background RGB [`NcComponent`]s (r, g, b).
|
||||
///
|
||||
/// *C style function: [channels_bg_rgb8()][crate::ncchannels_bg_rgb8].*
|
||||
fn bg_rgb8(&self) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::ncchannels_bg_rgb8(*self, &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the three foreground RGB [`NcComponent`]s (r, g, b), and
|
||||
/// marks the foreground [`NcChannel`] as not using the "default color".
|
||||
///
|
||||
/// *C style function: [channels_set_fg_rgb8()][crate::ncchannels_set_fg_rgb8].*
|
||||
fn set_fg_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self {
|
||||
crate::ncchannels_set_fg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the three background RGB [`NcComponent`]s (r, g, b), and
|
||||
/// marks the background [`NcChannel`] as not using the "default color".
|
||||
///
|
||||
/// *C style function: [channels_set_bg_rgb8()][crate::ncchannels_set_bg_rgb8].*
|
||||
fn set_bg_rgb8(&mut self, r: NcComponent, g: NcComponent, b: NcComponent) -> Self {
|
||||
crate::ncchannels_set_bg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Gets the foreground red [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_r(&self) -> NcComponent {
|
||||
crate::ncchannel_r(crate::ncchannels_fchannel(*self))
|
||||
}
|
||||
|
||||
/// Gets the foreground green [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_g(&self) -> NcComponent {
|
||||
crate::ncchannel_g(crate::ncchannels_fchannel(*self))
|
||||
}
|
||||
|
||||
/// Gets the foreground blue [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_b(&self) -> NcComponent {
|
||||
crate::ncchannel_b(crate::ncchannels_fchannel(*self))
|
||||
}
|
||||
|
||||
/// Gets the background red [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_r(&self) -> NcComponent {
|
||||
crate::ncchannel_r(crate::ncchannels_bchannel(*self))
|
||||
}
|
||||
|
||||
/// Gets the background green [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_g(&self) -> NcComponent {
|
||||
crate::ncchannel_g(crate::ncchannels_bchannel(*self))
|
||||
}
|
||||
|
||||
/// Gets the background blue [`NcComponent`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_b(&self) -> NcComponent {
|
||||
crate::ncchannel_b(crate::ncchannels_bchannel(*self))
|
||||
}
|
||||
|
||||
/// Sets the foreground red [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_set_r(&mut self, r: NcComponent) -> Self {
|
||||
let (_, g, b) = self.bg_rgb8();
|
||||
crate::ncchannels_set_fg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the foreground green [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_set_g(&mut self, g: NcComponent) -> Self {
|
||||
let (r, _, b) = self.bg_rgb8();
|
||||
crate::ncchannels_set_fg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the foreground blue [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn fg_set_b(&mut self, b: NcComponent) -> Self {
|
||||
let (r, g, _) = self.bg_rgb8();
|
||||
crate::ncchannels_set_fg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the background red [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_set_r(&mut self, r: NcComponent) -> Self {
|
||||
let (_, g, b) = self.bg_rgb8();
|
||||
crate::ncchannels_set_bg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the background green [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_set_g(&mut self, g: NcComponent) -> Self {
|
||||
let (r, _, b) = self.bg_rgb8();
|
||||
crate::ncchannels_set_bg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the background blue [`NcComponent`], and returns the new `NcChannels`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
fn bg_set_b(&mut self, b: NcComponent) -> Self {
|
||||
let (r, g, _) = self.bg_rgb8();
|
||||
crate::ncchannels_set_bg_rgb8(self, r, g, b)
|
||||
}
|
||||
|
||||
// default color
|
||||
|
||||
/// Is the background using the "default background color"?
|
||||
///
|
||||
/// *C style function: [channels_fg_default_p()][crate::ncchannels_fg_default_p].*
|
||||
fn fg_default_p(&self) -> bool {
|
||||
crate::ncchannels_fg_default_p(*self)
|
||||
}
|
||||
|
||||
/// Is the background using the "default background color"?
|
||||
///
|
||||
/// The "default background color" must generally be used to take advantage
|
||||
/// of terminal-effected transparency.
|
||||
///
|
||||
/// *C style function: [channels_bg_default_p()][crate::ncchannels_bg_default_p].*
|
||||
fn bg_default_p(&self) -> bool {
|
||||
crate::ncchannels_bg_default_p(*self)
|
||||
}
|
||||
|
||||
/// Marks the foreground as using its "default color", and
|
||||
/// returns the new [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_set_fg_default()][crate::ncchannels_set_fg_default].*
|
||||
fn set_fg_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_fg_default(self)
|
||||
}
|
||||
|
||||
/// Marks the background as using its "default color", and
|
||||
/// returns the new [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_set_bg_default()][crate::ncchannels_set_bg_default].*
|
||||
fn set_bg_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_bg_default(self)
|
||||
}
|
||||
|
||||
/// Marks the foreground as NOT using its "default color", and
|
||||
/// returns the new [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_set_fg_default()][crate::ncchannels_set_fg_default].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_fg_not_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_fg_not_default(self)
|
||||
}
|
||||
|
||||
/// Marks the background as NOT using its "default color", and
|
||||
/// returns the new [`NcChannels`].
|
||||
///
|
||||
/// *C style function: [channels_set_bg_not_default()][crate::ncchannels_set_bg_not_default].*
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_bg_not_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_bg_not_default(self)
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background as using its "default color", and
|
||||
/// returns the new [`NcChannels`].
|
||||
///
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_fg_default(&mut crate::ncchannels_set_bg_default(self))
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background as NOT using its "default color",
|
||||
/// and returns the new [`NcChannels`].
|
||||
///
|
||||
//
|
||||
// Not in the C API
|
||||
fn set_not_default(&mut self) -> Self {
|
||||
crate::ncchannels_set_fg_not_default(&mut crate::ncchannels_set_bg_not_default(self))
|
||||
}
|
||||
|
||||
// NcPaletteIndex
|
||||
|
||||
/// Is the foreground of using an [indexed][NcPaletteIndex]
|
||||
/// [NcPalette][crate::NcPalette] color?
|
||||
///
|
||||
/// *C style function: [channels_fg_palindex_p()][crate::ncchannels_fg_palindex_p].*
|
||||
fn fg_palindex_p(&self) -> bool {
|
||||
crate::ncchannels_fg_palindex_p(*self)
|
||||
}
|
||||
|
||||
/// Is the background of using an [indexed][NcPaletteIndex]
|
||||
/// [NcPalette][crate::NcPalette] color?
|
||||
///
|
||||
/// *C style function: [channels_bg_palindex_p()][crate::ncchannels_bg_palindex_p].*
|
||||
fn bg_palindex_p(&self) -> bool {
|
||||
crate::ncchannels_bg_palindex_p(*self)
|
||||
}
|
||||
|
||||
/// Sets the foreground of an [`NcChannels`] as using an
|
||||
/// [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color.
|
||||
///
|
||||
/// *C style function: [channels_set_fg_palindex()][crate::ncchannels_set_fg_palindex].*
|
||||
fn set_fg_palindex(&mut self, index: NcPaletteIndex) -> Self {
|
||||
crate::ncchannels_set_fg_palindex(self, index);
|
||||
*self
|
||||
}
|
||||
|
||||
/// Sets the background of an [`NcChannels`] as using an
|
||||
/// [indexed][NcPaletteIndex] [NcPalette][crate::NcPalette] color.
|
||||
///
|
||||
/// *C style function: [channels_set_bg_palindex()][crate::ncchannels_set_bg_palindex].*
|
||||
fn set_bg_palindex(&mut self, index: NcPaletteIndex) -> Self {
|
||||
crate::ncchannels_set_bg_palindex(self, index);
|
||||
*self
|
||||
}
|
||||
}
|
@ -1,314 +0,0 @@
|
||||
//! `NcChannel*`
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// - The channel components are u8 instead of u32.
|
||||
// Because of type enforcing, some runtime checks are now unnecessary.
|
||||
//
|
||||
// - None of the functions can't fail now. The original checks for dirty bits
|
||||
// have been substitued by mask cleaning (bitwise and)
|
||||
//
|
||||
// - These functions were deemed unnecessary to implement:
|
||||
// - `channel_set_rgb_clipped()`
|
||||
// - `channels_set_fg_rgb8_clipped()`
|
||||
// - `channels_set_bg_rgb8_clipped()`
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// functions manually reimplemented: 44
|
||||
// ------------------------------------------
|
||||
// (X) wont: 3
|
||||
// (+) done: 36 / 0
|
||||
// (#) test: 21
|
||||
// (W) wrap: 41
|
||||
// ------------------------------------------
|
||||
//W# channel_alpha
|
||||
//W# channel_b
|
||||
//W# channel_default_p
|
||||
//W# channel_g
|
||||
//W# channel_palindex_p
|
||||
//W# channel_r
|
||||
//W# channel_rgb8
|
||||
//W# channel_set
|
||||
//W# channel_set_alpha
|
||||
//W# channel_set_default
|
||||
//W# channel_set_not_default // not in the original C API
|
||||
//W# channel_set_rgb8
|
||||
// X channel_set_rgb_clipped // not needed
|
||||
//W# channels_bchannel
|
||||
//W+ channels_bg_alpha
|
||||
//W+ channels_bg_default_p
|
||||
//W# channels_bg_palindex_p
|
||||
//W+ channels_bg_rgb
|
||||
//W+ channels_bg_rgb8
|
||||
//W# channels_combine
|
||||
//W# channels_fchannel
|
||||
//W+ channels_fg_alpha
|
||||
//W+ channels_fg_default_p
|
||||
//W# channels_fg_palindex_p
|
||||
//W+ channels_fg_rgb
|
||||
//W+ channels_fg_rgb8
|
||||
//W# channels_set_bchannel
|
||||
//W+ channels_set_bg_alpha
|
||||
//W+ channels_set_bg_default
|
||||
//W channels_set_bg_not_default // not in the original C API
|
||||
//W# channels_set_bg_palindex
|
||||
//W+ channels_set_bg_rgb
|
||||
//W+ channels_set_bg_rgb8
|
||||
// X channels_set_bg_rgb8_clipped // not needed
|
||||
//W channels_set_default // not in the original C API
|
||||
//W# channels_set_fchannel
|
||||
//W+ channels_set_fg_alpha
|
||||
//W+ channels_set_fg_default
|
||||
//W channels_set_fg_not_default // not in the original C API
|
||||
//W# channels_set_fg_palindex
|
||||
//W+ channels_set_fg_rgb
|
||||
//W+ channels_set_fg_rgb8
|
||||
// X channels_set_fg_rgb8_clipped // not needed
|
||||
//W channels_set_not_default // not in the original C API
|
||||
|
||||
#[allow(unused_imports)] // for the doc comments
|
||||
use crate::{NcCell, NcRgba};
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
pub use methods::{NcChannelMethods, NcChannelsMethods};
|
||||
pub use reimplemented::*;
|
||||
|
||||
// NcChannel
|
||||
//
|
||||
/// 32 bits of context-dependent info
|
||||
/// containing RGB + 2 bits of alpha + extra
|
||||
///
|
||||
/// It is:
|
||||
/// - a 24-bit [`NcRgb`] value
|
||||
/// - plus 8 bits divided in:
|
||||
/// - 2 bits of [`NcAlphaBits`]
|
||||
/// - 6 bits of context-dependent info
|
||||
///
|
||||
/// The context details are documented in [`NcChannels`]
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// ~~AA~~~~ RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
/// ```
|
||||
/// `type in C: channel (uint32_t)`
|
||||
///
|
||||
/// See also: [NcRgb] and [NcRgba] types.
|
||||
pub type NcChannel = u32;
|
||||
|
||||
/// Extract these bits to get a channel's alpha value
|
||||
pub const NCCHANNEL_ALPHA_MASK: u32 = crate::bindings::ffi::NC_BG_ALPHA_MASK;
|
||||
|
||||
// NcAlphaBits
|
||||
//
|
||||
/// 2 bits of alpha (surrounded by context dependent bits).
|
||||
/// It is part of an [`NcChannel`].
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// ~~AA~~~~ -------- -------- --------
|
||||
/// ```
|
||||
/// `type in C: no data type`
|
||||
///
|
||||
pub type NcAlphaBits = u32;
|
||||
|
||||
/// [`NcAlphaBits`] bits indicating
|
||||
/// [`NcCell`]'s foreground or background color will be a composite between
|
||||
/// its color and the `NcCell`s' corresponding colors underneath it
|
||||
pub const NCALPHA_BLEND: u32 = crate::bindings::ffi::NCALPHA_BLEND;
|
||||
|
||||
/// [`NcAlphaBits`] bits indicating
|
||||
/// [`NcCell`]'s foreground color will be high-contrast (relative to the
|
||||
/// computed background). Background cannot be highcontrast
|
||||
pub const NCALPHA_HIGHCONTRAST: u32 = crate::bindings::ffi::NCALPHA_HIGHCONTRAST;
|
||||
|
||||
/// [`NcAlphaBits`] bits indicating
|
||||
/// [`NcCell`]'s foreground or background color is used unchanged
|
||||
pub const NCALPHA_OPAQUE: u32 = crate::bindings::ffi::NCALPHA_OPAQUE;
|
||||
|
||||
/// [`NcAlphaBits`] bits indicating
|
||||
/// [`NcCell`]'s foreground or background color is derived entirely from the
|
||||
/// `NcCell`s underneath it
|
||||
pub const NCALPHA_TRANSPARENT: u32 = crate::bindings::ffi::NCALPHA_TRANSPARENT;
|
||||
|
||||
/// If this bit is set, we are *not* using the default background color
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: This can also be used against a single [`NcChannel`]
|
||||
pub const NCALPHA_BGDEFAULT_MASK: u32 = crate::bindings::ffi::NC_BGDEFAULT_MASK;
|
||||
|
||||
/// Extract these bits to get the background alpha mask
|
||||
/// ([`NcAlphaBits`])
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: This can also be used against a single [`NcChannel`]
|
||||
pub const NCALPHA_BG_ALPHA_MASK: u32 = crate::bindings::ffi::NC_BG_ALPHA_MASK;
|
||||
|
||||
/// If this bit *and* [`NCALPHA_BGDEFAULT_MASK`] are set, we're using a
|
||||
/// palette-indexed background color
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: This can also be used against a single [`NcChannel`]
|
||||
pub const NCALPHA_BG_PALETTE: u32 = crate::bindings::ffi::NC_BG_PALETTE;
|
||||
|
||||
/// Extract these bits to get the background [`NcRgb`][crate::NcRgb] value
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: This can also be used against a single [`NcChannel`]
|
||||
pub const NCALPHA_BG_RGB_MASK: u32 = crate::bindings::ffi::NC_BG_RGB_MASK;
|
||||
|
||||
/// If this bit is set, we are *not* using the default foreground color
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: When working with a single [`NcChannel`] use [`NCALPHA_BGDEFAULT_MASK`];
|
||||
pub const NCALPHA_FGDEFAULT_MASK: u64 = crate::bindings::ffi::NC_FGDEFAULT_MASK;
|
||||
|
||||
/// Extract these bits to get the foreground alpha mask
|
||||
/// ([`NcAlphaBits`])
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: When working with a single [`NcChannel`] use [`NCALPHA_BG_ALPHA_MASK`];
|
||||
pub const NCALPHA_FG_ALPHA_MASK: u64 = crate::bindings::ffi::NC_FG_ALPHA_MASK;
|
||||
|
||||
/// If this bit *and* [`NCALPHA_FGDEFAULT_MASK`] are set, we're using a
|
||||
/// palette-indexed background color
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: When working with a single [`NcChannel`] use [`NCALPHA_BG_PALETTE`];
|
||||
pub const NCALPHA_FG_PALETTE: u64 = crate::bindings::ffi::NC_FG_PALETTE;
|
||||
|
||||
/// Extract these bits to get the foreground [`NcRgb`][crate::NcRgb] value
|
||||
///
|
||||
/// See the detailed diagram at [`NcChannels`][crate::NcChannels]
|
||||
///
|
||||
/// Note: When working with a single [`NcChannel`] use [`NCALPHA_BG_RGB_MASK`];
|
||||
pub const NCALPHA_FG_RGB_MASK: u64 = crate::bindings::ffi::NC_FG_RGB_MASK;
|
||||
|
||||
// NcChannels
|
||||
//
|
||||
/// 64 bits containing a foreground and background [`NcChannel`]
|
||||
///
|
||||
/// At render time, both 24-bit [`NcRgb`] values are quantized down to terminal
|
||||
/// capabilities, if necessary. There's a clear path to 10-bit support should
|
||||
/// we one day need it.
|
||||
///
|
||||
/// ## Default Color
|
||||
///
|
||||
/// The "default color" is best explained by
|
||||
/// [color(3NCURSES)](https://manpages.debian.org/stretch/ncurses-doc/color.3ncurses.en.html) and
|
||||
/// [default_colors(3NCURSES)](https://manpages.debian.org/stretch/ncurses-doc/default_colors.3ncurses.en.html).
|
||||
/// Ours is the same concept.
|
||||
///
|
||||
/// **Until the "not default color" bit is set, any color you load will be ignored.**
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// ~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB║~~AA~~~~|RRRRRRRR|GGGGGGGG|BBBBBBBB
|
||||
/// ↑↑↑↑↑↑↑↑↑↑↑↑ foreground ↑↑↑↑↑↑↑↑↑↑↑║↑↑↑↑↑↑↑↑↑↑↑↑ background ↑↑↑↑↑↑↑↑↑↑↑
|
||||
/// ```
|
||||
///
|
||||
/// Detailed info (specially on the context-dependent bits on each
|
||||
/// [`NcChannel`]'s 4th byte):
|
||||
///
|
||||
/// ```txt
|
||||
/// ~foreground channel~
|
||||
/// NCALPHA_WIDEASIAN_MASK: part of a wide glyph ↓bits view↓ ↓hex mask↓
|
||||
/// 1·······|········|········|········║········|········|········|········ = 8·······|········
|
||||
///
|
||||
/// NCALPHA_FGDEFAULT_MASK: foreground is NOT "default color"
|
||||
/// ·1······|········|········|········║········|········|········|········ = 4·······|········
|
||||
///
|
||||
/// NCALPHA_FG_ALPHA_MASK: foreground alpha (2bits)
|
||||
/// ··11····|········|········|········║········|········|········|········ = 3·······|········
|
||||
///
|
||||
/// NCALPHA_FG_PALETTE: foreground uses palette index
|
||||
/// ····1···|········|········|········║········|········|········|········ = ·8······|········
|
||||
///
|
||||
/// NCALPHA_NOBACKGROUND_MASK: glyph is entirely foreground
|
||||
/// ·····1··|········|········|········║········|········|········|········ = ·4······|········
|
||||
///
|
||||
/// reserved, must be 0
|
||||
/// ······00|········|········|········║········|········|········|········ = ·3······|········
|
||||
///
|
||||
/// NCALPHA_FG_RGB_MASK: foreground in 3x8 RGB (rrggbb)
|
||||
/// ········|11111111|11111111|11111111║········|········|········|········ = ··FFFFFF|········
|
||||
/// ```
|
||||
|
||||
/// ```txt
|
||||
/// ~background channel~
|
||||
/// reserved, must be 0 ↓bits view↓ ↓hex mask↓
|
||||
/// ········|········|········|········║0·······|········|········|········ = ········|8·······
|
||||
///
|
||||
/// NCALPHA_BGDEFAULT_MASK: background is NOT "default color"
|
||||
/// ········|········|········|········║·1······|········|········|········ = ········|4·······
|
||||
///
|
||||
/// NCALPHA_BG_ALPHA_MASK: background alpha (2 bits)
|
||||
/// ········|········|········|········║··11····|········|········|········ = ········|3·······
|
||||
///
|
||||
/// NCALPHA_BG_PALETTE: background uses palette index
|
||||
/// ········|········|········|········║····1···|········|········|········ = ········|·8······
|
||||
///
|
||||
/// reserved, must be 0
|
||||
/// ········|········|········|········║·····000|········|········|········ = ········|·7······
|
||||
///
|
||||
/// NCALPHA_BG_RGB_MASK: background in 3x8 RGB (rrggbb)
|
||||
/// ········|········|········|········║········|11111111|11111111|11111111 = ········|··FFFFFF
|
||||
/// ```
|
||||
/// `type in C: channels (uint64_t)`
|
||||
///
|
||||
/// ## `NcCell` Mask Flags
|
||||
///
|
||||
/// - [`NCALPHA_BGDEFAULT_MASK`][crate::NCALPHA_BGDEFAULT_MASK]
|
||||
/// - [`NCALPHA_BG_ALPHA_MASK`][crate::NCALPHA_BG_ALPHA_MASK]
|
||||
/// - [`NCALPHA_BG_PALETTE`][crate::NCALPHA_BG_PALETTE]
|
||||
/// - [`NCALPHA_BG_RGB_MASK`][crate::NCALPHA_BG_RGB_MASK]
|
||||
/// - [`NCALPHA_FGDEFAULT_MASK`][crate::NCALPHA_FGDEFAULT_MASK]
|
||||
/// - [`NCALPHA_FG_ALPHA_MASK`][crate::NCALPHA_FG_ALPHA_MASK]
|
||||
/// - [`NCALPHA_FG_PALETTE`][crate::NCALPHA_FG_PALETTE]
|
||||
/// - [`NCALPHA_FG_RGB_MASK`][crate::NCALPHA_FG_RGB_MASK]
|
||||
///
|
||||
pub type NcChannels = u64;
|
||||
|
||||
#[deprecated = "use NcChannels instead"]
|
||||
#[doc(hidden)]
|
||||
pub type NcChannelPair = NcChannels;
|
||||
|
||||
// NcRgb
|
||||
//
|
||||
/// 24 bits broken into 3x 8bpp channels.
|
||||
///
|
||||
/// Unlike with [`NcChannel`], operations involving `NcRgb` ignores the last 4th byte
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// -------- RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
/// ```
|
||||
/// `type in C: no data type`
|
||||
///
|
||||
/// See also: [NcRgba] and [NcChannel] types.
|
||||
pub type NcRgb = u32;
|
||||
|
||||
// NcComponent
|
||||
//
|
||||
/// 8 bits representing an R/G/B color component or an alpha channel component.
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// CCCCCCCC (1 Byte)
|
||||
/// ```
|
||||
/// `type in C: no data type`
|
||||
pub type NcComponent = u8;
|
@ -1,510 +0,0 @@
|
||||
//! `channel*_*` reimplemented functions.
|
||||
|
||||
use crate::{
|
||||
NcAlphaBits, NcChannel, NcChannels, NcComponent, NcPaletteIndex, NcRgb, NCALPHA_BGDEFAULT_MASK,
|
||||
NCALPHA_BG_PALETTE, NCALPHA_BG_RGB_MASK, NCALPHA_FGDEFAULT_MASK, NCALPHA_FG_PALETTE,
|
||||
NCALPHA_HIGHCONTRAST, NCALPHA_OPAQUE, NCCHANNEL_ALPHA_MASK,
|
||||
};
|
||||
|
||||
// Alpha -----------------------------------------------------------------------
|
||||
|
||||
/// Gets the [`NcAlphaBits`] from an [`NcChannel`].
|
||||
///
|
||||
/// *Method: NcChannel.[alpha()][NcChannel#method.alpha]*
|
||||
#[inline]
|
||||
pub const fn ncchannel_alpha(channel: NcChannel) -> NcAlphaBits {
|
||||
channel & NCCHANNEL_ALPHA_MASK
|
||||
}
|
||||
|
||||
/// Sets the [`NcAlphaBits`] of an [`NcChannel`].
|
||||
///
|
||||
/// *Method: NcChannel.[set_alpha()][NcChannel#method.set_alpha]*
|
||||
#[inline]
|
||||
pub fn ncchannel_set_alpha(channel: &mut NcChannel, alpha: NcAlphaBits) {
|
||||
let alpha_clean = alpha & NCCHANNEL_ALPHA_MASK;
|
||||
*channel = alpha_clean | (*channel & !NCCHANNEL_ALPHA_MASK);
|
||||
|
||||
if alpha != NCALPHA_OPAQUE {
|
||||
// indicate that we are *not* using the default background color
|
||||
*channel |= NCALPHA_BGDEFAULT_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the foreground [`NcAlphaBits`] from an [`NcChannels`], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcChannels.[fg_alpha()][NcChannels#method.fg_alpha]*
|
||||
#[inline]
|
||||
pub const fn ncchannels_fg_alpha(channels: NcChannels) -> NcAlphaBits {
|
||||
ncchannel_alpha(ncchannels_fchannel(channels))
|
||||
}
|
||||
|
||||
/// Gets the background [`NcAlphaBits`] from an [`NcChannels`], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcChannels.[bg_alpha()][NcChannels#method.bg_alpha]*
|
||||
#[inline]
|
||||
pub const fn ncchannels_bg_alpha(channels: NcChannels) -> NcAlphaBits {
|
||||
ncchannel_alpha(ncchannels_bchannel(channels))
|
||||
}
|
||||
|
||||
/// Sets the [`NcAlphaBits`] of the foreground [`NcChannel`] of an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_alpha()][NcChannels#method.set_fg_alpha]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fg_alpha(channels: &mut NcChannels, alpha: NcAlphaBits) {
|
||||
let mut channel = ncchannels_fchannel(*channels);
|
||||
ncchannel_set_alpha(&mut channel, alpha);
|
||||
*channels = (channel as NcChannels) << 32 | *channels & 0xffffffff_u64;
|
||||
}
|
||||
|
||||
/// Sets the [`NcAlphaBits`] of the background [`NcChannel`] of an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_alpha()][NcChannels#method.set_bg_alpha]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_alpha(channels: &mut NcChannels, alpha: NcAlphaBits) {
|
||||
let mut alpha_clean = alpha;
|
||||
if alpha == NCALPHA_HIGHCONTRAST {
|
||||
// forbidden for background alpha, so makes it opaque
|
||||
alpha_clean = NCALPHA_OPAQUE;
|
||||
}
|
||||
let mut channel = ncchannels_bchannel(*channels);
|
||||
ncchannel_set_alpha(&mut channel, alpha_clean);
|
||||
ncchannels_set_bchannel(channels, channel);
|
||||
}
|
||||
|
||||
// Channels --------------------------------------------------------------------
|
||||
|
||||
/// Extracts the background [`NcChannel`] from a [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[bchannel()][NcChannels#method.bchannel]*
|
||||
#[inline]
|
||||
pub const fn ncchannels_bchannel(channels: NcChannels) -> NcChannel {
|
||||
(channels & 0xffffffff_u64) as NcChannel
|
||||
}
|
||||
|
||||
/// Extracts the foreground [`NcChannel`] from an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[fchannel()][NcChannels#method.fchannel]*
|
||||
#[inline]
|
||||
pub const fn ncchannels_fchannel(channels: NcChannels) -> NcChannel {
|
||||
ncchannels_bchannel(channels >> 32)
|
||||
}
|
||||
|
||||
/// Sets the background [`NcChannel`] of an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_bchannel()][NcChannels#method.set_bchannel]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bchannel(channels: &mut NcChannels, bchannel: NcChannel) -> NcChannels {
|
||||
*channels = (*channels & 0xffffffff00000000_u64) | bchannel as u64;
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcChannel`] of an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_fchannel()][NcChannels#method.set_fchannel]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fchannel(channels: &mut NcChannels, fchannel: NcChannel) -> NcChannels {
|
||||
*channels = (*channels & 0xffffffff_u64) | (fchannel as u64) << 32;
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Combines two [`NcChannel`]s into an [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[combine()][NcChannels#method.combine]*
|
||||
#[inline]
|
||||
pub fn ncchannels_combine(fchannel: NcChannel, bchannel: NcChannel) -> NcChannels {
|
||||
let mut channels: NcChannels = 0;
|
||||
ncchannels_set_fchannel(&mut channels, fchannel);
|
||||
ncchannels_set_bchannel(&mut channels, bchannel);
|
||||
channels
|
||||
}
|
||||
|
||||
// NcComponent ---------------------------------------------------------------------
|
||||
|
||||
/// Gets the red [`NcComponent`] from an [`NcChannel`].
|
||||
///
|
||||
/// *Method: NcChannel.[r()][NcChannel#method.r]*
|
||||
#[inline]
|
||||
pub const fn ncchannel_r(channel: NcChannel) -> NcComponent {
|
||||
((channel & 0xff0000) >> 16) as NcComponent
|
||||
}
|
||||
|
||||
/// Gets the green [`NcComponent`] from an [`NcChannel`].
|
||||
///
|
||||
/// *Method: NcChannel.[g()][NcChannel#method.g]*
|
||||
#[inline]
|
||||
pub const fn ncchannel_g(channel: NcChannel) -> NcComponent {
|
||||
((channel & 0x00ff00) >> 8) as NcComponent
|
||||
}
|
||||
|
||||
/// Gets the blue [`NcComponent`] from an [`NcChannel`].
|
||||
///
|
||||
/// *Method: NcChannel.[b()][NcChannel#method.b]*
|
||||
#[inline]
|
||||
pub const fn ncchannel_b(channel: NcChannel) -> NcComponent {
|
||||
(channel & 0x0000ff) as NcComponent
|
||||
}
|
||||
|
||||
/// Sets the red [`NcComponent`] of an [`NcChannel`], and returns it.
|
||||
///
|
||||
/// *Method: NcChannel.[set_r()][NcChannel#method.set_r]*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncchannel_set_r(channel: &mut NcChannel, r: NcComponent) -> NcChannel {
|
||||
*channel = (r as NcChannel) << 16 | (*channel & 0xff00) | (*channel & 0xff);
|
||||
*channel
|
||||
}
|
||||
|
||||
/// Sets the green [`NcComponent`] of an [`NcChannel`], and returns it.
|
||||
///
|
||||
/// *Method: NcChannel.[set_g()][NcChannel#method.set_g]*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncchannel_set_g(channel: &mut NcChannel, g: NcComponent) -> NcChannel {
|
||||
*channel = (*channel & 0xff0000) | (g as NcChannel) << 8 | (*channel & 0xff);
|
||||
*channel
|
||||
}
|
||||
|
||||
/// Sets the blue [`NcComponent`] of an [`NcChannel`], and returns it.
|
||||
///
|
||||
/// *Method: NcChannel.[set_b()][NcChannel#method.set_b]*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncchannel_set_b(channel: &mut NcChannel, b: NcComponent) -> NcChannel {
|
||||
*channel = (*channel & 0xff0000) | (*channel & 0xff00) | (b as NcChannel);
|
||||
*channel
|
||||
}
|
||||
|
||||
/// Gets the three RGB [`NcComponent`]s from an [`NcChannel`], and returns it.
|
||||
///
|
||||
/// *Method: NcChannel.[rgb8()][NcChannel#method.rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannel_rgb8(
|
||||
channel: NcChannel,
|
||||
r: &mut NcComponent,
|
||||
g: &mut NcComponent,
|
||||
b: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
*r = ncchannel_r(channel);
|
||||
*g = ncchannel_g(channel);
|
||||
*b = ncchannel_b(channel);
|
||||
channel
|
||||
}
|
||||
|
||||
/// Sets the three RGB [`NcComponent`]s an [`NcChannel`], and marks it as NOT using the
|
||||
/// "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// *Method: NcChannel.[set_rgb8()][NcChannel#method.set_rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannel_set_rgb8(channel: &mut NcChannel, r: NcComponent, g: NcComponent, b: NcComponent) {
|
||||
let rgb: NcRgb = (r as NcChannel) << 16 | (g as NcChannel) << 8 | (b as NcChannel);
|
||||
*channel = (*channel & !NCALPHA_BG_RGB_MASK) | NCALPHA_BGDEFAULT_MASK | rgb;
|
||||
}
|
||||
|
||||
/// Gets the three foreground RGB [`NcComponent`]s from an [`NcChannels`], and
|
||||
/// returns the foreground [`NcChannel`] (which can have some extra bits set).
|
||||
///
|
||||
/// *Method: NcChannels.[fg_rgb8()][NcChannels#method.fg_rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannels_fg_rgb8(
|
||||
channels: NcChannels,
|
||||
r: &mut NcComponent,
|
||||
g: &mut NcComponent,
|
||||
b: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
ncchannel_rgb8(ncchannels_fchannel(channels), r, g, b)
|
||||
}
|
||||
|
||||
/// Gets the three background RGB [`NcComponent`]s from an [`NcChannels`], and
|
||||
/// returns the background [`NcChannel`] (which can have some extra bits set).
|
||||
///
|
||||
/// *Method: NcChannels.[bg_rgb8()][NcChannels#method.bg_rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannels_bg_rgb8(
|
||||
channels: NcChannels,
|
||||
r: &mut NcComponent,
|
||||
g: &mut NcComponent,
|
||||
b: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
ncchannel_rgb8(ncchannels_bchannel(channels), r, g, b)
|
||||
}
|
||||
|
||||
/// Sets the three foreground RGB [`NcComponent`]s of an [`NcChannels`], and
|
||||
/// marks it as NOT using the "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// Unlike the original C API, it also returns the new NcChannels.
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_rgb8()][NcChannels#method.set_fg_rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fg_rgb8(
|
||||
channels: &mut NcChannels,
|
||||
r: NcComponent,
|
||||
g: NcComponent,
|
||||
b: NcComponent,
|
||||
) -> NcChannels {
|
||||
let mut channel = ncchannels_fchannel(*channels);
|
||||
ncchannel_set_rgb8(&mut channel, r, g, b);
|
||||
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Sets the three background RGB [`NcComponent`]s of an [`NcChannels`], and
|
||||
/// marks it as NOT using the "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// Unlike the original C API, it also returns the new NcChannels.
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_rgb8()][NcChannels#method.set_bg_rgb8]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_rgb8(
|
||||
channels: &mut NcChannels,
|
||||
r: NcComponent,
|
||||
g: NcComponent,
|
||||
b: NcComponent,
|
||||
) -> NcChannels {
|
||||
let mut channel = ncchannels_bchannel(*channels);
|
||||
ncchannel_set_rgb8(&mut channel, r, g, b);
|
||||
ncchannels_set_bchannel(channels, channel);
|
||||
*channels
|
||||
}
|
||||
|
||||
// NcRgb -----------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [`NcRgb`] from an [`NcChannels`], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcChannels.[fg_rgb()][NcChannels#method.fg_rgb]*
|
||||
#[inline]
|
||||
pub fn ncchannels_fg_rgb(channels: NcChannels) -> NcRgb {
|
||||
ncchannels_fchannel(channels) & NCALPHA_BG_RGB_MASK
|
||||
}
|
||||
|
||||
/// Gets the background [`NcRgb`] from an [`NcChannels`], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcChannels.[bg_rgb()][NcChannels#method.bg_rgb]*
|
||||
#[inline]
|
||||
pub fn ncchannels_bg_rgb(channels: NcChannels) -> NcRgb {
|
||||
ncchannels_bchannel(channels) & NCALPHA_BG_RGB_MASK
|
||||
}
|
||||
|
||||
/// Gets the [`NcRgb`] of an [`NcChannel`].
|
||||
///
|
||||
/// This function basically removes the 4th byte of the NcChannel.
|
||||
///
|
||||
/// *Method: NcChannel.[rgb()][NcChannel#method.rgb]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub const fn ncchannel_rgb(channel: NcChannel) -> NcRgb {
|
||||
channel & NCALPHA_BG_RGB_MASK
|
||||
}
|
||||
|
||||
/// Sets the [`NcRgb`] of an [`NcChannel`], and marks it as NOT using the
|
||||
/// "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// *Method: NcChannel.[set()][NcChannel#method.set]*
|
||||
#[inline]
|
||||
pub fn ncchannel_set(channel: &mut NcChannel, rgb: NcRgb) {
|
||||
*channel = (*channel & !NCALPHA_BG_RGB_MASK) | NCALPHA_BGDEFAULT_MASK | (rgb & 0x00ffffff);
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcRgb`] of an [`NcChannels`], and marks it as NOT using
|
||||
/// the "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_rgb()][NcChannels#method.set_fg_rgb]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fg_rgb(channels: &mut NcChannels, rgb: NcRgb) {
|
||||
let mut channel = ncchannels_fchannel(*channels);
|
||||
ncchannel_set(&mut channel, rgb);
|
||||
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
|
||||
}
|
||||
|
||||
/// Sets the foreground [`NcRgb`] of an [`NcChannels`], and marks it as NOT using
|
||||
/// the "default color", retaining the other bits unchanged.
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_rgb()][NcChannels#method.set_bg_rgb]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_rgb(channels: &mut NcChannels, rgb: NcRgb) {
|
||||
let mut channel = ncchannels_bchannel(*channels);
|
||||
ncchannel_set(&mut channel, rgb);
|
||||
ncchannels_set_bchannel(channels, channel);
|
||||
}
|
||||
|
||||
// Default ---------------------------------------------------------------------
|
||||
|
||||
/// Is this [`NcChannel`] using the "default color" rather than RGB/palette-indexed?
|
||||
///
|
||||
/// *Method: NcChannel.[default_p()][NcChannel#method.default_p]*
|
||||
#[inline]
|
||||
pub const fn ncchannel_default_p(channel: NcChannel) -> bool {
|
||||
(channel & NCALPHA_BGDEFAULT_MASK) == 0
|
||||
}
|
||||
|
||||
/// Marks an [`NcChannel`] as using its "default color", which also marks it opaque.
|
||||
///
|
||||
/// *Method: NcChannel.[set_default()][NcChannel#method.set_default]*
|
||||
#[inline]
|
||||
pub fn ncchannel_set_default(channel: &mut NcChannel) -> NcChannel {
|
||||
*channel &= !(NCALPHA_BGDEFAULT_MASK | NCALPHA_HIGHCONTRAST);
|
||||
*channel
|
||||
}
|
||||
|
||||
/// Marks an [`NcChannel`] as NOT using its "default color",
|
||||
/// retaining the other bits unchanged.
|
||||
///
|
||||
/// *Method: NcChannel.[set_not_default()][NcChannel#method.set_not_default]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub fn ncchannel_set_not_default(channel: &mut NcChannel) -> NcChannel {
|
||||
*channel |= NCALPHA_BGDEFAULT_MASK;
|
||||
*channel
|
||||
}
|
||||
|
||||
/// Is the foreground of an [`NcChannels`] using the "default foreground color"?
|
||||
///
|
||||
/// *Method: NcChannels.[fg_default_p()][NcChannels#method.fg_default_p]*
|
||||
#[inline]
|
||||
pub fn ncchannels_fg_default_p(channels: NcChannels) -> bool {
|
||||
ncchannel_default_p(ncchannels_fchannel(channels))
|
||||
}
|
||||
|
||||
/// Is the background using the "default background color"?
|
||||
///
|
||||
/// The "default background color" must generally be used to take advantage of
|
||||
/// terminal-effected transparency.
|
||||
///
|
||||
/// *Method: NcChannels.[bg_default_p()][NcChannels#method.bg_default_p]*
|
||||
#[inline]
|
||||
pub fn ncchannels_bg_default_p(channels: NcChannels) -> bool {
|
||||
ncchannel_default_p(ncchannels_bchannel(channels))
|
||||
}
|
||||
|
||||
/// Marks the foreground of an [`NcChannels`] as using its "default color",
|
||||
/// which also marks it opaque, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_default()][NcChannels#method.set_fg_default]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fg_default(channels: &mut NcChannels) -> NcChannels {
|
||||
let mut channel = ncchannels_fchannel(*channels);
|
||||
ncchannel_set_default(&mut channel);
|
||||
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Marks the foreground of an [`NcChannels`] as NOT using its "default color",
|
||||
/// retaining the other bits unchanged, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_not_default()][NcChannels#method.set_fg_not_default]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub fn ncchannels_set_fg_not_default(channels: &mut NcChannels) -> NcChannels {
|
||||
let mut channel = ncchannels_fchannel(*channels);
|
||||
ncchannel_set_not_default(&mut channel);
|
||||
*channels = (channel as u64) << 32 | *channels & 0xffffffff_u64;
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Marks the background of an [`NcChannels`] as using its "default color",
|
||||
/// which also marks it opaque, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_default()][NcChannels#method.set_bg_default]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_default(channels: &mut NcChannels) -> NcChannels {
|
||||
let mut channel = ncchannels_bchannel(*channels);
|
||||
ncchannel_set_default(&mut channel);
|
||||
ncchannels_set_bchannel(channels, channel);
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Marks the background of an [`NcChannels`] as NOT using its "default color",
|
||||
/// retaining the other bits unchanged, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_not_default()][NcChannels#method.set_bg_not_default]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_not_default(channels: &mut NcChannels) -> NcChannels {
|
||||
let mut channel = ncchannels_bchannel(*channels);
|
||||
ncchannel_set_not_default(&mut channel);
|
||||
ncchannels_set_bchannel(channels, channel);
|
||||
*channels
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background of an [`NcChannels`] as using their
|
||||
/// "default color", which also marks them opaque, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_default()][NcChannels#method.set_default]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub fn ncchannels_set_default(channels: &mut NcChannels) -> NcChannels {
|
||||
ncchannels_set_bg_default(&mut ncchannels_set_fg_default(channels))
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background of an [`NcChannels`] as NOT using their
|
||||
/// "default color", retaining the other bits unchanged, and returns the new [`NcChannels`].
|
||||
///
|
||||
/// *Method: NcChannels.[set_not_default()][NcChannels#method.set_not_default]*
|
||||
//
|
||||
// Not in the C API
|
||||
#[inline]
|
||||
pub fn ncchannels_set_not_default(channels: &mut NcChannels) -> NcChannels {
|
||||
ncchannels_set_bg_not_default(&mut ncchannels_set_fg_not_default(channels))
|
||||
}
|
||||
|
||||
// Palette ---------------------------------------------------------------------
|
||||
|
||||
/// Is this [`NcChannel`] using palette-indexed color rather than RGB?
|
||||
///
|
||||
/// *Method: NcChannel.[palindex_p()][NcChannel#method.palindex_p]*
|
||||
#[inline]
|
||||
pub fn ncchannel_palindex_p(channel: NcChannel) -> bool {
|
||||
!(ncchannel_default_p(channel) && (channel & NCALPHA_BG_PALETTE) == 0)
|
||||
}
|
||||
|
||||
/// Is the foreground of an [`NcChannels`] using an [indexed][`NcPaletteIndex`]
|
||||
/// [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *Method: NcChannels.[fg_palindex_p()][NcChannels#method.fg_palindex_p]*
|
||||
#[inline]
|
||||
pub fn ncchannels_fg_palindex_p(channels: NcChannels) -> bool {
|
||||
ncchannel_palindex_p(ncchannels_fchannel(channels))
|
||||
}
|
||||
|
||||
/// Is the background of an [`NcChannels`] using an [indexed][`NcPaletteIndex`]
|
||||
/// [`NcPalette`][crate::NcPalette] color?
|
||||
///
|
||||
/// *Method: NcChannels.[bg_palindex_p()][NcChannels#method.bg_palindex_p]*
|
||||
#[inline]
|
||||
pub fn ncchannels_bg_palindex_p(channels: NcChannels) -> bool {
|
||||
ncchannel_palindex_p(ncchannels_bchannel(channels))
|
||||
}
|
||||
|
||||
/// Sets the foreground of an [`NcChannels`] as using an
|
||||
/// [indexed][`NcPaletteIndex`] [`NcPalette`][crate::NcPalette] color.
|
||||
///
|
||||
/// *Method: NcChannels.[set_fg_palindex()][NcChannels#method.set_fg_palindex]*
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub fn ncchannels_set_fg_palindex(channels: &mut NcChannels, index: NcPaletteIndex) {
|
||||
*channels |= NCALPHA_FGDEFAULT_MASK;
|
||||
*channels |= NCALPHA_FG_PALETTE as NcChannels;
|
||||
ncchannels_set_fg_alpha(channels, NCALPHA_OPAQUE);
|
||||
*channels &= 0xff000000ffffffff as NcChannels;
|
||||
*channels |= (index as NcChannels) << 32;
|
||||
}
|
||||
|
||||
/// Sets the background of an [`NcChannels`] as using an
|
||||
/// [indexed][`NcPaletteIndex`] [`NcPalette`][crate::NcPalette] color.
|
||||
///
|
||||
/// *Method: NcChannels.[set_bg_palindex()][NcChannels#method.set_bg_palindex]*
|
||||
#[inline]
|
||||
pub fn ncchannels_set_bg_palindex(channels: &mut NcChannels, index: NcPaletteIndex) {
|
||||
*channels |= NCALPHA_BGDEFAULT_MASK as NcChannels;
|
||||
*channels |= NCALPHA_BG_PALETTE as NcChannels;
|
||||
ncchannels_set_bg_alpha(channels, NCALPHA_OPAQUE);
|
||||
*channels &= 0xffffffffff000000;
|
||||
*channels |= index as NcChannels;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
//! Test `NcChannel*` methods and associated functions.
|
||||
|
||||
// use crate::{NcChannel, NcChannels};
|
||||
//
|
||||
// use serial_test::serial;
|
||||
//
|
||||
// #[test]
|
||||
// #[serial]
|
||||
// fn () {
|
||||
// }
|
@ -1,7 +0,0 @@
|
||||
//! `NcChannel*` tests.
|
||||
|
||||
#[cfg(test)]
|
||||
mod methods;
|
||||
|
||||
#[cfg(test)]
|
||||
mod reimplemented;
|
@ -1,226 +0,0 @@
|
||||
//! Test `channel*_*` reimplemented functions.
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::{
|
||||
NcChannel, NcChannels, NCALPHA_BLEND, NCALPHA_HIGHCONTRAST, NCALPHA_OPAQUE, NCALPHA_TRANSPARENT,
|
||||
};
|
||||
|
||||
// NcChannel tests -------------------------------------------------------------
|
||||
|
||||
/// retrieves the red NcComponent component
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_r() {
|
||||
let c: NcChannel = 0x112233;
|
||||
assert_eq!(crate::ncchannel_r(c), 0x11);
|
||||
}
|
||||
|
||||
/// retrieves the green NcComponent component
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_g() {
|
||||
let c: NcChannel = 0x112233;
|
||||
assert_eq!(crate::ncchannel_g(c), 0x22);
|
||||
}
|
||||
|
||||
/// retrieves the blue NcComponent component
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_b() {
|
||||
let c: NcChannel = 0x112233;
|
||||
assert_eq!(crate::ncchannel_b(c), 0x33);
|
||||
}
|
||||
|
||||
/// writes out the three RGB NcComponent components
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_rgb8() {
|
||||
let c: NcChannel = 0x112233;
|
||||
let mut r = 0;
|
||||
let mut g = 0;
|
||||
let mut b = 0;
|
||||
crate::ncchannel_rgb8(c, &mut r, &mut g, &mut b);
|
||||
assert_eq!(r, 0x11);
|
||||
assert_eq!(g, 0x22);
|
||||
assert_eq!(b, 0x33);
|
||||
}
|
||||
|
||||
/// sets the three RGB NcComponent components
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_set_rgb8() {
|
||||
let mut c = 0x000000;
|
||||
// by default it uses the default color
|
||||
assert_eq!(true, crate::ncchannel_default_p(c));
|
||||
|
||||
crate::ncchannel_set_rgb8(&mut c, 0x11, 0x22, 0x33);
|
||||
|
||||
assert_eq!(crate::ncchannel_r(c), 0x11);
|
||||
assert_eq!(crate::ncchannel_g(c), 0x22);
|
||||
assert_eq!(crate::ncchannel_b(c), 0x33);
|
||||
|
||||
// now it shoud be marked as NOT using the default color
|
||||
assert_eq!(false, crate::ncchannel_default_p(c));
|
||||
}
|
||||
|
||||
/// sets the NcRGB color components
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_set() {
|
||||
let mut c = 0x000000;
|
||||
// by default it uses the default color
|
||||
assert_eq!(true, crate::ncchannel_default_p(c));
|
||||
|
||||
crate::ncchannel_set(&mut c, 0x112233);
|
||||
println!("\n {:08x}", c); // DEBUG
|
||||
|
||||
assert_eq!(crate::ncchannel_r(c), 0x11);
|
||||
assert_eq!(crate::ncchannel_g(c), 0x22);
|
||||
assert_eq!(crate::ncchannel_b(c), 0x33);
|
||||
|
||||
// now it shoud be marked as NOT using the default color
|
||||
assert_eq!(false, crate::ncchannel_default_p(c));
|
||||
}
|
||||
|
||||
/// gets the alpha component
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_alpha() {
|
||||
let c: NcChannel = 0x112233;
|
||||
assert_ne!(crate::ncchannel_alpha(c), NCALPHA_TRANSPARENT);
|
||||
|
||||
let c: NcChannel = 0x112233 | NCALPHA_TRANSPARENT;
|
||||
assert_eq!(crate::ncchannel_alpha(c), NCALPHA_TRANSPARENT);
|
||||
}
|
||||
|
||||
/// sets the alpha component
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_set_alpha() {
|
||||
let mut c: NcChannel = 0x112233;
|
||||
crate::ncchannel_set_alpha(&mut c, NCALPHA_HIGHCONTRAST);
|
||||
assert_eq!(NCALPHA_HIGHCONTRAST, crate::ncchannel_alpha(c));
|
||||
|
||||
crate::ncchannel_set_alpha(&mut c, NCALPHA_TRANSPARENT);
|
||||
assert_eq!(NCALPHA_TRANSPARENT, crate::ncchannel_alpha(c));
|
||||
|
||||
crate::ncchannel_set_alpha(&mut c, NCALPHA_BLEND);
|
||||
assert_eq!(NCALPHA_BLEND, crate::ncchannel_alpha(c));
|
||||
|
||||
crate::ncchannel_set_alpha(&mut c, NCALPHA_OPAQUE);
|
||||
assert_eq!(NCALPHA_OPAQUE, crate::ncchannel_alpha(c));
|
||||
// TODO: CHECK for NCALPHA_BGDEFAULT_MASK
|
||||
}
|
||||
|
||||
/// sets the channel as using the default color
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_set_default() {
|
||||
let channel = 0x_00_112233;
|
||||
// By default a channel uses the default color, if the proper bit isn't set
|
||||
assert_eq!(true, crate::ncchannel_default_p(channel));
|
||||
|
||||
// If we change it from being opaque...
|
||||
let mut channel_transp = channel | NCALPHA_TRANSPARENT;
|
||||
assert_eq!(0x_20_112233, channel_transp); // the transparent bit is now set
|
||||
|
||||
crate::ncchannel_set_not_default(&mut channel_transp);
|
||||
// both the "not default" & transparent bits are now set
|
||||
assert_eq!(0x_60_112233, channel_transp);
|
||||
|
||||
// and calling set_default() should make it both default & opaque again
|
||||
assert_eq!(
|
||||
0x_00_112233,
|
||||
crate::ncchannel_set_default(&mut channel_transp)
|
||||
);
|
||||
}
|
||||
|
||||
/// sets the channel as *not* using the default color
|
||||
//
|
||||
// more functions that marks as NOT using the default color:
|
||||
// - channel_set()
|
||||
// - channel_set_rgb8()
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_set_not_default() {
|
||||
let mut channel = 0x_00_112233;
|
||||
// By default a channel uses the default color, if the proper bit isn't set
|
||||
assert_eq!(true, crate::ncchannel_default_p(channel));
|
||||
|
||||
// marking it as NOT using the default color
|
||||
crate::ncchannel_set_not_default(&mut channel);
|
||||
assert_eq!(0x_40_112233, channel); // check the "not default" bit is set
|
||||
assert_eq!(false, crate::ncchannel_default_p(channel));
|
||||
}
|
||||
|
||||
/// checks whether the channel is using the default color
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channel_default_p() {
|
||||
let mut c: NcChannel = 0x112233;
|
||||
assert_eq!(true, crate::ncchannel_default_p(c));
|
||||
|
||||
let _ = crate::ncchannel_set_alpha(&mut c, NCALPHA_OPAQUE);
|
||||
assert_eq!(true, crate::ncchannel_default_p(c));
|
||||
|
||||
crate::ncchannel_set(&mut c, 0x112233);
|
||||
assert_eq!(false, crate::ncchannel_default_p(c));
|
||||
}
|
||||
|
||||
// NcChannels tests ---------------------------------------------------------
|
||||
|
||||
///
|
||||
#[test]
|
||||
#[serial]
|
||||
#[allow(non_snake_case)]
|
||||
fn channels_set_fchannel__channels_fchannel() {
|
||||
let fc: NcChannel = 0x112233;
|
||||
let mut cp: NcChannels = 0;
|
||||
crate::ncchannels_set_fchannel(&mut cp, fc);
|
||||
assert_eq!(crate::ncchannels_fchannel(cp), fc);
|
||||
}
|
||||
|
||||
///
|
||||
#[test]
|
||||
#[serial]
|
||||
#[allow(non_snake_case)]
|
||||
fn channels_set_bchannel__channels_bchannel() {
|
||||
let bc: NcChannel = 0x112233;
|
||||
let mut cp: NcChannels = 0;
|
||||
crate::ncchannels_set_bchannel(&mut cp, bc);
|
||||
assert_eq!(crate::ncchannels_bchannel(cp), bc);
|
||||
}
|
||||
|
||||
///
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channels_combine() {
|
||||
let bc: NcChannel = 0x112233;
|
||||
let fc: NcChannel = 0x445566;
|
||||
let mut cp1: NcChannels = 0;
|
||||
let mut _cp2: NcChannels = 0;
|
||||
crate::ncchannels_set_bchannel(&mut cp1, bc);
|
||||
crate::ncchannels_set_fchannel(&mut cp1, fc);
|
||||
_cp2 = crate::ncchannels_combine(fc, bc);
|
||||
assert_eq!(cp1, _cp2);
|
||||
}
|
||||
|
||||
///
|
||||
#[test]
|
||||
#[serial]
|
||||
fn channels_palette() {
|
||||
let bc: NcChannel = 0x112233;
|
||||
let fc: NcChannel = 0x445566;
|
||||
assert_eq!(false, crate::ncchannel_palindex_p(bc));
|
||||
assert_eq!(false, crate::ncchannel_palindex_p(fc));
|
||||
|
||||
let mut channels = crate::ncchannels_combine(fc, bc);
|
||||
assert_eq!(false, crate::ncchannels_fg_palindex_p(channels));
|
||||
assert_eq!(false, crate::ncchannels_bg_palindex_p(channels));
|
||||
|
||||
crate::ncchannels_set_fg_palindex(&mut channels, 5);
|
||||
crate::ncchannels_set_bg_palindex(&mut channels, 6);
|
||||
assert_eq!(true, crate::ncchannels_fg_palindex_p(channels));
|
||||
assert_eq!(true, crate::ncchannels_bg_palindex_p(channels));
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
//! `NcDim`, `NcOffset`
|
||||
|
||||
/// Represents a dimension in rows or columns. Can't be negative.
|
||||
pub type NcDim = u32;
|
||||
|
||||
/// Represents an offset in rows or columns. Can be negative.
|
||||
pub type NcOffset = i32;
|
@ -1,767 +0,0 @@
|
||||
//! `NcDirect` methods and associated functions.
|
||||
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
use crate::{
|
||||
cstring, error, error_ref_mut, rstring, NcAlign, NcBlitter, NcCapabilities, NcChannels,
|
||||
NcComponent, NcDim, NcDirect, NcDirectFlags, NcError, NcInput, NcOffset, NcPaletteIndex,
|
||||
NcPlane, NcResult, NcRgb, NcScale, NcStyle, NcTime, NCRESULT_ERR,
|
||||
};
|
||||
|
||||
/// # `NcDirect` constructors and destructors
|
||||
impl NcDirect {
|
||||
/// New NcDirect with the default options.
|
||||
///
|
||||
/// Initializes a direct-mode notcurses context on the tty.
|
||||
///
|
||||
/// Direct mode supports a limited subset of notcurses routines,
|
||||
/// and neither supports nor requires
|
||||
/// [notcurses_render()][crate::notcurses_render]. This can be used to add
|
||||
/// color and styling to text in the standard output paradigm.
|
||||
///
|
||||
/// *C style function: [ncdirect_init()][crate::ncdirect_init].*
|
||||
pub fn new<'a>() -> NcResult<&'a mut NcDirect> {
|
||||
Self::with_flags(0)
|
||||
}
|
||||
|
||||
/// New NcDirect with optional flags.
|
||||
///
|
||||
/// `flags` is a bitmask over:
|
||||
/// - [NCDIRECT_OPTION_INHIBIT_CBREAK][crate::NCDIRECT_OPTION_INHIBIT_CBREAK]
|
||||
/// - [NCDIRECT_OPTION_INHIBIT_SETLOCALE][crate::NCDIRECT_OPTION_INHIBIT_SETLOCALE]
|
||||
/// - [NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS][crate::NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS]
|
||||
/// - [NCDIRECT_OPTION_VERBOSE][crate::NCDIRECT_OPTION_VERBOSE]
|
||||
/// - [NCDIRECT_OPTION_VERY_VERBOSE][crate::NCDIRECT_OPTION_VERY_VERBOSE]
|
||||
///
|
||||
/// *C style function: [ncdirect_init()][crate::ncdirect_init].*
|
||||
pub fn with_flags<'a>(flags: NcDirectFlags) -> NcResult<&'a mut NcDirect> {
|
||||
let res = unsafe { crate::ncdirect_init(null(), null_mut(), flags) };
|
||||
error_ref_mut![res, "Initializing NcDirect"]
|
||||
}
|
||||
|
||||
/// Releases this NcDirect and any associated resources.
|
||||
///
|
||||
/// *C style function: [ncdirect_stop()][crate::ncdirect_stop].*
|
||||
pub fn stop(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_stop(self) }, "NcDirect.stop()"]
|
||||
}
|
||||
}
|
||||
|
||||
/// ## NcDirect methods: clear, flush, render
|
||||
impl NcDirect {
|
||||
/// Clears the screen.
|
||||
///
|
||||
/// *C style function: [ncdirect_clear()][crate::ncdirect_clear].*
|
||||
pub fn clear(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_clear(self) }, "NcDirect.clear()"]
|
||||
}
|
||||
|
||||
/// Forces a flush.
|
||||
///
|
||||
/// *C style function: [ncdirect_flush()][crate::ncdirect_flush].*
|
||||
pub fn flush(&self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_flush(self) }, "NcDirect.clear()"]
|
||||
}
|
||||
|
||||
/// Takes the result of [`render_frame`][NcDirect#method.render_frame]
|
||||
/// and writes it to the output.
|
||||
///
|
||||
/// *C style function: [ncdirect_raster_frame()][crate::ncdirect_raster_frame].*
|
||||
pub fn raster_frame(&mut self, frame: &mut NcPlane, align: NcAlign) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_raster_frame(self, frame, align) },
|
||||
"NcDirect.raster_frame()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Renders an image using the specified blitter and scaling,
|
||||
/// but doesn't write the result.
|
||||
///
|
||||
/// The image may be arbitrarily many rows -- the output will scroll --
|
||||
/// but will only occupy the column of the cursor, and those to the right.
|
||||
///
|
||||
/// To actually write (and free) this, invoke ncdirect_raster_frame().
|
||||
///
|
||||
/// `max_y' and 'max_x` (cell geometry, *not* pixel), if greater than 0,
|
||||
/// are used for scaling; the terminal's geometry is otherwise used.
|
||||
///
|
||||
/// *C style function: [ncdirect_render_frame()][crate::ncdirect_render_frame].*
|
||||
pub fn render_frame<'a>(
|
||||
&mut self,
|
||||
filename: &str,
|
||||
blitter: NcBlitter,
|
||||
scale: NcScale,
|
||||
max_y: NcDim,
|
||||
max_x: NcDim,
|
||||
) -> NcResult<&'a mut NcPlane> {
|
||||
let res = unsafe {
|
||||
crate::ncdirect_render_frame(
|
||||
self,
|
||||
cstring![filename],
|
||||
blitter,
|
||||
scale,
|
||||
max_y as i32,
|
||||
max_x as i32,
|
||||
)
|
||||
};
|
||||
error_ref_mut![
|
||||
res,
|
||||
&format!(
|
||||
"NcDirect.render_frame({:?}, {:?}, {:?})",
|
||||
filename, blitter, scale
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Displays an image using the specified blitter and scaling.
|
||||
///
|
||||
/// The image may be arbitrarily many rows -- the output will scroll -- but
|
||||
/// will only occupy the column of the cursor, and those to the right.
|
||||
///
|
||||
/// The render/raster process can be split by using
|
||||
/// [render_frame()][#method.render_frame] and
|
||||
/// [raster_frame()][#method.raster_frame].
|
||||
///
|
||||
/// *C style function: [ncdirect_render_image()][crate::ncdirect_render_image].*
|
||||
pub fn render_image(
|
||||
&mut self,
|
||||
filename: &str,
|
||||
align: NcAlign,
|
||||
blitter: NcBlitter,
|
||||
scale: NcScale,
|
||||
) -> NcResult<()> {
|
||||
error![
|
||||
unsafe {
|
||||
crate::ncdirect_render_image(self, cstring![filename], align, blitter, scale)
|
||||
},
|
||||
&format!(
|
||||
"NcDirect.render_image({:?}, {:?}, {:?}, {:?})",
|
||||
filename, align, blitter, scale
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// ## NcDirect methods: `NcPaletteIndex`, `NcRgb`, `NcStyle` & default color
|
||||
impl NcDirect {
|
||||
/// Sets the foreground [NcPaletteIndex].
|
||||
///
|
||||
/// *C style function: [ncdirect_set_fg_palindex()][crate::ncdirect_set_fg_palindex].*
|
||||
pub fn set_fg_palindex(&mut self, index: NcPaletteIndex) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_fg_palindex(self, index as i32) },
|
||||
&format!("NcDirect.set_fg_palindex({})", index)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the background [NcPaletteIndex].
|
||||
///
|
||||
/// *C style function: [ncdirect_set_bg_palindex()][crate::ncdirect_set_bg_palindex].*
|
||||
pub fn set_bg_palindex(&mut self, index: NcPaletteIndex) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_bg_palindex(self, index as i32) },
|
||||
&format!("NcDirect.set_fg_palindex({})", index)
|
||||
]
|
||||
}
|
||||
|
||||
/// Returns the number of simultaneous colors claimed to be supported,
|
||||
/// if there is color support.
|
||||
///
|
||||
/// Note that several terminal emulators advertise more colors than they
|
||||
/// actually support, downsampling internally.
|
||||
///
|
||||
/// *C style function: [ncdirect_palette_size()][crate::ncdirect_palette_size].*
|
||||
pub fn palette_size(&self) -> NcResult<u32> {
|
||||
let res = unsafe { crate::ncdirect_palette_size(self) };
|
||||
if res == 1 {
|
||||
return Err(NcError::with_msg(
|
||||
1,
|
||||
"No color support ← NcDirect.palette_size()",
|
||||
));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Sets the foreground [NcRgb].
|
||||
///
|
||||
/// *C style function: [ncdirect_set_fg_rgb()][crate::ncdirect_set_fg_rgb].*
|
||||
pub fn set_fg_rgb(&mut self, rgb: NcRgb) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_fg_rgb(self, rgb) },
|
||||
&format!("NcDirect.set_fg_rgb({})", rgb)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the background [NcRgb].
|
||||
///
|
||||
/// *C style function: [ncdirect_set_bg_rgb()][crate::ncdirect_set_bg_rgb].*
|
||||
pub fn set_bg_rgb(&mut self, rgb: NcRgb) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_bg_rgb(self, rgb) },
|
||||
&format!("NcDirect.set_bg_rgb({})", rgb)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the foreground [NcComponent] components.
|
||||
///
|
||||
/// *C style function: [ncdirect_set_fg_rgb8()][crate::ncdirect_set_fg_rgb8].*
|
||||
pub fn set_fg_rgb8(
|
||||
&mut self,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) -> NcResult<()> {
|
||||
error![
|
||||
crate::ncdirect_set_fg_rgb8(self, red, green, blue),
|
||||
&format!("NcDirect.set_fg_rgb8({}, {}, {})", red, green, blue)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the background [NcComponent] components.
|
||||
///
|
||||
/// *C style function: [ncdirect_set_bg_rgb()][crate::ncdirect_set_bg_rgb].*
|
||||
pub fn set_bg_rgb8(
|
||||
&mut self,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) -> NcResult<()> {
|
||||
error![
|
||||
crate::ncdirect_set_bg_rgb8(self, red, green, blue),
|
||||
&format!("NcDirect.set_bg_rgb8({}, {}, {})", red, green, blue)
|
||||
]
|
||||
}
|
||||
|
||||
/// Removes the specified styles.
|
||||
///
|
||||
/// *C style function: [ncdirect_off_styles()][crate::ncdirect_off_styles].*
|
||||
pub fn styles_off(&mut self, stylebits: NcStyle) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_off_styles(self, stylebits.into()) },
|
||||
&format!("NcDirect.styles_off({:0X})", stylebits)
|
||||
]
|
||||
}
|
||||
|
||||
/// Adds the specified styles.
|
||||
///
|
||||
/// *C style function: [ncdirect_on_styles()][crate::ncdirect_on_styles].*
|
||||
pub fn styles_on(&mut self, stylebits: NcStyle) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_on_styles(self, stylebits.into()) },
|
||||
&format!("NcDirect.styles_on({:0X})", stylebits)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets just the specified styles.
|
||||
///
|
||||
/// *C style function: [ncdirect_set_styles()][crate::ncdirect_set_styles].*
|
||||
pub fn styles_set(&mut self, stylebits: NcStyle) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_styles(self, stylebits.into()) },
|
||||
&format!("NcDirect.styles_set({:0X})", stylebits)
|
||||
]
|
||||
}
|
||||
|
||||
/// Indicates to use the "default color" for the foreground.
|
||||
///
|
||||
/// *C style function: [ncdirect_set_fg_default()][crate::ncdirect_set_fg_default].*
|
||||
pub fn set_fg_default(&mut self) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_fg_default(self) },
|
||||
"NcDirect.set_fg_default()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Indicates to use the "default color" for the background.
|
||||
///
|
||||
/// *C style function: [ncdirect_set_bg_default()][crate::ncdirect_set_bg_default].*
|
||||
pub fn set_bg_default(&mut self) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_set_bg_default(self) },
|
||||
"NcDirect.set_bg_default()"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// ## NcDirect methods: capabilities, cursor, dimensions
|
||||
impl NcDirect {
|
||||
/// Is there support for acquiring the cursor's current position?
|
||||
///
|
||||
/// Requires the u7 terminfo capability, and that we are connected to an
|
||||
/// actual terminal.
|
||||
pub fn canget_cursor(&self) -> bool {
|
||||
unsafe { crate::ncdirect_canget_cursor(self) }
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode braille?
|
||||
///
|
||||
/// *C style function: [ncdirect_canbraille()][crate::ncdirect_canbraille].*
|
||||
pub fn canbraille(&self) -> bool {
|
||||
crate::ncdirect_canbraille(self)
|
||||
}
|
||||
|
||||
/// Can we set the "hardware" palette?
|
||||
///
|
||||
/// Requires the "ccc" terminfo capability.
|
||||
///
|
||||
/// *C style function: [ncdirect_canchangecolor()][crate::ncdirect_canchangecolor].*
|
||||
pub fn canchangecolor(&self) -> bool {
|
||||
crate::ncdirect_canchangecolor(self)
|
||||
}
|
||||
|
||||
/// Can we fade?
|
||||
///
|
||||
/// Requires either the "rgb" or "ccc" terminfo capability.
|
||||
///
|
||||
/// *C style function: [ncdirect_canfade()][crate::ncdirect_canfade].*
|
||||
pub fn canfade(&self) -> bool {
|
||||
crate::ncdirect_canfade(self)
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode halfblocks?
|
||||
///
|
||||
/// *C style function: [ncdirect_canhalfblock()][crate::ncdirect_canhalfblock].*
|
||||
pub fn canhalfblock(&self) -> bool {
|
||||
crate::ncdirect_canhalfblock(self)
|
||||
}
|
||||
|
||||
/// Can we load images?
|
||||
///
|
||||
/// Requires being built against FFmpeg/OIIO.
|
||||
///
|
||||
/// *C style function: [ncdirect_canopen_images()][crate::ncdirect_canopen_images].*
|
||||
pub fn canopen_images(&self) -> bool {
|
||||
unsafe { crate::ncdirect_canopen_images(self) }
|
||||
}
|
||||
|
||||
/// Can we load videos?
|
||||
///
|
||||
/// Requires being built against FFmpeg/OIIO.
|
||||
///
|
||||
/// *C style function: [ncdirect_canopen_videos()][crate::ncdirect_canopen_videos].*
|
||||
pub fn canopen_videos(&self) -> bool {
|
||||
crate::ncdirect_canopen_videos(self)
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode quadrants?
|
||||
///
|
||||
/// *C style function: [ncdirect_canquadrant()][crate::ncdirect_canquadrant].*
|
||||
pub fn canquadrant(&self) -> bool {
|
||||
crate::ncdirect_canquadrant(self)
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode sextants?
|
||||
///
|
||||
/// *C style function: [ncdirect_cansextant()][crate::ncdirect_cansextant].*
|
||||
pub fn cansextant(&self) -> bool {
|
||||
crate::ncdirect_cansextant(self)
|
||||
}
|
||||
|
||||
/// Can we directly specify RGB values per cell, or only use palettes?
|
||||
///
|
||||
/// *C style function: [ncdirect_cantruecolor()][crate::ncdirect_cantruecolor].*
|
||||
pub fn cantruecolor(&self) -> bool {
|
||||
crate::ncdirect_cantruecolor(self)
|
||||
}
|
||||
|
||||
/// Is our encoding UTF-8?
|
||||
///
|
||||
/// Requires LANG being set to a UTF8 locale.
|
||||
///
|
||||
/// *C style function: [ncdirect_canutf8()][crate::ncdirect_canutf8].*
|
||||
pub fn canutf8(&self) -> bool {
|
||||
unsafe { crate::ncdirect_canutf8(self) }
|
||||
}
|
||||
|
||||
/// Returns the [`NcCapabilities`].
|
||||
///
|
||||
/// *C style function: [ncdirect_capabilities()][crate::ncdirect_capabilities].*
|
||||
pub fn capabilities(&self) -> NcCapabilities {
|
||||
crate::ncdirect_capabilities(self)
|
||||
}
|
||||
|
||||
/// Checks for pixel support.
|
||||
///
|
||||
/// Returns `false` for no support, or `true` if pixel output is supported.
|
||||
///
|
||||
/// This function must successfully return before NCBLIT_PIXEL is available.
|
||||
///
|
||||
/// Must not be called concurrently with either input or rasterization.
|
||||
///
|
||||
/// *C style function: [ncdirect_check_pixel_support()][crate::ncdirect_check-pixel_support].*
|
||||
#[allow(clippy::wildcard_in_or_patterns)]
|
||||
pub fn check_pixel_support(&self) -> NcResult<bool> {
|
||||
let res = unsafe { crate::ncdirect_check_pixel_support(self) };
|
||||
match res {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
NCRESULT_ERR | _ => Err(NcError::with_msg(res, "NcDirect.check_pixel_support()")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Disables the terminal's cursor, if supported.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_disable()][crate::ncdirect_cursor_disable].*
|
||||
pub fn cursor_disable(&mut self) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_disable(self) },
|
||||
"NcDirect.cursor_disable()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Enables the terminal's cursor, if supported.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_enable()][crate::ncdirect_cursor_enable].*
|
||||
pub fn cursor_enable(&mut self) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_enable(self) },
|
||||
"NcDirect.cursor_enable()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves the cursor down any number of rows.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_down()][crate::ncdirect_cursor_down].*
|
||||
pub fn cursor_down(&mut self, rows: NcOffset) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_down(self, rows as i32) },
|
||||
&format!("NcDirect.cursor_down({})", rows)
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves the cursor left any number of columns.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_left()][crate::ncdirect_cursor_left].*
|
||||
pub fn cursor_left(&mut self, cols: NcOffset) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_left(self, cols as i32) },
|
||||
&format!("NcDirect.cursor_left({})", cols)
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves the cursor right any number of columns.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_right()][crate::ncdirect_cursor_right].*
|
||||
pub fn cursor_right(&mut self, cols: NcOffset) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_right(self, cols as i32) },
|
||||
&format!("NcDirect.cursor_right({})", cols)
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves the cursor up any number of rows.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_up()][crate::ncdirect_cursor_up].*
|
||||
pub fn cursor_up(&mut self, rows: NcOffset) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_up(self, rows as i32) },
|
||||
&format!("NcDirect.cursor_up({})", rows)
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the cursor to the specified row `y`, column `x`.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_move_yx()][crate::ncdirect_cursor_move_yx].*
|
||||
pub fn cursor_set_yx(&mut self, y: NcDim, x: NcDim) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_cursor_move_yx(self, y as i32, x as i32) }]
|
||||
}
|
||||
|
||||
/// Sets the cursor to the specified row `y`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn cursor_set_y(&mut self, y: NcDim) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_cursor_move_yx(self, y as i32, -1) }]
|
||||
}
|
||||
|
||||
/// Sets the cursor to the specified column `x`.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn cursor_set_x(&mut self, x: NcDim) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_cursor_move_yx(self, -1, x as i32) }]
|
||||
}
|
||||
|
||||
/// Gets the cursor (y, x) position, when supported.
|
||||
///
|
||||
/// This requires writing to the terminal, and then reading from it.
|
||||
/// If the terminal doesn't reply, or doesn't reply in a way we understand,
|
||||
/// the results might be detrimental.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_yx()][crate::ncdirect_cursor_yx].*
|
||||
pub fn cursor_yx(&mut self) -> NcResult<(NcDim, NcDim)> {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
error![
|
||||
unsafe { crate::ncdirect_cursor_yx(self, &mut y, &mut x) },
|
||||
"",
|
||||
(y as NcDim, x as NcDim)
|
||||
]
|
||||
}
|
||||
|
||||
/// Pushes the cursor location to the terminal's stack.
|
||||
///
|
||||
/// The depth of this stack, and indeed its existence, is terminal-dependent.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_push()][crate::ncdirect_cursor_push].*
|
||||
pub fn cursor_push(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_cursor_push(self) }]
|
||||
}
|
||||
|
||||
/// Pops the cursor location from the terminal's stack.
|
||||
///
|
||||
/// The depth of this stack, and indeed its existence, is terminal-dependent.
|
||||
///
|
||||
/// *C style function: [ncdirect_cursor_pop()][crate::ncdirect_cursor_pop].*
|
||||
pub fn cursor_pop(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_cursor_pop(self) }]
|
||||
}
|
||||
|
||||
/// Gets the current number of rows.
|
||||
///
|
||||
/// *C style function: [ncdirect_dim_y()][crate::ncdirect_dim_y].*
|
||||
pub fn dim_y(&mut self) -> NcDim {
|
||||
unsafe { crate::ncdirect_dim_y(self) as NcDim }
|
||||
}
|
||||
|
||||
/// Gets the current number of columns.
|
||||
///
|
||||
/// *C style function: [ncdirect_dim_x()][crate::ncdirect_dim_x].*
|
||||
pub fn dim_x(&mut self) -> NcDim {
|
||||
unsafe { crate::ncdirect_dim_x(self) as NcDim }
|
||||
}
|
||||
|
||||
/// Gets the current number of rows and columns.
|
||||
///
|
||||
/// *C style function: [ncdirect_dim_y()][crate::ncdirect_dim_y].*
|
||||
pub fn dim_yx(&mut self) -> (NcDim, NcDim) {
|
||||
let y = unsafe { crate::ncdirect_dim_y(self) as NcDim };
|
||||
let x = unsafe { crate::ncdirect_dim_x(self) as NcDim };
|
||||
(y, x)
|
||||
}
|
||||
|
||||
/// Returns the name of the detected terminal.
|
||||
///
|
||||
/// *C style function: [ncdirect_detected_terminal()][crate::ncdirect_detected_terminal].*
|
||||
pub fn detected_terminal(&self) -> String {
|
||||
rstring![crate::ncdirect_detected_terminal(self)].to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// ## NcDirect methods: I/O
|
||||
impl NcDirect {
|
||||
/// Returns a [char] representing a single unicode point.
|
||||
///
|
||||
/// If an event is processed, the return value is the `id` field from that
|
||||
/// event.
|
||||
///
|
||||
/// Provide a None `time` to block at length, a `time` of 0 for non-blocking
|
||||
/// operation, and otherwise a timespec to bound blocking.
|
||||
///
|
||||
/// *C style function: [ncdirect_getc()][crate::ncdirect_getc].*
|
||||
//
|
||||
// CHECK returns 0 on a timeout.
|
||||
pub fn getc(&mut self, time: Option<NcTime>, input: Option<&mut NcInput>) -> NcResult<char> {
|
||||
let ntime;
|
||||
if let Some(time) = time {
|
||||
ntime = &time as *const _;
|
||||
} else {
|
||||
ntime = null();
|
||||
}
|
||||
let ninput;
|
||||
if let Some(input) = input {
|
||||
ninput = input as *mut _;
|
||||
} else {
|
||||
ninput = null_mut();
|
||||
}
|
||||
let c = unsafe { core::char::from_u32_unchecked(crate::ncdirect_get(self, ntime, ninput)) };
|
||||
if c as u32 as i32 == NCRESULT_ERR {
|
||||
return Err(NcError::new());
|
||||
}
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
///
|
||||
/// *C style function: [ncdirect_getc_nblock()][crate::ncdirect_getc_nblock].*
|
||||
pub fn getc_nblock(&mut self, input: &mut NcInput) -> char {
|
||||
crate::ncdirect_getc_nblock(self, input)
|
||||
}
|
||||
|
||||
///
|
||||
/// *C style function: [ncdirect_getc_blocking()][crate::ncdirect_getc_blocking].*
|
||||
pub fn getc_blocking(&mut self, input: &mut NcInput) -> char {
|
||||
crate::ncdirect_getc_blocking(self, input)
|
||||
}
|
||||
|
||||
/// Get a file descriptor suitable for input event poll()ing.
|
||||
///
|
||||
/// When this descriptor becomes available, you can call
|
||||
/// [getc_nblock()][NcDirect#method.getc_nblock], and input ought be ready.
|
||||
///
|
||||
/// This file descriptor is not necessarily the file descriptor associated
|
||||
/// with stdin (but it might be!).
|
||||
///
|
||||
/// *C style function: [ncdirect_inputready_fd()][crate::ncdirect_inputready_fd].*
|
||||
pub fn inputready_fd(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncdirect_inputready_fd(self) }]
|
||||
}
|
||||
|
||||
/// Outputs the `string` according to the `channels`, and
|
||||
/// returns the total number of characters written on success.
|
||||
///
|
||||
/// Note that it does not explicitly flush output buffers, so it will not
|
||||
/// necessarily be immediately visible.
|
||||
///
|
||||
/// It will fail if the NcDirect context and the foreground channel
|
||||
/// are both marked as using the default color.
|
||||
///
|
||||
/// *C style function: [ncdirect_putstr()][crate::ncdirect_putstr].*
|
||||
pub fn putstr(&mut self, channels: NcChannels, string: &str) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncdirect_putstr(self, channels, cstring![string]) },
|
||||
&format!("NcDirect.putstr({:0X}, {:?})", channels, string)
|
||||
]
|
||||
}
|
||||
|
||||
/// Reads a (heap-allocated) line of text using the Readline library.
|
||||
///
|
||||
/// Initializes Readline the first time it's called.
|
||||
///
|
||||
/// For input to be echoed to the terminal, it is necessary that the flag
|
||||
/// [NCDIRECT_OPTION_INHIBIT_CBREAK][crate::NCDIRECT_OPTION_INHIBIT_CBREAK]
|
||||
/// be provided to the constructor.
|
||||
///
|
||||
/// *C style function: [ncdirect_readline()][crate::ncdirect_readline].*
|
||||
pub fn readline(&mut self, prompt: &str) -> NcResult<&str> {
|
||||
let res = unsafe { crate::ncdirect_readline(self, cstring![prompt]) };
|
||||
if !res.is_null() {
|
||||
return Ok(rstring![res]);
|
||||
} else {
|
||||
Err(NcError::with_msg(
|
||||
NCRESULT_ERR,
|
||||
&format!["NcDirect.readline({})", prompt],
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws a box with its upper-left corner at the current cursor position,
|
||||
/// having dimensions `ylen` * `xlen`.
|
||||
///
|
||||
/// See NcPlane.[box()][NcPlane#method.box] for more information.
|
||||
///
|
||||
/// The minimum box size is 2x2, and it cannot be drawn off-screen.
|
||||
///
|
||||
/// `wchars` is an array of 6 characters: UL, UR, LL, LR, HL, VL.
|
||||
///
|
||||
/// *C style function: [ncdirect_box()][crate::ncdirect_box].*
|
||||
// TODO: CHECK, specially wchars.
|
||||
pub fn r#box(
|
||||
&mut self,
|
||||
ul: NcChannels,
|
||||
ur: NcChannels,
|
||||
ll: NcChannels,
|
||||
lr: NcChannels,
|
||||
wchars: &[char; 6],
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
ctlword: u32,
|
||||
) -> NcResult<()> {
|
||||
error![
|
||||
unsafe {
|
||||
let wchars = core::mem::transmute(wchars);
|
||||
crate::ncdirect_box(
|
||||
self,
|
||||
ul,
|
||||
ur,
|
||||
ll,
|
||||
lr,
|
||||
wchars,
|
||||
y_len as i32,
|
||||
x_len as i32,
|
||||
ctlword,
|
||||
)
|
||||
},
|
||||
&format!(
|
||||
"NcDirect.box({:0X}, {:0X}, {:0X}, {:0X}, {:?}, {}, {}, {})",
|
||||
ul, ur, ll, lr, wchars, y_len, x_len, ctlword
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// NcDirect.[box()][NcDirect#method.box] with the double box-drawing characters.
|
||||
///
|
||||
/// *C style function: [ncdirect_double_box()][crate::ncdirect_double_box].*
|
||||
pub fn double_box(
|
||||
&mut self,
|
||||
ul: NcChannels,
|
||||
ur: NcChannels,
|
||||
ll: NcChannels,
|
||||
lr: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
ctlword: u32,
|
||||
) -> NcResult<()> {
|
||||
error![unsafe {
|
||||
crate::ncdirect_double_box(self, ul, ur, ll, lr, y_len as i32, x_len as i32, ctlword)
|
||||
}]
|
||||
}
|
||||
|
||||
/// NcDirect.[box()][NcDirect#method.box] with the rounded box-drawing characters.
|
||||
///
|
||||
/// *C style function: [ncdirect_rounded_box()][crate::ncdirect_rounded_box].*
|
||||
pub fn rounded_box(
|
||||
&mut self,
|
||||
ul: NcChannels,
|
||||
ur: NcChannels,
|
||||
ll: NcChannels,
|
||||
lr: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
ctlword: u32,
|
||||
) -> NcResult<()> {
|
||||
error![unsafe {
|
||||
crate::ncdirect_rounded_box(self, ul, ur, ll, lr, y_len as i32, x_len as i32, ctlword)
|
||||
}]
|
||||
}
|
||||
|
||||
/// Draws horizontal lines using the specified [NcChannels]s, interpolating
|
||||
/// between them as we go.
|
||||
///
|
||||
/// All lines start at the current cursor position.
|
||||
///
|
||||
/// The string at `egc` may not use more than one column.
|
||||
///
|
||||
/// For a horizontal line, `len` cannot exceed the screen width minus the
|
||||
/// cursor's offset.
|
||||
///
|
||||
/// *C style function: [ncdirect_hline_interp()][crate::ncdirect_hline_interp].*
|
||||
#[inline]
|
||||
pub fn hline_interp(
|
||||
&mut self,
|
||||
egc: &str,
|
||||
len: NcDim,
|
||||
h1: NcChannels,
|
||||
h2: NcChannels,
|
||||
) -> NcResult<()> {
|
||||
error![crate::ncdirect_hline_interp(self, egc, len, h1, h2)]
|
||||
}
|
||||
|
||||
/// Draws horizontal lines using the specified [NcChannels]s, interpolating
|
||||
/// between them as we go.
|
||||
///
|
||||
/// All lines start at the current cursor position.
|
||||
///
|
||||
/// The string at `egc` may not use more than one column.
|
||||
///
|
||||
/// For a vertical line, `len` may be as long as you'd like; the screen
|
||||
/// will scroll as necessary.
|
||||
///
|
||||
/// *C style function: [ncdirect_vline_interp()][crate::ncdirect_vline_interp].*
|
||||
#[inline]
|
||||
pub fn vline_interp(
|
||||
&mut self,
|
||||
egc: &str,
|
||||
len: NcDim,
|
||||
h1: NcChannels,
|
||||
h2: NcChannels,
|
||||
) -> NcResult<()> {
|
||||
error![crate::ncdirect_vline_interp(self, egc, len, h1, h2)]
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
//! `NcDirect`
|
||||
|
||||
// total: 62
|
||||
// ---------------------------------------------------
|
||||
// (X) 1 : wont do
|
||||
// (~) 3 : TODO / WIP
|
||||
//
|
||||
// (f) 46 : unsafe ffi function exported by bindgen
|
||||
// (w) 1 : safely wrapped ffi function
|
||||
// (r) 11 : static function manually reimplemented
|
||||
//
|
||||
// (m) 55 : method implemented
|
||||
//
|
||||
// (t) 0 : unit test done for the function
|
||||
// (T) 0 : unit test done also for the method
|
||||
// ---------------------------------------------------
|
||||
// fm ncdirect_bg_default
|
||||
// fm ncdirect_bg_palindex
|
||||
// fm ncdirect_bg_rgb
|
||||
// fm ncdirect_box
|
||||
// rm ncdirect_canbraille
|
||||
// rm ncdirect_canchangecolor
|
||||
// fm ncdirect_canget_cursor
|
||||
// rm ncdirect_canfade
|
||||
// rm ncdirect_canhalfblock
|
||||
// fm ncdirect_canopen_images
|
||||
// rm ncdirect_canopen_videos
|
||||
// rm ncdirect_canquadrant
|
||||
// rm ncdirect_cantruecolor
|
||||
// fm ncdirect_canutf8
|
||||
// wm ncdirect_capabilities
|
||||
// fm ncdirect_check_pixel_support
|
||||
// fm ncdirect_clear
|
||||
//~f ncdirect_core_init
|
||||
// fm ncdirect_cursor_disable
|
||||
// fm ncdirect_cursor_down
|
||||
// fm ncdirect_cursor_enable
|
||||
// fm ncdirect_cursor_left
|
||||
// fm ncdirect_cursor_move_yx
|
||||
// fm ncdirect_cursor_pop
|
||||
// fm ncdirect_cursor_push
|
||||
// fm ncdirect_cursor_right
|
||||
// fm ncdirect_cursor_up
|
||||
// fm ncdirect_cursor_yx
|
||||
// fm ncdirect_detected_terminal
|
||||
// fm ncdirect_dim_x
|
||||
// fm ncdirect_dim_y
|
||||
// fm ncdirect_double_box
|
||||
// fm ncdirect_fg_default
|
||||
// fm ncdirect_fg_palindex
|
||||
// fm ncdirect_fg_rgb
|
||||
// fm ncdirect_flush
|
||||
// fm ncdirect_getc
|
||||
//~r ncdirect_heavy_box,
|
||||
// fm ncdirect_hline_interp
|
||||
// fm ncdirect_init
|
||||
// fm ncdirect_inputready_fd
|
||||
//~r ncdirect_light_box,
|
||||
// fm ncplane_on_styles
|
||||
// fm ncplane_off_styles
|
||||
// fm ncdirect_palette_size
|
||||
//X ncdirect_printf_aligned
|
||||
// fm ncdirect_putstr
|
||||
// fm ncdirect_raster_frame
|
||||
// fm ncdirect_readline
|
||||
// fm ncdirect_render_frame
|
||||
// fm ncdirect_render_image
|
||||
// fm ncdirect_rounded_box
|
||||
// fm ncplane_set_styles
|
||||
// fm ncdirect_stop
|
||||
// f ncdirect_stream
|
||||
// f ncdirect_styles
|
||||
// f ncdirect_supported_styles
|
||||
// fm ncdirect_vline_interp
|
||||
// rm ncdirect_bg_rgb8
|
||||
// rm ncdirect_fg_rgb8
|
||||
// rm ncdirect_getc_nblock
|
||||
// rm ncdirect_getc_nblocking
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
|
||||
pub use reimplemented::*;
|
||||
|
||||
/// Minimal notcurses instance for styling text.
|
||||
pub type NcDirect = crate::bindings::ffi::ncdirect;
|
||||
|
||||
/// Flags (options) for [`NcDirect`]
|
||||
pub type NcDirectFlags = u64;
|
||||
|
||||
/// Flag that avoids placing the terminal into cbreak mode
|
||||
/// (disabling echo and line buffering)
|
||||
///
|
||||
pub const NCDIRECT_OPTION_INHIBIT_CBREAK: NcDirectFlags =
|
||||
crate::bindings::ffi::NCDIRECT_OPTION_INHIBIT_CBREAK as NcDirectFlags;
|
||||
|
||||
/// Flag that avoids calling setlocale(LC_ALL, NULL)
|
||||
///
|
||||
/// If the result is either "C" or "POSIX", it will print a
|
||||
/// diagnostic to stderr, and then call setlocale(LC_ALL, "").
|
||||
///
|
||||
/// This will attempt to set the locale based off the LANG
|
||||
/// environment variable. Your program should call setlocale(3)
|
||||
/// itself, usually as one of the first lines.
|
||||
///
|
||||
pub const NCDIRECT_OPTION_INHIBIT_SETLOCALE: NcDirectFlags =
|
||||
crate::bindings::ffi::NCDIRECT_OPTION_INHIBIT_SETLOCALE as NcDirectFlags;
|
||||
|
||||
/// Flag that inhibits registration of the SIGINT, SIGSEGV, SIGABRT & SIGQUIT
|
||||
/// signal handlers.
|
||||
pub const NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS: NcDirectFlags =
|
||||
crate::bindings::ffi::NCDIRECT_OPTION_NO_QUIT_SIGHANDLERS as NcDirectFlags;
|
||||
|
||||
/// Flag that enables showing detailed information.
|
||||
pub const NCDIRECT_OPTION_VERBOSE: NcDirectFlags =
|
||||
crate::bindings::ffi::NCDIRECT_OPTION_VERBOSE as NcDirectFlags;
|
||||
|
||||
/// Flag that enables showing all diagnostics (equivalent to
|
||||
/// [`NCLOGLEVEL_TRACE`][crate::NCLOGLEVEL_TRACE]).
|
||||
/// Implies [`NCDIRECT_OPTION_VERBOSE`].
|
||||
pub const NCDIRECT_OPTION_VERY_VERBOSE: NcDirectFlags =
|
||||
crate::bindings::ffi::NCDIRECT_OPTION_VERY_VERBOSE as NcDirectFlags;
|
@ -1,169 +0,0 @@
|
||||
//! `ncdirect_*` reimplemented functions.
|
||||
|
||||
use core::ptr::null;
|
||||
|
||||
use crate::{
|
||||
cstring, NcCapabilities, NcChannels, NcComponent, NcDim, NcDirect, NcInput, NcIntResult, NcRgb,
|
||||
NcTime,
|
||||
};
|
||||
|
||||
/// Can we directly specify RGB values per cell, or only use palettes?
|
||||
#[inline]
|
||||
pub fn ncdirect_cantruecolor(ncd: &NcDirect) -> bool {
|
||||
ncdirect_capabilities(ncd).rgb
|
||||
}
|
||||
|
||||
/// Can we set the "hardware" palette? Requires the "ccc" terminfo capability.
|
||||
#[inline]
|
||||
pub fn ncdirect_canchangecolor(ncd: &NcDirect) -> bool {
|
||||
crate::nccapability_canchangecolor(&ncdirect_capabilities(ncd))
|
||||
}
|
||||
|
||||
/// Can we fade? Fading requires either the "rgb" or "ccc" terminfo capability.
|
||||
#[inline]
|
||||
pub fn ncdirect_canfade(ncd: &NcDirect) -> bool {
|
||||
ncdirect_canchangecolor(ncd) || ncdirect_cantruecolor(ncd)
|
||||
}
|
||||
|
||||
/// Can we load videos? This requires being built against FFmpeg.
|
||||
#[inline]
|
||||
pub fn ncdirect_canopen_videos(_ncd: &NcDirect) -> bool {
|
||||
unsafe { crate::notcurses_canopen_videos(null()) }
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode halfblocks?
|
||||
#[inline]
|
||||
pub fn ncdirect_canhalfblock(ncd: &NcDirect) -> bool {
|
||||
unsafe { crate::ncdirect_canutf8(ncd) }
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode quadrants?
|
||||
#[inline]
|
||||
pub fn ncdirect_canquadrant(ncd: &NcDirect) -> bool {
|
||||
(unsafe { crate::ncdirect_canutf8(ncd) }) && ncdirect_capabilities(ncd).quadrants
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode 13 sextants?
|
||||
#[inline]
|
||||
pub fn ncdirect_cansextant(ncd: &NcDirect) -> bool {
|
||||
(unsafe { crate::ncdirect_canutf8(ncd) }) && ncdirect_capabilities(ncd).sextants
|
||||
}
|
||||
|
||||
/// Can we reliably use Unicode Braille?
|
||||
#[inline]
|
||||
pub fn ncdirect_canbraille(_ncd: &NcDirect) -> bool {
|
||||
unsafe { crate::notcurses_canbraille(null()) }
|
||||
}
|
||||
|
||||
/// Returns the detected [`NcCapabilities`].
|
||||
#[inline]
|
||||
pub fn ncdirect_capabilities(ncd: &NcDirect) -> NcCapabilities {
|
||||
unsafe { *crate::bindings::ffi::ncdirect_capabilities(ncd) }
|
||||
}
|
||||
|
||||
/// 'input' may be NULL if the caller is uninterested in event details.
|
||||
/// Blocks until an event is processed or a signal is received.
|
||||
///
|
||||
/// *Method: NcDirect.[getc_blocking()][NcDirect#method.getc_blocking].*
|
||||
// TODO: use from_u32 & return Option.
|
||||
#[inline]
|
||||
pub fn ncdirect_getc_blocking(ncd: &mut NcDirect, input: &mut NcInput) -> char {
|
||||
unsafe { core::char::from_u32_unchecked(crate::ncdirect_get(ncd, null(), input)) }
|
||||
}
|
||||
|
||||
///
|
||||
/// If no event is ready, returns 0.
|
||||
///
|
||||
/// *Method: NcDirect.[getc_nblock()][NcDirect#method.getc_nblock].*
|
||||
//
|
||||
// `input` may be NULL if the caller is uninterested in event details.
|
||||
#[inline]
|
||||
pub fn ncdirect_getc_nblock(ncd: &mut NcDirect, input: &mut NcInput) -> char {
|
||||
unsafe {
|
||||
let ts = NcTime::new();
|
||||
core::char::from_u32_unchecked(crate::ncdirect_get(ncd, &ts, input))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the foreground [NcComponent] components.
|
||||
///
|
||||
/// *Method: NcDirect.[set_fg_rgb8()][NcDirect#method.set_fg_rgb8].*
|
||||
#[inline]
|
||||
pub fn ncdirect_set_fg_rgb8(
|
||||
ncd: &mut NcDirect,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) -> NcIntResult {
|
||||
let rgb = (red as NcRgb) << 16 | (green as NcRgb) << 8 | blue as NcRgb;
|
||||
unsafe { crate::ncdirect_set_fg_rgb(ncd, rgb) }
|
||||
}
|
||||
|
||||
/// Sets the background [NcComponent] components.
|
||||
///
|
||||
/// *Method: NcDirect.[set_bg_rgb8()][NcDirect#method.set_bg_rgb8].*
|
||||
#[inline]
|
||||
pub fn ncdirect_set_bg_rgb8(
|
||||
ncd: &mut NcDirect,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) -> NcIntResult {
|
||||
let rgb = (red as NcRgb) << 16 | (green as NcRgb) << 8 | blue as NcRgb;
|
||||
unsafe { crate::ncdirect_set_bg_rgb(ncd, rgb) }
|
||||
}
|
||||
|
||||
/// Draws horizontal lines using the specified [NcChannels]s, interpolating
|
||||
/// between them as we go.
|
||||
///
|
||||
/// The string at `egc` may not use more than one column.
|
||||
///
|
||||
/// All lines start at the current cursor position.
|
||||
///
|
||||
/// For a horizontal line, `len` cannot exceed the screen width minus the
|
||||
/// cursor's offset.
|
||||
// TODO:MAYBE saturate the `len` value
|
||||
///
|
||||
/// *Method: NcDirect.[hline_interp()][NcDirect#method.hline_interp].*
|
||||
#[inline]
|
||||
pub fn ncdirect_hline_interp(
|
||||
ncd: &mut NcDirect,
|
||||
egc: &str,
|
||||
len: NcDim,
|
||||
h1: NcChannels,
|
||||
h2: NcChannels,
|
||||
) -> NcIntResult {
|
||||
#[cfg(any(target_arch = "armv7l", target_arch = "i686"))]
|
||||
let egc_ptr = cstring![egc] as *const i8;
|
||||
#[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))]
|
||||
let egc_ptr = cstring![egc];
|
||||
|
||||
unsafe { crate::bindings::ffi::ncdirect_hline_interp(ncd, egc_ptr, len as i32, h1, h2) }
|
||||
}
|
||||
|
||||
/// Draws horizontal lines using the specified [NcChannels]s, interpolating
|
||||
/// between them as we go.
|
||||
///
|
||||
/// The string at `egc` may not use more than one column.
|
||||
///
|
||||
/// All lines start at the current cursor position.
|
||||
///
|
||||
/// For a vertical line, `len` may be as long as you'd like; the screen
|
||||
/// will scroll as necessary.
|
||||
///
|
||||
/// *Method: NcDirect.[vline_interp()][NcDirect#method.vline_interp].*
|
||||
#[inline]
|
||||
pub fn ncdirect_vline_interp(
|
||||
ncd: &mut NcDirect,
|
||||
egc: &str,
|
||||
len: NcDim,
|
||||
h1: NcChannels,
|
||||
h2: NcChannels,
|
||||
) -> NcIntResult {
|
||||
#[cfg(any(target_arch = "armv7l", target_arch = "i686"))]
|
||||
let egc_ptr = cstring![egc] as *const i8;
|
||||
#[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))]
|
||||
let egc_ptr = cstring![egc];
|
||||
|
||||
unsafe { crate::bindings::ffi::ncdirect_vline_interp(ncd, egc_ptr, len as i32, h1, h2) }
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,80 +0,0 @@
|
||||
//! Error handling with `Error`, `NcResult` & `NcIntResult` for error handling
|
||||
|
||||
use std::{self, error, fmt};
|
||||
|
||||
/// The [`i32`] value used to return errors by the underlying C API.
|
||||
///
|
||||
/// A value < 0 means error, (usually -1).
|
||||
///
|
||||
/// # Defined constants:
|
||||
///
|
||||
/// - [`NCRESULT_OK`]
|
||||
/// - [`NCRESULT_ERR`]
|
||||
/// - [`NCRESULT_MAX`]
|
||||
pub type NcIntResult = i32;
|
||||
|
||||
/// OK value, for the functions that return [`NcIntResult`].
|
||||
pub const NCRESULT_OK: i32 = 0;
|
||||
|
||||
/// ERROR value, for the functions that return an [`NcIntResult`].
|
||||
pub const NCRESULT_ERR: i32 = -1;
|
||||
|
||||
/// MAX value, for the functions that return [`NcIntResult`].
|
||||
pub const NCRESULT_MAX: i32 = i32::MAX;
|
||||
|
||||
/// The error type for the Rust methods API.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct NcError {
|
||||
/// [NcIntResult].
|
||||
pub int: i32,
|
||||
pub msg: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for NcError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "NcError {}: {}", self.int, self.msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for NcError {
|
||||
fn description(&self) -> &str {
|
||||
&self.msg
|
||||
}
|
||||
}
|
||||
|
||||
impl NcError {
|
||||
/// New NcError with default [NCRESULT_ERR] error number, and without message.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
int: NCRESULT_ERR,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// New NcError with custom error number, and without message.
|
||||
pub fn new_err(int: NcIntResult) -> Self {
|
||||
Self {
|
||||
int,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// New NcError with default [NCRESULT_ERR] error number and a custom message.
|
||||
pub fn new_msg(msg: &str) -> Self {
|
||||
Self {
|
||||
int: NCRESULT_ERR,
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// New NcError with both a custom error number and a custom message.
|
||||
pub fn with_msg(int: NcIntResult, msg: &str) -> Self {
|
||||
Self {
|
||||
int,
|
||||
msg: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The result type for the Rust methods API.
|
||||
pub type NcResult<T> = Result<T, NcError>;
|
@ -1,49 +0,0 @@
|
||||
//! `NcFadeCb` & `NcFadeCtx`
|
||||
|
||||
// functions already exported by bindgen : 3
|
||||
// -------------------------------------------
|
||||
// (#) test: 0
|
||||
// (W) wrap: 3 / 0
|
||||
// -------------------------------------------
|
||||
//W ncfadectx_free
|
||||
//W ncfadectx_iterations
|
||||
//W ncfadectx_setup
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
use crate::{Nc, NcIntResult, NcPlane, NcTime};
|
||||
|
||||
/// Called for each fade iteration on the NcPlane.
|
||||
///
|
||||
/// If anything but 0 is returned, the fading operation ceases immediately,
|
||||
/// and that value is propagated out.
|
||||
///
|
||||
/// The recommended absolute display time target is passed in 'tspec'.
|
||||
pub type NcFadeCb =
|
||||
Option<unsafe extern "C" fn(*mut Nc, *mut NcPlane, *const NcTime, *mut c_void) -> NcIntResult>;
|
||||
|
||||
/// Context for a palette fade operation
|
||||
pub type NcFadeCtx = crate::bindings::ffi::ncfadectx;
|
||||
|
||||
impl NcFadeCtx {
|
||||
/// NcFadeCtx constructor.
|
||||
///
|
||||
/// Rather than the simple ncplane_fade{in/out}(),
|
||||
/// ncfadectx_setup() can be paired with a loop over
|
||||
/// ncplane_fade{in/out}_iteration() + ncfadectx_free().
|
||||
pub fn setup(plane: &mut NcPlane) -> &mut NcFadeCtx {
|
||||
unsafe { &mut *crate::ncfadectx_setup(plane) }
|
||||
}
|
||||
|
||||
/// Releases the resources associated.
|
||||
pub fn free(&mut self) {
|
||||
unsafe {
|
||||
crate::ncfadectx_free(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of iterations through which will fade.
|
||||
pub fn iterations(&self) -> u32 {
|
||||
unsafe { crate::ncfadectx_iterations(self) as u32 }
|
||||
}
|
||||
}
|
@ -1,366 +0,0 @@
|
||||
//! `NcVisual*` methods and associated functions.
|
||||
|
||||
use core::ptr::null_mut;
|
||||
use libc::c_void;
|
||||
|
||||
use crate::{
|
||||
// cstring, error, error_ref_mut, rstring, NcBlitter, NcDim, NcError, NcIntResult, NcPixel,
|
||||
// NcPlane, NcResult, NcRgba, NcScale, NcTime, NcVisual, NcVisualOptions, Notcurses, NCBLIT_PIXEL,
|
||||
// NCRESULT_ERR,
|
||||
};
|
||||
|
||||
/// # NcVisualOptions Constructors
|
||||
impl NcSubprocOptions {
|
||||
|
||||
///
|
||||
pub fn new(
|
||||
curry: *mut c_void,
|
||||
restart_period: u64,
|
||||
// flags: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
curry:,
|
||||
// restart this many seconds after an exit (watch)
|
||||
restart_period,
|
||||
// bitfield over NCOPTION_SUBPROC_* (none yet)
|
||||
flags: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcSubproc Constructors & Destructors
|
||||
impl NcSubproc {
|
||||
/// Opens a visual at `file`, extracts the codec and parameters and
|
||||
/// decodes the first image to memory.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_file()][crate::ncvisual_from_file].*
|
||||
pub fn new<'a>(file: &str) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncvisual_from_file(cstring![file]) },
|
||||
&format!("NcVisual::from_file()")
|
||||
]
|
||||
}
|
||||
|
||||
/// Promotes an NcPlane to an NcVisual.
|
||||
///
|
||||
/// The plane may contain only spaces, half blocks, and full blocks.
|
||||
/// This will be checked, and any other glyph will result in an error.
|
||||
///
|
||||
/// This function exists so that planes can be subjected to NcVisual transformations.
|
||||
/// If possible, it's better to create the ncvisual from memory using
|
||||
/// [from_rgba][NcVisual#method.from_rgba].
|
||||
///
|
||||
/// *C style function: [ncvisual_from_plane()][crate::ncvisual_from_plane].*
|
||||
pub fn from_plane<'a>(
|
||||
plane: &NcPlane,
|
||||
blitter: NcBlitter,
|
||||
beg_y: NcDim,
|
||||
beg_x: NcDim,
|
||||
len_y: NcDim,
|
||||
len_x: NcDim,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_plane(
|
||||
plane,
|
||||
blitter,
|
||||
beg_y as i32,
|
||||
beg_x as i32,
|
||||
len_y as i32,
|
||||
len_x as i32,
|
||||
)
|
||||
},
|
||||
&format!("NcVisual::from_file()")
|
||||
]
|
||||
}
|
||||
|
||||
/// Prepares an NcVisual, and its underlying NcPlane, based off RGBA content
|
||||
/// in memory at `rgba`.
|
||||
///
|
||||
/// `rgba` is laid out as `rows` lines, each of which is `rowstride` bytes in length.
|
||||
/// Each line has `cols` 32-bit 8bpc RGBA pixels followed by possible padding
|
||||
/// (there will be rowstride - cols * 4 bytes of padding).
|
||||
///
|
||||
/// The total size of `rgba` is thus (rows * rowstride) bytes, of which
|
||||
/// (rows * cols * 4) bytes are actual non-padding data.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_rgba()][crate::ncvisual_from_rgba].*
|
||||
pub fn from_rgba<'a>(
|
||||
rgba: &[u8],
|
||||
rows: NcDim,
|
||||
rowstride: NcDim,
|
||||
cols: NcDim,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_rgba(
|
||||
rgba.as_ptr() as *const c_void,
|
||||
rows as i32,
|
||||
rowstride as i32,
|
||||
cols as i32,
|
||||
)
|
||||
},
|
||||
&format!("NcVisual::from_rgba()")
|
||||
]
|
||||
}
|
||||
|
||||
/// Destroys this NcVisual.
|
||||
///
|
||||
/// Rendered elements will not be disrupted, but the visual can be neither
|
||||
/// decoded nor rendered any further.
|
||||
///
|
||||
/// *C style function: [ncvisual_destroy()][crate::ncvisual_destroy].*
|
||||
pub fn destroy(&mut self) {
|
||||
unsafe { crate::ncvisual_destroy(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcVisual Methods
|
||||
impl NcVisual {
|
||||
/// Gets the specified pixel from this NcVisual.
|
||||
///
|
||||
/// *C style function: [ncvisual_at_yx()][crate::ncvisual_at_yx].*
|
||||
pub fn at_yx(&self, y: NcDim, x: NcDim) -> NcResult<NcPixel> {
|
||||
let mut pixel = 0;
|
||||
let res = unsafe { crate::ncvisual_at_yx(self, y as i32, x as i32, &mut pixel) };
|
||||
error![res, "NcVisual.at_yx()", pixel]
|
||||
}
|
||||
|
||||
/// Extracts the next frame from the NcVisual.
|
||||
///
|
||||
/// Returns 0 for normal frames, and 1 to indicate EOF.
|
||||
///
|
||||
/// *C style function: [ncvisual_decode()][crate::ncvisual_decode].*
|
||||
pub fn decode(&mut self) -> NcResult<NcIntResult> {
|
||||
let res = unsafe { crate::ncvisual_decode(self) };
|
||||
if res == NCRESULT_ERR {
|
||||
return Err(NcError::with_msg(res, "NcVisual.decode()"));
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the next frame from the NcVisual, ala [decode][NcVisual#method.decode],
|
||||
/// but if we have reached the end, rewinds to the first frame.
|
||||
///
|
||||
/// *A subsequent [NcVisual.render]() will render the first frame,
|
||||
/// as if the ncvisual had been closed and reopened.*
|
||||
///
|
||||
/// Returns 0 for normal frames and 1 to indicate EOF.
|
||||
///
|
||||
/// *C style function: [ncvisual_decode_loop()][crate::ncvisual_decode_loop].*
|
||||
pub fn decode_loop(&mut self) -> NcResult<NcIntResult> {
|
||||
let res = unsafe { crate::ncvisual_decode_loop(self) };
|
||||
if res == NCRESULT_ERR {
|
||||
return Err(NcError::with_msg(res, "NcVisual.decode_loop()"));
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Inflates each pixel in the image to 'scale'x'scale' pixels.
|
||||
///
|
||||
/// The original color is retained.
|
||||
pub fn inflate(&mut self, scale: u32) -> NcResult<NcIntResult> {
|
||||
let res = unsafe { crate::ncvisual_inflate(self, scale as i32) };
|
||||
error![res, &format!["NcVisual.inflate({})", scale], res]
|
||||
}
|
||||
|
||||
/// Gets the size and ratio of NcVisual pixels to output cells along the
|
||||
/// `y→to_y` and `x→to_x` axes.
|
||||
///
|
||||
/// Returns a tuple with (y, x, to_y, to_x)
|
||||
///
|
||||
/// An NcVisual of `y` by `x` pixels will require
|
||||
/// (`y` * `to_y`) by (`x` * `to_x`) cells for full output.
|
||||
///
|
||||
/// Errors on invalid blitter in `options`. Scaling is taken into consideration.
|
||||
///
|
||||
/// *C style function: [ncvisual_blitter_geom()][crate::ncvisual_blitter_geom].*
|
||||
pub fn geom(
|
||||
&self,
|
||||
nc: &Notcurses,
|
||||
options: &NcVisualOptions,
|
||||
) -> NcResult<(NcDim, NcDim, NcDim, NcDim)> {
|
||||
let mut y = 0;
|
||||
let mut x = 0;
|
||||
let mut to_y = 0;
|
||||
let mut to_x = 0;
|
||||
|
||||
let res = unsafe {
|
||||
crate::ncvisual_blitter_geom(
|
||||
nc,
|
||||
self,
|
||||
options,
|
||||
&mut y,
|
||||
&mut x,
|
||||
&mut to_y,
|
||||
&mut to_x,
|
||||
null_mut(),
|
||||
)
|
||||
};
|
||||
error![
|
||||
res,
|
||||
"NcVisual.geom()",
|
||||
(y as NcDim, x as NcDim, to_y as NcDim, to_x as NcDim)
|
||||
];
|
||||
}
|
||||
|
||||
/// Gets the default media (not plot) blitter for this environment when using
|
||||
/// the specified scaling method.
|
||||
///
|
||||
/// Currently, this means:
|
||||
/// - if lacking UTF-8, NCBLIT_1x1.
|
||||
/// - otherwise, if not NCSCALE_STRETCH, NCBLIT_2x1.
|
||||
/// - otherwise, if sextants are not known to be good, NCBLIT_2x2.
|
||||
/// - otherwise NCBLIT_3x2 NCBLIT_2x2 and NCBLIT_3x2 both distort the original
|
||||
/// aspect ratio, thus NCBLIT_2x1 is used outside of NCSCALE_STRETCH.
|
||||
///
|
||||
/// *C style function: [ncvisual_media_defblitter()][crate::ncvisual_media_defblitter].*
|
||||
pub fn media_defblitter(nc: &Notcurses, scale: NcScale) -> NcBlitter {
|
||||
unsafe { crate::ncvisual_media_defblitter(nc, scale) }
|
||||
}
|
||||
|
||||
/// Polyfills at the specified location using `rgba`.
|
||||
///
|
||||
/// *C style function: [ncvisual_polyfill_yx()][crate::ncvisual_polyfill_yx].*
|
||||
pub fn polyfill_yx(&mut self, y: NcDim, x: NcDim, rgba: NcRgba) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_polyfill_yx(self, y as i32, x as i32, rgba) },
|
||||
&format!["NcVisual.polyfill_yx({}, {}, {})", y, x, rgba]
|
||||
]
|
||||
}
|
||||
|
||||
/// Renders the decoded frame to the specified [NcPlane].
|
||||
///
|
||||
/// See [`NcVisualOptions`].
|
||||
///
|
||||
/// *C style function: [ncvisual_render()][crate::ncvisual_render].*
|
||||
pub fn render(
|
||||
&mut self,
|
||||
nc: &mut Notcurses,
|
||||
options: &NcVisualOptions,
|
||||
) -> NcResult<&mut NcPlane> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncvisual_render(nc, self, options) },
|
||||
"NcVisual.render()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Resizes the visual to `rows` X `columns` pixels.
|
||||
///
|
||||
/// This is a lossy transformation, unless the size is unchanged.
|
||||
///
|
||||
/// *C style function: [ncvisual_resize()][crate::ncvisual_resize].*
|
||||
pub fn resize(&mut self, rows: NcDim, cols: NcDim) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_resize(self, rows as i32, cols as i32) },
|
||||
&format!["NcVisual.resize({}, {})", rows, cols]
|
||||
]
|
||||
}
|
||||
|
||||
/// Rotates the visual `rads` radians.
|
||||
///
|
||||
/// Only M_PI/2 and -M_PI/2 are supported at the moment,
|
||||
/// but this will change. (FIXME)
|
||||
///
|
||||
/// *C style function: [ncvisual_rotate()][crate::ncvisual_rotate].*
|
||||
pub fn rotate(&mut self, rads: f64) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_rotate(self, rads) },
|
||||
&format!["NcVisual.rotate({})", rads]
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the specified pixel.
|
||||
///
|
||||
/// *C style function: [ncvisual_set_yx()][crate::ncvisual_set_yx].*
|
||||
pub fn set_yx(&mut self, y: NcDim, x: NcDim, pixel: NcPixel) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_set_yx(self, y as i32, x as i32, pixel) },
|
||||
&format!["NcVisual.set_yx({}, {}, {})", y, x, pixel]
|
||||
]
|
||||
}
|
||||
|
||||
/// Displays frames.
|
||||
///
|
||||
/// *Provide as an argument to ncvisual_stream().*
|
||||
///
|
||||
/// If you'd like subtitles to be decoded, provide an ncplane as the curry.
|
||||
/// If the curry is NULL, subtitles will not be displayed.
|
||||
///
|
||||
/// *C style function: [ncvisual_simple_streamer()][crate::ncvisual_simple_streamer].*
|
||||
pub fn simple_streamer(
|
||||
&mut self,
|
||||
options: &mut NcVisualOptions,
|
||||
time: &NcTime,
|
||||
curry: Option<&mut NcPlane>,
|
||||
) -> NcResult<()> {
|
||||
if let Some(plane) = curry {
|
||||
error![
|
||||
unsafe {
|
||||
crate::ncvisual_simple_streamer(
|
||||
self,
|
||||
options,
|
||||
time,
|
||||
plane as *mut _ as *mut libc::c_void,
|
||||
)
|
||||
},
|
||||
&format![
|
||||
"NcVisual.simple_streamer({:?}, {:?}, ncplane)",
|
||||
options, time
|
||||
]
|
||||
]
|
||||
} else {
|
||||
error![
|
||||
unsafe { crate::ncvisual_simple_streamer(self, options, time, null_mut()) },
|
||||
&format!["NcVisual.simple_streamer({:?}, {:?}, null)", options, time]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// // TODO
|
||||
//
|
||||
// /// Streams the entirety of the media, according to its own timing.
|
||||
// ///
|
||||
// /// Blocking, obviously.
|
||||
// ///
|
||||
// /// If `streamer` is provided it will be called for each frame, and its return
|
||||
// /// value handled as outlined for streamcb.
|
||||
// /// If streamer() returns non-zero, the stream is aborted, and that value is
|
||||
// /// returned. By convention, return a positive number to indicate intentional
|
||||
// /// abort from within streamer().
|
||||
// ///
|
||||
// /// `timescale` allows the frame duration time to be scaled.
|
||||
// /// For a visual naturally running at 30FPS, a 'timescale' of 0.1 will result
|
||||
// /// in 300 FPS, and a `timescale` of 10 will result in 3 FPS.
|
||||
// /// It is an error to supply `timescale` less than or equal to 0.
|
||||
// ///
|
||||
// /// *C style function: [ncvisual_streamer()][crate::ncvisual_streamer].*
|
||||
// //
|
||||
// // TODO: add streamcb
|
||||
// // INFO: QUESTION: is curry also optional like in simple_streamer?
|
||||
// //
|
||||
// pub fn simple_streamer(
|
||||
// &mut self,
|
||||
// nc: &mut Notcurses,
|
||||
// timescale: f32,
|
||||
// //streamer: Option<streamcb>
|
||||
// options: &NcVisualOptions,
|
||||
// curry: Option<&mut NcPlane>,
|
||||
// ) -> NcResult<()> {
|
||||
// }
|
||||
|
||||
/// If a subtitle ought be displayed at this time, returns a heap-allocated
|
||||
/// copy of the UTF8 text.
|
||||
///
|
||||
/// *C style function: [ncvisual_subtitle()][crate::ncvisual_subtitle].*
|
||||
pub fn subtitle(&self) -> NcResult<&str> {
|
||||
let res = unsafe { crate::ncvisual_subtitle(self) };
|
||||
if res != null_mut() {
|
||||
return Ok(rstring![res]);
|
||||
} else {
|
||||
Err(NcError::with_msg(NCRESULT_ERR, "NcVisual.subtitle()"))
|
||||
}
|
||||
}
|
||||
}
|
335
rust/src/file.rs
335
rust/src/file.rs
@ -1,335 +0,0 @@
|
||||
//! Wrapper for `libc::FILE`, both as used by notcurses and the libc crate
|
||||
//!
|
||||
//! The interface is largely based on the implementation of the
|
||||
//! [cfile-rs crate](https://github.com/jkarns275/cfile) by Joshua Karns
|
||||
|
||||
use core::ptr::{null_mut, NonNull};
|
||||
|
||||
use std::io::{Error, ErrorKind, Read, Seek, SeekFrom};
|
||||
|
||||
use libc::{
|
||||
c_long, c_void, fclose, /* feof, */ fread, fseek, ftell, SEEK_CUR, SEEK_END, SEEK_SET,
|
||||
};
|
||||
|
||||
/// See [NcFile]. Notcurses functions expects this type of `*FILE` (a struct)
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub type FILE_NC = crate::ffi::FILE;
|
||||
|
||||
/// See [NcFile]. The [`libc`](https://docs.rs/libc/) crate expects this type
|
||||
/// of `*FILE` (an opaque enum)
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub type FILE_LIBC = libc::FILE;
|
||||
|
||||
// TODO: the following static strings aren't made public
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will open the file in a way that will allow reading and writing,
|
||||
/// including overwriting old data.
|
||||
/// It will not create the file if it does not exist.
|
||||
pub static RANDOM_ACCESS_MODE: &str = "rb+";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will open the file in a way that will allow reading and writing,
|
||||
/// including overwriting old data
|
||||
pub static UPDATE: &str = "rb+";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will only allow reading.
|
||||
pub static READ_ONLY: &str = "r";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will only allow writing.
|
||||
pub static WRITE_ONLY: &str = "w";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will only allow data to be appended to the end of the file.
|
||||
pub static APPEND_ONLY: &str = "a";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will allow data to be appended to the end of the file, and data to be
|
||||
/// read from the file. It will create the file if it doesn't exist.
|
||||
pub static APPEND_READ: &str = "a+";
|
||||
|
||||
/// Intended to be passed into the CFile::open method.
|
||||
/// It will open the file in a way that will allow reading and writing,
|
||||
/// including overwriting old data. It will create the file if it doesn't exist
|
||||
pub static TRUNCATE_RANDOM_ACCESS_MODE: &str = "wb+";
|
||||
|
||||
/// A utility function to pull the current value of errno and put it into an
|
||||
/// Error::Errno
|
||||
fn get_error<T>() -> Result<T, Error> {
|
||||
Err(Error::last_os_error())
|
||||
}
|
||||
|
||||
/// A wrapper struct around
|
||||
/// [`libc::FILE`](https://docs.rs/libc/0.2.80/libc/enum.FILE.html)
|
||||
///
|
||||
/// The notcurses `FILE` type [`FILE_NC`] a struct imported through bindgen,
|
||||
/// while the equivalent [`libc`](https://docs.rs/libc) crate FILE
|
||||
/// ([`FILE_LIBC`]) is an opaque enum.
|
||||
///
|
||||
/// Several methods are provided to cast back and forth between both types,
|
||||
/// in order to allow both rust libc operations and notcurses file operations
|
||||
/// over the same underlying `*FILE`.
|
||||
#[derive(Debug)]
|
||||
pub struct NcFile {
|
||||
file_ptr: NonNull<FILE_LIBC>,
|
||||
}
|
||||
|
||||
impl NcFile {
|
||||
// constructors --
|
||||
|
||||
/// `NcFile` constructor from a file produced by notcurses
|
||||
pub fn from_nc(file: *mut FILE_NC) -> Self {
|
||||
NcFile {
|
||||
file_ptr: unsafe { NonNull::new_unchecked(NcFile::nc2libc(file)) },
|
||||
}
|
||||
}
|
||||
|
||||
/// `NcFile` constructor from a file produced by the libc crate
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe fn from_libc(file: *mut FILE_LIBC) -> Self {
|
||||
NcFile {
|
||||
file_ptr: NonNull::new_unchecked(file),
|
||||
}
|
||||
}
|
||||
|
||||
// methods --
|
||||
|
||||
/// Returns the file pointer in the format expected by the [`libc`] crate
|
||||
#[inline]
|
||||
pub fn as_libc_ptr(&self) -> *mut FILE_LIBC {
|
||||
self.file_ptr.as_ptr()
|
||||
}
|
||||
|
||||
/// Returns the file pointer in the format expected by notcurses
|
||||
#[inline]
|
||||
pub fn as_nc_ptr(&self) -> *mut FILE_NC {
|
||||
Self::libc2nc(self.file_ptr.as_ptr())
|
||||
}
|
||||
|
||||
/// Returns the current position in the file.
|
||||
///
|
||||
/// On error `Error::Errno(errno)` is returned.
|
||||
pub fn current_pos(&self) -> Result<u64, Error> {
|
||||
unsafe {
|
||||
let pos = ftell(self.as_libc_ptr());
|
||||
if pos != -1 {
|
||||
Ok(pos as u64)
|
||||
} else {
|
||||
get_error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the file from start to end. Convenience method
|
||||
///
|
||||
#[inline]
|
||||
pub fn read_all(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error> {
|
||||
let _ = self.seek(SeekFrom::Start(0));
|
||||
self.read_to_end(buf)
|
||||
}
|
||||
|
||||
// private methods --
|
||||
|
||||
/// Converts a file pointer from the struct notcurses uses to the
|
||||
/// opaque enum type libc expects
|
||||
#[inline]
|
||||
fn nc2libc(file: *mut FILE_NC) -> *mut FILE_LIBC {
|
||||
file as *mut _ as *mut FILE_LIBC
|
||||
}
|
||||
|
||||
/// Converts a file pointer from the libc opaque enum format to the struct
|
||||
/// expected by notcurses
|
||||
#[inline]
|
||||
fn libc2nc(file: *mut FILE_LIBC) -> *mut FILE_NC {
|
||||
file as *mut _ as *mut FILE_NC
|
||||
}
|
||||
|
||||
/// A utility function to expand a vector without increasing its capacity
|
||||
/// more than it needs to be expanded.
|
||||
fn expand_buffer(buff: &mut Vec<u8>, by: usize) {
|
||||
if buff.capacity() < buff.len() + by {
|
||||
buff.reserve(by);
|
||||
}
|
||||
for _ in 0..by {
|
||||
buff.push(0u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for NcFile {
|
||||
/// Reads exactly the number of bytes required to fill buf.
|
||||
///
|
||||
/// If the end of the file is reached before buf is filled,
|
||||
/// `Err(EndOfFile(bytes_read))` will be returned. The data that was read
|
||||
/// before that will still have been placed into buf.
|
||||
///
|
||||
/// Upon some other error, `Err(Errno(errno))` will be returned.
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
unsafe {
|
||||
let result = fread(
|
||||
buf.as_ptr() as *mut c_void,
|
||||
1,
|
||||
buf.len(),
|
||||
self.as_libc_ptr(),
|
||||
);
|
||||
if result != buf.len() {
|
||||
match get_error::<u8>() {
|
||||
Err(err) => {
|
||||
if err.kind() == ErrorKind::UnexpectedEof {
|
||||
Ok(result)
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
Ok(_) => panic!("This is impossible"),
|
||||
}
|
||||
} else {
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the entire file starting from the current_position
|
||||
/// expanding buf as needed.
|
||||
///
|
||||
/// On a successful read, this function will return `Ok(bytes_read)`.
|
||||
///
|
||||
/// If an error occurs during reading, some varient of error will be returned.
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error> {
|
||||
let pos = self.current_pos();
|
||||
let _ = self.seek(SeekFrom::End(0));
|
||||
let end = self.current_pos();
|
||||
match pos {
|
||||
Ok(cur_pos) => match end {
|
||||
Ok(end_pos) => {
|
||||
if end_pos == cur_pos {
|
||||
return Ok(0);
|
||||
}
|
||||
let to_read = (end_pos - cur_pos) as usize;
|
||||
if buf.len() < to_read {
|
||||
let to_reserve = to_read - buf.len();
|
||||
Self::expand_buffer(buf, to_reserve);
|
||||
}
|
||||
let _ = self.seek(SeekFrom::Start(cur_pos as u64));
|
||||
match self.read_exact(buf) {
|
||||
Ok(()) => Ok(to_read),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the entire file from the beginning and stores it in a string
|
||||
///
|
||||
/// On a successful read, this function will return `Ok(bytes_read)`.
|
||||
///
|
||||
/// If an error occurs during reading, some varient of error will be returned.
|
||||
fn read_to_string(&mut self, strbuf: &mut String) -> Result<usize, Error> {
|
||||
let mut bytes_read = 0_usize;
|
||||
let mut buffer = vec![0u8];
|
||||
let result = self.read_all(&mut buffer);
|
||||
|
||||
if let Ok(bytes) = result {
|
||||
bytes_read = bytes;
|
||||
}
|
||||
if let Err(e) = result {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
let result = std::str::from_utf8(&buffer);
|
||||
|
||||
if let Ok(strslice) = result {
|
||||
*strbuf = strslice.to_string();
|
||||
Ok(bytes_read)
|
||||
} else {
|
||||
get_error()
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads exactly the number of bytes required to fill buf.
|
||||
///
|
||||
/// If the end of the file is reached before buf is filled,
|
||||
/// `Err(EndOfFile(bytes_read))` will be returned. The data that was read
|
||||
/// before that will still have been placed into buf.
|
||||
///
|
||||
/// Upon some other error, `Err(Errno(errno))` will be returned.
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error> {
|
||||
unsafe {
|
||||
let result = fread(
|
||||
buf.as_ptr() as *mut c_void,
|
||||
1,
|
||||
buf.len(),
|
||||
self.as_libc_ptr(),
|
||||
);
|
||||
if result == buf.len() {
|
||||
Ok(())
|
||||
} else {
|
||||
// Check if we hit the end of the file
|
||||
// FIXME
|
||||
// if feof(self.as_libc_ptr()) != 0 {
|
||||
// get_error()
|
||||
// } else {
|
||||
// get_error()
|
||||
// }
|
||||
get_error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Seek for NcFile {
|
||||
/// Changes the current position in the file using the [`SeekFrom`] enum.
|
||||
///
|
||||
/// To set relative to the beginning of the file (i.e. index is 0 + offset):
|
||||
/// ```ignore
|
||||
/// SeekFrom::Start(offset)
|
||||
/// ```
|
||||
/// To set relative to the end of the file (i.e. index is file_lenth - 1 - offset):
|
||||
/// ```ignore
|
||||
/// SeekFrom::End(offset)
|
||||
/// ```
|
||||
/// To set relative to the current position:
|
||||
/// ```ignore
|
||||
/// SeekFrom::End(offset)
|
||||
/// ```
|
||||
///
|
||||
/// On error `Error::Errno(errno)` is returned.
|
||||
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Error> {
|
||||
unsafe {
|
||||
let result = match pos {
|
||||
SeekFrom::Start(from) => fseek(self.as_libc_ptr(), from as c_long, SEEK_SET),
|
||||
SeekFrom::End(from) => fseek(self.as_libc_ptr(), from as c_long, SEEK_END),
|
||||
SeekFrom::Current(delta) => fseek(self.as_libc_ptr(), delta as c_long, SEEK_CUR),
|
||||
};
|
||||
if result == 0 {
|
||||
self.current_pos()
|
||||
} else {
|
||||
get_error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NcFile {
|
||||
/// Ensures the file stream is closed before abandoning the data.
|
||||
fn drop(&mut self) {
|
||||
let _ = unsafe {
|
||||
if !(self.as_libc_ptr()).is_null() {
|
||||
let res = fclose(self.as_libc_ptr());
|
||||
if res == 0 {
|
||||
self.file_ptr = NonNull::new_unchecked(null_mut::<FILE_LIBC>());
|
||||
Ok(())
|
||||
} else {
|
||||
get_error()
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
// functions manually reimplemented: 2
|
||||
// ------------------------------------------
|
||||
// (+) done: 2 / 0
|
||||
// (#) test: 0 / 2
|
||||
// ------------------------------------------
|
||||
// + nckey_mouse_p
|
||||
// + nckey_supppuab_p
|
||||
|
||||
use crate::{NCKEY_BUTTON1, NCKEY_RELEASE};
|
||||
|
||||
/// Is this [char] a Supplementary Private Use Area-B codepoint?
|
||||
///
|
||||
/// Links:
|
||||
/// - https://en.wikipedia.org/wiki/Private_Use_Areas
|
||||
/// - https://codepoints.net/supplementary_private_use_area-b
|
||||
#[inline]
|
||||
pub fn nckey_supppuab_p(w: char) -> bool {
|
||||
w as u32 >= 0x100000_u32 && w as u32 <= 0x10fffd_u32
|
||||
}
|
||||
|
||||
/// Is the event a synthesized mouse event?
|
||||
#[inline]
|
||||
pub const fn nckey_mouse_p(r: char) -> bool {
|
||||
r >= NCKEY_BUTTON1 && r <= NCKEY_RELEASE
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
//! Special composed key definitions. These values are added to 0x100000.
|
||||
#![allow(clippy::transmute_int_to_char)]
|
||||
|
||||
use std::mem::transmute;
|
||||
|
||||
// NOTE: Waiting for: https://github.com/rust-lang/rust/issues/53605
|
||||
// const fn suppuabize(w: u32) -> char {
|
||||
const fn suppuabize(w: u32) -> u32 {
|
||||
// unsafe { transmute(w + 0x100000) }
|
||||
w + 0x100000
|
||||
}
|
||||
|
||||
pub const NCKEY_INVALID: char = unsafe { transmute(suppuabize(0)) };
|
||||
///generated interally in response to SIGWINCH
|
||||
pub const NCKEY_RESIZE: char = unsafe { transmute(suppuabize(1)) };
|
||||
pub const NCKEY_UP: char = unsafe { transmute(suppuabize(2)) };
|
||||
pub const NCKEY_RIGHT: char = unsafe { transmute(suppuabize(3)) };
|
||||
pub const NCKEY_DOWN: char = unsafe { transmute(suppuabize(4)) };
|
||||
pub const NCKEY_LEFT: char = unsafe { transmute(suppuabize(5)) };
|
||||
pub const NCKEY_INS: char = unsafe { transmute(suppuabize(6)) };
|
||||
pub const NCKEY_DEL: char = unsafe { transmute(suppuabize(7)) };
|
||||
/// backspace (sometimes)
|
||||
pub const NCKEY_BACKSPACE: char = unsafe { transmute(suppuabize(8)) };
|
||||
pub const NCKEY_PGDOWN: char = unsafe { transmute(suppuabize(9)) };
|
||||
pub const NCKEY_PGUP: char = unsafe { transmute(suppuabize(10)) };
|
||||
pub const NCKEY_HOME: char = unsafe { transmute(suppuabize(11)) };
|
||||
pub const NCKEY_END: char = unsafe { transmute(suppuabize(12)) };
|
||||
pub const NCKEY_F00: char = unsafe { transmute(suppuabize(20)) };
|
||||
pub const NCKEY_F01: char = unsafe { transmute(suppuabize(21)) };
|
||||
pub const NCKEY_F02: char = unsafe { transmute(suppuabize(22)) };
|
||||
pub const NCKEY_F03: char = unsafe { transmute(suppuabize(23)) };
|
||||
pub const NCKEY_F04: char = unsafe { transmute(suppuabize(24)) };
|
||||
pub const NCKEY_F05: char = unsafe { transmute(suppuabize(25)) };
|
||||
pub const NCKEY_F06: char = unsafe { transmute(suppuabize(26)) };
|
||||
pub const NCKEY_F07: char = unsafe { transmute(suppuabize(27)) };
|
||||
pub const NCKEY_F08: char = unsafe { transmute(suppuabize(28)) };
|
||||
pub const NCKEY_F09: char = unsafe { transmute(suppuabize(29)) };
|
||||
pub const NCKEY_F10: char = unsafe { transmute(suppuabize(30)) };
|
||||
pub const NCKEY_F11: char = unsafe { transmute(suppuabize(31)) };
|
||||
pub const NCKEY_F12: char = unsafe { transmute(suppuabize(32)) };
|
||||
pub const NCKEY_F13: char = unsafe { transmute(suppuabize(33)) };
|
||||
pub const NCKEY_F14: char = unsafe { transmute(suppuabize(34)) };
|
||||
pub const NCKEY_F15: char = unsafe { transmute(suppuabize(35)) };
|
||||
pub const NCKEY_F16: char = unsafe { transmute(suppuabize(36)) };
|
||||
pub const NCKEY_F17: char = unsafe { transmute(suppuabize(37)) };
|
||||
pub const NCKEY_F18: char = unsafe { transmute(suppuabize(38)) };
|
||||
pub const NCKEY_F19: char = unsafe { transmute(suppuabize(39)) };
|
||||
pub const NCKEY_F20: char = unsafe { transmute(suppuabize(40)) };
|
||||
pub const NCKEY_F21: char = unsafe { transmute(suppuabize(41)) };
|
||||
pub const NCKEY_F22: char = unsafe { transmute(suppuabize(42)) };
|
||||
pub const NCKEY_F23: char = unsafe { transmute(suppuabize(43)) };
|
||||
pub const NCKEY_F24: char = unsafe { transmute(suppuabize(44)) };
|
||||
pub const NCKEY_F25: char = unsafe { transmute(suppuabize(45)) };
|
||||
pub const NCKEY_F26: char = unsafe { transmute(suppuabize(46)) };
|
||||
pub const NCKEY_F27: char = unsafe { transmute(suppuabize(47)) };
|
||||
pub const NCKEY_F28: char = unsafe { transmute(suppuabize(48)) };
|
||||
pub const NCKEY_F29: char = unsafe { transmute(suppuabize(49)) };
|
||||
pub const NCKEY_F30: char = unsafe { transmute(suppuabize(50)) };
|
||||
pub const NCKEY_F31: char = unsafe { transmute(suppuabize(51)) };
|
||||
pub const NCKEY_F32: char = unsafe { transmute(suppuabize(52)) };
|
||||
pub const NCKEY_F33: char = unsafe { transmute(suppuabize(53)) };
|
||||
pub const NCKEY_F34: char = unsafe { transmute(suppuabize(54)) };
|
||||
pub const NCKEY_F35: char = unsafe { transmute(suppuabize(55)) };
|
||||
pub const NCKEY_F36: char = unsafe { transmute(suppuabize(56)) };
|
||||
pub const NCKEY_F37: char = unsafe { transmute(suppuabize(57)) };
|
||||
pub const NCKEY_F38: char = unsafe { transmute(suppuabize(58)) };
|
||||
pub const NCKEY_F39: char = unsafe { transmute(suppuabize(59)) };
|
||||
pub const NCKEY_F40: char = unsafe { transmute(suppuabize(60)) };
|
||||
pub const NCKEY_F41: char = unsafe { transmute(suppuabize(61)) };
|
||||
pub const NCKEY_F42: char = unsafe { transmute(suppuabize(62)) };
|
||||
pub const NCKEY_F43: char = unsafe { transmute(suppuabize(63)) };
|
||||
pub const NCKEY_F44: char = unsafe { transmute(suppuabize(64)) };
|
||||
pub const NCKEY_F45: char = unsafe { transmute(suppuabize(65)) };
|
||||
pub const NCKEY_F46: char = unsafe { transmute(suppuabize(66)) };
|
||||
pub const NCKEY_F47: char = unsafe { transmute(suppuabize(67)) };
|
||||
pub const NCKEY_F48: char = unsafe { transmute(suppuabize(68)) };
|
||||
pub const NCKEY_F49: char = unsafe { transmute(suppuabize(69)) };
|
||||
pub const NCKEY_F50: char = unsafe { transmute(suppuabize(70)) };
|
||||
pub const NCKEY_F51: char = unsafe { transmute(suppuabize(71)) };
|
||||
pub const NCKEY_F52: char = unsafe { transmute(suppuabize(72)) };
|
||||
pub const NCKEY_F53: char = unsafe { transmute(suppuabize(73)) };
|
||||
pub const NCKEY_F54: char = unsafe { transmute(suppuabize(74)) };
|
||||
pub const NCKEY_F55: char = unsafe { transmute(suppuabize(75)) };
|
||||
pub const NCKEY_F56: char = unsafe { transmute(suppuabize(76)) };
|
||||
pub const NCKEY_F57: char = unsafe { transmute(suppuabize(77)) };
|
||||
pub const NCKEY_F58: char = unsafe { transmute(suppuabize(78)) };
|
||||
pub const NCKEY_F59: char = unsafe { transmute(suppuabize(79)) };
|
||||
pub const NCKEY_F60: char = unsafe { transmute(suppuabize(80)) };
|
||||
|
||||
// ... leave room for up to 100 function keys, egads
|
||||
|
||||
pub const NCKEY_ENTER: char = unsafe { transmute(suppuabize(121)) };
|
||||
/// "clear-screen or erase"
|
||||
pub const NCKEY_CLS: char = unsafe { transmute(suppuabize(122)) };
|
||||
/// down + left on keypad
|
||||
pub const NCKEY_DLEFT: char = unsafe { transmute(suppuabize(123)) };
|
||||
pub const NCKEY_DRIGHT: char = unsafe { transmute(suppuabize(124)) };
|
||||
/// up + left on keypad
|
||||
pub const NCKEY_ULEFT: char = unsafe { transmute(suppuabize(125)) };
|
||||
pub const NCKEY_URIGHT: char = unsafe { transmute(suppuabize(126)) };
|
||||
/// the most truly neutral of keypresses
|
||||
pub const NCKEY_CENTER: char = unsafe { transmute(suppuabize(127)) };
|
||||
pub const NCKEY_BEGIN: char = unsafe { transmute(suppuabize(128)) };
|
||||
pub const NCKEY_CANCEL: char = unsafe { transmute(suppuabize(129)) };
|
||||
pub const NCKEY_CLOSE: char = unsafe { transmute(suppuabize(130)) };
|
||||
pub const NCKEY_COMMAND: char = unsafe { transmute(suppuabize(131)) };
|
||||
pub const NCKEY_COPY: char = unsafe { transmute(suppuabize(132)) };
|
||||
pub const NCKEY_EXIT: char = unsafe { transmute(suppuabize(133)) };
|
||||
pub const NCKEY_PRINT: char = unsafe { transmute(suppuabize(134)) };
|
||||
pub const NCKEY_REFRESH: char = unsafe { transmute(suppuabize(135)) };
|
||||
|
||||
// Mouse events. We try to encode some details into the char32_t (i.e. which
|
||||
// button was pressed);, but some is embedded in the ncinput event. The release
|
||||
// event is generic across buttons; callers must maintain state, if they care.
|
||||
pub const NCKEY_BUTTON1: char = unsafe { transmute(suppuabize(201)) };
|
||||
pub const NCKEY_BUTTON2: char = unsafe { transmute(suppuabize(202)) };
|
||||
pub const NCKEY_BUTTON3: char = unsafe { transmute(suppuabize(203)) };
|
||||
/// scrollwheel up
|
||||
pub const NCKEY_BUTTON4: char = unsafe { transmute(suppuabize(204)) };
|
||||
/// scrollwheel down
|
||||
pub const NCKEY_BUTTON5: char = unsafe { transmute(suppuabize(205)) };
|
||||
pub const NCKEY_BUTTON6: char = unsafe { transmute(suppuabize(206)) };
|
||||
pub const NCKEY_BUTTON7: char = unsafe { transmute(suppuabize(207)) };
|
||||
pub const NCKEY_BUTTON8: char = unsafe { transmute(suppuabize(208)) };
|
||||
pub const NCKEY_BUTTON9: char = unsafe { transmute(suppuabize(209)) };
|
||||
pub const NCKEY_BUTTON10: char = unsafe { transmute(suppuabize(210)) };
|
||||
pub const NCKEY_BUTTON11: char = unsafe { transmute(suppuabize(211)) };
|
||||
pub const NCKEY_RELEASE: char = unsafe { transmute(suppuabize(212)) };
|
||||
|
||||
// Synonyms (so far as we're concerned)
|
||||
pub const NCKEY_SCROLL_UP: char = NCKEY_BUTTON4;
|
||||
pub const NCKEY_SCROLL_DOWN: char = NCKEY_BUTTON5;
|
||||
pub const NCKEY_RETURN: char = NCKEY_ENTER;
|
||||
|
||||
// Aliases, from the 128 characters common to ASCII+UTF8
|
||||
pub const NCKEY_ESC: char = unsafe { transmute(0x1b) };
|
||||
pub const NCKEY_SPACE: char = unsafe { transmute(0x20) };
|
@ -1,139 +0,0 @@
|
||||
//! `NcInput` & `NcKey`
|
||||
|
||||
// functions manually reimplemented: 4
|
||||
// ------------------------------------------
|
||||
// (+) done: 4
|
||||
// (#) test: 0
|
||||
// ------------------------------------------
|
||||
// + ncinput_equal_p
|
||||
// + ncinput_nomod_p
|
||||
// + nckey_mouse_p
|
||||
// + nckey_supppuab_p
|
||||
|
||||
use crate::NcDim;
|
||||
|
||||
mod keycodes;
|
||||
pub use keycodes::*;
|
||||
|
||||
/// Reads and decodes input events.
|
||||
///
|
||||
/// Reads from stdin and decodes the input to stdout, including synthesized
|
||||
/// events and mouse events. Notcurses provides input from keyboards and mice.
|
||||
/// Single Unicode codepoints are received from the keyboard, directly encoded
|
||||
/// as `u32`.
|
||||
///
|
||||
/// The input system must deal with numerous keyboard signals which do not map
|
||||
/// to Unicode code points. This includes the keypad arrows and function keys.
|
||||
/// These "synthesized" codepoints are enumerated in , and mapped into the
|
||||
/// Supplementary Private Use Area-B (U+100000..U+10FFFD).
|
||||
/// Mouse button events are similarly mapped into the SPUA-B.
|
||||
///
|
||||
/// All events carry a ncinput structure with them.
|
||||
/// For mouse events, the x and y coordinates are reported within this struct.
|
||||
/// For all events, modifiers (e.g. "Alt") are carried as bools in this struct.
|
||||
pub type NcInput = crate::bindings::ffi::ncinput;
|
||||
|
||||
/// New NcInput.
|
||||
impl NcInput {
|
||||
/// New empty NcInput.
|
||||
pub const fn new_empty() -> NcInput {
|
||||
NcInput {
|
||||
id: 0,
|
||||
y: 0,
|
||||
x: 0,
|
||||
alt: false,
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
seqnum: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// New NcInput.
|
||||
pub const fn new(id: char) -> NcInput {
|
||||
Self::with_all_args(id, None, None, false, false, false, 0)
|
||||
}
|
||||
|
||||
/// New NcInput with alt key.
|
||||
pub const fn with_alt(id: char) -> NcInput {
|
||||
Self::with_all_args(id, None, None, true, false, false, 0)
|
||||
}
|
||||
|
||||
/// New NcInput with shift key.
|
||||
pub const fn with_shift(id: char) -> NcInput {
|
||||
Self::with_all_args(id, None, None, false, true, false, 0)
|
||||
}
|
||||
|
||||
/// New NcInput with ctrl key.
|
||||
pub const fn with_ctrl(id: char) -> NcInput {
|
||||
Self::with_all_args(id, None, None, false, false, true, 0)
|
||||
}
|
||||
|
||||
/// New NcInput, expecting all the arguments.
|
||||
pub const fn with_all_args(
|
||||
id: char,
|
||||
x: Option<NcDim>,
|
||||
y: Option<NcDim>,
|
||||
alt: bool,
|
||||
shift: bool,
|
||||
ctrl: bool,
|
||||
seqnum: u64,
|
||||
) -> NcInput {
|
||||
let (ix, iy);
|
||||
if let Some(x) = x {
|
||||
ix = x as i32
|
||||
} else {
|
||||
ix = -1
|
||||
};
|
||||
if let Some(y) = y {
|
||||
iy = y as i32
|
||||
} else {
|
||||
iy = -1
|
||||
};
|
||||
|
||||
NcInput {
|
||||
id: id as u32,
|
||||
y: ix,
|
||||
x: iy,
|
||||
alt,
|
||||
shift,
|
||||
ctrl,
|
||||
seqnum,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compares two ncinput structs for data equality by doing a field-by-field
|
||||
/// comparison for equality (excepting seqnum).
|
||||
///
|
||||
/// Returns true if the two are data-equivalent.
|
||||
pub const fn ncinput_equal_p(n1: NcInput, n2: NcInput) -> bool {
|
||||
if n1.id != n2.id {
|
||||
return false;
|
||||
}
|
||||
if n1.y != n2.y || n1.x != n2.x {
|
||||
return false;
|
||||
}
|
||||
// do not check seqnum
|
||||
true
|
||||
}
|
||||
|
||||
/// Are all the modifiers off (alt, control, shift)?
|
||||
pub const fn ncinput_nomod_p(input: &NcInput) -> bool {
|
||||
!input.alt && !input.ctrl && !input.shift
|
||||
}
|
||||
|
||||
/// Is this [char] a Supplementary Private Use Area-B codepoint?
|
||||
///
|
||||
/// Links:
|
||||
/// - <https://en.wikipedia.org/wiki/Private_Use_Areas>
|
||||
/// - <https://codepoints.net/supplementary_private_use_area-b>
|
||||
#[inline]
|
||||
pub const fn nckey_supppuab_p(w: char) -> bool {
|
||||
w as u32 >= 0x100000_u32 && w as u32 <= 0x10fffd_u32
|
||||
}
|
||||
|
||||
/// Is the event a synthesized mouse event?
|
||||
#[inline]
|
||||
pub const fn nckey_mouse_p(r: char) -> bool {
|
||||
r >= NCKEY_BUTTON1 && r <= NCKEY_RELEASE
|
||||
}
|
162
rust/src/lib.rs
162
rust/src/lib.rs
@ -1,162 +0,0 @@
|
||||
//! `libnotcurses-sys` is a low-level Rust wrapper for the [notcurses
|
||||
//! C library](https://www.github.com/dankamongmen/notcurses/)
|
||||
//!
|
||||
//! *This is a work in progress.*
|
||||
//!
|
||||
//! This library is built with several layers of zero-overhead abstractions
|
||||
//! over the C functions and pointers accessed through FFI.
|
||||
//!
|
||||
//! # How to use this library
|
||||
//!
|
||||
//! There are basically two ways: The [**Rust way**](#1-the-rust-way),
|
||||
//! and the [**C way**](#2-the-c-way). (Or a mix of both).
|
||||
//!
|
||||
//! ## 1. The Rust way
|
||||
//!
|
||||
//! Where you use the safely wrapped types, with its methods and constructors,
|
||||
//! and painless error handling, like this:
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use libnotcurses_sys::*;
|
||||
//!
|
||||
//! # #[cfg(not(miri))]
|
||||
//! fn main() -> NcResult<()> {
|
||||
//! let mut nc = Nc::with_flags(NCOPTION_NO_ALTERNATE_SCREEN)?;
|
||||
//! let plane = nc.stdplane();
|
||||
//! plane.putstr("hello world")?;
|
||||
//! nc.render()?;
|
||||
//! nc.stop()?;
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! # #[cfg(miri)]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! Although you still have to manually call the `stop()` method for [`Nc`] and
|
||||
//! [`NcDirect`] objects, and the `destroy()` method for the rest of types that
|
||||
//! allocate, (like [`NcPlane`], [`NcVisual`]…) at the end of their scope, since
|
||||
//! the Drop trait is not implemented for any wrapping type in libnotcurses-sys.
|
||||
//!
|
||||
//! But they do implement methods and use [`NcResult`] as the return type,
|
||||
//! for handling errors in the way we are used to in Rust.
|
||||
//!
|
||||
//! For the types that don't allocate, most are based on primitives like `i32`,
|
||||
//! `u32`, `u64`… without a name in the C library. In Rust they are type aliased
|
||||
//! (e.g.: [`NcChannel`], [`NcChannels`], [`NcRgb`], [`NcComponent`]…), to
|
||||
//! leverage type checking, and they implement methods through [traits](#traits)
|
||||
//! (e.g. [`NcChannelMethods`] must be in scope to use the `NcChannel` methods.
|
||||
//!
|
||||
//!
|
||||
//! ## 2. The C way
|
||||
//!
|
||||
//! You can always use the C API functions directly if you prefer,
|
||||
//! in a very similar way as the C library is used.
|
||||
//!
|
||||
//! It requires the use of unsafe, since most functions are wrapped directly
|
||||
//! by `bindgen` marked as such.
|
||||
//!
|
||||
//! Error handling is done this way by checking the returned [`NcIntResult`],
|
||||
//! or in case of receiving a pointer, by comparing it
|
||||
//! to [null_mut()][core::ptr::null_mut].
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use core::ptr::{null, null_mut};
|
||||
//! use std::process::exit;
|
||||
//!
|
||||
//! use libnotcurses_sys::*;
|
||||
//!
|
||||
//! # #[cfg(not(miri))]
|
||||
//! fn main() {
|
||||
//! let options = ffi::notcurses_options {
|
||||
//! termtype: null(),
|
||||
//! renderfp: null_mut(),
|
||||
//! loglevel: 0,
|
||||
//! margin_t: 0,
|
||||
//! margin_r: 0,
|
||||
//! margin_b: 0,
|
||||
//! margin_l: 0,
|
||||
//! flags: NCOPTION_NO_ALTERNATE_SCREEN,
|
||||
//! };
|
||||
//! unsafe {
|
||||
//! let nc = notcurses_init(&options, null_mut());
|
||||
//! if nc.is_null() {
|
||||
//! exit(1);
|
||||
//! }
|
||||
//! let plane = notcurses_stdplane(nc);
|
||||
//! let cols = ncplane_putstr(&mut *plane, "hello world");
|
||||
//! if cols < NCRESULT_OK {
|
||||
//! notcurses_stop(nc);
|
||||
//! exit(cols.abs());
|
||||
//! }
|
||||
//! if notcurses_stop(nc) < NCRESULT_OK {
|
||||
//! exit(2);
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! # #[cfg(miri)]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! ### The `notcurses` C API docs
|
||||
//!
|
||||
//! - [API reference (man pages)](https://notcurses.com/)
|
||||
//! - [Wiki Page](https://nick-black.com/dankwiki/index.php/Notcurses)
|
||||
//! - [The Book Guide (pdf)](https://nick-black.com/htp-notcurses.pdf)
|
||||
//! - [USAGE.md](https://github.com/dankamongmen/notcurses/blob/master/USAGE.md)
|
||||
//! - [HACKING.md](https://github.com/dankamongmen/notcurses/blob/master/doc/HACKING.md)
|
||||
//! - [Doxygen Documentation](https://nick-black.com/notcurses/html/index.html)
|
||||
//! - [FOSDEM 2021 presentation](https://fosdem.org/2021/schedule/event/notcurses/)
|
||||
//!
|
||||
#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case)]
|
||||
#![allow(clippy::too_many_arguments, clippy::needless_doctest_main)]
|
||||
|
||||
mod bindings;
|
||||
#[doc(inline)]
|
||||
pub use bindings::*;
|
||||
|
||||
mod r#box;
|
||||
mod capabilities;
|
||||
mod cells;
|
||||
mod channel;
|
||||
mod dimension;
|
||||
mod direct;
|
||||
mod error;
|
||||
mod fade;
|
||||
mod file;
|
||||
mod input;
|
||||
mod macros;
|
||||
mod metric;
|
||||
mod notcurses;
|
||||
mod palette;
|
||||
mod pixel;
|
||||
mod plane;
|
||||
mod resizecb;
|
||||
mod stats;
|
||||
mod time;
|
||||
mod visual;
|
||||
pub mod widgets;
|
||||
|
||||
pub use crate::input::*;
|
||||
pub use capabilities::*;
|
||||
pub use cells::*;
|
||||
pub use channel::*;
|
||||
pub use dimension::*;
|
||||
pub use direct::*;
|
||||
pub use error::*;
|
||||
pub use fade::*;
|
||||
pub use file::*;
|
||||
pub use macros::*;
|
||||
pub use metric::*;
|
||||
pub use notcurses::*;
|
||||
pub use palette::*;
|
||||
pub use pixel::*;
|
||||
pub use plane::*;
|
||||
pub use r#box::*;
|
||||
pub use resizecb::*;
|
||||
pub use stats::*;
|
||||
pub use time::*;
|
||||
pub use visual::*;
|
@ -1,276 +0,0 @@
|
||||
//! Macros
|
||||
//!
|
||||
//
|
||||
// NOTE: Use full paths everywhere. Don't assume anything will be in scope.
|
||||
|
||||
#[allow(unused_imports)]
|
||||
// enjoy briefer doc comments
|
||||
use crate::{Nc, NcDirect, NcError, NcPlane, NcResult, NCRESULT_ERR, NCRESULT_OK};
|
||||
|
||||
// Sleep, Render & Flush Macros ------------------------------------------------
|
||||
|
||||
/// Sleeps for `$s` seconds + `$ms` milliseconds
|
||||
/// + `$us` microseconds + `$ns` nanoseconds
|
||||
#[macro_export]
|
||||
macro_rules! sleep {
|
||||
($s:expr) => {
|
||||
std::thread::sleep(std::time::Duration::from_secs($s));
|
||||
};
|
||||
|
||||
($s:expr, $ms:expr) => {
|
||||
std::thread::sleep(std::time::Duration::from_millis($s * 1000 + $ms));
|
||||
};
|
||||
($s:expr, $ms:expr, $us:expr) => {
|
||||
std::thread::sleep(std::time::Duration::from_micros(
|
||||
$s * 1_000_000 + $ms * 1_000 + $us,
|
||||
));
|
||||
};
|
||||
($s:expr, $ms:expr, $us:expr, $ns:expr) => {
|
||||
std::thread::sleep(std::time::Duration::from_nanos(
|
||||
$s * 1_000_000_000 + $ms * 1_000_000 + $us * 1_000 + $ns,
|
||||
));
|
||||
};
|
||||
}
|
||||
|
||||
/// notcurses render sleep:
|
||||
/// [`Nc::render`][Nc#method.render]\(`$nc`\)? + [`sleep!`]`[$sleep_args]`.
|
||||
///
|
||||
/// Renders the `$nc` [`Nc`] object's standard plane pile and then,
|
||||
/// if there's no error, calls the sleep macro with the rest of the arguments.
|
||||
///
|
||||
/// Returns [NcResult].
|
||||
#[macro_export]
|
||||
macro_rules! nrs {
|
||||
($nc:expr, $( $sleep_args:expr),+ ) => {
|
||||
crate::Nc::render($nc)?;
|
||||
sleep![$( $sleep_args ),+];
|
||||
};
|
||||
($nc:expr, $( $sleep_args:expr),+ ,) => {
|
||||
rsleep![$nc, $( $sleep_args ),* ]
|
||||
};
|
||||
}
|
||||
|
||||
/// plane render sleep:
|
||||
/// [`NcPlane::render`][NcPlane#method.render]\(`$p`\)? +
|
||||
/// [`NcPlane::rasterize`][NcPlane#method.rasterize]\(`$p`\)? +
|
||||
/// [`sleep!`]`[$sleep_args]`.
|
||||
///
|
||||
/// Renders and rasterizes the `$p` [NcPlane] pile and then, if there are
|
||||
/// no errors, calls the sleep macro with the rest of the arguments.
|
||||
///
|
||||
/// Returns [NcResult].
|
||||
#[macro_export]
|
||||
macro_rules! prs {
|
||||
($p:expr, $( $sleep_args:expr),+ ) => {
|
||||
crate::NcPlane::render($p)?;
|
||||
crate::NcPlane::rasterize($p)?;
|
||||
sleep![$( $sleep_args ),+];
|
||||
};
|
||||
($nc:expr, $( $sleep_args:expr),+ ,) => {
|
||||
rsleep![$nc, $( $sleep_args ),* ]
|
||||
};
|
||||
}
|
||||
|
||||
/// [`NcDirect::flush`][NcDirect#method.flush]\(`$ncd`\)? + [`sleep!`]`[$sleep_args]`.
|
||||
///
|
||||
/// Flushes the `$ncd` [NcDirect] object and, if there's no error,
|
||||
/// calls the sleep macro with the rest of the arguments.
|
||||
///
|
||||
/// Returns [NcResult].
|
||||
#[macro_export]
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
macro_rules! fsleep {
|
||||
($ncd:expr, $( $sleep_args:expr),+ ) => {
|
||||
// Rust style, with methods & NcResult
|
||||
crate::NcDirect::flush($ncd)?;
|
||||
sleep![$( $sleep_args ),+];
|
||||
};
|
||||
($ncd:expr, $( $sleep_args:expr),+ ,) => {
|
||||
rsleep![$ncd, $( $sleep_args ),* ]
|
||||
};
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! prsleep {
|
||||
($p:expr, $( $sleep_args:expr),+ ) => {
|
||||
prs![$p, $( $sleep_args ),+];
|
||||
};
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! psleep {
|
||||
($p:expr, $( $sleep_args:expr),+ ) => {
|
||||
prs![$p, $( $sleep_args ),+];
|
||||
};
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! rsleep {
|
||||
($nc:expr, $( $sleep_args:expr),+ ) => {
|
||||
nrs![$nc, $( $sleep_args ),+];
|
||||
};
|
||||
}
|
||||
|
||||
// String & Print Macros -------------------------------------------------------
|
||||
|
||||
/// Converts an `&str` into `*const c_char`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! cstring {
|
||||
($s:expr) => {
|
||||
std::ffi::CString::new($s).unwrap().as_ptr()
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts an `&str` into `*mut c_char`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! cstring_mut {
|
||||
($s:expr) => {
|
||||
std::ffi::CString::new($s).unwrap().into_raw()
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts a `*const c_char` into an `&str`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! rstring {
|
||||
($s:expr) => {
|
||||
unsafe { std::ffi::CStr::from_ptr($s).to_str().unwrap() }
|
||||
// possible alternative:
|
||||
// unsafe { std::ffi::CStr::from_ptr($s).to_string_lossy() }
|
||||
};
|
||||
}
|
||||
|
||||
/// Wrapper around [libc::printf].
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! printf {
|
||||
($s:expr) => {
|
||||
unsafe { libc::printf(cstring![$s]) }
|
||||
};
|
||||
($s:expr $(, $opt:expr)*) => {
|
||||
unsafe { libc::printf(cstring![$s], $($opt),*) }
|
||||
};
|
||||
}
|
||||
|
||||
// Error Wrappers Macros -------------------------------------------------------
|
||||
|
||||
/// Returns an `Ok($ok)`,
|
||||
/// or an `Err(`[`NcError`]`)` if `$res` < [`NCRESULT_OK`].
|
||||
///
|
||||
/// In other words:
|
||||
/// Returns Ok(`$ok`) if `$res` >= [NCRESULT_OK], otherwise returns
|
||||
/// Err([NcError]::[new][NcError#method.new](`$res`, `$msg`)).
|
||||
///
|
||||
/// `$ok` & `$msg` are optional. By default they will be the unit
|
||||
/// type `()`, and an empty `&str` `""`, respectively.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! error {
|
||||
($res:expr, $msg:expr, $ok:expr) => {{
|
||||
let res = $res;
|
||||
if res >= crate::NCRESULT_OK {
|
||||
return Ok($ok);
|
||||
} else {
|
||||
return Err(crate::NcError::with_msg(res, $msg));
|
||||
}
|
||||
}};
|
||||
($res:expr, $msg:expr) => {
|
||||
error![$res, $msg, ()]
|
||||
};
|
||||
($res:expr) => {
|
||||
error![$res, "", ()]
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns an `Ok(&T)` from a `*const T` pointer,
|
||||
/// or an `Err(`[`NcError`]`)` if the pointer is null.
|
||||
///
|
||||
/// In other words:
|
||||
/// Returns Ok(&*`$ptr`) if `!$ptr.is_null()`, otherwise returns
|
||||
/// Err([NcError]]::[new][NcError#method.new]([NCRESULT_ERR], `$msg`)).
|
||||
///
|
||||
/// `$msg` is optional. By default it will be an empty `&str` `""`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! error_ref {
|
||||
($ptr:expr, $msg:expr, $ok:expr) => {{
|
||||
let ptr = $ptr; // avoid calling a function multiple times
|
||||
if ptr.is_null() {
|
||||
return Err(crate::NcError::with_msg(crate::NCRESULT_ERR, $msg));
|
||||
} else {
|
||||
#[allow(unused_unsafe)]
|
||||
return Ok(unsafe { $ok });
|
||||
}
|
||||
}};
|
||||
($ptr:expr, $msg:expr) => {{
|
||||
let ptr = $ptr;
|
||||
error_ref![$ptr, $msg, unsafe { &*ptr }];
|
||||
}};
|
||||
($ptr:expr) => {{
|
||||
let ptr = $ptr;
|
||||
error_ref![$ptr, "", unsafe { &*ptr }];
|
||||
}};
|
||||
}
|
||||
|
||||
/// Returns an `Ok(&mut T)` from a `*mut T` pointer,
|
||||
/// or an `Err(`[`NcError`]`)` if the pointer is null.
|
||||
///
|
||||
/// In other words:
|
||||
/// Returns Ok(&mut *`$ptr`) if `!$ptr._is_null()`, otherwise returns
|
||||
/// Err([NcError]]::[new][NcError#method.new]([NCRESULT_ERR], `$msg`)).
|
||||
///
|
||||
/// `$msg` is optional. By default it will be an empty `&str` `""`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! error_ref_mut {
|
||||
($ptr:expr, $msg:expr, $ok:expr) => {{
|
||||
let ptr = $ptr; // avoid calling a function multiple times
|
||||
if ptr.is_null() {
|
||||
return Err(crate::NcError::with_msg(crate::NCRESULT_ERR, $msg));
|
||||
} else {
|
||||
#[allow(unused_unsafe)]
|
||||
return Ok(unsafe { $ok });
|
||||
}
|
||||
}};
|
||||
($ptr:expr, $msg:expr) => {{
|
||||
let ptr = $ptr;
|
||||
error_ref_mut![ptr, $msg, unsafe { &mut *ptr }];
|
||||
}};
|
||||
($ptr:expr) => {{
|
||||
let ptr = $ptr;
|
||||
error_ref_mut![ptr, "", unsafe { &mut *ptr }];
|
||||
}};
|
||||
}
|
||||
|
||||
/// Returns an `Ok(String)` from a `*const` pointer to a C string,
|
||||
/// or an `Err(`[`NcError`]`)` if the pointer is null.
|
||||
///
|
||||
/// In other words:
|
||||
/// Returns Ok((&*`$str`).to_string()) if `!$str.is_null()`, otherwise returns
|
||||
/// Err([NcError]]::[new][NcError#method.new]([NCRESULT_ERR], `$msg`)).
|
||||
///
|
||||
/// `$msg` is optional. By default it will be an empty `&str` `""`.
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! error_str {
|
||||
($str:expr, $msg:expr) => {
|
||||
if !$str.is_null() {
|
||||
#[allow(unused_unsafe)]
|
||||
return Ok(unsafe { (&*$str).to_string() });
|
||||
} else {
|
||||
return Err(crate::NcError::with_msg(crate::NCRESULT_ERR, $msg));
|
||||
}
|
||||
};
|
||||
($str:expr) => {
|
||||
error_str![$str, ""];
|
||||
};
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
//! `NcMetric`
|
||||
|
||||
use crate::{cstring_mut, rstring};
|
||||
|
||||
// TODO: clarify, update and visibilize doc-comments
|
||||
|
||||
/// Takes an arbitrarily large number, and prints it into a fixed-size buffer by
|
||||
/// adding the necessary SI suffix.
|
||||
///
|
||||
/// Usually, pass a `|[IB]PREFIXSTRLEN+1|-sized` buffer to generate up to
|
||||
/// `|[IB]PREFIXCOLUMNS|` columns' worth of EGCs. The characteristic can occupy
|
||||
/// up through `|mult-1|` characters (3 for 1000, 4 for 1024).
|
||||
/// The mantissa can occupy either zero or two characters.
|
||||
///
|
||||
/// Floating-point is never used, because an IEEE758 double can only losslessly
|
||||
/// represent integers through 2^53-1.
|
||||
///
|
||||
/// 2^64-1 is 18446744073709551615, 18.45E(xa). KMGTPEZY thus suffice to handle
|
||||
/// an 89-bit uintmax_t. Beyond Z(etta) and Y(otta) lie lands unspecified by SI.
|
||||
/// 2^-63 is 0.000000000000000000108, 1.08a(tto). val: value to print decimal:
|
||||
/// scaling. '1' if none has taken place. buf: buffer in which string will be
|
||||
/// generated omitdec: inhibit printing of all-0 decimal portions mult: base of
|
||||
/// suffix system (almost always 1000 or 1024) uprefix: character to print
|
||||
/// following suffix ('i' for kibibytes basically). only printed if suffix is
|
||||
/// actually printed (input >= mult).
|
||||
///
|
||||
/// You are encouraged to consult notcurses_metric(3).
|
||||
///
|
||||
pub fn ncmetric(val: u64, decimal: u64, buf: &str, omitdec: i32, mult: u64, uprefix: i32) -> &str {
|
||||
let buf = cstring_mut![buf];
|
||||
rstring![crate::ffi::ncmetric(
|
||||
val, decimal, buf, omitdec, mult, uprefix
|
||||
)]
|
||||
}
|
||||
|
||||
// The number of columns is one fewer, as the STRLEN expressions must leave
|
||||
// an extra byte open in case 'µ' (U+00B5, 0xC2 0xB5) shows up.
|
||||
|
||||
// This is the true number of columns;
|
||||
//
|
||||
// to set up a printf()-style maximum field width,
|
||||
// you should use [IB]PREFIXFMT (see below).
|
||||
pub const NCMETRIC_PREFIXCOLUMNS: u32 = crate::bindings::ffi::PREFIXCOLUMNS;
|
||||
|
||||
// The maximum number of columns used by a mult == 1000 (standard)
|
||||
// ncmetric() call.
|
||||
pub const NCMETRIC_BPREFIXCOLUMNS: u32 = crate::bindings::ffi::BPREFIXCOLUMNS;
|
||||
|
||||
// IPREFIXCOLUMNS is the maximum number of columns used by a mult == 1024
|
||||
// (digital information) ncmetric().
|
||||
pub const NCMETRIC_IPREFIXCOLUMNS: u32 = crate::bindings::ffi::IPREFIXCOLUMNS;
|
||||
|
||||
//
|
||||
// Does not include a '\0' (xxx.xxU)
|
||||
pub const NCMETRIC_PREFIXSTRLEN: u32 = crate::bindings::ffi::PREFIXSTRLEN;
|
||||
|
||||
// The maximum number of columns used by a mult == 1024 call making use of
|
||||
// the 'i' suffix.
|
||||
// Does not include a '\0' (xxxx.xxUi), i == prefix
|
||||
pub const NCMETRIC_BPREFIXSTRLEN: u32 = crate::bindings::ffi::BPREFIXSTRLEN;
|
||||
|
||||
// Does not include a '\0' (xxxx.xxU)
|
||||
pub const NCMETRIC_IPREFIXSTRLEN: u32 = crate::bindings::ffi::IPREFIXSTRLEN;
|
||||
|
||||
// TODO:?
|
||||
// WCHAR_MAX_UTF8BYTES
|
@ -1,10 +0,0 @@
|
||||
use crate::{notcurses_init, Nc, NcOptions, NCOPTION_SUPPRESS_BANNERS};
|
||||
|
||||
/// Helper function for initializing Nc on C style tests.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) unsafe fn notcurses_init_test<'a>() -> &'a mut Nc {
|
||||
&mut *notcurses_init(
|
||||
&NcOptions::with_flags(NCOPTION_SUPPRESS_BANNERS),
|
||||
core::ptr::null_mut(),
|
||||
)
|
||||
}
|
@ -1,740 +0,0 @@
|
||||
//! `Nc*` methods and associated functions.
|
||||
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
use crate::{
|
||||
cstring, error, error_ref_mut, notcurses_init, rstring, Nc, NcAlign, NcBlitter, NcChannels,
|
||||
NcDim, NcError, NcFile, NcInput, NcLogLevel, NcOptions, NcPixelImpl, NcPlane, NcResult,
|
||||
NcScale, NcStats, NcStyle, NcStyleMethods, NcTime, NCOPTION_NO_ALTERNATE_SCREEN,
|
||||
NCOPTION_SUPPRESS_BANNERS, NCRESULT_ERR, NCSTYLE_BOLD, NCSTYLE_ITALIC, NCSTYLE_NONE,
|
||||
NCSTYLE_STRUCK, NCSTYLE_UNDERCURL, NCSTYLE_UNDERLINE,
|
||||
};
|
||||
|
||||
/// # `NcOptions` Constructors
|
||||
impl NcOptions {
|
||||
/// New NcOptions.
|
||||
pub const fn new() -> Self {
|
||||
Self::with_all_options(0, 0, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
/// New NcOptions, with margins.
|
||||
pub const fn with_margins(top: NcDim, right: NcDim, bottom: NcDim, left: NcDim) -> Self {
|
||||
Self::with_all_options(0, top, right, bottom, left, 0)
|
||||
}
|
||||
|
||||
/// New NcOptions, with flags.
|
||||
pub const fn with_flags(flags: u64) -> Self {
|
||||
Self::with_all_options(0, 0, 0, 0, 0, flags)
|
||||
}
|
||||
|
||||
/// New NcOptions, with all the options.
|
||||
///
|
||||
/// ## Arguments
|
||||
///
|
||||
/// - loglevel
|
||||
///
|
||||
/// Progressively higher log levels result in more logging to stderr. By
|
||||
/// default, nothing is printed to stderr once fullscreen service begins.
|
||||
///
|
||||
/// - margin_t, margin_r, margin_b, margin_l
|
||||
///
|
||||
/// Desirable margins (top, right, bottom, left).
|
||||
///
|
||||
/// If all are 0 (default), we will render to the entirety of the screen.
|
||||
/// If the screen is too small, we do what we can.
|
||||
/// Absolute coordinates are relative to the rendering area
|
||||
/// ((0, 0) is always the origin of the rendering area).
|
||||
///
|
||||
/// - flags
|
||||
///
|
||||
/// General flags; This is expressed as a bitfield so that future options
|
||||
/// can be added without reshaping the struct.
|
||||
/// Undefined bits must be set to 0.
|
||||
///
|
||||
/// - [`NCOPTION_INHIBIT_SETLOCALE`][crate::NCOPTION_INHIBIT_SETLOCALE]
|
||||
/// - [`NCOPTION_NO_ALTERNATE_SCREEN`]
|
||||
/// - [`NCOPTION_NO_FONT_CHANGES`][crate::NCOPTION_NO_FONT_CHANGES]
|
||||
/// - [`NCOPTION_NO_QUIT_SIGHANDLERS`][crate::NCOPTION_NO_QUIT_SIGHANDLERS]
|
||||
/// - [`NCOPTION_NO_WINCH_SIGHANDLER`][crate::NCOPTION_NO_WINCH_SIGHANDLER]
|
||||
/// - [`NCOPTION_SUPPRESS_BANNERS`]
|
||||
///
|
||||
pub const fn with_all_options(
|
||||
loglevel: NcLogLevel,
|
||||
margin_t: NcDim,
|
||||
margin_r: NcDim,
|
||||
margin_b: NcDim,
|
||||
margin_l: NcDim,
|
||||
flags: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
termtype: null(),
|
||||
loglevel,
|
||||
renderfp: null_mut(),
|
||||
margin_t: margin_t as i32,
|
||||
margin_r: margin_r as i32,
|
||||
margin_b: margin_b as i32,
|
||||
margin_l: margin_l as i32,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # `Nc` Constructors
|
||||
impl Nc {
|
||||
/// New notcurses context (without banners).
|
||||
pub fn new<'a>() -> NcResult<&'a mut Nc> {
|
||||
Self::with_flags(NCOPTION_SUPPRESS_BANNERS)
|
||||
}
|
||||
|
||||
/// New notcurses context, with banners.
|
||||
///
|
||||
/// This is the default in the C library.
|
||||
pub fn with_banners<'a>() -> NcResult<&'a mut Nc> {
|
||||
Self::with_flags(0)
|
||||
}
|
||||
|
||||
/// New notcurses context, without an alternate screen (nor banners).
|
||||
pub fn without_altscreen<'a>() -> NcResult<&'a mut Nc> {
|
||||
Self::with_flags(NCOPTION_NO_ALTERNATE_SCREEN | NCOPTION_SUPPRESS_BANNERS)
|
||||
}
|
||||
|
||||
/// New notcurses context, expects `NCOPTION_*` flags.
|
||||
pub fn with_flags<'a>(flags: u64) -> NcResult<&'a mut Nc> {
|
||||
Self::with_options(NcOptions::with_flags(flags))
|
||||
}
|
||||
|
||||
/// New notcurses context, expects [NcOptions].
|
||||
pub fn with_options<'a>(options: NcOptions) -> NcResult<&'a mut Nc> {
|
||||
let res = unsafe { notcurses_init(&options, null_mut()) };
|
||||
error_ref_mut![res, "Notcurses.with_options()"]
|
||||
}
|
||||
|
||||
/// New notcurses context, expects [NcLogLevel] and flags.
|
||||
pub fn with_debug<'a>(loglevel: NcLogLevel, flags: u64) -> NcResult<&'a mut Nc> {
|
||||
Self::with_options(NcOptions::with_all_options(loglevel, 0, 0, 0, 0, flags))
|
||||
}
|
||||
}
|
||||
|
||||
/// # `Nc` methods
|
||||
impl Nc {
|
||||
/// Returns the offset into `availcols` at which `cols` ought be output given
|
||||
/// the requirements of `align`.
|
||||
///
|
||||
/// Returns `-`[`NCRESULT_MAX`][crate::NCRESULT_MAX] if
|
||||
/// [NCALIGN_UNALIGNED][crate::NCALIGN_UNALIGNED] or invalid [NcAlign].
|
||||
///
|
||||
/// *C style function: [notcurses_align()][crate::notcurses_align].*
|
||||
//
|
||||
// TODO: handle error rightfully.
|
||||
pub fn align(availcols: NcDim, align: NcAlign, cols: NcDim) -> NcResult<()> {
|
||||
error![crate::notcurses_align(availcols, align, cols)]
|
||||
}
|
||||
|
||||
/// Retrieves the current contents of the specified [NcCell][crate::NcCell]
|
||||
/// as last rendered, returning the `EGC` (or None on error) and writing
|
||||
/// out the [`NcStyle`] and the [`NcChannels`].
|
||||
///
|
||||
// possible BUG? CHECK:
|
||||
/// This `EGC` must be freed by the caller.
|
||||
///
|
||||
/// *C style function: [notcurses_at_yx()][crate::notcurses_at_yx].*
|
||||
pub fn at_yx(
|
||||
&mut self,
|
||||
y: NcDim,
|
||||
x: NcDim,
|
||||
stylemask: &mut NcStyle,
|
||||
channels: &mut NcChannels,
|
||||
) -> Option<String> {
|
||||
let egc = unsafe { crate::notcurses_at_yx(self, x as i32, y as i32, stylemask, channels) };
|
||||
if egc.is_null() {
|
||||
return None;
|
||||
}
|
||||
Some(rstring![egc].into())
|
||||
}
|
||||
|
||||
/// Returns the bottommost [`NcPlane`] on the standard pile,
|
||||
/// of which there is always at least one.
|
||||
///
|
||||
/// *C style function: [notcurses_bottom()][crate::notcurses_bottom].*
|
||||
pub fn bottom(&mut self) -> &mut NcPlane {
|
||||
unsafe { &mut *crate::notcurses_bottom(self) }
|
||||
}
|
||||
|
||||
/// Returns true if we can reliably use Unicode Braille.
|
||||
///
|
||||
/// See also [NCBLIT_BRAILLE][crate::NCBLIT_BRAILLE].
|
||||
///
|
||||
/// *C style function: [notcurses_canbraille()][crate::notcurses_canbraille].*
|
||||
pub fn canbraille(&self) -> bool {
|
||||
unsafe { crate::notcurses_canbraille(self) }
|
||||
}
|
||||
|
||||
/// Returns true if it's possible to set the "hardware" palette.
|
||||
///
|
||||
/// Requires the "ccc" terminfo capability.
|
||||
///
|
||||
/// *C style function: [notcurses_canchangecolor()][crate::notcurses_canchangecolor].*
|
||||
pub fn canchangecolor(&self) -> bool {
|
||||
unsafe { crate::notcurses_canchangecolor(self) }
|
||||
}
|
||||
|
||||
/// Returns true if fading is possible.
|
||||
///
|
||||
/// Fading requires either the "rgb" or "ccc" terminfo capability.
|
||||
///
|
||||
/// *C style function: [notcurses_canfade()][crate::notcurses_canfade].*
|
||||
pub fn canfade(&self) -> bool {
|
||||
unsafe { crate::notcurses_canfade(self) }
|
||||
}
|
||||
|
||||
/// Returns true if we can reliably use Unicode half blocks.
|
||||
///
|
||||
/// See also [NCBLIT_2x1][crate::NCBLIT_2x1].
|
||||
///
|
||||
/// *C style function: [notcurses_canhalfblock()][crate::notcurses_canhalfblock].*
|
||||
pub fn canhalfblock(&self) -> bool {
|
||||
unsafe { crate::notcurses_canhalfblock(self) }
|
||||
}
|
||||
|
||||
/// Returns true if loading images is possible.
|
||||
///
|
||||
/// This requires being built against FFmpeg/OIIO.
|
||||
///
|
||||
/// *C style function: [notcurses_canopen_images()][crate::notcurses_canopen_images].*
|
||||
pub fn canopen_images(&self) -> bool {
|
||||
unsafe { crate::notcurses_canopen_images(self) }
|
||||
}
|
||||
|
||||
/// Returns true if loading videos is possible.
|
||||
///
|
||||
/// This requires being built against FFmpeg.
|
||||
///
|
||||
/// *C style function: [notcurses_canopen_videos()][crate::notcurses_canopen_videos].*
|
||||
pub fn canopen_videos(&self) -> bool {
|
||||
unsafe { crate::notcurses_canopen_videos(self) }
|
||||
}
|
||||
|
||||
/// Returns true if we can reliably use Unicode quadrant blocks.
|
||||
///
|
||||
/// See also [NCBLIT_2x2][crate::NCBLIT_2x2].
|
||||
///
|
||||
/// *C style function: [notcurses_canquadrant()][crate::notcurses_canquadrant].*
|
||||
pub fn canquadrant(&self) -> bool {
|
||||
unsafe { crate::notcurses_canquadrant(self) }
|
||||
}
|
||||
|
||||
/// Returns true if we can reliably use Unicode 13 sextants.
|
||||
///
|
||||
/// See also [NCBLIT_3x2][crate::NCBLIT_3x2].
|
||||
///
|
||||
/// *C style function: [notcurses_cansextant()][crate::notcurses_cansextant].*
|
||||
pub fn cansextant(&self) -> bool {
|
||||
unsafe { crate::notcurses_cansextant(self) }
|
||||
}
|
||||
|
||||
/// Returns true if it's possible to directly specify RGB values per cell,
|
||||
/// or false if it's only possible to use palettes.
|
||||
///
|
||||
/// *C style function: [notcurses_cantruecolor()][crate::notcurses_cantruecolor].*
|
||||
pub fn cantruecolor(&self) -> bool {
|
||||
unsafe { crate::notcurses_cantruecolor(self) }
|
||||
}
|
||||
|
||||
/// Returns true if the encoding is UTF-8.
|
||||
///
|
||||
/// Requires `LANG` being set to a UTF-8 locale.
|
||||
///
|
||||
/// *C style function: [notcurses_canutf8()][crate::notcurses_canutf8].*
|
||||
pub fn canutf8(&self) -> bool {
|
||||
unsafe { crate::notcurses_canutf8(self) }
|
||||
}
|
||||
|
||||
/// Checks for pixel support.
|
||||
///
|
||||
/// Returns [`NcPixelImpl`] with a non-zero constant corresponding to some
|
||||
/// pixel-blitting mechanism if bitmap support (via any mechanism) has been
|
||||
/// detected, or else 0 (NCPIXEL_NONE).
|
||||
///
|
||||
/// *C style function: [notcurses_check_pixel_support()][crate::notcurses_check-pixel_support].*
|
||||
#[allow(clippy::wildcard_in_or_patterns)]
|
||||
pub fn check_pixel_support(&self) -> NcPixelImpl {
|
||||
unsafe { crate::notcurses_check_pixel_support(self) }
|
||||
}
|
||||
|
||||
/// Disables the terminal's cursor, if supported.
|
||||
///
|
||||
/// Immediate effect (no need for a call to notcurses_render()).
|
||||
///
|
||||
/// *C style function: [notcurses_cursor_disable()][crate::notcurses_cursor_disable].*
|
||||
pub fn cursor_disable(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_cursor_disable(self) }]
|
||||
}
|
||||
|
||||
/// Enables the terminal's cursor, if supported, placing it at `y`, `x`.
|
||||
///
|
||||
/// Immediate effect (no need for a call to notcurses_render()).
|
||||
/// It is an error if `y`, `x` lies outside the standard plane.
|
||||
///
|
||||
/// *C style function: [notcurses_cursor_enable()][crate::notcurses_cursor_enable].*
|
||||
pub fn cursor_enable(&mut self, y: NcDim, x: NcDim) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_cursor_enable(self, y as i32, x as i32) }]
|
||||
}
|
||||
|
||||
/// Dumps notcurses state to the supplied `debugfp`.
|
||||
///
|
||||
/// Output is freeform, and subject to change. It includes geometry of all
|
||||
/// planes, from all piles.
|
||||
///
|
||||
/// *C style function: [notcurses_debug()][crate::notcurses_debug].*
|
||||
pub fn debug(&mut self, debugfp: &mut NcFile) {
|
||||
unsafe {
|
||||
crate::notcurses_debug(self, debugfp.as_nc_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of the detected terminal.
|
||||
///
|
||||
/// *C style function: [notcurses_detected_terminal()][crate::notcurses_detected_terminal].*
|
||||
pub fn detected_terminal(&self) -> String {
|
||||
rstring![crate::notcurses_detected_terminal(self)].to_string()
|
||||
}
|
||||
|
||||
/// Destroys all [`NcPlane`]s other than the stdplane.
|
||||
///
|
||||
/// *C style function: [notcurses_drop_planes()][crate::notcurses_drop_planes].*
|
||||
pub fn drop_planes(&mut self) {
|
||||
unsafe {
|
||||
crate::notcurses_drop_planes(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [char] representing a single unicode point.
|
||||
///
|
||||
/// If an event is processed, the return value is the `id` field from that
|
||||
/// event.
|
||||
///
|
||||
/// Provide a None `time` to block at length, a `time` of 0 for non-blocking
|
||||
/// operation, and otherwise a timespec to bound blocking.
|
||||
///
|
||||
/// *C style function: [notcurses_getc()][crate::notcurses_getc].*
|
||||
pub fn getc(&mut self, time: Option<NcTime>, input: Option<&mut NcInput>) -> NcResult<char> {
|
||||
let ntime;
|
||||
if let Some(time) = time {
|
||||
ntime = &time as *const _;
|
||||
} else {
|
||||
ntime = null();
|
||||
}
|
||||
|
||||
let ninput;
|
||||
if let Some(input) = input {
|
||||
ninput = input as *mut _;
|
||||
} else {
|
||||
ninput = null_mut();
|
||||
}
|
||||
let c =
|
||||
unsafe { core::char::from_u32_unchecked(crate::notcurses_get(self, ntime, ninput)) };
|
||||
if c as u32 as i32 == NCRESULT_ERR {
|
||||
return Err(NcError::new());
|
||||
}
|
||||
Ok(c)
|
||||
}
|
||||
|
||||
/// If no event is ready, returns 0.
|
||||
///
|
||||
/// *C style function: [notcurses_getc_nblock()][crate::notcurses_getc_nblock].*
|
||||
pub fn getc_nblock(&mut self, input: &mut NcInput) -> char {
|
||||
crate::notcurses_getc_nblock(self, input)
|
||||
}
|
||||
|
||||
/// Blocks until a codepoint or special key is read,
|
||||
/// or until interrupted by a signal.
|
||||
///
|
||||
/// In the case of a valid read, a 32-bit Unicode codepoint is returned.
|
||||
///
|
||||
/// Optionally writes the event details in `input`.
|
||||
///
|
||||
/// *C style function: [notcurses_getc_blocking()][crate::notcurses_getc_blocking].*
|
||||
pub fn getc_blocking(&mut self, input: Option<&mut NcInput>) -> NcResult<char> {
|
||||
let input_txt;
|
||||
if cfg!(debug_assertions) {
|
||||
input_txt = format!("{:?}", input);
|
||||
} else {
|
||||
input_txt = String::from("");
|
||||
}
|
||||
|
||||
let res = crate::notcurses_getc_blocking(self, input);
|
||||
|
||||
// An invalid read is indicated with -1
|
||||
if res as u32 as i32 != -1 {
|
||||
Ok(res)
|
||||
} else {
|
||||
error![-1, &format!("Nc.getc_blocking({:?})", input_txt), res]
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a file descriptor suitable for input event poll()ing.
|
||||
///
|
||||
/// When this descriptor becomes available, you can call
|
||||
/// [getc_nblock()][Nc#method.getc_nblock], and input ought be ready.
|
||||
///
|
||||
/// This file descriptor is not necessarily the file descriptor associated
|
||||
/// with stdin (but it might be!).
|
||||
///
|
||||
/// *C style function: [notcurses_inputready_fd()][crate::notcurses_inputready_fd].*
|
||||
pub fn inputready_fd(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_inputready_fd(self) }]
|
||||
}
|
||||
|
||||
/// Returns an [`NcBlitter`] from a string representation.
|
||||
///
|
||||
/// *C style function: [notcurses_lex_blitter()][crate::notcurses_lex_blitter].*
|
||||
pub fn lex_blitter(blitter_str: &str) -> NcResult<NcBlitter> {
|
||||
let mut blitter = 0;
|
||||
error![
|
||||
unsafe { crate::notcurses_lex_blitter(cstring![blitter_str], &mut blitter) },
|
||||
"Invalid blitter name", blitter
|
||||
]
|
||||
}
|
||||
|
||||
/// Lexes a margin argument according to the standard notcurses definition.
|
||||
///
|
||||
/// There can be either a single number, which will define all margins equally,
|
||||
/// or there can be four numbers separated by commas.
|
||||
///
|
||||
/// *C style function: [notcurses_lex_margins()][crate::notcurses_lex_margins].*
|
||||
pub fn lex_margins(margins_str: &str, options: &mut NcOptions) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_lex_margins(cstring![margins_str], options) }]
|
||||
}
|
||||
|
||||
/// Returns an [`NcScale`] from a string representation.
|
||||
///
|
||||
/// *C style function: [notcurses_lex_scalemode()][crate::notcurses_lex_scalemode].*
|
||||
pub fn lex_scalemode(scalemode_str: &str) -> NcResult<NcScale> {
|
||||
let mut scalemode = 0;
|
||||
error![
|
||||
unsafe { crate::notcurses_lex_scalemode(cstring![scalemode_str], &mut scalemode) },
|
||||
"", scalemode
|
||||
]
|
||||
}
|
||||
|
||||
/// Returns an [`NcStyle`] from a string representation.
|
||||
///
|
||||
/// It is case-insensitive, and supports multiple styles separated by
|
||||
/// spaces.
|
||||
///
|
||||
/// The supported styles are: `italic`, `underline`, `undercurl`,
|
||||
/// `struck`, `bold`, and `none`.
|
||||
///
|
||||
/// If a style is are not recognized returns an error.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn lex_styles(styles_str: &str) -> NcResult<NcStyle> {
|
||||
let mut style = NCSTYLE_NONE;
|
||||
let mut errstr = String::new();
|
||||
|
||||
for s in styles_str.split(' ') {
|
||||
match s.to_lowercase().as_str() {
|
||||
"italic" => style.add(NCSTYLE_ITALIC),
|
||||
"underline" => style.add(NCSTYLE_UNDERLINE),
|
||||
"undercurl" => style.add(NCSTYLE_UNDERCURL),
|
||||
"struck" => style.add(NCSTYLE_STRUCK),
|
||||
"bold" => style.add(NCSTYLE_BOLD),
|
||||
"none" => (),
|
||||
_ => {
|
||||
errstr.push_str(s);
|
||||
errstr.push(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
if errstr.is_empty() {
|
||||
Ok(style)
|
||||
} else {
|
||||
let _ = errstr.pop();
|
||||
Err(NcError::new_msg(&format![
|
||||
"the following styles are not recognized: '{}'",
|
||||
errstr
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
/// Disables signals originating from the terminal's line discipline, i.e.
|
||||
/// SIGINT (^C), SIGQUIT (^), and SIGTSTP (^Z). They are enabled by default.
|
||||
///
|
||||
/// *C style function: [notcurses_linesigs_disable()][crate::notcurses_linesigs_disable].*
|
||||
pub fn linesigs_disable(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_linesigs_disable(self) }]
|
||||
}
|
||||
|
||||
/// Restores signals originating from the terminal's line discipline, i.e.
|
||||
/// SIGINT (^C), SIGQUIT (^), and SIGTSTP (^Z), if disabled.
|
||||
///
|
||||
/// *C style function: [notcurses_linesigs_enable()][crate::notcurses_linesigs_enable].*
|
||||
pub fn linesigs_enable(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_linesigs_enable(self) }]
|
||||
}
|
||||
|
||||
/// Disables mouse events.
|
||||
///
|
||||
/// Any events in the input queue can still be delivered.
|
||||
///
|
||||
/// *C style function: [notcurses_mouse_disable()][crate::notcurses_mouse_disable].*
|
||||
pub fn mouse_disable(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_mouse_disable(self) }]
|
||||
}
|
||||
|
||||
/// Enable the mouse in "button-event tracking" mode with focus detection
|
||||
/// and UTF8-style extended coordinates.
|
||||
///
|
||||
/// On success, mouse events will be published to [getc()][Nc#method.getc].
|
||||
///
|
||||
/// *C style function: [notcurses_mouse_enable()][crate::notcurses_mouse_enable].*
|
||||
pub fn mouse_enable(&mut self) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::notcurses_mouse_enable(self) },
|
||||
"Nc.mouse_enable()"
|
||||
]
|
||||
}
|
||||
|
||||
/// Returns the number of simultaneous colors claimed to be supported,
|
||||
/// if there is color support.
|
||||
///
|
||||
/// Note that several terminal emulators advertise more colors than they
|
||||
/// actually support, downsampling internally.
|
||||
///
|
||||
/// *C style function: [notcurses_palette_size()][crate::notcurses_palette_size].*
|
||||
pub fn palette_size(&self) -> NcResult<u32> {
|
||||
let res = unsafe { crate::notcurses_palette_size(self) };
|
||||
if res == 1 {
|
||||
return Err(NcError::with_msg(1, "No color support ← Nc.palette_size()"));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Refreshes the physical screen to match what was last rendered (i.e.,
|
||||
/// without reflecting any changes since the last call to
|
||||
/// [`render`][crate::Nc#method.render]).
|
||||
///
|
||||
/// Returns the current screen geometry (`y`, `x`).
|
||||
///
|
||||
/// This is primarily useful if the screen is externally corrupted, or if an
|
||||
/// [NCKEY_RESIZE][crate::NCKEY_RESIZE] event has been read and you're not
|
||||
/// yet ready to render.
|
||||
///
|
||||
/// *C style function: [notcurses_refresh()][crate::notcurses_refresh].*
|
||||
//
|
||||
pub fn refresh(&mut self) -> NcResult<(NcDim, NcDim)> {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
error![
|
||||
unsafe { crate::notcurses_refresh(self, &mut y, &mut x) },
|
||||
"",
|
||||
(y as NcDim, x as NcDim)
|
||||
]
|
||||
}
|
||||
|
||||
/// Renders and rasterizes the standard pile in one shot. Blocking call.
|
||||
///
|
||||
/// *C style function: [notcurses_render()][crate::notcurses_render].*
|
||||
pub fn render(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_render(self) }, "Nc.render()"]
|
||||
}
|
||||
|
||||
/// Performs the rendering and rasterization portion of
|
||||
/// [`render`][Nc#method.render] but do not write the resulting buffer
|
||||
/// out to the terminal.
|
||||
///
|
||||
/// Using this function, the user can control the writeout process,
|
||||
/// and render a second frame while writing another.
|
||||
///
|
||||
// possible BUG? CHECK:
|
||||
/// The returned buffer must be freed by the caller.
|
||||
///
|
||||
/// *C style function: [notcurses_render_to_buffer()][crate::notcurses_render_to_buffer].*
|
||||
//
|
||||
// CHECK that this works.
|
||||
pub fn render_to_buffer(&mut self, buffer: &mut Vec<u8>) -> NcResult<()> {
|
||||
#[allow(unused_mut)] // CHECK whether it actually works without the mut
|
||||
let mut len = buffer.len() as u32;
|
||||
|
||||
// https://github.com/dankamongmen/notcurses/issues/1339
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "i686", target_arch = "x86"))]
|
||||
let mut buf = buffer.as_mut_ptr() as *mut i8;
|
||||
#[cfg(not(any(target_arch = "x86_64", target_arch = "i686", target_arch = "x86")))]
|
||||
let mut buf = buffer.as_mut_ptr() as *mut u8;
|
||||
|
||||
error![unsafe { crate::notcurses_render_to_buffer(self, &mut buf, &mut len.into()) }]
|
||||
}
|
||||
|
||||
/// Writes the last rendered frame, in its entirety, to 'fp'.
|
||||
///
|
||||
/// If [`render`][Nc#method.render] has not yet been called,
|
||||
/// nothing will be written.
|
||||
///
|
||||
/// *C style function: [notcurses_render_to_file()][crate::notcurses_render_to_file].*
|
||||
pub fn render_to_file(&mut self, fp: &mut NcFile) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_render_to_file(self, fp.as_nc_ptr()) }]
|
||||
}
|
||||
|
||||
/// Acquires an atomic snapshot of the notcurses object's stats.
|
||||
///
|
||||
/// *C style function: [notcurses_stats()][crate::notcurses_stats].*
|
||||
pub fn stats(&mut self, stats: &mut NcStats) {
|
||||
unsafe {
|
||||
crate::notcurses_stats(self, stats);
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates an [`NcStats`] object.
|
||||
///
|
||||
/// Use this rather than allocating your own, since future versions of
|
||||
/// notcurses might enlarge this structure.
|
||||
///
|
||||
/// *C style function: [notcurses_stats_alloc()][crate::notcurses_stats_alloc].*
|
||||
pub fn stats_alloc(&mut self) -> &mut NcStats {
|
||||
unsafe { &mut *crate::notcurses_stats_alloc(self) }
|
||||
}
|
||||
|
||||
/// Resets all cumulative stats (immediate ones, such as fbbytes, are not reset).
|
||||
///
|
||||
/// *C style function: [notcurses_stats_reset()][crate::notcurses_stats_reset].*
|
||||
pub fn stats_reset(&mut self, stats: &mut NcStats) {
|
||||
unsafe {
|
||||
crate::notcurses_stats_reset(self, stats);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: decide what to do with these two:
|
||||
//
|
||||
// /// [notcurses_stdplane()][crate::notcurses_stdplane], plus free bonus
|
||||
// /// dimensions written to non-NULL y/x!
|
||||
// ///
|
||||
// /// *C style function: [notcurses_stddim_yx()][crate::notcurses_stddim_yx].*
|
||||
// #[inline]
|
||||
// pub fn stddim_yx<'a>(
|
||||
// &'a mut self,
|
||||
// y: &mut NcDim,
|
||||
// x: &mut NcDim,
|
||||
// ) -> NcResult<&'a mut NcPlane> {
|
||||
// crate::notcurses_stddim_yx(self, y, x)
|
||||
// }
|
||||
|
||||
// /// [stdplane_const()][Notcurses#method.stdplane_const], plus free
|
||||
// /// bonus dimensions written to non-NULL y/x!
|
||||
// ///
|
||||
// /// *C style function: [notcurses_stddim_yx()][crate::notcurses_stddim_yx].*
|
||||
// #[inline]
|
||||
// pub fn stddim_yx_const<'a>(
|
||||
// &'a self,
|
||||
// y: &mut NcDim,
|
||||
// x: &mut NcDim,
|
||||
// ) -> NcResult<&'a NcPlane> {
|
||||
// crate::notcurses_stddim_yx_const(self, y, x)
|
||||
// }
|
||||
|
||||
/// Returns a mutable reference to the standard [`NcPlane`] for this terminal.
|
||||
///
|
||||
/// The standard plane always exists, and its origin is always at the
|
||||
/// uppermost, leftmost cell.
|
||||
///
|
||||
/// *C style function: [notcurses_stdplane()][crate::notcurses_stdplane].*
|
||||
pub fn stdplane<'a>(&mut self) -> &'a mut NcPlane {
|
||||
unsafe { &mut *crate::notcurses_stdplane(self) }
|
||||
}
|
||||
|
||||
/// Returns a reference to the standard [`NcPlane`] for this terminal.
|
||||
///
|
||||
/// The standard plane always exists, and its origin is always at the
|
||||
/// uppermost, leftmost cell.
|
||||
///
|
||||
/// *C style function: [notcurses_stdplane_const()][crate::notcurses_stdplane_const].*
|
||||
pub fn stdplane_const<'a>(&self) -> &'a NcPlane {
|
||||
unsafe { &*crate::notcurses_stdplane_const(self) }
|
||||
}
|
||||
|
||||
/// Destroys the notcurses context.
|
||||
///
|
||||
/// *C style function: [notcurses_stop()][crate::notcurses_stop].*
|
||||
pub fn stop(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::notcurses_stop(self) }]
|
||||
}
|
||||
|
||||
/// Gets the name of an [`NcBlitter`] blitter.
|
||||
///
|
||||
/// *C style function: [notcurses_str_blitter()][crate::notcurses_str_blitter].*
|
||||
pub fn str_blitter(blitter: NcBlitter) -> String {
|
||||
rstring![crate::notcurses_str_blitter(blitter)].to_string()
|
||||
}
|
||||
|
||||
/// Gets the name of an [`NcScale`] scaling mode.
|
||||
///
|
||||
/// *C style function: [notcurses_str_scalemode()][crate::notcurses_str_scalemode].*
|
||||
pub fn str_scalemode(scalemode: NcScale) -> String {
|
||||
rstring![crate::notcurses_str_scalemode(scalemode)].to_string()
|
||||
}
|
||||
|
||||
/// Gets the lowercase name (or names) of the styles included in an [`NcStyle`].
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn str_styles(style: NcStyle) -> String {
|
||||
let mut string = String::new();
|
||||
for s in style.to_vec() {
|
||||
string.push_str(match s {
|
||||
NCSTYLE_ITALIC => "italic",
|
||||
NCSTYLE_UNDERLINE => "underline",
|
||||
NCSTYLE_UNDERCURL => "undercurl",
|
||||
NCSTYLE_STRUCK => "struck",
|
||||
NCSTYLE_BOLD => "bold",
|
||||
#[allow(unreachable_patterns)] // FIXME
|
||||
NCSTYLE_NONE => "none",
|
||||
_ => "none",
|
||||
});
|
||||
string.push(' ');
|
||||
}
|
||||
let _ = string.pop();
|
||||
string
|
||||
}
|
||||
|
||||
/// Returns an [`NcStyle`] with the supported curses-style attributes.
|
||||
///
|
||||
/// The attribute is only indicated as supported if the terminal can support
|
||||
/// it together with color.
|
||||
///
|
||||
/// For more information, see the "ncv" capability in terminfo(5).
|
||||
///
|
||||
/// *C style function: [notcurses_supported_styles()][crate::notcurses_supported_styles].*
|
||||
pub fn supported_styles(&self) -> NcStyle {
|
||||
unsafe { crate::notcurses_supported_styles(self) as NcStyle }
|
||||
}
|
||||
|
||||
/// Returns our current idea of the terminal dimensions in rows and cols.
|
||||
///
|
||||
/// *C style function: [notcurses_term_dim_yx()][crate::notcurses_term_dim_yx].*
|
||||
pub fn term_dim_yx(&self) -> (NcDim, NcDim) {
|
||||
crate::notcurses_term_dim_yx(self)
|
||||
}
|
||||
|
||||
/// Returns the topmost [`NcPlane`], of which there is always at least one.
|
||||
///
|
||||
/// *C style function: [notcurses_top()][crate::notcurses_top].*
|
||||
pub fn top(&mut self) -> &mut NcPlane {
|
||||
unsafe { &mut *crate::notcurses_top(self) }
|
||||
}
|
||||
|
||||
/// Returns a human-readable string describing the running notcurses version.
|
||||
///
|
||||
/// *C style function: [notcurses_version()][crate::notcurses_version].*
|
||||
pub fn version() -> String {
|
||||
rstring![crate::notcurses_version()].to_string()
|
||||
}
|
||||
|
||||
/// Returns the running notcurses version components
|
||||
/// (major, minor, patch, tweak).
|
||||
///
|
||||
/// *C style function: [notcurses_version_components()][crate::notcurses_version_components].*
|
||||
pub fn version_components() -> (u32, u32, u32, u32) {
|
||||
let (mut major, mut minor, mut patch, mut tweak) = (0, 0, 0, 0);
|
||||
unsafe {
|
||||
crate::notcurses_version_components(&mut major, &mut minor, &mut patch, &mut tweak);
|
||||
}
|
||||
(major as u32, minor as u32, patch as u32, tweak as u32)
|
||||
}
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
//! `Nc`
|
||||
|
||||
// total: 53
|
||||
// ---------------------------------------------------
|
||||
// (X) 1 : wont do
|
||||
// (…) 4 : TODO / WIP
|
||||
//
|
||||
// (f) 45 : unsafe ffi function exported by bindgen
|
||||
// (w) 0 : safely wrapped ffi function
|
||||
// (r) 6 : static function manually reimplemented
|
||||
//
|
||||
// (m) 38 : method implemented
|
||||
//
|
||||
// (t) 13 : unit test done for the function
|
||||
// (T) 0 : unit test done also for the method
|
||||
// ---------------------------------------------------
|
||||
// fm notcurses_at_yx
|
||||
// fm notcurses_bottom
|
||||
// fm notcurses_canbraille
|
||||
// fmt notcurses_canchangecolor
|
||||
// fmt notcurses_canfade
|
||||
// fmt notcurses_canopen_images
|
||||
// fmt notcurses_canopen_videos
|
||||
// fmt notcurses_cansextant
|
||||
// fmt notcurses_cantruecolor
|
||||
// fmt notcurses_canutf8
|
||||
// fm notcurses_check_pixel_support
|
||||
//~f notcurses_core_init
|
||||
// fm notcurses_cursor_disable
|
||||
// fm notcurses_cursor_enable
|
||||
// f notcurses_cursor_yx
|
||||
// fmt notcurses_debug
|
||||
//~f notcurses_detected_terminal
|
||||
// fmt notcurses_drop_planes
|
||||
// fm notcurses_getc
|
||||
// fmt notcurses_init
|
||||
// fm notcurses_inputready_fd
|
||||
// fm notcurses_lex_blitter
|
||||
// fm notcurses_lex_margins
|
||||
// fm notcurses_lex_scalemode
|
||||
// fm notcurses_linesigs_disable
|
||||
// fm notcurses_linesigs_enable
|
||||
// fm notcurses_mouse_disable
|
||||
// fm notcurses_mouse_enable
|
||||
// fm notcurses_palette_size
|
||||
// fm notcurses_refresh
|
||||
// fm notcurses_render
|
||||
// fm notcurses_render_to_buffer
|
||||
// fm notcurses_render_to_file
|
||||
// fm notcurses_stats
|
||||
// fm notcurses_stats_alloc
|
||||
// fm notcurses_stats_reset
|
||||
// fm notcurses_stdplane
|
||||
// fm notcurses_stdplane_const
|
||||
// fmt notcurses_stop
|
||||
// fm notcurses_str_blitter
|
||||
// fm notcurses_str_scalemode
|
||||
// fm notcurses_supported_styles
|
||||
// fm notcurses_top
|
||||
//X notcurses_ucs32_to_utf8 (not needed in rust)
|
||||
// fmt notcurses_version
|
||||
// fm notcurses_version_components
|
||||
// rmt notcurses_align
|
||||
// rm notcurses_getc_blocking
|
||||
// rm notcurses_getc_nblock
|
||||
//~r notcurses_stddim_yx // multiple mutable references errors
|
||||
//~r notcurses_stddim_yx_const //
|
||||
// rm notcurses_term_dim_yx
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod helpers;
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use helpers::*;
|
||||
pub use reimplemented::*;
|
||||
|
||||
/// The full **notcurses** context.
|
||||
///
|
||||
/// It's built atop the terminfo abstraction layer to provide reasonably
|
||||
/// portable vivid character displays.
|
||||
pub type Nc = crate::bindings::ffi::notcurses;
|
||||
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
pub type Notcurses = Nc;
|
||||
|
||||
/// Options struct for [`Notcurses`]
|
||||
pub type NcOptions = crate::bindings::ffi::notcurses_options;
|
||||
|
||||
#[deprecated]
|
||||
#[doc(hidden)]
|
||||
pub type NotcursesOptions = NcOptions;
|
||||
|
||||
/// Do not call setlocale()
|
||||
///
|
||||
/// notcurses_init() will call setlocale() to inspect the current locale. If
|
||||
/// that locale is "C" or "POSIX", it will call setlocale(LC_ALL, "") to set
|
||||
/// the locale according to the LANG environment variable. Ideally, this will
|
||||
/// result in UTF8 being enabled, even if the client app didn't call
|
||||
/// setlocale() itself. Unless you're certain that you're invoking setlocale()
|
||||
/// prior to notcurses_init(), you should not set this bit. Even if you are
|
||||
/// invoking setlocale(), this behavior shouldn't be an issue unless you're
|
||||
/// doing something weird (setting a locale not based on LANG).
|
||||
pub const NCOPTION_INHIBIT_SETLOCALE: u64 = crate::bindings::ffi::NCOPTION_INHIBIT_SETLOCALE as u64;
|
||||
|
||||
/// Do not enter alternate mode.
|
||||
///
|
||||
/// If smcup/rmcup capabilities are indicated, notcurses defaults to making use
|
||||
/// of the "alternate screen". This flag inhibits use of smcup/rmcup.
|
||||
pub const NCOPTION_NO_ALTERNATE_SCREEN: u64 =
|
||||
crate::bindings::ffi::NCOPTION_NO_ALTERNATE_SCREEN as u64;
|
||||
|
||||
/// Do not try to clear any preexisting bitmaps.
|
||||
///
|
||||
/// Note that they might still get cleared even if this is set, and they might
|
||||
/// not get cleared even if this is not set.
|
||||
pub const NCOPTION_NO_CLEAR_BITMAPS: u64 = crate::bindings::ffi::NCOPTION_NO_CLEAR_BITMAPS as u64;
|
||||
|
||||
/// Do not modify the font.
|
||||
///
|
||||
/// Notcurses might attempt to change the font slightly, to support certain
|
||||
/// glyphs (especially on the Linux console). If this is set, no such
|
||||
/// modifications will be made. Note that font changes will not affect anything
|
||||
/// but the virtual console/terminal in which notcurses is running.
|
||||
pub const NCOPTION_NO_FONT_CHANGES: u64 = crate::bindings::ffi::NCOPTION_NO_FONT_CHANGES as u64;
|
||||
|
||||
/// Do not handle SIG{ING, SEGV, ABRT, QUIT}.
|
||||
///
|
||||
/// A signal handler will usually be installed for SIGINT, SIGQUIT, SIGSEGV,
|
||||
/// SIGTERM, and SIGABRT, cleaning up the terminal on such exceptions.
|
||||
/// With this flag, the handler will not be installed.
|
||||
pub const NCOPTION_NO_QUIT_SIGHANDLERS: u64 =
|
||||
crate::bindings::ffi::NCOPTION_NO_QUIT_SIGHANDLERS as u64;
|
||||
|
||||
/// Do not handle SIGWINCH.
|
||||
///
|
||||
/// A signal handler will usually be installed for SIGWINCH, resulting in
|
||||
/// NCKEY_RESIZE events being generated on input.
|
||||
/// With this flag, the handler will not be installed.
|
||||
pub const NCOPTION_NO_WINCH_SIGHANDLER: u64 =
|
||||
crate::bindings::ffi::NCOPTION_NO_WINCH_SIGHANDLER as u64;
|
||||
|
||||
/// Initialize the standard plane's virtual cursor to match the physical cursor
|
||||
/// at context creation time.
|
||||
///
|
||||
/// Together with [`NCOPTION_NO_ALTERNATE_SCREEN`] and a scrolling standard plane,
|
||||
/// this facilitates easy scrolling-style programs in rendered mode.
|
||||
pub const NCOPTION_PRESERVE_CURSOR: u64 = crate::bindings::ffi::NCOPTION_PRESERVE_CURSOR as u64;
|
||||
|
||||
/// Do not print banners.
|
||||
///
|
||||
/// Notcurses typically prints version info in notcurses_init() and performance
|
||||
/// info in notcurses_stop(). This inhibits that output.
|
||||
pub const NCOPTION_SUPPRESS_BANNERS: u64 = crate::bindings::ffi::NCOPTION_SUPPRESS_BANNERS as u64;
|
||||
|
||||
// NcLogLevel ------------------------------------------------------------------
|
||||
|
||||
/// Log level for [`NcOptions`]
|
||||
///
|
||||
/// These log levels consciously map cleanly to those of libav; notcurses itself
|
||||
/// does not use this full granularity. The log level does not affect the opening
|
||||
/// and closing banners, which can be disabled via the `NcOptions`
|
||||
/// `NCOPTION_SUPPRESS_BANNERS`.
|
||||
/// Note that if stderr is connected to the same terminal on which we're
|
||||
/// rendering, any kind of logging will disrupt the output.
|
||||
pub type NcLogLevel = crate::bindings::ffi::ncloglevel_e;
|
||||
|
||||
/// this is honestly a bit much
|
||||
pub const NCLOGLEVEL_DEBUG: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_DEBUG;
|
||||
|
||||
/// we can't keep doin' this, but we can do other things
|
||||
pub const NCLOGLEVEL_ERROR: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_ERROR;
|
||||
|
||||
/// we're hanging around, but we've had a horrible fault
|
||||
pub const NCLOGLEVEL_FATAL: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_FATAL;
|
||||
|
||||
/// "detailed information
|
||||
pub const NCLOGLEVEL_INFO: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_INFO;
|
||||
|
||||
/// print diagnostics immediately related to crashing
|
||||
pub const NCLOGLEVEL_PANIC: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_PANIC;
|
||||
|
||||
/// default. print nothing once fullscreen service begins
|
||||
pub const NCLOGLEVEL_SILENT: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_SILENT;
|
||||
|
||||
/// there's probably a better way to do what you want
|
||||
pub const NCLOGLEVEL_TRACE: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_TRACE;
|
||||
|
||||
/// "detailed information
|
||||
pub const NCLOGLEVEL_VERBOSE: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_VERBOSE;
|
||||
|
||||
/// you probably don't want what's happening to happen
|
||||
pub const NCLOGLEVEL_WARNING: NcLogLevel = crate::bindings::ffi::ncloglevel_e_NCLOGLEVEL_WARNING;
|
||||
|
||||
// NcAlign ---------------------------------------------------------------------
|
||||
|
||||
/// Alignment within a plane or terminal.
|
||||
/// Left/right-justified, or centered.
|
||||
///
|
||||
/// ## Defined constants
|
||||
///
|
||||
/// - [NCALIGN_UNALIGNED]
|
||||
/// - [NCALIGN_LEFT]
|
||||
/// - [NCALIGN_CENTER]
|
||||
/// - [NCALIGN_RIGHT]
|
||||
pub type NcAlign = crate::bindings::ffi::ncalign_e;
|
||||
|
||||
/// Left alignment within an [`NcPlane`][crate::NcPlane] or terminal.
|
||||
pub const NCALIGN_LEFT: NcAlign = crate::bindings::ffi::ncalign_e_NCALIGN_LEFT;
|
||||
|
||||
/// Right alignment within an [`NcPlane`][crate::NcPlane] or terminal.
|
||||
pub const NCALIGN_RIGHT: NcAlign = crate::bindings::ffi::ncalign_e_NCALIGN_RIGHT;
|
||||
|
||||
/// Center alignment within an [`NcPlane`][crate::NcPlane] or terminal.
|
||||
pub const NCALIGN_CENTER: NcAlign = crate::bindings::ffi::ncalign_e_NCALIGN_CENTER;
|
||||
|
||||
/// Do not align an [`NcPlane`][crate::NcPlane] or terminal.
|
||||
pub const NCALIGN_UNALIGNED: NcAlign = crate::bindings::ffi::ncalign_e_NCALIGN_UNALIGNED;
|
||||
|
||||
// NcPixelImpl -----------------------------------------------------------------
|
||||
|
||||
/// Pixel blitting implementations. (Informative only).
|
||||
///
|
||||
/// Returned by [`check_pixel_support`][Notcurses#method.check_pixel_support].
|
||||
pub type NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e;
|
||||
|
||||
/// No pixel support.
|
||||
pub const NCPIXEL_NONE: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_NONE;
|
||||
/// Sixel
|
||||
pub const NCPIXEL_SIXEL: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_SIXEL;
|
||||
/// Linux framebuffer.
|
||||
pub const NCPIXEL_LINUXFB: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_LINUXFB;
|
||||
/// iTerm2
|
||||
pub const NCPIXEL_ITERM2: NcPixelImpl = crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_ITERM2;
|
||||
/// Kitty prior to C=1 and animation.
|
||||
pub const NCPIXEL_KITTY_STATIC: NcPixelImpl =
|
||||
crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_STATIC;
|
||||
/// Kitty with animation but not reflexive composition.
|
||||
pub const NCPIXEL_KITTY_ANIMATED: NcPixelImpl =
|
||||
crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_ANIMATED;
|
||||
/// Kitty with reflexive composition.
|
||||
pub const NCPIXEL_KITTY_SELFREF: NcPixelImpl =
|
||||
crate::bindings::ffi::ncpixelimpl_e_NCPIXEL_KITTY_SELFREF;
|
@ -1,119 +0,0 @@
|
||||
//! `notcurses_*` reimplemented functions.
|
||||
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
use crate::{
|
||||
Nc, NcAlign, NcDim, NcError, NcInput, NcOffset, NcPlane, NcResult, NcTime, NCALIGN_CENTER,
|
||||
NCALIGN_LEFT, NCALIGN_RIGHT, NCRESULT_MAX,
|
||||
};
|
||||
|
||||
/// Returns the offset into `availcols` at which `cols` ought be output given
|
||||
/// the requirements of `align`.
|
||||
///
|
||||
/// Returns `-`[`NCRESULT_MAX`] if [NCALIGN_UNALIGNED][crate::NCALIGN_UNALIGNED]
|
||||
/// or invalid [NcAlign].
|
||||
///
|
||||
/// *Method: Nc.[align()][Nc#method.align].*
|
||||
#[inline]
|
||||
pub fn notcurses_align(availcols: NcDim, align: NcAlign, cols: NcDim) -> NcOffset {
|
||||
if align == NCALIGN_LEFT {
|
||||
return 0;
|
||||
}
|
||||
if cols > availcols {
|
||||
return 0;
|
||||
}
|
||||
if align == NCALIGN_CENTER {
|
||||
return ((availcols - cols) / 2) as NcOffset;
|
||||
}
|
||||
if align == NCALIGN_RIGHT {
|
||||
return (availcols - cols) as NcOffset;
|
||||
}
|
||||
-NCRESULT_MAX // NCALIGN_UNALIGNED
|
||||
}
|
||||
|
||||
///
|
||||
/// If no event is ready, returns 0.
|
||||
///
|
||||
/// *Method: Nc.[getc_nblock()][Nc#method.getc_nblock].*
|
||||
//
|
||||
// TODO: use from_u32 & return Option.
|
||||
#[inline]
|
||||
pub fn notcurses_getc_nblock(nc: &mut Nc, input: &mut NcInput) -> char {
|
||||
unsafe {
|
||||
let ts = NcTime {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
core::char::from_u32_unchecked(crate::notcurses_get(nc, &ts, input))
|
||||
}
|
||||
}
|
||||
|
||||
/// Blocks until an event is processed or a signal is received.
|
||||
///
|
||||
/// Optionally writes the event details in `input`.
|
||||
///
|
||||
/// In case of an invalid read (including on EOF) *-1 as char* is returned.
|
||||
///
|
||||
/// *Method: Nc.[getc_blocking()][Nc#method.getc_blocking].*
|
||||
#[inline]
|
||||
pub fn notcurses_getc_blocking(nc: &mut Nc, input: Option<&mut NcInput>) -> char {
|
||||
let input_ptr;
|
||||
if let Some(i) = input {
|
||||
input_ptr = i as *mut _;
|
||||
} else {
|
||||
input_ptr = null_mut();
|
||||
}
|
||||
unsafe { core::char::from_u32_unchecked(crate::notcurses_get(nc, null(), input_ptr)) }
|
||||
}
|
||||
|
||||
/// [notcurses_stdplane()][crate::notcurses_stdplane], plus free bonus
|
||||
/// dimensions written to non-NULL y/x!
|
||||
///
|
||||
/// *Method: Nc.[getc_stddim_yx()][Nc#method.stddim_yx].*
|
||||
#[inline]
|
||||
pub fn notcurses_stddim_yx<'a>(
|
||||
nc: &'a mut Nc,
|
||||
y: &mut NcDim,
|
||||
x: &mut NcDim,
|
||||
) -> NcResult<&'a mut NcPlane> {
|
||||
unsafe {
|
||||
let sp = crate::notcurses_stdplane(nc);
|
||||
if !sp.is_null() {
|
||||
crate::ncplane_dim_yx(sp, &mut (*y as i32), &mut (*x as i32));
|
||||
return Ok(&mut *sp);
|
||||
}
|
||||
}
|
||||
Err(NcError::new())
|
||||
}
|
||||
|
||||
/// [notcurses_stdplane_const()][crate::notcurses_stdplane_const], plus free
|
||||
/// bonus dimensions written to non-NULL y/x!
|
||||
///
|
||||
/// *Method: Nc.[getc_stddim_yx_const()][Nc#method.stddim_yx_const].*
|
||||
#[inline]
|
||||
pub fn notcurses_stddim_yx_const<'a>(
|
||||
nc: &'a Nc,
|
||||
y: &mut NcDim,
|
||||
x: &mut NcDim,
|
||||
) -> NcResult<&'a NcPlane> {
|
||||
unsafe {
|
||||
let sp = crate::notcurses_stdplane_const(nc);
|
||||
if !sp.is_null() {
|
||||
crate::ncplane_dim_yx(sp, &mut (*y as i32), &mut (*x as i32));
|
||||
return Ok(&*sp);
|
||||
}
|
||||
}
|
||||
Err(NcError::new())
|
||||
}
|
||||
|
||||
/// Returns our current idea of the terminal dimensions in rows and cols.
|
||||
///
|
||||
/// *Method: Nc.[getc_term_yx()][Nc#method.term_yx].*
|
||||
#[inline]
|
||||
pub fn notcurses_term_dim_yx(nc: &Nc) -> (NcDim, NcDim) {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_dim_yx(crate::notcurses_stdplane_const(nc), &mut y, &mut x);
|
||||
}
|
||||
(y as NcDim, x as NcDim)
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
//! Test `Notcurses` methods and associated functions.
|
||||
|
||||
// use crate::Notcurses;
|
||||
// use serial_test::serial;
|
@ -1,7 +0,0 @@
|
||||
//! `Notcurses` tests.
|
||||
|
||||
#[cfg(test)]
|
||||
mod methods;
|
||||
|
||||
#[cfg(test)]
|
||||
mod reimplemented;
|
@ -1,191 +0,0 @@
|
||||
//! Test `notcurses_*` reimplemented functions.
|
||||
|
||||
use serial_test::serial;
|
||||
use std::io::Read;
|
||||
|
||||
use crate::{notcurses_init_test, notcurses_stop, NCRESULT_MAX};
|
||||
|
||||
use crate::NcFile;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_align() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
assert_eq![0, crate::notcurses_align(30, crate::NCALIGN_LEFT, 20)];
|
||||
assert_eq![5, crate::notcurses_align(30, crate::NCALIGN_CENTER, 20)];
|
||||
assert_eq![10, crate::notcurses_align(30, crate::NCALIGN_RIGHT, 20)];
|
||||
assert_eq![
|
||||
-NCRESULT_MAX,
|
||||
crate::notcurses_align(30, crate::NCALIGN_UNALIGNED, 20)
|
||||
];
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_canchangecolor() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_canchangecolor(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_canfade() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_canfade(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_canopen_images() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_canopen_images(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_canopen_videos() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_canopen_videos(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_cansextant() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_cansextant(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_cantruecolor() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_cantruecolor(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_canutf8() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let res = crate::notcurses_canutf8(nc);
|
||||
notcurses_stop(nc);
|
||||
print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_drop_planes() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let stdplane = crate::notcurses_stdplane(nc);
|
||||
let plane1 = crate::ncplane_new_bound_test(&mut *stdplane, 0, 0, 10, 10);
|
||||
let _plane2 = crate::ncplane_new_bound_test(plane1, 0, 0, 10, 10);
|
||||
|
||||
crate::notcurses_drop_planes(nc);
|
||||
// TODO: CHECK that planes are really dropped.
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn notcurses_initialization() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
assert![nc as *mut _ != core::ptr::null_mut()];
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
#[ignore]
|
||||
// FIXME: always return null
|
||||
fn notcurses_at_yx() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let mut sm = 0;
|
||||
let mut ch = 0;
|
||||
let res = crate::notcurses_at_yx(nc, 0, 0, &mut sm, &mut ch);
|
||||
notcurses_stop(nc);
|
||||
assert![!res.is_null()];
|
||||
|
||||
//print!("[{}] ", res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
#[cfg_attr(target_os = "macos", ignore)] // FIXME
|
||||
#[ignore] // FIXME https://github.com/dankamongmen/notcurses/issues/2111
|
||||
fn notcurses_debug() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
|
||||
#[cfg(any(
|
||||
target_arch = "s390x",
|
||||
target_arch = "powerpc64le",
|
||||
target_arch = "armv7hl",
|
||||
target_arch = "aarch64"
|
||||
))]
|
||||
let mut _p: *mut u8 = &mut 0;
|
||||
#[cfg(not(any(
|
||||
target_arch = "s390x",
|
||||
target_arch = "powerpc64le",
|
||||
target_arch = "armv7hl",
|
||||
target_arch = "aarch64"
|
||||
)))]
|
||||
let mut _p: *mut i8 = &mut 0;
|
||||
|
||||
let mut _size: *mut usize = &mut 0;
|
||||
let mut file = NcFile::from_libc(libc::open_memstream(&mut _p, _size));
|
||||
crate::notcurses_debug(nc, file.as_nc_ptr());
|
||||
notcurses_stop(nc);
|
||||
|
||||
let mut string1 = String::new();
|
||||
let _result = file.read_to_string(&mut string1);
|
||||
|
||||
let string2 =
|
||||
" -------------------------- notcurses debug state -----------------------------";
|
||||
|
||||
assert_eq![&string1[0..string2.len()], &string2[..]];
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
// TODO test version_components
|
||||
fn notcurses_version() {
|
||||
let c_str = unsafe { crate::notcurses_version() };
|
||||
assert!(!c_str.is_null());
|
||||
print!("v{} ", crate::rstring![c_str]);
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//! `NcPalette` methods and associated functions.
|
||||
|
||||
use crate::{error, Nc, NcChannel, NcComponent, NcPalette, NcPaletteIndex, NcResult, NcRgb};
|
||||
|
||||
impl NcPalette {
|
||||
/// New `NcPalette`.
|
||||
///
|
||||
/// *C style function: [ncpalette_new()][crate::ncpalette_new].*
|
||||
pub fn new<'a>(nc: &mut Nc) -> &'a mut Self {
|
||||
unsafe { &mut *crate::ncpalette_new(nc) }
|
||||
}
|
||||
|
||||
/// Frees this `NcPalette`.
|
||||
///
|
||||
/// *C style function: [ncpalette_free()][crate::ncpalette_free].*
|
||||
pub fn free(&mut self) {
|
||||
unsafe {
|
||||
crate::ncpalette_free(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to configure the terminal with this NcPalette.
|
||||
///
|
||||
/// *C style function: [ncpalette_use()][crate::ncpalette_use].*
|
||||
pub fn r#use(&self, nc: &mut Nc) -> NcResult<()> {
|
||||
error![unsafe { crate::ncpalette_use(nc, self) }]
|
||||
}
|
||||
|
||||
/// Returns the [`NcComponent`]s from the [`NcChannel`] in this `NcPalette`.
|
||||
///
|
||||
/// *C style function: [ncpalette_get_rgb()][crate::ncpalette_get_rgb8].*
|
||||
pub fn get_rgb8(&self, index: NcPaletteIndex) -> (NcComponent, NcComponent, NcComponent) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::ncchannel_rgb8(self.chans[index as usize], &mut r, &mut g, &mut b);
|
||||
(r, g, b)
|
||||
}
|
||||
|
||||
/// Extracts the [`NcComponent`]s from an [`NcChannel`] entry inside
|
||||
/// this NcPalette, and returns the NcChannel.
|
||||
///
|
||||
/// *C style function: [ncpalette_get_rgb()][crate::ncpalette_get_rgb8].*
|
||||
pub fn get_rgb(&self, index: NcPaletteIndex) -> NcChannel {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
crate::ncchannel_rgb8(self.chans[index as usize], &mut r, &mut g, &mut b)
|
||||
}
|
||||
|
||||
/// Sets the [`NcRgb`] value of the [`NcChannel`][crate::NcChannel] entry
|
||||
/// inside this NcPalette.
|
||||
///
|
||||
/// *C style function: [ncpalette_set()][crate::ncpalette_set].*
|
||||
pub fn set(&mut self, index: NcPaletteIndex, rgb: NcRgb) {
|
||||
crate::ncchannel_set(&mut self.chans[index as usize], rgb);
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
//! `NcPalette*`
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Now none of these functions can't fail and therefore don't return errors.
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// functions already exported by bindgen : 3
|
||||
// -----------------------------------------
|
||||
// (#) test: 0
|
||||
// (W) wrap: 3 / 0
|
||||
// -----------------------------------------
|
||||
//W ncpalette_free
|
||||
//W ncpalette_new
|
||||
//W ncpalette_use
|
||||
//
|
||||
// functions manually reimplemented: 5
|
||||
// -----------------------------------------
|
||||
// (+) done: 3 / 0
|
||||
// (#) test: 0
|
||||
// (W) wrap: 3 / 0
|
||||
// -----------------------------------------
|
||||
//W+ ncpalette_get_rgb
|
||||
// ncpalette_get_rgb8
|
||||
//W+ ncpalette_set
|
||||
//W+ ncpalette_set_rgb
|
||||
// ncpalette_set_rgb8
|
||||
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
pub use methods::*;
|
||||
pub use reimplemented::*;
|
||||
|
||||
/// NcPalette structure consisting of an array of 256
|
||||
/// [`NcChannel`][crate::NcChannel]s.
|
||||
///
|
||||
/// See also [NcPaletteIndex].
|
||||
///
|
||||
/// Some terminals only support 256 colors, but allow the full
|
||||
/// palette to be specified with arbitrary RGB colors. In all cases, it's more
|
||||
/// performant to use indexed colors, since it's much less data to write to the
|
||||
/// terminal. If you can limit yourself to 256 colors, that's probably best.
|
||||
///
|
||||
/// `type in C: ncncpalette (struct)`
|
||||
///
|
||||
pub type NcPalette = crate::bindings::ffi::ncpalette;
|
||||
|
||||
/// 8-bit value used for indexing into a [`NcPalette`]
|
||||
///
|
||||
pub type NcPaletteIndex = u8;
|
@ -1,42 +0,0 @@
|
||||
//! `ncpalette_*` reimplemented functions.
|
||||
|
||||
use crate::{NcChannel, NcComponent, NcPalette, NcPaletteIndex, NcRgb};
|
||||
|
||||
/// Extracts the RGB [`NcComponent`]s from an [`NcChannel`] entry inside
|
||||
/// an [`NcPalette`], and returns the `NcChannel`.
|
||||
///
|
||||
/// *Method: NcPalette.[get_rgb()][NcPalette#method.get_rgb].*
|
||||
/// *Method: NcPalette.[get_rgb8()][NcPalette#method.get_rgb8].*
|
||||
#[inline]
|
||||
pub fn ncpalette_get_rgb8(
|
||||
palette: &NcPalette,
|
||||
index: NcPaletteIndex,
|
||||
red: &mut NcComponent,
|
||||
green: &mut NcComponent,
|
||||
blue: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
crate::ncchannel_rgb8(palette.chans[index as usize], red, green, blue)
|
||||
}
|
||||
|
||||
/// Sets the [`NcRgb`] value of the [`NcChannel`] entry inside an [`NcPalette`].
|
||||
///
|
||||
/// *Method: NcPalette.[set()][NcPalette#method.set].*
|
||||
#[inline]
|
||||
pub fn ncpalette_set(palette: &mut NcPalette, index: NcPaletteIndex, rgb: NcRgb) {
|
||||
crate::ncchannel_set(&mut palette.chans[index as usize], rgb);
|
||||
}
|
||||
|
||||
/// Sets the RGB [`NcComponent`]s of the [`NcChannel`] entry inside an
|
||||
/// [`NcPalette`].
|
||||
///
|
||||
/// *Method: NcPalette.[set_rgb()][NcPalette#method.set_rgb].*
|
||||
#[inline]
|
||||
pub fn ncpalette_set_rgb8(
|
||||
palette: &mut NcPalette,
|
||||
index: NcPaletteIndex,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) {
|
||||
crate::ncchannel_set_rgb8(&mut palette.chans[index as usize], red, green, blue)
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
//! The ncpixel API facilitates direct management of the pixels within an
|
||||
//! ncvisual (ncvisuals keep a backing store of 32-bit RGBA pixels, and render
|
||||
//! them down to terminal graphics in ncvisual_render()).
|
||||
//
|
||||
// - NOTE: The pixel color & alpha [`NcComponent`]s are u8 instead of u32.
|
||||
// Because of type enforcing, some runtime checks are now unnecessary.
|
||||
//
|
||||
// - NOTE: None of the functions can't fail anymore and don't have to return an error.
|
||||
//
|
||||
// functions manually reimplemented: 10
|
||||
// ------------------------------------------
|
||||
// (+) done: 10 / 0
|
||||
// (#) test: 0
|
||||
// (W) wrap: 10
|
||||
// ------------------------------------------
|
||||
//W+ ncpixel
|
||||
//W+ ncpixel_a
|
||||
//W+ ncpixel_b
|
||||
//W+ ncpixel_g
|
||||
//W+ ncpixel_r
|
||||
//W+ ncpixel_set_a
|
||||
//W+ ncpixel_set_b
|
||||
//W+ ncpixel_set_g
|
||||
//W+ ncpixel_set_r
|
||||
//W+ ncpixel_set_rgb8
|
||||
|
||||
use crate::NcComponent;
|
||||
|
||||
// NcPixel (RGBA)
|
||||
/// An ABGR pixel.
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// AAAAAAAA GGGGGGGG BBBBBBBB RRRRRRRR
|
||||
/// ```
|
||||
///
|
||||
/// `type in C: ncpixel (uint32_t)`
|
||||
///
|
||||
/// NcPixel has 8 bits of alpha, more or less linear, contributing
|
||||
/// directly to the usual alpha blending equation.
|
||||
///
|
||||
/// We map the 8 bits of alpha to 2 bits of alpha via a [level
|
||||
/// function](https://nick-black.com/dankwiki/index.php?title=Notcurses#Transparency.2FContrasting)
|
||||
///
|
||||
/// The ncpixel API facilitates direct management of the pixels within an
|
||||
/// ncvisual (ncvisuals keep a backing store of 32-bit RGBA pixels, and render
|
||||
/// them down to terminal graphics in ncvisual_render()).
|
||||
///
|
||||
/// Per libav, we "store as BGRA on little-endian, and ARGB on big-endian".
|
||||
/// This is an RGBA *byte-order* scheme. libav emits bytes, not words. Those
|
||||
/// bytes are R-G-B-A. When read as words, on little endian this will be ABGR,
|
||||
/// and on big-endian this will be RGBA. force everything to LE ABGR.
|
||||
///
|
||||
pub type NcPixel = u32;
|
||||
|
||||
/// Constructs a libav-compatible ABGR pixel from RGB [`NcComponent`]s.
|
||||
#[inline]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub const fn ncpixel(red: NcComponent, green: NcComponent, blue: NcComponent) -> NcPixel {
|
||||
0xff000000 as NcPixel | red as NcPixel | (blue as NcPixel) << 8 | (green as NcPixel) << 16
|
||||
}
|
||||
|
||||
/// Extracts the 8-bit alpha [`NcComponent`] from an ABGR pixel.
|
||||
#[inline]
|
||||
pub const fn ncpixel_a(pixel: NcPixel) -> NcComponent {
|
||||
((pixel.to_le() & 0xff000000) >> 24) as NcComponent
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit blue [`NcComponent`] from an ABGR pixel.
|
||||
#[inline]
|
||||
pub const fn ncpixel_b(pixel: NcPixel) -> NcComponent {
|
||||
((pixel.to_le() & 0x00ff0000) >> 16) as NcComponent
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit green [`NcComponent`] from an ABGR pixel.
|
||||
#[inline]
|
||||
pub const fn ncpixel_g(pixel: NcPixel) -> NcComponent {
|
||||
((pixel.to_le() & 0x0000ff00) >> 8) as NcComponent
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit red [`NcComponent`] from an ABGR pixel.
|
||||
#[inline]
|
||||
pub const fn ncpixel_r(pixel: NcPixel) -> NcComponent {
|
||||
(pixel.to_le() & 0x000000ff) as NcComponent
|
||||
}
|
||||
|
||||
/// Sets the 8-bit alpha [`NcComponent`] of an ABGR pixel.
|
||||
#[inline]
|
||||
pub fn ncpixel_set_a(pixel: &mut NcPixel, alpha: NcComponent) {
|
||||
*pixel = (((*pixel).to_le() & 0x00ffffff) | ((alpha as NcPixel) << 24)).to_le();
|
||||
}
|
||||
|
||||
/// Sets the 8-bit blue [`NcComponent`] of an ABGR pixel.
|
||||
#[inline]
|
||||
pub fn ncpixel_set_b(pixel: &mut NcPixel, blue: NcComponent) {
|
||||
*pixel = (((*pixel).to_le() & 0xffff00ff) | ((blue as NcPixel) << 8)).to_le();
|
||||
}
|
||||
|
||||
/// Sets the 8-bit green [`NcComponent`] of an ABGR pixel.
|
||||
#[inline]
|
||||
pub fn ncpixel_set_g(pixel: &mut NcPixel, green: NcComponent) {
|
||||
*pixel = (((*pixel).to_le() & 0xff00ffff) | ((green as NcPixel) << 16)).to_le();
|
||||
}
|
||||
|
||||
/// Sets the 8-bit red [`NcComponent`] of an ABGR pixel.
|
||||
#[inline]
|
||||
pub fn ncpixel_set_r(pixel: &mut NcPixel, red: NcComponent) {
|
||||
*pixel = (((*pixel).to_le() & 0xffffff00) | red as NcPixel).to_le();
|
||||
}
|
||||
|
||||
/// Sets the RGB [`NcComponent`]s of an ABGR pixel.
|
||||
#[inline]
|
||||
pub fn ncpixel_set_rgb8(
|
||||
pixel: &mut NcPixel,
|
||||
red: NcComponent,
|
||||
green: NcComponent,
|
||||
blue: NcComponent,
|
||||
) {
|
||||
ncpixel_set_r(pixel, red);
|
||||
ncpixel_set_g(pixel, green);
|
||||
ncpixel_set_b(pixel, blue);
|
||||
}
|
||||
|
||||
/// Enables the [NcPixel] methods.
|
||||
//
|
||||
// NOTE: waiting for: https://github.com/rust-lang/rust/issues/56546
|
||||
// to move doc comments to the trait and appear unhidden at the implementation.
|
||||
pub trait NcPixelMethods {
|
||||
fn new(r: NcComponent, g: NcComponent, b: NcComponent) -> Self;
|
||||
fn a(self) -> NcComponent;
|
||||
fn b(self) -> NcComponent;
|
||||
fn g(self) -> NcComponent;
|
||||
fn r(self) -> NcComponent;
|
||||
fn set_a(&mut self, green: NcComponent);
|
||||
fn set_b(&mut self, blue: NcComponent);
|
||||
fn set_g(&mut self, green: NcComponent);
|
||||
fn set_r(&mut self, red: NcComponent);
|
||||
fn set_rgb8(&mut self, red: NcComponent, green: NcComponent, blue: NcComponent);
|
||||
}
|
||||
|
||||
impl NcPixelMethods for NcPixel {
|
||||
/// Constructs a libav-compatible ABGR pixel from RGB [`NcComponent`]s.
|
||||
fn new(red: NcComponent, green: NcComponent, blue: NcComponent) -> Self {
|
||||
ncpixel(red, green, blue)
|
||||
}
|
||||
|
||||
/// Extracts the 8-bit alpha [`NcComponent`] from an ABGR pixel.
|
||||
fn a(self) -> NcComponent {
|
||||
ncpixel_a(self)
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit blue [`NcComponent`] from an ABGR pixel.
|
||||
fn b(self) -> NcComponent {
|
||||
ncpixel_b(self)
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit green [`NcComponent`] from an ABGR pixel.
|
||||
fn g(self) -> NcComponent {
|
||||
ncpixel_g(self)
|
||||
}
|
||||
|
||||
/// Extracts the 8 bit red [`NcComponent`] from an ABGR pixel.
|
||||
fn r(self) -> NcComponent {
|
||||
ncpixel_r(self)
|
||||
}
|
||||
|
||||
/// Sets the 8-bit alpha [`NcComponent`] of an ABGR pixel.
|
||||
fn set_a(&mut self, alpha: NcComponent) {
|
||||
ncpixel_set_a(self, alpha)
|
||||
}
|
||||
|
||||
/// Sets the 8-bit green [`NcComponent`] of an ABGR pixel.
|
||||
fn set_g(&mut self, green: NcComponent) {
|
||||
ncpixel_set_b(self, green)
|
||||
}
|
||||
|
||||
/// Sets the 8-bit blue [`NcComponent`] of an ABGR pixel.
|
||||
fn set_b(&mut self, blue: NcComponent) {
|
||||
ncpixel_set_b(self, blue)
|
||||
}
|
||||
|
||||
/// Sets the 8-bit red [`NcComponent`] of an ABGR pixel.
|
||||
fn set_r(&mut self, red: NcComponent) {
|
||||
ncpixel_set_r(self, red)
|
||||
}
|
||||
|
||||
/// Sets the RGB [`NcComponent`]s of an ABGR pixel.
|
||||
fn set_rgb8(&mut self, red: NcComponent, green: NcComponent, blue: NcComponent) {
|
||||
ncpixel_set_rgb8(self, red, green, blue);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
use crate::{Nc, NcDim, NcOffset, NcPlane, NcPlaneOptions};
|
||||
|
||||
/// Helper function for a new NcPlane on C style tests.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) unsafe fn ncplane_new_test<'a>(
|
||||
nc: &mut Nc,
|
||||
y: NcOffset,
|
||||
x: NcOffset,
|
||||
rows: NcDim,
|
||||
cols: NcDim,
|
||||
) -> &'a mut NcPlane {
|
||||
&mut *crate::ncpile_create(nc, &NcPlaneOptions::new(y, x, rows, cols))
|
||||
}
|
||||
|
||||
/// Helper function for a new bound NcPlane on C style tests.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) unsafe fn ncplane_new_bound_test<'a>(
|
||||
plane: &mut NcPlane,
|
||||
y: NcOffset,
|
||||
x: NcOffset,
|
||||
rows: NcDim,
|
||||
cols: NcDim,
|
||||
) -> &'a mut NcPlane {
|
||||
&mut *crate::ncplane_create(plane, &NcPlaneOptions::new(y, x, rows, cols))
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,298 +0,0 @@
|
||||
//! `NcPlane`
|
||||
|
||||
// functions already exported by bindgen : 117
|
||||
// -------------------------------------------
|
||||
// (X) wont: 10
|
||||
// (D) depr: 4
|
||||
// (#) test: 13
|
||||
// (W) wrap: 83
|
||||
// -------------------------------------------
|
||||
//W ncpile_bottom
|
||||
//W# ncpile_create
|
||||
//W ncpile_rasterize
|
||||
//W ncpile_render
|
||||
//W ncpile_top
|
||||
//W ncplane_above
|
||||
//W ncplane_abs_x
|
||||
//W ncplane_abs_y
|
||||
//W ncplane_abs_yx
|
||||
//W ncplane_at_cursor
|
||||
//W ncplane_at_cursor_cell
|
||||
//W ncplane_at_yx
|
||||
//W ncplane_at_yx_cell
|
||||
//W ncplane_base
|
||||
//W ncplane_below
|
||||
//W ncplane_box
|
||||
//W ncplane_center_abs
|
||||
//W# ncplane_channels
|
||||
//W ncplane_contents
|
||||
//W ncplane_create
|
||||
//W# ncplane_cursor_move_yx
|
||||
//W# ncplane_cursor_yx
|
||||
//W ncplane_destroy
|
||||
//W# ncplane_dim_yx
|
||||
//W ncplane_dup
|
||||
//W# ncplane_erase
|
||||
// ncplane_erase_region
|
||||
//W ncplane_fadein
|
||||
//W ncplane_fadein_iteration
|
||||
//W ncplane_fadeout
|
||||
//W ncplane_fadeout_iteration
|
||||
//W ncplane_format
|
||||
//W ncplane_gradient
|
||||
//W ncplane_greyscale
|
||||
// ncplane_halign
|
||||
//W ncplane_highgradient
|
||||
//W ncplane_highgradient_sized
|
||||
// ncplane_hline_interp
|
||||
//W# ncplane_home
|
||||
//W ncplane_mergedown
|
||||
//W ncplane_mergedown_simple
|
||||
//W ncplane_move_above
|
||||
//W ncplane_move_below
|
||||
//W ncplane_move_bottom
|
||||
//W ncplane_move_top
|
||||
//W ncplane_move_yx
|
||||
//W# ncplane_notcurses
|
||||
//W# ncplane_notcurses_const
|
||||
//W ncplane_off_styles
|
||||
//W ncplane_on_styles
|
||||
//W ncplane_parent
|
||||
//W ncplane_parent_const
|
||||
//W ncplane_pixelgeom
|
||||
// ncplane_polyfill_yx
|
||||
//W ncplane_pulse
|
||||
// ncplane_putchar_stained
|
||||
// ncplane_putc_yx
|
||||
// X ncplane_putegc_stained // unneeded
|
||||
// X ncplane_putegc_yx // unneeded
|
||||
// ncplane_putnstr_aligned
|
||||
// ncplane_putnstr_yx
|
||||
//W ncplane_putstr_aligned
|
||||
//W ncplane_putstr_stained
|
||||
//W ncplane_putstr_yx
|
||||
// ncplane_puttext
|
||||
// X ncplane_putwegc_stained // unneeded
|
||||
// X ncplane_putwstr_stained // unneeded
|
||||
// ncplane_qrcode
|
||||
//W ncplane_reparent
|
||||
//W ncplane_reparent_family
|
||||
//W# ncplane_resize
|
||||
//W ncplane_resizecb
|
||||
//W ncplane_resize_marginalize
|
||||
//W ncplane_resize_maximize
|
||||
//W ncplane_resize_realign
|
||||
//W ncplane_rgba
|
||||
//W ncplane_rotate_ccw
|
||||
//W ncplane_rotate_cw
|
||||
//W ncplane_scrolling_p
|
||||
//W ncplane_set_base
|
||||
//W ncplane_set_base_cell
|
||||
//W# ncplane_set_bchannel
|
||||
//W ncplane_set_bg_alpha
|
||||
//W ncplane_set_bg_default
|
||||
//W ncplane_set_bg_palindex
|
||||
//W ncplane_set_bg_rgb
|
||||
//W ncplane_set_bg_rgb8
|
||||
// X ncplane_set_bg_rgb8_clipped // unneeded
|
||||
//W# ncplane_set_channels
|
||||
//W# ncplane_set_fchannel
|
||||
//W ncplane_set_fg_alpha
|
||||
//W ncplane_set_fg_default
|
||||
//W ncplane_set_fg_palindex
|
||||
//W ncplane_set_fg_rgb
|
||||
//W ncplane_set_fg_rgb8
|
||||
// X ncplane_set_fg_rgb8_clipped // unneeded
|
||||
//W ncplane_set_resizecb
|
||||
//W ncplane_set_scrolling
|
||||
//W ncplane_set_styles
|
||||
// ncplane_set_userptr
|
||||
//W ncplane_stain
|
||||
//W ncplane_styles
|
||||
//W ncplane_translate
|
||||
//W ncplane_translate_abs
|
||||
// ncplane_userptr
|
||||
// ncplane_valign
|
||||
// ncplane_vline_interp
|
||||
// X ncplane_vprintf_aligned
|
||||
// X ncplane_vprintf_stained
|
||||
// X ncplane_vprintf_yx
|
||||
//W ncplane_x
|
||||
//W ncplane_y
|
||||
//W ncplane_yx
|
||||
//
|
||||
// functions manually reimplemented: 40
|
||||
// ------------------------------------------
|
||||
// (X) wont: 9
|
||||
// (+) done: 33 / 0
|
||||
// (W) wrap: 25
|
||||
// (#) test: 5
|
||||
// ------------------------------------------
|
||||
//W+ ncplane_bchannel
|
||||
//W+ ncplane_bg_alpha
|
||||
//W# ncplane_bg_default_p
|
||||
//W+ ncplane_bg_rgb
|
||||
//W+ ncplane_bg_rgb8
|
||||
//W+ ncplane_box_sized
|
||||
//W# ncplane_dim_x
|
||||
//W# ncplane_dim_y
|
||||
//W+ ncplane_double_box
|
||||
//W+ ncplane_double_box_sized
|
||||
//W+ ncplane_fchannel
|
||||
//W+ ncplane_fg_alpha
|
||||
//W# ncplane_fg_default_p
|
||||
//W+ ncplane_fg_rgb
|
||||
//W+ ncplane_fg_rgb8
|
||||
//W+ ncplane_gradient_sized
|
||||
//W+ ncplane_halign
|
||||
// + ncplane_hline
|
||||
//W ncplane_moverel
|
||||
//W+ ncplane_perimeter
|
||||
//W+ ncplane_perimeter_double
|
||||
//W+ ncplane_perimeter_rounded
|
||||
// + ncplane_putc
|
||||
// + ncplane_putchar
|
||||
// + ncplane_putchar_yx
|
||||
// X ncplane_putegc // unneeded
|
||||
// + ncplane_putnstr
|
||||
//W+ ncplane_putstr
|
||||
// X ncplane_putwc // unneeded
|
||||
// X ncplane_putwc_stained // unneeded
|
||||
// X ncplane_putwc_yx // unneeded
|
||||
// X ncplane_putwegc // unneeded
|
||||
// X ncplane_putwegc_yx // unneeded
|
||||
// X ncplane_putwstr // unneeded
|
||||
// X ncplane_putwstr_aligned // unneeded
|
||||
// X ncplane_putwstr_yx // unneeded
|
||||
//W# ncplane_resize_simple
|
||||
// + ncplane_rounded_box
|
||||
// + ncplane_rounded_box_sized
|
||||
//W+ ncplane_halign
|
||||
// + ncplane_vline
|
||||
// X ncplane_vprintf
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
mod helpers;
|
||||
mod methods;
|
||||
mod reimplemented;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use helpers::*;
|
||||
pub use reimplemented::*;
|
||||
|
||||
// NcPlane
|
||||
/// Fundamental drawing surface.
|
||||
///
|
||||
/// Unites a:
|
||||
/// - CellMatrix
|
||||
/// - EgcPool
|
||||
///
|
||||
/// `type in C: ncplane (struct)`
|
||||
///
|
||||
///
|
||||
/// # About planes and piles
|
||||
///
|
||||
/// A given notcurses context is made up of one or more piles.
|
||||
///
|
||||
/// A pile is made up of [`NcPlane`]s, totally ordered on a z-axis.
|
||||
///
|
||||
/// You can't manage the piles directly, but only the `NcPlanes`.
|
||||
///
|
||||
/// A pile is destroyed when all its planes are destroyed or moved to other
|
||||
/// piles.
|
||||
///
|
||||
/// A pile has a top and bottom plane (this might be a single `NcPlane`),
|
||||
/// and one or more root planes (`NcPlane`s which are bound to themselves).
|
||||
///
|
||||
/// Multiple threads can concurrently operate on distinct piles, rendering or
|
||||
/// mutating it, while another thread concurrently renders or mutates another.
|
||||
///
|
||||
/// Each `NcPlane` is part of one and only one pile. By default, an `NcPlane` is
|
||||
/// part of the same pile that contains the `NcPlane` to which it is bound.
|
||||
///
|
||||
/// When an `NcPlane` is created without being bound to another `NcPlane`, then
|
||||
/// it becomes the root plane, top, and bottom of a new pile. As a root plane,
|
||||
/// it is bound to itself.
|
||||
///
|
||||
/// A new pile can also be created by reparenting an `NcPlane` to itself,
|
||||
/// though if the plane is already a root plane, this is a no-op.
|
||||
///
|
||||
/// When an `NcPlane` is moved to a different pile (whether new or preexisting),
|
||||
/// any `NcPlane`s which were bound to it are rebound to its previous parent.
|
||||
/// If the `NcPlane` was a root plane of some pile, any bound planes become root
|
||||
/// planes. The new `NcPlane` is placed immediately atop its new parent on its
|
||||
/// new pile's z-axis.
|
||||
///
|
||||
/// When [`NcPlane::reparent_family`][NcPlane#method.reparent_family] is used,
|
||||
/// all `NcPlanes` bound to the reparented `NcPlane` are moved along with it.
|
||||
/// Their relative z-order is maintained.
|
||||
//
|
||||
/// Rendering reduces a pile of `NcPlane`s to a single `NcPlane`, proceeding
|
||||
/// from the top to the bottom along a pile's z-axis. The result is a matrix of
|
||||
/// [`NcCell`][crate::NcCell]s. Rasterizing takes this matrix, together with the
|
||||
/// current state of the visual area, and produces a stream of optimized control
|
||||
/// sequences and `EGC`s for the terminal. By writing this stream to the
|
||||
/// terminal, the physical display is synced to some pile's `NcPlane`s.
|
||||
///
|
||||
/// [`NcPlane.render`][crate::NcPlane#method.render] performs the first of these
|
||||
/// tasks for the pile of which the plane is a part. The output is maintained
|
||||
/// internally; calling `render` again on the same pile will replace this state
|
||||
/// with a fresh render. Multiple piles can be concurrently rendered.
|
||||
/// [`NcPlane.rasterize`][crate::NcPlane#method.rasterize] performs
|
||||
/// rasterization, and writes the result to the terminal. It is a blocking call,
|
||||
/// and only one rasterization operation may proceed at a time.
|
||||
///
|
||||
/// It is necessary to call `NcPlane.rasterize` to generate any visible output;
|
||||
/// the various *output calls* only draw to the virtual `NcPlane`s. Most of the
|
||||
/// notcurses `statistics` are updated as a result of a render, and screen
|
||||
/// geometry is refreshed (similarly to
|
||||
/// [`Notcurses.refresh`][crate::Notcurses#method.refresh]) following the render.
|
||||
///
|
||||
/// # Methods & Associated Functions
|
||||
///
|
||||
/// - [Constructors & Destructors](#ncplane-constructors--destructors)
|
||||
///
|
||||
/// Methods:
|
||||
/// - [`NcAlphaBits`](#ncplane-methods-ncalphabits)
|
||||
/// - [`NcChannel` & `NcChannels`](#ncplane-methods-ncchannel)
|
||||
/// - [`NcComponent`, `NcRgb` & default color](#ncplane-methods-nccomponent-ncrgb--default-color)
|
||||
/// - [`NcStyle` & `NcPaletteIndex`](#ncplane-methods-ncstylemask--paletteindex)
|
||||
/// - [`NcCell` & strings](#ncplane-methods-nccell--strings)
|
||||
/// - [cursor](#ncplane-methods-cursor)
|
||||
/// - [`NcPlane` & `Notcurses`](#ncplane-methods-ncplane--notcurses)
|
||||
/// - [boxes & perimeters](#ncplane-methods-boxes--perimeters)
|
||||
/// - [Size, position & alignment](#ncplane-methods-size-position--alignment)
|
||||
/// - [fading, gradients & greyscale](#ncplane-methods-fading-gradients--greyscale)
|
||||
///
|
||||
pub type NcPlane = crate::bindings::ffi::ncplane;
|
||||
|
||||
/// Options struct for [`NcPlane`]
|
||||
pub type NcPlaneOptions = crate::bindings::ffi::ncplane_options;
|
||||
|
||||
/// Horizontal alignment relative to the parent plane. Use NcAlign for 'x'.
|
||||
pub const NCPLANE_OPTION_HORALIGNED: u64 = crate::bindings::ffi::NCPLANE_OPTION_HORALIGNED as u64;
|
||||
|
||||
/// Vertical alignment relative to the parent plane. Use NcAlign for 'y'.
|
||||
pub const NCPLANE_OPTION_VERALIGNED: u64 = crate::bindings::ffi::NCPLANE_OPTION_VERALIGNED as u64;
|
||||
|
||||
/// Maximize relative to the parent plane, modulo the provided margins.
|
||||
///
|
||||
/// The margins are best-effort; the plane will always be at least 1 column by
|
||||
/// 1 row. If the margins can be effected, the plane will be sized to all
|
||||
/// remaining space. 'y' and 'x' are overloaded as the top and left margins
|
||||
/// when this flag is used. 'rows' and 'cols' must be 0 when this flag is
|
||||
/// used. This flag is exclusive with both of the alignment flags.
|
||||
pub const NCPLANE_OPTION_MARGINALIZED: u64 =
|
||||
crate::bindings::ffi::NCPLANE_OPTION_MARGINALIZED as u64;
|
||||
|
||||
/// I/O wrapper to dump file descriptor to [`NcPlane`]
|
||||
///
|
||||
/// `type in C: ncfdplane (struct)`
|
||||
pub type NcFdPlane = crate::bindings::ffi::ncfdplane;
|
||||
|
||||
/// Options struct for [`NcFdPlane`]
|
||||
///
|
||||
/// `type in C: ncplane_options (struct)`
|
||||
pub type NcFdPlaneOptions = crate::bindings::ffi::ncfdplane_options;
|
@ -1,854 +0,0 @@
|
||||
//! `ncplane_*` reimplemented functions.
|
||||
|
||||
use core::ptr::null_mut;
|
||||
|
||||
use crate::{
|
||||
cstring, nccell_release, NcAlign, NcAlphaBits, NcBoxMask, NcCell, NcChannel, NcChannels,
|
||||
NcComponent, NcDim, NcIntResult, NcOffset, NcPlane, NcRgb, NcStyle, NCRESULT_ERR, NCRESULT_OK,
|
||||
};
|
||||
|
||||
// Alpha -----------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [NcAlphaBits] from the [NcPlane], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcPlane.[fg_alpha()][NcPlane#method.fg_alpha].*
|
||||
#[inline]
|
||||
pub fn ncplane_fg_alpha(plane: &NcPlane) -> NcAlphaBits {
|
||||
crate::ncchannels_fg_alpha(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Gets the background [NcAlphaBits] from the [NcPlane], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcPlane.[bg_alpha()][NcPlane#method.bg_alpha].*
|
||||
#[inline]
|
||||
pub fn ncplane_bg_alpha(plane: &NcPlane) -> NcAlphaBits {
|
||||
crate::ncchannels_bg_alpha(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
// NcChannel -------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [NcChannel] from an [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[fchannel()][NcPlane#method.fchannel].*
|
||||
#[inline]
|
||||
pub fn ncplane_fchannel(plane: &NcPlane) -> NcChannel {
|
||||
crate::ncchannels_fchannel(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Gets the background [NcChannel] from an [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[bchannel()][NcPlane#method.bchannel].*
|
||||
#[inline]
|
||||
pub fn ncplane_bchannel(plane: &NcPlane) -> NcChannel {
|
||||
crate::ncchannels_bchannel(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Sets the foreground [NcChannel] on an [NcPlane],
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_fchannel()][NcPlane#method.set_fchannel].*
|
||||
#[inline]
|
||||
pub fn ncplane_set_fchannel(plane: &mut NcPlane, channel: NcChannel) -> NcChannels {
|
||||
unsafe { crate::ffi::ncplane_set_fchannel(plane, channel) }
|
||||
}
|
||||
|
||||
/// Sets the background [NcChannel] on an [NcPlane],
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_bchannel()][NcPlane#method.set_bchannel].*
|
||||
#[inline]
|
||||
pub fn ncplane_set_bchannel(plane: &mut NcPlane, channel: NcChannel) -> NcChannels {
|
||||
unsafe { crate::ffi::ncplane_set_bchannel(plane, channel) }
|
||||
}
|
||||
|
||||
/// Gets the [NcChannels] of an [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[channels()][NcPlane#method.channels].*
|
||||
#[inline]
|
||||
pub fn ncplane_channels(plane: &NcPlane) -> NcChannels {
|
||||
unsafe { crate::ffi::ncplane_channels(plane) }
|
||||
}
|
||||
|
||||
/// Sets the [NcChannels] of an [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[set_channels()][NcPlane#method.set_channels].*
|
||||
#[inline]
|
||||
pub fn ncplane_set_channels(plane: &mut NcPlane, channels: NcChannels) {
|
||||
unsafe { crate::ffi::ncplane_set_channels(plane, channels) };
|
||||
}
|
||||
|
||||
// NcComponent ---------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground RGB [NcComponent]s from an [NcPlane].
|
||||
/// and returns the background [NcChannel].
|
||||
///
|
||||
/// *Method: NcPlane.[fg_rgb8()][NcPlane#method.fg_rgb8].*
|
||||
#[inline]
|
||||
pub fn ncplane_fg_rgb8(
|
||||
plane: &NcPlane,
|
||||
red: &mut NcComponent,
|
||||
green: &mut NcComponent,
|
||||
blue: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
crate::ncchannels_fg_rgb8(ncplane_channels(plane), red, green, blue)
|
||||
}
|
||||
|
||||
/// Gets the background RGB [NcComponent]s from an [NcPlane],
|
||||
/// and returns the background [NcChannel].
|
||||
///
|
||||
/// *Method: NcPlane.[bg_rgb8()][NcPlane#method.bg_rgb8].*
|
||||
#[inline]
|
||||
pub fn ncplane_bg_rgb8(
|
||||
plane: &NcPlane,
|
||||
red: &mut NcComponent,
|
||||
green: &mut NcComponent,
|
||||
blue: &mut NcComponent,
|
||||
) -> NcChannel {
|
||||
crate::ncchannels_bg_rgb8(ncplane_channels(plane), red, green, blue)
|
||||
}
|
||||
|
||||
// NcRgb -----------------------------------------------------------------------
|
||||
|
||||
/// Gets the foreground [NcRgb] from an [NcPlane], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcPlane.[fg_rgb()][NcPlane#method.fg_rgb].*
|
||||
#[inline]
|
||||
pub fn ncplane_fg_rgb(plane: &NcPlane) -> NcRgb {
|
||||
crate::ncchannels_fg_rgb(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Gets the background [NcRgb] from an [NcPlane], shifted to LSBs.
|
||||
///
|
||||
/// *Method: NcPlane.[bg_rgb()][NcPlane#method.bg_rgb].*
|
||||
#[inline]
|
||||
pub fn ncplane_bg_rgb(plane: &NcPlane) -> NcRgb {
|
||||
crate::ncchannels_bg_rgb(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
// Default ---------------------------------------------------------------------
|
||||
|
||||
/// Is the plane's foreground using the "default foreground color"?
|
||||
///
|
||||
/// *Method: NcPlane.[fg_default_p()][NcPlane#method.fg_default_p].*
|
||||
#[inline]
|
||||
pub fn ncplane_fg_default_p(plane: &NcPlane) -> bool {
|
||||
crate::ncchannels_fg_default_p(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Is the plane's background using the "default background color"?
|
||||
///
|
||||
/// *Method: NcPlane.[bg_default_p()][NcPlane#method.bg_default_p].*
|
||||
#[inline]
|
||||
pub fn ncplane_bg_default_p(plane: &NcPlane) -> bool {
|
||||
crate::ncchannels_bg_default_p(ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background as using the "default color",
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_default()][NcPlane#method.set_default].*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncplane_set_default(plane: &mut NcPlane) -> NcChannels {
|
||||
let channels = crate::ncchannels_set_default(&mut ncplane_channels(plane));
|
||||
ncplane_set_channels(plane, channels);
|
||||
channels
|
||||
}
|
||||
|
||||
/// Marks both the foreground and background as NOT using the "default color",
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_not_default()][NcPlane#method.set_not_default].*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncplane_set_not_default(plane: &mut NcPlane) -> NcChannels {
|
||||
let channels = crate::ncchannels_set_not_default(&mut ncplane_channels(plane));
|
||||
crate::ncplane_set_channels(plane, channels);
|
||||
channels
|
||||
}
|
||||
|
||||
/// Marks the foreground as NOT using the "default color",
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_fg_not_default()][NcPlane#method.set_fg_not_default].*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncplane_set_fg_not_default(plane: &NcPlane) -> NcChannels {
|
||||
crate::ncchannels_set_fg_not_default(&mut ncplane_channels(plane))
|
||||
}
|
||||
|
||||
/// Marks the background as NOT using the "default color",
|
||||
/// and returns the new [NcChannels].
|
||||
///
|
||||
/// *Method: NcPlane.[set_bg_not_default()][NcPlane#method.set_bg_not_default].*
|
||||
//
|
||||
// Not in the C API.
|
||||
#[inline]
|
||||
pub fn ncplane_set_bg_not_default(plane: &NcPlane) -> NcChannels {
|
||||
crate::ncchannels_set_bg_not_default(&mut ncplane_channels(plane))
|
||||
}
|
||||
|
||||
// put & print -----------------------------------------------------------------
|
||||
|
||||
/// Calls [ncplane_putc_yx()][crate::ncplane_putc_yx] for the current cursor location.
|
||||
///
|
||||
/// *Method: NcPlane.[putc()][NcPlane#method.putc].*
|
||||
#[inline]
|
||||
pub fn ncplane_putc(plane: &mut NcPlane, cell: &NcCell) -> NcIntResult {
|
||||
unsafe { crate::ncplane_putc_yx(plane, -1, -1, cell) }
|
||||
}
|
||||
|
||||
/// Calls ncplane_putchar_yx() at the current cursor location.
|
||||
///
|
||||
/// *Method: NcPlane.[putchar()][NcPlane#method.putchar].*
|
||||
#[inline]
|
||||
pub fn ncplane_putchar(plane: &mut NcPlane, ch: char) -> NcIntResult {
|
||||
unsafe {
|
||||
let cell = NcCell::from_char(ch, plane);
|
||||
crate::ncplane_putc_yx(plane, -1, -1, &cell)
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the [NcCell] at the specified coordinates with the provided char.
|
||||
/// Advances the cursor by 1.
|
||||
///
|
||||
/// *Method: NcPlane.[putchar_yx()][NcPlane#method.putchar_yx].*
|
||||
#[inline]
|
||||
pub fn ncplane_putchar_yx(plane: &mut NcPlane, y: NcDim, x: NcDim, ch: char) -> NcIntResult {
|
||||
unsafe {
|
||||
let cell = NcCell::from_char(ch, plane);
|
||||
crate::ncplane_putc_yx(plane, y as i32, x as i32, &cell)
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a series of `EGC`s to the current location, using the current style.
|
||||
///
|
||||
/// Advances the cursor by some positive number of columns
|
||||
/// (though not beyond the end of the plane),
|
||||
/// and this number is returned on success.
|
||||
///
|
||||
/// On error, a non-positive number is returned, indicating
|
||||
/// the number of columns which were written before the error.
|
||||
///
|
||||
/// *Method: NcPlane.[putstr()][NcPlane#method.putstr].*
|
||||
#[inline]
|
||||
pub fn ncplane_putstr(plane: &mut NcPlane, string: &str) -> NcIntResult {
|
||||
unsafe { crate::ncplane_putstr_yx(plane, -1, -1, cstring![string]) }
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[putnstr()][NcPlane#method.putnstr].*
|
||||
#[inline]
|
||||
pub fn ncplane_putnstr(plane: &mut NcPlane, size: u32, gclustarr: &[u8]) -> NcIntResult {
|
||||
unsafe { crate::ncplane_putnstr_yx(plane, -1, -1, size.into(), cstring![gclustarr]) }
|
||||
}
|
||||
|
||||
// movement, size & alignment --------------------------------------------------
|
||||
|
||||
/// Moves this `NcPlane` relative to its current location.
|
||||
///
|
||||
/// Negative values move up and left, respectively.
|
||||
/// Pass 0 to hold an axis constant.
|
||||
///
|
||||
/// It is an error to attempt to move the standard plane.
|
||||
///
|
||||
/// *C style function: [ncplane_moverel()][crate::ncplane_moverel].*
|
||||
pub fn ncplane_moverel(plane: &mut NcPlane, rows: NcOffset, cols: NcOffset) -> NcIntResult {
|
||||
let (mut orig_y, mut orig_x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_dim_yx(plane, &mut orig_y, &mut orig_x);
|
||||
crate::ncplane_move_yx(plane, orig_y + rows, orig_x + cols)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the columns of the [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[dim_x()][NcPlane#method.dim_x].*
|
||||
#[inline]
|
||||
pub fn ncplane_dim_x(plane: &NcPlane) -> NcDim {
|
||||
unsafe {
|
||||
let mut x = 0;
|
||||
crate::ncplane_dim_yx(plane, null_mut(), &mut x);
|
||||
x as NcDim
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the rows of the [NcPlane].
|
||||
///
|
||||
/// *Method: NcPlane.[dim_y()][NcPlane#method.dim_y].*
|
||||
#[inline]
|
||||
#[inline]
|
||||
pub fn ncplane_dim_y(plane: &NcPlane) -> NcDim {
|
||||
unsafe {
|
||||
let mut y = 0;
|
||||
crate::ncplane_dim_yx(plane, &mut y, null_mut());
|
||||
y as NcDim
|
||||
}
|
||||
}
|
||||
|
||||
/// Resizes the plane, retaining what data we can (everything, unless we're
|
||||
/// shrinking in some dimension). Keep the origin where it is.
|
||||
///
|
||||
/// *Method: NcPlane.[resize_simple()][NcPlane#method.resize_simple].*
|
||||
#[inline]
|
||||
pub fn ncplane_resize_simple(plane: &mut NcPlane, y_len: NcDim, x_len: NcDim) -> NcIntResult {
|
||||
let (mut old_y, mut old_x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_dim_yx(plane, &mut old_y, &mut old_x);
|
||||
}
|
||||
let keep_len_y = {
|
||||
if old_y > y_len as i32 {
|
||||
y_len as i32
|
||||
} else {
|
||||
old_y
|
||||
}
|
||||
};
|
||||
let keep_len_x = {
|
||||
if old_x > x_len as i32 {
|
||||
x_len as i32
|
||||
} else {
|
||||
old_x
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
crate::ncplane_resize(
|
||||
plane,
|
||||
0,
|
||||
0,
|
||||
keep_len_y,
|
||||
keep_len_x,
|
||||
0,
|
||||
0,
|
||||
y_len as i32,
|
||||
x_len as i32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the column at which `cols` columns ought start in order to be aligned
|
||||
/// according to `align` within this NcPlane.
|
||||
///
|
||||
/// Returns `-`[`NCRESULT_MAX`][crate::NCRESULT_MAX] if
|
||||
/// [NCALIGN_UNALIGNED][crate::NCALIGN_UNALIGNED] or invalid [NcAlign].
|
||||
///
|
||||
/// *Method: NcPlane.[halign()][NcPlane#method.halign].*
|
||||
#[inline]
|
||||
pub fn ncplane_halign(plane: &NcPlane, align: NcAlign, cols: NcDim) -> NcIntResult {
|
||||
crate::notcurses_align(ncplane_dim_x(plane), align, cols)
|
||||
}
|
||||
|
||||
/// Returns the row at which `rows` rows ought start in order to be aligned
|
||||
/// according to `align` within this NcPlane.
|
||||
///
|
||||
/// Returns `-`[`NCRESULT_MAX`][crate::NCRESULT_MAX] if
|
||||
/// [NCALIGN_UNALIGNED][crate::NCALIGN_UNALIGNED] or invalid [NcAlign].
|
||||
///
|
||||
/// *Method: NcPlane.[valign()][NcPlane#method.valign].*
|
||||
#[inline]
|
||||
pub fn ncplane_valign(plane: &NcPlane, align: NcAlign, rows: NcDim) -> NcIntResult {
|
||||
crate::notcurses_align(ncplane_dim_y(plane), align, rows)
|
||||
}
|
||||
|
||||
// line ------------------------------------------------------------------------
|
||||
|
||||
/// Draws horizontal lines using the specified NcCell, starting at the current
|
||||
/// cursor position.
|
||||
///
|
||||
/// The cursor will end at the cell following the last cell output,
|
||||
/// just as if ncplane_putc() was called at that spot.
|
||||
///
|
||||
/// Returns the number of cells drawn on success. On error, returns the negative
|
||||
/// number of cells drawn.
|
||||
///
|
||||
/// *Method: NcPlane.[hline()][NcPlane#method.hline].*
|
||||
#[inline]
|
||||
pub fn ncplane_hline(plane: &mut NcPlane, cell: &NcCell, len: NcDim) -> NcIntResult {
|
||||
unsafe { crate::ncplane_hline_interp(plane, cell, len as i32, cell.channels, cell.channels) }
|
||||
}
|
||||
|
||||
/// Draws vertical lines using the specified NcCell, starting at the current
|
||||
/// cursor position.
|
||||
///
|
||||
/// The cursor will end at the cell following the last cell output,
|
||||
/// just as if ncplane_putc() was called at that spot.
|
||||
///
|
||||
/// Returns the number of cells drawn on success. On error, returns the negative
|
||||
/// number of cells drawn.
|
||||
///
|
||||
/// *Method: NcPlane.[vline()][NcPlane#method.vline].*
|
||||
#[inline]
|
||||
pub fn ncplane_vline(plane: &mut NcPlane, cell: &NcCell, len: NcDim) -> NcIntResult {
|
||||
unsafe { crate::ncplane_vline_interp(plane, cell, len as i32, cell.channels, cell.channels) }
|
||||
}
|
||||
|
||||
// perimeter -------------------------------------------------------------------
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[perimeter()][NcPlane#method.perimeter].*
|
||||
#[inline]
|
||||
pub fn ncplane_perimeter(
|
||||
plane: &mut NcPlane,
|
||||
ul: &NcCell,
|
||||
ur: &NcCell,
|
||||
ll: &NcCell,
|
||||
lr: &NcCell,
|
||||
hline: &NcCell,
|
||||
vline: &NcCell,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
unsafe {
|
||||
crate::ncplane_cursor_move_yx(plane, 0, 0);
|
||||
let (mut dimy, mut dimx) = (0, 0);
|
||||
crate::ncplane_dim_yx(plane, &mut dimy, &mut dimx);
|
||||
ncplane_box_sized(
|
||||
plane,
|
||||
ul,
|
||||
ur,
|
||||
ll,
|
||||
lr,
|
||||
hline,
|
||||
vline,
|
||||
dimy as NcDim,
|
||||
dimx as NcDim,
|
||||
boxmask,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[perimeter_double()][NcPlane#method.perimeter_double].*
|
||||
#[inline]
|
||||
pub fn ncplane_perimeter_double(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
if unsafe { crate::ncplane_cursor_move_yx(plane, 0, 0) } != NCRESULT_OK {
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
let (mut dimy, mut dimx) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_dim_yx(plane, &mut dimy, &mut dimx);
|
||||
}
|
||||
let mut ul = NcCell::new();
|
||||
let mut ur = NcCell::new();
|
||||
let mut ll = NcCell::new();
|
||||
let mut lr = NcCell::new();
|
||||
let mut hl = NcCell::new();
|
||||
let mut vl = NcCell::new();
|
||||
if unsafe {
|
||||
crate::nccells_double_box(
|
||||
plane,
|
||||
stylemask as u32,
|
||||
channels,
|
||||
&mut ul,
|
||||
&mut ur,
|
||||
&mut ll,
|
||||
&mut lr,
|
||||
&mut hl,
|
||||
&mut vl,
|
||||
)
|
||||
} != NCRESULT_OK
|
||||
{
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
let ret = ncplane_box_sized(
|
||||
plane,
|
||||
&ul,
|
||||
&ur,
|
||||
&ll,
|
||||
&lr,
|
||||
&hl,
|
||||
&vl,
|
||||
dimy as NcDim,
|
||||
dimx as NcDim,
|
||||
boxmask,
|
||||
);
|
||||
unsafe {
|
||||
nccell_release(plane, &mut ul);
|
||||
nccell_release(plane, &mut ur);
|
||||
nccell_release(plane, &mut ll);
|
||||
nccell_release(plane, &mut lr);
|
||||
nccell_release(plane, &mut hl);
|
||||
nccell_release(plane, &mut vl);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[perimeter_rounded()][NcPlane#method.perimeter_rounded].*
|
||||
#[inline]
|
||||
pub fn ncplane_perimeter_rounded(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
if unsafe { crate::ncplane_cursor_move_yx(plane, 0, 0) } != NCRESULT_OK {
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
let (mut dimy, mut dimx) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_dim_yx(plane, &mut dimy, &mut dimx);
|
||||
}
|
||||
let mut ul = NcCell::new();
|
||||
let mut ur = NcCell::new();
|
||||
let mut ll = NcCell::new();
|
||||
let mut lr = NcCell::new();
|
||||
let mut hl = NcCell::new();
|
||||
let mut vl = NcCell::new();
|
||||
if unsafe {
|
||||
crate::nccells_rounded_box(
|
||||
plane,
|
||||
stylemask as u32,
|
||||
channels,
|
||||
&mut ul,
|
||||
&mut ur,
|
||||
&mut ll,
|
||||
&mut lr,
|
||||
&mut hl,
|
||||
&mut vl,
|
||||
)
|
||||
} != NCRESULT_OK
|
||||
{
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
let ret = ncplane_box_sized(
|
||||
plane,
|
||||
&ul,
|
||||
&ur,
|
||||
&ll,
|
||||
&lr,
|
||||
&hl,
|
||||
&vl,
|
||||
dimy as NcDim,
|
||||
dimx as NcDim,
|
||||
boxmask,
|
||||
);
|
||||
unsafe {
|
||||
nccell_release(plane, &mut ul);
|
||||
nccell_release(plane, &mut ur);
|
||||
nccell_release(plane, &mut ll);
|
||||
nccell_release(plane, &mut lr);
|
||||
nccell_release(plane, &mut hl);
|
||||
nccell_release(plane, &mut vl);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
// box -------------------------------------------------------------------------
|
||||
|
||||
/// Draws a box with its upper-left corner at the current cursor position,
|
||||
/// having dimensions `y_len` * `x_len`.
|
||||
///
|
||||
/// The minimum box size is 2x2, and it cannot be drawn off-screen.
|
||||
///
|
||||
/// See [ncplane_box()](crate::ncplane_box) for more information.
|
||||
///
|
||||
/// *Method: NcPlane.[box_sized()][NcPlane#method.box_sized].*
|
||||
#[inline]
|
||||
pub fn ncplane_box_sized(
|
||||
plane: &mut NcPlane,
|
||||
ul: &NcCell,
|
||||
ur: &NcCell,
|
||||
ll: &NcCell,
|
||||
lr: &NcCell,
|
||||
hline: &NcCell,
|
||||
vline: &NcCell,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
crate::ncplane_box(
|
||||
plane,
|
||||
ul,
|
||||
ur,
|
||||
ll,
|
||||
lr,
|
||||
hline,
|
||||
vline,
|
||||
y + y_len as i32 - 1,
|
||||
x + x_len as i32 - 1,
|
||||
boxmask,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[double_box()][NcPlane#method.double_box].*
|
||||
#[inline]
|
||||
pub fn ncplane_double_box(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
y_stop: NcDim,
|
||||
x_stop: NcDim,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
#[allow(unused_assignments)]
|
||||
let mut ret = NCRESULT_OK;
|
||||
|
||||
let mut ul = NcCell::new();
|
||||
let mut ur = NcCell::new();
|
||||
let mut ll = NcCell::new();
|
||||
let mut lr = NcCell::new();
|
||||
let mut hl = NcCell::new();
|
||||
let mut vl = NcCell::new();
|
||||
|
||||
unsafe {
|
||||
ret = crate::nccells_double_box(
|
||||
plane,
|
||||
stylemask as u32,
|
||||
channels,
|
||||
&mut ul,
|
||||
&mut ur,
|
||||
&mut ll,
|
||||
&mut lr,
|
||||
&mut hl,
|
||||
&mut vl,
|
||||
);
|
||||
if ret == NCRESULT_OK {
|
||||
ret = crate::ncplane_box(
|
||||
plane,
|
||||
&ul,
|
||||
&ur,
|
||||
&ll,
|
||||
&lr,
|
||||
&hl,
|
||||
&vl,
|
||||
y_stop as i32,
|
||||
x_stop as i32,
|
||||
boxmask,
|
||||
);
|
||||
}
|
||||
|
||||
nccell_release(plane, &mut ul);
|
||||
nccell_release(plane, &mut ur);
|
||||
nccell_release(plane, &mut ll);
|
||||
nccell_release(plane, &mut lr);
|
||||
nccell_release(plane, &mut hl);
|
||||
nccell_release(plane, &mut vl);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[double_box_sized()][NcPlane#method.double_box_sized].*
|
||||
#[inline]
|
||||
pub fn ncplane_double_box_sized(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
}
|
||||
crate::ncplane_double_box(
|
||||
plane,
|
||||
stylemask,
|
||||
channels,
|
||||
y as NcDim + y_len - 1,
|
||||
x as NcDim + x_len - 1,
|
||||
boxmask,
|
||||
)
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[rounded_box()][NcPlane#method.rounded_box].*
|
||||
#[inline]
|
||||
pub fn ncplane_rounded_box(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
y_stop: NcDim,
|
||||
x_stop: NcDim,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
#[allow(unused_assignments)]
|
||||
let mut ret = NCRESULT_OK;
|
||||
|
||||
let mut ul = NcCell::new();
|
||||
let mut ur = NcCell::new();
|
||||
let mut ll = NcCell::new();
|
||||
let mut lr = NcCell::new();
|
||||
let mut hl = NcCell::new();
|
||||
let mut vl = NcCell::new();
|
||||
|
||||
unsafe {
|
||||
ret = crate::nccells_rounded_box(
|
||||
plane,
|
||||
stylemask as u32,
|
||||
channels,
|
||||
&mut ul,
|
||||
&mut ur,
|
||||
&mut ll,
|
||||
&mut lr,
|
||||
&mut hl,
|
||||
&mut vl,
|
||||
);
|
||||
if ret == NCRESULT_OK {
|
||||
ret = crate::ncplane_box(
|
||||
plane,
|
||||
&ul,
|
||||
&ur,
|
||||
&ll,
|
||||
&lr,
|
||||
&hl,
|
||||
&vl,
|
||||
y_stop as i32,
|
||||
x_stop as i32,
|
||||
boxmask,
|
||||
);
|
||||
}
|
||||
nccell_release(plane, &mut ul);
|
||||
nccell_release(plane, &mut ur);
|
||||
nccell_release(plane, &mut ll);
|
||||
nccell_release(plane, &mut lr);
|
||||
nccell_release(plane, &mut hl);
|
||||
nccell_release(plane, &mut vl);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
/// *Method: NcPlane.[rounded_box_sized()][NcPlane#method.rounded_box_sized].*
|
||||
#[inline]
|
||||
pub fn ncplane_rounded_box_sized(
|
||||
plane: &mut NcPlane,
|
||||
stylemask: NcStyle,
|
||||
channels: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
boxmask: NcBoxMask,
|
||||
) -> NcIntResult {
|
||||
let (mut y, mut x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
}
|
||||
ncplane_rounded_box(
|
||||
plane,
|
||||
stylemask,
|
||||
channels,
|
||||
y as NcDim + y_len - 1,
|
||||
x as NcDim + x_len - 1,
|
||||
boxmask,
|
||||
)
|
||||
}
|
||||
|
||||
// gradient --------------------------------------------------------------------
|
||||
|
||||
/// Draws a gradient with its upper-left corner at the current cursor position,
|
||||
/// stopping at `ystop`×`xstop`.
|
||||
///
|
||||
/// The glyph composed of `egc` and `stylemask` is used for all cells. The
|
||||
/// `NcChannels` specified by `ul`, `ur`, `ll`, and `lr` are composed into
|
||||
/// foreground and background gradients.
|
||||
///
|
||||
/// - To do a vertical gradient, `ul` ought equal `ur` and `ll` ought equal `lr`.
|
||||
/// - To do a horizontal gradient, `ul` ought equal `ll` and `ur` ought equal `ul`.
|
||||
/// - To color everything the same, all four channels should be equivalent. The
|
||||
/// resulting alpha values are equal to incoming alpha values. Returns the number
|
||||
/// of cells filled on success, or -1 on failure.
|
||||
///
|
||||
/// Palette-indexed color is not supported.
|
||||
///
|
||||
/// Preconditions for gradient operations (error otherwise):
|
||||
/// - all: only RGB colors, unless all four channels match as default
|
||||
/// - all: all alpha values must be the same
|
||||
/// - 1x1: all four colors must be the same
|
||||
/// - 1xN: both top and both bottom colors must be the same (vertical gradient)
|
||||
/// - Nx1: both left and both right colors must be the same (horizontal gradient)
|
||||
///
|
||||
/// *Method: NcPlane.[gradient()][NcPlane#method.gradient].*
|
||||
#[inline]
|
||||
pub fn ncplane_gradient(
|
||||
plane: &mut NcPlane,
|
||||
egc: &str,
|
||||
stylemask: NcStyle,
|
||||
ul: NcChannels,
|
||||
ur: NcChannels,
|
||||
ll: NcChannels,
|
||||
lr: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
) -> NcIntResult {
|
||||
if y_len < 1 || x_len < 1 {
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "armv7l", target_arch = "i686"))]
|
||||
let egc_ptr = cstring![egc] as *const i8;
|
||||
#[cfg(not(any(target_arch = "armv7l", target_arch = "i686")))]
|
||||
let egc_ptr = cstring![egc];
|
||||
|
||||
unsafe {
|
||||
crate::bindings::ffi::ncplane_gradient(
|
||||
plane,
|
||||
egc_ptr,
|
||||
stylemask as u32,
|
||||
ul,
|
||||
ur,
|
||||
ll,
|
||||
lr,
|
||||
y_len as i32,
|
||||
x_len as i32,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a gradient with its upper-left corner at the current cursor position,
|
||||
/// having dimensions `y_len` * `x_len`.
|
||||
///
|
||||
/// See [ncplane_gradient][crate::ncplane_gradient] for more information.
|
||||
///
|
||||
/// *Method: NcPlane.[gradient_sized()][NcPlane#method.gradient_sized].*
|
||||
#[inline]
|
||||
pub fn ncplane_gradient_sized(
|
||||
plane: &mut NcPlane,
|
||||
egc: &str,
|
||||
stylemask: NcStyle,
|
||||
ul: NcChannels,
|
||||
ur: NcChannels,
|
||||
ll: NcChannels,
|
||||
lr: NcChannels,
|
||||
y_len: NcDim,
|
||||
x_len: NcDim,
|
||||
) -> NcIntResult {
|
||||
if y_len < 1 || x_len < 1 {
|
||||
return NCRESULT_ERR;
|
||||
}
|
||||
let (mut y, mut x) = (0, 0);
|
||||
unsafe {
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
ncplane_gradient(
|
||||
plane,
|
||||
egc,
|
||||
stylemask,
|
||||
ul,
|
||||
ur,
|
||||
ll,
|
||||
lr,
|
||||
y as u32 + y_len - 1,
|
||||
x as u32 + x_len - 1,
|
||||
)
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
//! Test `NcPlane` methods and associated functions.
|
||||
|
||||
// use crate::NcPlane;
|
||||
// use serial_test::serial;
|
@ -1,7 +0,0 @@
|
||||
//! `NcPlane` tests.
|
||||
|
||||
#[cfg(test)]
|
||||
mod methods;
|
||||
|
||||
#[cfg(test)]
|
||||
mod reimplemented;
|
@ -1,240 +0,0 @@
|
||||
//! Test `ncplane_*` reimplemented functions.
|
||||
|
||||
use crate::{ncplane_new_test, notcurses_init_test, notcurses_stop, NCRESULT_OK};
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_notcurses() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
let nc2 = crate::ncplane_notcurses(plane);
|
||||
assert_eq![nc as *mut _, nc2];
|
||||
|
||||
let nc3 = crate::ncplane_notcurses_const(plane);
|
||||
assert_eq![nc as *const _, nc3];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_cursor() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
let (mut y, mut x) = (0, 0);
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
assert_eq![x, 0];
|
||||
assert_eq![y, 0];
|
||||
|
||||
let res = crate::ncplane_cursor_move_yx(plane, 10, 15);
|
||||
assert_eq![res, 0];
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
assert_eq![x, 15];
|
||||
assert_eq![y, 10];
|
||||
|
||||
crate::ncplane_home(plane);
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
assert_eq![x, 0];
|
||||
assert_eq![y, 0];
|
||||
|
||||
let _res = crate::ncplane_cursor_move_yx(plane, 10, 15);
|
||||
crate::ncplane_erase(plane); // has to move the cursor to 0,0
|
||||
crate::ncplane_cursor_yx(plane, &mut y, &mut x);
|
||||
assert_eq![x, 0];
|
||||
assert_eq![y, 0];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_channels() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
let channels = crate::ncplane_channels(plane);
|
||||
assert_eq![channels, 0];
|
||||
|
||||
crate::ncplane_set_channels(plane, 0x1122334455667788);
|
||||
assert_eq![0x1122334455667788, crate::ncplane_channels(plane)];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_fchannel() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
crate::ncplane_set_channels(plane, 0x1122334455667788);
|
||||
let channels = crate::ncplane_channels(plane);
|
||||
assert_eq![0x11223344, crate::ncchannels_fchannel(channels)];
|
||||
|
||||
let channels = crate::ncplane_set_fchannel(plane, 0x10203040);
|
||||
assert_eq![0x10203040, crate::ncchannels_fchannel(channels)];
|
||||
assert_eq![0x1020304055667788, channels];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_bchannel() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
crate::ncplane_set_channels(plane, 0x1122334455667788);
|
||||
let channels = crate::ncplane_channels(plane);
|
||||
assert_eq![0x55667788, crate::ncchannels_bchannel(channels)];
|
||||
|
||||
// BUG? ncplane_set_bchannel and ncplane_set_fchannel don't get
|
||||
// applied unless they are assigned to a variable. Weird.
|
||||
|
||||
let channels = crate::ncplane_set_bchannel(plane, 0x50607080);
|
||||
assert_eq![0x50607080, crate::ncchannels_bchannel(channels)];
|
||||
assert_eq![0x1122334450607080, channels];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_rgb() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
crate::ncplane_set_fg_rgb(plane, 0x112233);
|
||||
assert_eq![0x112233, crate::ncplane_fg_rgb(plane)];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_default() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
assert_eq![true, crate::ncplane_bg_default_p(plane)];
|
||||
assert_eq![true, crate::ncplane_fg_default_p(plane)];
|
||||
|
||||
crate::ncplane_set_bg_rgb8(plane, 11, 22, 33);
|
||||
crate::ncplane_set_fg_rgb8(plane, 44, 55, 66);
|
||||
assert_eq![false, crate::ncplane_bg_default_p(plane)];
|
||||
assert_eq![false, crate::ncplane_fg_default_p(plane)];
|
||||
|
||||
crate::ncplane_set_bg_default(plane);
|
||||
crate::ncplane_set_fg_default(plane);
|
||||
assert_eq![true, crate::ncplane_bg_default_p(plane)];
|
||||
assert_eq![true, crate::ncplane_fg_default_p(plane)];
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_dimensions() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 10, 20);
|
||||
|
||||
let (mut y, mut x) = (0, 0);
|
||||
crate::ncplane_dim_yx(plane, &mut y, &mut x);
|
||||
assert_eq!((10, 20), (y, x));
|
||||
|
||||
assert_eq!(10, crate::ncplane_dim_y(plane));
|
||||
assert_eq!(20, crate::ncplane_dim_x(plane));
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn ncplane_resize() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
let res = crate::ncplane_resize_simple(plane, 40, 40);
|
||||
assert_eq![NCRESULT_OK, res];
|
||||
|
||||
let (mut y, mut x) = (0, 0);
|
||||
crate::ncplane_dim_yx(plane, &mut y, &mut x);
|
||||
assert_eq!((40, 40), (y, x));
|
||||
|
||||
// TODO: test further plane subset keeping unchanged features
|
||||
let res = crate::ncplane_resize(plane, 0, 0, 0, 0, 0, 0, 60, 70);
|
||||
assert_eq![NCRESULT_OK, res];
|
||||
|
||||
assert_eq!(60, crate::ncplane_dim_y(plane));
|
||||
assert_eq!(70, crate::ncplane_dim_x(plane));
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: resizecb
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
// TODO: CHECK: zeroes out every cell of the plane, dumps the egcpool,
|
||||
// The base cell is preserved.
|
||||
fn ncplane_erase() {
|
||||
unsafe {
|
||||
let nc = notcurses_init_test();
|
||||
let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
|
||||
crate::ncplane_set_bg_rgb(plane, 0x112233);
|
||||
crate::ncplane_set_fg_rgb(plane, 0x445566);
|
||||
assert_eq![false, crate::ncplane_bg_default_p(plane)];
|
||||
assert_eq![false, crate::ncplane_fg_default_p(plane)];
|
||||
|
||||
// FIXME? DEBUG
|
||||
crate::ncplane_erase(plane);
|
||||
// assert_eq![true, crate::ncplane_bg_default_p(plane)];
|
||||
// assert_eq![true, crate::ncplane_fg_default_p(plane)];
|
||||
//print!(" C: {:#0x} ", crate::ncplane_channels(plane));
|
||||
|
||||
notcurses_stop(nc);
|
||||
}
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// #[serial]
|
||||
// fn ncplane_at_cursor() {
|
||||
// unsafe {
|
||||
// let nc = notcurses_init_test();
|
||||
// let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
//
|
||||
// notcurses_stop(nc);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// #[serial]
|
||||
// fn ncplane_at_cursor_cell() {
|
||||
// unsafe {
|
||||
// let nc = notcurses_init_test();
|
||||
// let plane = ncplane_new_test(nc, 0, 0, 20, 20);
|
||||
//
|
||||
// notcurses_stop(nc);
|
||||
// }
|
||||
// }
|
@ -1,58 +0,0 @@
|
||||
//! `NcResizeCb`
|
||||
|
||||
use crate::{NcIntResult, NcPlane};
|
||||
|
||||
/// A callback function called when an [NcPlane] is resized.
|
||||
///
|
||||
/// See also [ncresizecb_to_rust] & [ncresizecb_to_c].
|
||||
///
|
||||
pub type NcResizeCb = fn(&mut NcPlane) -> NcIntResult;
|
||||
|
||||
/// The unsafe version of [NcResizeCb] expected by the notcurses C API.
|
||||
pub type NcResizeCbUnsafe = unsafe extern "C" fn(*mut NcPlane) -> NcIntResult;
|
||||
|
||||
/// Converts [NcResizeCbUnsafe] to [NcResizeCb].
|
||||
pub fn ncresizecb_to_rust(resizecb: Option<NcResizeCbUnsafe>) -> Option<NcResizeCb> {
|
||||
resizecb.map(|cb| unsafe { core::mem::transmute(cb) })
|
||||
}
|
||||
|
||||
/// Converts [NcResizeCb] to [NcResizeCbUnsafe].
|
||||
///
|
||||
// waiting for https://github.com/rust-lang/rust/issues/53605
|
||||
// to make this function const, and then NcPlaneOptions constructors.
|
||||
pub fn ncresizecb_to_c(resizecb: Option<NcResizeCb>) -> Option<NcResizeCbUnsafe> {
|
||||
resizecb.map(|cb| unsafe { core::mem::transmute(cb) })
|
||||
}
|
||||
|
||||
/// Enables the [NcResizeCb] methods.
|
||||
pub trait NcResizeCbMethods {
|
||||
fn to_rust(&self) -> Option<NcResizeCb>;
|
||||
fn to_c(&self) -> Option<NcResizeCbUnsafe>;
|
||||
}
|
||||
|
||||
impl NcResizeCbMethods for NcResizeCb {
|
||||
/// Returns [NcResizeCbUnsafe].
|
||||
///
|
||||
/// *C style function: [ncresizecb_to_c()][ncresizecb_to_c].*
|
||||
fn to_c(&self) -> Option<NcResizeCbUnsafe> {
|
||||
ncresizecb_to_c(Some(*self))
|
||||
}
|
||||
/// no-op.
|
||||
fn to_rust(&self) -> Option<NcResizeCb> {
|
||||
Some(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl NcResizeCbMethods for NcResizeCbUnsafe {
|
||||
/// no-op.
|
||||
fn to_c(&self) -> Option<NcResizeCbUnsafe> {
|
||||
Some(*self)
|
||||
}
|
||||
|
||||
/// Returns [NcResizeCb].
|
||||
///
|
||||
/// *C style function: [ncresizecb_to_rust()][ncresizecb_to_rust].*
|
||||
fn to_rust(&self) -> Option<NcResizeCb> {
|
||||
ncresizecb_to_rust(Some(*self))
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
//! `NcStats`
|
||||
|
||||
use crate::Nc;
|
||||
|
||||
/// notcurses runtime statistics
|
||||
pub type NcStats = crate::bindings::ffi::ncstats;
|
||||
|
||||
/// # `NcStats` Methods.
|
||||
impl NcStats {
|
||||
/// Allocates an NcStats object.
|
||||
pub fn new(nc: &mut Nc) -> &mut Self {
|
||||
unsafe { &mut *crate::notcurses_stats_alloc(nc) }
|
||||
}
|
||||
|
||||
/// Acquires an atomic snapshot of the notcurses object's stats.
|
||||
pub fn stats(&mut self, nc: &mut Nc) {
|
||||
unsafe { crate::notcurses_stats(nc, self) }
|
||||
}
|
||||
|
||||
/// Resets all cumulative stats (immediate ones are not reset).
|
||||
pub fn reset(&mut self, nc: &mut Nc) {
|
||||
unsafe { crate::notcurses_stats_reset(nc, self) }
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
//! `NcTime`
|
||||
|
||||
///
|
||||
// Expected by [`notcurses_getc`] & [`notcurses_getc_nblock`], that can't use
|
||||
// libc::timespec
|
||||
pub type NcTime = crate::bindings::ffi::timespec;
|
||||
|
||||
impl NcTime {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,618 +0,0 @@
|
||||
//! `NcVisual*` methods and associated functions.
|
||||
|
||||
use core::ptr::null_mut;
|
||||
use libc::c_void;
|
||||
|
||||
use crate::{
|
||||
cstring, error, error_ref_mut, rstring, Nc, NcBlitter, NcComponent, NcDim, NcDirect, NcDirectF,
|
||||
NcError, NcIntResult, NcPixel, NcPlane, NcResult, NcRgba, NcScale, NcTime, NcVGeom, NcVisual,
|
||||
NcVisualOptions, NCBLIT_PIXEL, NCRESULT_ERR,
|
||||
};
|
||||
|
||||
/// # NcVisualOptions Constructors
|
||||
impl NcVisualOptions {
|
||||
// /// New NcVisualOptions
|
||||
// pub fn new() -> Self {
|
||||
// Self::with_flags()
|
||||
// }
|
||||
//
|
||||
// pub fn new_aligned() -> Self {
|
||||
// Self::with_flags_aligned()
|
||||
// }
|
||||
|
||||
// TODO:
|
||||
// - horizontally aligned
|
||||
// - copy from NcPlaneOptions (with_flags_aligned & with_flags,)
|
||||
// y is an ncalign_e if NCVISUAL_OPTION_VERALIGNED is provided.
|
||||
// x is an ncalign_e value if NCVISUAL_OPTION_HORALIGNED is provided.
|
||||
|
||||
/// Specify an existing plane.
|
||||
///
|
||||
/// If [`NCVISUAL_OPTION_CHILDPLANE`][crate::NCVISUAL_OPTION_CHILDPLANE] is
|
||||
/// used in `flags` then the `plane` is interpreted as the parent [`NcPlane`]
|
||||
/// of the new plane created for this [`NcVisual`].
|
||||
pub fn with_plane(
|
||||
plane: &mut NcPlane,
|
||||
scale: NcScale,
|
||||
y: NcDim,
|
||||
x: NcDim,
|
||||
begy: NcDim,
|
||||
begx: NcDim,
|
||||
leny: NcDim,
|
||||
lenx: NcDim,
|
||||
blitter: NcBlitter,
|
||||
flags: u32,
|
||||
transcolor: NcRgba,
|
||||
) -> Self {
|
||||
Self {
|
||||
// provided plane
|
||||
n: plane,
|
||||
// the source is stretched/scaled relative to the provided ncplane
|
||||
scaling: scale,
|
||||
y: y as i32,
|
||||
x: x as i32,
|
||||
// origin of rendered section
|
||||
begy: begy as i32,
|
||||
begx: begx as i32,
|
||||
// size of rendered section
|
||||
leny: leny as i32,
|
||||
lenx: lenx as i32,
|
||||
// glyph set to use
|
||||
blitter,
|
||||
// bitmask over NCVISUAL_OPTION_*
|
||||
flags: flags as u64,
|
||||
transcolor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn without_plane(
|
||||
y: NcDim,
|
||||
x: NcDim,
|
||||
begy: NcDim,
|
||||
begx: NcDim,
|
||||
leny: NcDim,
|
||||
lenx: NcDim,
|
||||
blitter: NcBlitter,
|
||||
flags: u32,
|
||||
transcolor: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
n: null_mut(),
|
||||
scaling: crate::NCSCALE_NONE,
|
||||
// where the created ncplane will be placed relative to the standard plane's origin
|
||||
y: y as i32,
|
||||
x: x as i32,
|
||||
// origin of rendered section
|
||||
begy: begy as i32,
|
||||
begx: begx as i32,
|
||||
// size of rendered section
|
||||
leny: leny as i32,
|
||||
lenx: lenx as i32,
|
||||
// glyph set to use
|
||||
blitter,
|
||||
// bitmask over NCVISUAL_OPTION_*
|
||||
flags: flags as u64,
|
||||
// This color will be treated as transparent with flag [NCVISUAL_OPTION_ADDALPHA].
|
||||
transcolor,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fullsize_pixel_without_plane(y: NcDim, x: NcDim, leny: NcDim, lenx: NcDim) -> Self {
|
||||
Self::without_plane(y, x, 0, 0, leny, lenx, NCBLIT_PIXEL, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcVisual Constructors & destructors
|
||||
impl NcVisual {
|
||||
/// Like [from_rgba][NcVisual#method.from_rgba], but 'bgra' is arranged as BGRA.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_bgra()][crate::ncvisual_from_bgra].*
|
||||
pub fn from_bgra<'a>(
|
||||
bgra: &[u8],
|
||||
rows: NcDim,
|
||||
rowstride: NcDim,
|
||||
cols: NcDim,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_bgra(
|
||||
bgra.as_ptr() as *const c_void,
|
||||
rows as i32,
|
||||
rowstride as i32,
|
||||
cols as i32,
|
||||
)
|
||||
},
|
||||
&format![
|
||||
"NcVisual::from_bgra(bgra, {}, {}, {})",
|
||||
rows, rowstride, cols
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
/// Opens a visual at `file`, extracts the codec and parameters and
|
||||
/// decodes the first image to memory.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_file()][crate::ncvisual_from_file].*
|
||||
pub fn from_file<'a>(file: &str) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncvisual_from_file(cstring![file]) },
|
||||
&format!("NcVisual::from_file({})", file)
|
||||
]
|
||||
}
|
||||
|
||||
/// Promotes an NcPlane to an NcVisual.
|
||||
///
|
||||
/// The plane may contain only spaces, half blocks, and full blocks.
|
||||
/// This will be checked, and any other glyph will result in an error.
|
||||
///
|
||||
/// This function exists so that planes can be subjected to NcVisual transformations.
|
||||
/// If possible, it's better to create the ncvisual from memory using
|
||||
/// [from_rgba][NcVisual#method.from_rgba].
|
||||
///
|
||||
/// *C style function: [ncvisual_from_plane()][crate::ncvisual_from_plane].*
|
||||
pub fn from_plane<'a>(
|
||||
plane: &NcPlane,
|
||||
blitter: NcBlitter,
|
||||
beg_y: NcDim,
|
||||
beg_x: NcDim,
|
||||
len_y: NcDim,
|
||||
len_x: NcDim,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_plane(
|
||||
plane,
|
||||
blitter,
|
||||
beg_y as i32,
|
||||
beg_x as i32,
|
||||
len_y as i32,
|
||||
len_x as i32,
|
||||
)
|
||||
},
|
||||
&format!(
|
||||
"NcVisual::from_file(plane, {}, {}, {}, {}, {})",
|
||||
blitter, beg_y, beg_x, len_y, len_x
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Like [`from_rgba`][NcVisual#method.from_rgba], but the pixels are
|
||||
/// 4-byte RGBX. Alpha is filled in throughout using 'alpha'.
|
||||
///
|
||||
/// `rowstride` must be a multiple of 4.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_rgb_loose()][crate::ncvisual_from_rgb_loose].*
|
||||
pub fn from_rgb_loose<'a>(
|
||||
rgb: &[u8],
|
||||
rows: NcDim,
|
||||
rowstride: NcDim,
|
||||
cols: NcDim,
|
||||
alpha: NcComponent,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_rgb_loose(
|
||||
rgb.as_ptr() as *const c_void,
|
||||
rows as i32,
|
||||
rowstride as i32,
|
||||
cols as i32,
|
||||
alpha as i32,
|
||||
)
|
||||
},
|
||||
&format!(
|
||||
"NcVisual::from_rgb_loose(rgba, {}, {}, {}, {})",
|
||||
rows, rowstride, cols, alpha
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Like [`from_rgba`][NcVisual#method.from_rgba], but the pixels are
|
||||
/// 3-byte RGB. Alpha is filled in throughout using 'alpha'.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_rgb_packed()][crate::ncvisual_from_rgb_packed].*
|
||||
pub fn from_rgb_packed<'a>(
|
||||
rgb: &[u8],
|
||||
rows: NcDim,
|
||||
rowstride: NcDim,
|
||||
cols: NcDim,
|
||||
alpha: NcComponent,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_rgb_packed(
|
||||
rgb.as_ptr() as *const c_void,
|
||||
rows as i32,
|
||||
rowstride as i32,
|
||||
cols as i32,
|
||||
alpha as i32,
|
||||
)
|
||||
},
|
||||
&format!(
|
||||
"NcVisual::from_rgb_packed(rgba, {}, {}, {}, {})",
|
||||
rows, rowstride, cols, alpha
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Prepares an NcVisual, and its underlying NcPlane, based off RGBA content
|
||||
/// in memory at `rgba`.
|
||||
///
|
||||
/// `rgba` is laid out as `rows` lines, each of which is `rowstride` bytes in length.
|
||||
/// Each line has `cols` 32-bit 8bpc RGBA pixels followed by possible padding
|
||||
/// (there will be rowstride - cols * 4 bytes of padding).
|
||||
///
|
||||
/// The total size of `rgba` is thus (rows * rowstride) bytes, of which
|
||||
/// (rows * cols * 4) bytes are actual non-padding data.
|
||||
///
|
||||
/// *C style function: [ncvisual_from_rgba()][crate::ncvisual_from_rgba].*
|
||||
pub fn from_rgba<'a>(
|
||||
rgba: &[u8],
|
||||
rows: NcDim,
|
||||
rowstride: NcDim,
|
||||
cols: NcDim,
|
||||
) -> NcResult<&'a mut NcVisual> {
|
||||
error_ref_mut![
|
||||
unsafe {
|
||||
crate::ncvisual_from_rgba(
|
||||
rgba.as_ptr() as *const c_void,
|
||||
rows as i32,
|
||||
rowstride as i32,
|
||||
cols as i32,
|
||||
)
|
||||
},
|
||||
&format!(
|
||||
"NcVisual::from_rgba(rgba, {}, {}, {})",
|
||||
rows, rowstride, cols
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Destroys this NcVisual.
|
||||
///
|
||||
/// Rendered elements will not be disrupted, but the visual can be neither
|
||||
/// decoded nor rendered any further.
|
||||
///
|
||||
/// *C style function: [ncvisual_destroy()][crate::ncvisual_destroy].*
|
||||
pub fn destroy(&mut self) {
|
||||
unsafe { crate::ncvisual_destroy(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcVisual Methods
|
||||
impl NcVisual {
|
||||
/// Gets the specified pixel from this NcVisual.
|
||||
///
|
||||
/// *C style function: [ncvisual_at_yx()][crate::ncvisual_at_yx].*
|
||||
pub fn at_yx(&self, y: NcDim, x: NcDim) -> NcResult<NcPixel> {
|
||||
let mut pixel = 0;
|
||||
let res = unsafe { crate::ncvisual_at_yx(self, y as i32, x as i32, &mut pixel) };
|
||||
error![res, "NcVisual.at_yx()", pixel]
|
||||
}
|
||||
|
||||
/// Extracts the next frame from the NcVisual.
|
||||
///
|
||||
/// Returns 0 for normal frames, and 1 to indicate EOF.
|
||||
///
|
||||
/// *C style function: [ncvisual_decode()][crate::ncvisual_decode].*
|
||||
pub fn decode(&mut self) -> NcResult<NcIntResult> {
|
||||
let res = unsafe { crate::ncvisual_decode(self) };
|
||||
if res == NCRESULT_ERR {
|
||||
Err(NcError::with_msg(res, "NcVisual.decode()"))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the next frame from the NcVisual, ala [decode][NcVisual#method.decode],
|
||||
/// but if we have reached the end, rewinds to the first frame.
|
||||
///
|
||||
/// *A subsequent [NcVisual.render]() will render the first frame,
|
||||
/// as if the ncvisual had been closed and reopened.*
|
||||
///
|
||||
/// Returns 0 for normal frames and 1 to indicate EOF.
|
||||
///
|
||||
/// *C style function: [ncvisual_decode_loop()][crate::ncvisual_decode_loop].*
|
||||
pub fn decode_loop(&mut self) -> NcResult<NcIntResult> {
|
||||
let res = unsafe { crate::ncvisual_decode_loop(self) };
|
||||
if res == NCRESULT_ERR {
|
||||
Err(NcError::with_msg(res, "NcVisual.decode_loop()"))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the size and ratio of NcVisual pixels to output cells along the
|
||||
/// `y→to_y` and `x→to_x` axes.
|
||||
///
|
||||
/// Returns a tuple with (y, x, to_y, to_x)
|
||||
///
|
||||
/// An NcVisual of `y` by `x` pixels will require
|
||||
/// (`y` * `to_y`) by (`x` * `to_x`) cells for full output.
|
||||
///
|
||||
/// Errors on invalid blitter in `options`. Scaling is taken into consideration.
|
||||
///
|
||||
/// *C style function: [ncvisual_blitter_geom()][crate::ncvisual_blitter_geom].*
|
||||
pub fn geom(
|
||||
&self,
|
||||
nc: &Nc,
|
||||
options: &NcVisualOptions,
|
||||
) -> NcResult<(NcDim, NcDim, NcDim, NcDim)> {
|
||||
let mut y = 0;
|
||||
let mut x = 0;
|
||||
let mut to_y = 0;
|
||||
let mut to_x = 0;
|
||||
|
||||
let res = unsafe {
|
||||
crate::ncvisual_blitter_geom(
|
||||
nc,
|
||||
self,
|
||||
options,
|
||||
&mut y,
|
||||
&mut x,
|
||||
&mut to_y,
|
||||
&mut to_x,
|
||||
null_mut(),
|
||||
)
|
||||
};
|
||||
error![
|
||||
res,
|
||||
"NcVisual.geom()",
|
||||
(y as NcDim, x as NcDim, to_y as NcDim, to_x as NcDim)
|
||||
];
|
||||
}
|
||||
|
||||
/// Gets the default media (not plot) blitter for this environment when using
|
||||
/// the specified scaling method.
|
||||
///
|
||||
/// Currently, this means:
|
||||
/// - if lacking UTF-8, NCBLIT_1x1.
|
||||
/// - otherwise, if not NCSCALE_STRETCH, NCBLIT_2x1.
|
||||
/// - otherwise, if sextants are not known to be good, NCBLIT_2x2.
|
||||
/// - otherwise NCBLIT_3x2 NCBLIT_2x2 and NCBLIT_3x2 both distort the original
|
||||
/// aspect ratio, thus NCBLIT_2x1 is used outside of NCSCALE_STRETCH.
|
||||
///
|
||||
/// *C style function: [ncvisual_media_defblitter()][crate::ncvisual_media_defblitter].*
|
||||
pub fn media_defblitter(nc: &Nc, scale: NcScale) -> NcBlitter {
|
||||
unsafe { crate::ncvisual_media_defblitter(nc, scale) }
|
||||
}
|
||||
|
||||
/// Polyfills at the specified location using `rgba`.
|
||||
///
|
||||
/// *C style function: [ncvisual_polyfill_yx()][crate::ncvisual_polyfill_yx].*
|
||||
pub fn polyfill_yx(&mut self, y: NcDim, x: NcDim, rgba: NcRgba) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_polyfill_yx(self, y as i32, x as i32, rgba) },
|
||||
&format!["NcVisual.polyfill_yx({}, {}, {})", y, x, rgba]
|
||||
]
|
||||
}
|
||||
|
||||
/// Renders the decoded frame to the specified [`NcPlane`].
|
||||
///
|
||||
/// See [`NcVisualOptions`].
|
||||
///
|
||||
/// *C style function: [ncvisual_render()][crate::ncvisual_render].*
|
||||
pub fn render(&mut self, nc: &mut Nc, options: &NcVisualOptions) -> NcResult<&mut NcPlane> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncvisual_render(nc, self, options) },
|
||||
"NcVisual.render(Nc, &NcVisualOptions)"
|
||||
]
|
||||
}
|
||||
|
||||
/// Resizes the visual to `cols` X `rows` pixels.
|
||||
///
|
||||
/// This is a lossy transformation, unless the size is unchanged.
|
||||
///
|
||||
/// *C style function: [ncvisual_resize()][crate::ncvisual_resize].*
|
||||
pub fn resize(&mut self, rows: NcDim, cols: NcDim) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_resize(self, rows as i32, cols as i32) },
|
||||
&format!["NcVisual.resize({}, {})", rows, cols]
|
||||
]
|
||||
}
|
||||
|
||||
/// Resizes the visual to in the image to `rows` X `cols` pixels, without
|
||||
/// interpolating the color values.
|
||||
///
|
||||
/// The original color is retained.
|
||||
///
|
||||
/// *C style function:
|
||||
/// [ncvisual_resize_noninterpolative()][crate::ncvisual_resize_noninterpolative].*
|
||||
pub fn resize_noninterpolative(&mut self, rows: NcDim, cols: NcDim) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_resize_noninterpolative(self, rows as i32, cols as i32) },
|
||||
&format!["NcVisual.resize_noninterpolative({}, {})", cols, rows]
|
||||
]
|
||||
}
|
||||
|
||||
/// Rotates the visual `rads` radians.
|
||||
///
|
||||
/// Only M_PI/2 and -M_PI/2 are supported at the moment,
|
||||
/// but this will change. (FIXME)
|
||||
///
|
||||
/// *C style function: [ncvisual_rotate()][crate::ncvisual_rotate].*
|
||||
pub fn rotate(&mut self, rads: f64) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_rotate(self, rads) },
|
||||
&format!["NcVisual.rotate({})", rads]
|
||||
]
|
||||
}
|
||||
|
||||
/// Sets the specified pixel.
|
||||
///
|
||||
/// *C style function: [ncvisual_set_yx()][crate::ncvisual_set_yx].*
|
||||
pub fn set_yx(&mut self, y: NcDim, x: NcDim, pixel: NcPixel) -> NcResult<()> {
|
||||
error![
|
||||
unsafe { crate::ncvisual_set_yx(self, y as i32, x as i32, pixel) },
|
||||
&format!["NcVisual.set_yx({}, {}, {})", y, x, pixel]
|
||||
]
|
||||
}
|
||||
|
||||
/// Displays frames.
|
||||
///
|
||||
/// *Provide as an argument to ncvisual_stream().*
|
||||
///
|
||||
/// If you'd like subtitles to be decoded, provide an ncplane as the curry.
|
||||
/// If the curry is NULL, subtitles will not be displayed.
|
||||
///
|
||||
/// *C style function: [ncvisual_simple_streamer()][crate::ncvisual_simple_streamer].*
|
||||
pub fn simple_streamer(
|
||||
&mut self,
|
||||
options: &mut NcVisualOptions,
|
||||
time: &NcTime,
|
||||
curry: Option<&mut NcPlane>,
|
||||
) -> NcResult<()> {
|
||||
if let Some(plane) = curry {
|
||||
error![
|
||||
unsafe {
|
||||
crate::ncvisual_simple_streamer(
|
||||
self,
|
||||
options,
|
||||
time,
|
||||
plane as *mut _ as *mut libc::c_void,
|
||||
)
|
||||
},
|
||||
&format![
|
||||
"NcVisual.simple_streamer({:?}, {:?}, ncplane)",
|
||||
options, time
|
||||
]
|
||||
]
|
||||
} else {
|
||||
error![
|
||||
unsafe { crate::ncvisual_simple_streamer(self, options, time, null_mut()) },
|
||||
&format!["NcVisual.simple_streamer({:?}, {:?}, null)", options, time]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// // TODO
|
||||
//
|
||||
// /// Streams the entirety of the media, according to its own timing.
|
||||
// ///
|
||||
// /// Blocking, obviously.
|
||||
// ///
|
||||
// /// If `streamer` is provided it will be called for each frame, and its return
|
||||
// /// value handled as outlined for streamcb.
|
||||
// /// If streamer() returns non-zero, the stream is aborted, and that value is
|
||||
// /// returned. By convention, return a positive number to indicate intentional
|
||||
// /// abort from within streamer().
|
||||
// ///
|
||||
// /// `timescale` allows the frame duration time to be scaled.
|
||||
// /// For a visual naturally running at 30FPS, a 'timescale' of 0.1 will result
|
||||
// /// in 300 FPS, and a `timescale` of 10 will result in 3 FPS.
|
||||
// /// It is an error to supply `timescale` less than or equal to 0.
|
||||
// ///
|
||||
// /// *C style function: [ncvisual_streamer()][crate::ncvisual_streamer].*
|
||||
// //
|
||||
// // TODO: add streamcb
|
||||
// // INFO: QUESTION: is curry also optional like in simple_streamer?
|
||||
// //
|
||||
// pub fn simple_streamer(
|
||||
// &mut self,
|
||||
// nc: &mut Nc,
|
||||
// timescale: f32,
|
||||
// //streamer: Option<streamcb>
|
||||
// options: &NcVisualOptions,
|
||||
// curry: Option<&mut NcPlane>,
|
||||
// ) -> NcResult<()> {
|
||||
// }
|
||||
|
||||
/// If a subtitle ought be displayed at this time, returns a heap-allocated
|
||||
/// copy of the UTF8 text.
|
||||
///
|
||||
/// *C style function: [ncvisual_subtitle()][crate::ncvisual_subtitle].*
|
||||
pub fn subtitle(&self) -> NcResult<&str> {
|
||||
let res = unsafe { crate::ncvisual_subtitle(self) };
|
||||
if !res.is_null() {
|
||||
Ok(rstring![res])
|
||||
} else {
|
||||
Err(NcError::with_msg(NCRESULT_ERR, "NcVisual.subtitle()"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcDirectF Constructors & destructors
|
||||
impl NcDirectF {
|
||||
/// Loads media from disk, but do not yet renders it (presumably because you
|
||||
/// want to get its geometry via [ncdirectf_geom()][0], or to use the same
|
||||
/// file with [ncdirectf_render()][1] multiple times).
|
||||
///
|
||||
/// You must destroy the result with [ncdirectf_free()][2];
|
||||
///
|
||||
/// [0]: crate::NcDirectF#method.ncdirectf_geom
|
||||
/// [1]: crate::NcDirectF#method.ncdirectf_render
|
||||
/// [2]: crate::NcDirectF#method.ncdirectf_free
|
||||
///
|
||||
/// *C style function: [ncdirectf_from_file()][crate::ncdirectf_from_file].*
|
||||
pub fn ncdirectf_from_file<'a>(ncd: &mut NcDirect, file: &str) -> NcResult<&'a mut NcDirectF> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncdirectf_from_file(ncd, cstring![file]) },
|
||||
&format!("NcDirectF::ncdirectf_from_file(ncd, {})", file)
|
||||
]
|
||||
}
|
||||
|
||||
/// Frees a [`NcDirectF`] returned from [ncdirectf_from_file()][0].
|
||||
///
|
||||
/// [0]: crate::NcDirectF#method.ncdirectf_from_file
|
||||
///
|
||||
/// *C style function: [ncdirectf_free()][crate::ncdirectf_free].*
|
||||
pub fn ncdirectf_free(&mut self) {
|
||||
unsafe { crate::ncdirectf_free(self) };
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcDirectF Methods
|
||||
impl NcDirectF {
|
||||
/// Same as [`NcDirect.render_frame()`][0], except `frame` must already have
|
||||
/// been loaded.
|
||||
///
|
||||
/// A loaded frame may be rendered in different ways before it is destroyed.
|
||||
///
|
||||
/// [0]: NcDirect#method.render_frame
|
||||
///
|
||||
/// *C style function: [ncvisual_render()][crate::ncvisual_render].*
|
||||
pub fn ncdirectf_render(
|
||||
&mut self,
|
||||
ncd: &mut NcDirect,
|
||||
options: &NcVisualOptions,
|
||||
) -> NcResult<&mut NcPlane> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncdirectf_render(ncd, self, options) },
|
||||
"NcVisual.render()"
|
||||
]
|
||||
}
|
||||
/// Having loaded the `frame`, get the geometry of a potential render.
|
||||
///
|
||||
/// *C style function: [ncdirectf_geom()][crate::ncdirectf_geom].*
|
||||
pub fn ncdirectf_geom(
|
||||
&mut self,
|
||||
ncd: &mut NcDirect,
|
||||
options: &NcVisualOptions,
|
||||
) -> NcResult<NcVGeom> {
|
||||
let mut geom = NcVGeom::new();
|
||||
|
||||
let res = unsafe { crate::ncdirectf_geom(ncd, self, options, &mut geom) };
|
||||
error![res, "NcDirectF.ncdirectf_geom()", geom];
|
||||
}
|
||||
}
|
||||
|
||||
/// # NcVGeom Constructors
|
||||
impl NcVGeom {
|
||||
/// Returns a new `NcVGeom` with zeroed fields.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pixy: 0,
|
||||
pixx: 0,
|
||||
cdimy: 0,
|
||||
cdimx: 0,
|
||||
rpixy: 0,
|
||||
rpixx: 0,
|
||||
rcelly: 0,
|
||||
rcellx: 0,
|
||||
scaley: 0,
|
||||
scalex: 0,
|
||||
maxpixely: 0,
|
||||
maxpixelx: 0,
|
||||
blitter: 0,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
// functions already exported by bindgen : 26
|
||||
// -----------------------------------------
|
||||
// (W) wrap: 22
|
||||
// (#) test: 0
|
||||
// -----------------------------------------
|
||||
//W ncdirectf_free
|
||||
//W ncdirectf_from_file
|
||||
// ncdirectf_geom
|
||||
// ncdirectf_render
|
||||
//W ncvisual_at_yx
|
||||
//W ncvisual_decode
|
||||
//W ncvisual_decode_loop
|
||||
//W ncvisual_destroy
|
||||
//W ncvisual_from_bgra
|
||||
//W ncvisual_from_file
|
||||
//W ncvisual_from_plane
|
||||
//W ncvisual_from_rgba
|
||||
//W ncvisual_from_rgb_packed
|
||||
//W ncvisual_from_rgb_loose
|
||||
//W ncvisual_inflate
|
||||
//W ncvisual_blitter_geom
|
||||
//W ncvisual_media_defblitter
|
||||
//W ncvisual_polyfill_yx
|
||||
// ncvisual_plane_create
|
||||
//W ncvisual_render
|
||||
//W ncvisual_resize
|
||||
//W ncvisual_rotate
|
||||
//W ncvisual_set_yx
|
||||
//W ncvisual_simple_streamer
|
||||
//~ ncvisual_stream
|
||||
//W ncvisual_subtitle
|
||||
|
||||
#[allow(unused_imports)] // for the doc comments
|
||||
use crate::{NcChannel, NcDim, NcRgb};
|
||||
|
||||
mod methods;
|
||||
|
||||
/// Indicates how to scale an [`NcVisual`] during rendering.
|
||||
///
|
||||
/// - [`NCSCALE_NONE`] will apply no scaling.
|
||||
/// - [`NCSCALE_SCALE`] scales a visual to the plane's size,
|
||||
/// maintaining aspect ratio.
|
||||
/// - [`NCSCALE_STRETCH`] stretches and scales the image in an
|
||||
/// attempt to fill the entirety of the plane.
|
||||
/// - [`NCSCALE_NONE_HIRES`] like `NCSCALE_NONE` admitting high-res blitters.
|
||||
/// - [`NCSCALE_SCALE_HIRES`] like `NCSCALE_SCALE` admitting high-res blitters.
|
||||
///
|
||||
/// The `NCSCALE_*` preferences are applied only for the context of
|
||||
/// [`NcVisual.render`][NcVisual#method.render]. You can think of it as a pipeline:
|
||||
///
|
||||
/// ```txt
|
||||
/// NcVisual::fromfile() → frame → NcVisual.render() → scaling → output frame → blit
|
||||
/// ```
|
||||
///
|
||||
/// where you still have the original frame. Whereas
|
||||
/// [`NcVisual.resize`][NcVisual#method.resize] and
|
||||
/// [`NcVisual.resize_noninterpolative`][NcVisual#method.resize_noninterpolative]
|
||||
/// are changing that original frame.
|
||||
///
|
||||
pub type NcScale = crate::bindings::ffi::ncscale_e;
|
||||
|
||||
/// Maintains original size.
|
||||
pub const NCSCALE_NONE: NcScale = crate::bindings::ffi::ncscale_e_NCSCALE_NONE;
|
||||
|
||||
/// Maintains aspect ratio.
|
||||
pub const NCSCALE_SCALE: NcScale = crate::bindings::ffi::ncscale_e_NCSCALE_SCALE;
|
||||
|
||||
/// Throws away aspect ratio.
|
||||
pub const NCSCALE_STRETCH: NcScale = crate::bindings::ffi::ncscale_e_NCSCALE_STRETCH;
|
||||
|
||||
/// Maintains original size, admitting high-resolution blitters
|
||||
/// that don't preserve aspect ratio.
|
||||
pub const NCSCALE_NONE_HIRES: NcScale = crate::bindings::ffi::ncscale_e_NCSCALE_NONE_HIRES;
|
||||
|
||||
/// Maintains aspect ratio, admitting high-resolution blitters
|
||||
/// that don't preserve aspect ratio.
|
||||
pub const NCSCALE_SCALE_HIRES: NcScale = crate::bindings::ffi::ncscale_e_NCSCALE_SCALE_HIRES;
|
||||
|
||||
/// A visual bit of multimedia.
|
||||
///
|
||||
/// It can be constructed from a rgba or bgra buffer.
|
||||
///
|
||||
/// The [NcVisualOptions] structure is used only by the following methods:
|
||||
/// - [.geom][NcVisual#method.geom]
|
||||
/// - [.render][NcVisual#method.render]
|
||||
/// - [.simple_streamer][NcVisual#method.simple_streamer]
|
||||
pub type NcVisual = crate::bindings::ffi::ncvisual;
|
||||
|
||||
/// A type alias of [`NcVisual`] (NcDirect ***F**rame*) intended to be used
|
||||
/// with its `ncdirectf_*` methods, in [`NcDirect`][crate::NcDirect] mode.
|
||||
pub type NcDirectF = NcVisual;
|
||||
|
||||
/// Describes all geometries of an [`NcVisual`] ncvisual–both those which are inherent, and
|
||||
/// those in a given rendering regime.
|
||||
///
|
||||
/// *FIXME this ought be used in the rendered mode API as well;
|
||||
/// it’s currently only used by direct mode.*
|
||||
/// *(See [ncvgeom][1] more more information)*
|
||||
///
|
||||
/// This is the return type of the [NcDirectF.ncdirectf_geom()][0] method.
|
||||
///
|
||||
/// [0]: NcDirectF#method.ncdirectf_geom
|
||||
/// [1]: crate::bindings::ffi::ncvgeom
|
||||
pub type NcVGeom = crate::bindings::ffi::ncvgeom;
|
||||
|
||||
/// Options struct for [`NcVisual`]
|
||||
///
|
||||
/// If a plane is not provided, one will be created, having the exact size
|
||||
/// necessary to display the visual (this might be smaller or larger than
|
||||
/// the rendering area). if NCVISUAL_OPTION_CHILDPLANE is provided, this
|
||||
/// will be interpreted as the parent.
|
||||
///
|
||||
/// A subregion of the visual can be rendered using `begx`, `begy`, `lenx`, and `leny`.
|
||||
pub type NcVisualOptions = crate::bindings::ffi::ncvisual_options;
|
||||
|
||||
// NcRgba
|
||||
//
|
||||
/// 32 bits broken into 3x 8bpp RGB channels + 8ppp alpha.
|
||||
///
|
||||
/// Unlike with [`NcChannel`], operations involving `NcRgb` ignores the last 4th byte
|
||||
///
|
||||
/// ## Diagram
|
||||
///
|
||||
/// ```txt
|
||||
/// AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
|
||||
/// ```
|
||||
/// `type in C: no data type`
|
||||
///
|
||||
/// See also: [NcRgb] and [NcChannel] types.
|
||||
pub type NcRgba = u32;
|
||||
|
||||
// // NcBgra
|
||||
// //
|
||||
// /// 32 bits broken into 3x 8bpp BGR channels + 8ppp alpha.
|
||||
// ///
|
||||
// /// ## Diagram
|
||||
// ///
|
||||
// /// ```txt
|
||||
// /// AAAAAAAA BBBBBBBB GGGGGGGG RRRRRRRR
|
||||
// /// ```
|
||||
// ///
|
||||
// /// `type in C: no data type`
|
||||
// ///
|
||||
// /// See also: [NcRgba], [NcRgb] and [NcChannel] types.
|
||||
// pub type NcBgra = u32;
|
||||
|
||||
/// Treats as transparent the color specified in the `transcolor` field.
|
||||
pub const NCVISUAL_OPTION_ADDALPHA: u32 = crate::bindings::ffi::NCVISUAL_OPTION_ADDALPHA;
|
||||
|
||||
/// Uses [`NCALPHA_BLEND`][crate::NCALPHA_BLEND] with visual.
|
||||
pub const NCVISUAL_OPTION_BLEND: u32 = crate::bindings::ffi::NCVISUAL_OPTION_BLEND;
|
||||
|
||||
/// allows you to indicate that the n field of ncvisual_options refers not to
|
||||
/// the plane onto which you'd like to blit, but the parent of a new plane.
|
||||
///
|
||||
/// A plane will be created using the other parameters in the ncvisual_options,
|
||||
/// as a child of this parent. This means things like, say, vertically centering
|
||||
/// a sprixel relative to the standard plane can be done in one step.
|
||||
pub const NCVISUAL_OPTION_CHILDPLANE: u32 = crate::bindings::ffi::NCVISUAL_OPTION_CHILDPLANE;
|
||||
|
||||
/// Fails rather than gracefully degrade. See [NcBlitter].
|
||||
pub const NCVISUAL_OPTION_NODEGRADE: u32 = crate::bindings::ffi::NCVISUAL_OPTION_NODEGRADE;
|
||||
|
||||
/// Y is an alignment, not absolute.
|
||||
pub const NCVISUAL_OPTION_VERALIGNED: u32 = crate::bindings::ffi::NCVISUAL_OPTION_VERALIGNED;
|
||||
|
||||
/// X is an alignment, not absolute.
|
||||
pub const NCVISUAL_OPTION_HORALIGNED: u32 = crate::bindings::ffi::NCVISUAL_OPTION_HORALIGNED;
|
||||
|
||||
/// Uses non-interpolative scaling.
|
||||
pub const NCVISUAL_OPTION_NOINTERPOLATE: u32 = crate::bindings::ffi::NCVISUAL_OPTION_NOINTERPOLATE;
|
||||
|
||||
/// The blitter mode to use for rasterizing an [`NcVisual`].
|
||||
///
|
||||
/// We never blit full blocks, but instead spaces (more efficient) with the
|
||||
/// background set to the desired foreground.
|
||||
///
|
||||
/// ## Modes
|
||||
///
|
||||
/// - [`NCBLIT_1x1`]
|
||||
/// - [`NCBLIT_2x1`]
|
||||
/// - [`NCBLIT_2x2`]
|
||||
/// - [`NCBLIT_3x2`]
|
||||
/// - [`NCBLIT_4x1`]
|
||||
/// - [`NCBLIT_8x1`]
|
||||
/// - [`NCBLIT_BRAILLE`]
|
||||
/// - [`NCBLIT_DEFAULT`]
|
||||
/// - [`NCBLIT_PIXEL`]
|
||||
///
|
||||
/// There is a mechanism of graceful degradation, that works as follows:
|
||||
/// - without braille support, NCBLIT_BRAILLE decays to NCBLIT_3x2
|
||||
/// - without bitmap support, NCBLIT_PIXEL decays to NCBLIT_3x2
|
||||
/// - without sextant support, NCBLIT_3x2 decays to NCBLIT_2x2
|
||||
/// - without quadrant support, NCBLIT_2x2 decays to NCBLIT_2x1
|
||||
/// - the only viable blitters in ASCII are NCBLIT_1x1 and NCBLIT_PIXEL
|
||||
///
|
||||
/// If you don't want this behaviour you have to use [NCVISUAL_OPTION_NODEGRADE]
|
||||
///
|
||||
pub type NcBlitter = crate::bindings::ffi::ncblitter_e;
|
||||
|
||||
/// [`NcBlitter`] mode using: space, compatible with ASCII
|
||||
pub const NCBLIT_1x1: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_1x1;
|
||||
|
||||
/// [`NcBlitter`] mode using: halves + 1x1 (space)
|
||||
/// ▄▀
|
||||
pub const NCBLIT_2x1: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_2x1;
|
||||
|
||||
/// [`NcBlitter`] mode using: quadrants + 2x1
|
||||
/// ▗▐ ▖▀▟▌▙
|
||||
pub const NCBLIT_2x2: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_2x2;
|
||||
|
||||
/// [`NcBlitter`] mode using: sextants
|
||||
/// 🬀🬁🬂🬃🬄🬅🬆🬇🬈🬉🬊🬋🬌🬍🬎🬏🬐🬑🬒🬓🬔🬕🬖🬗🬘🬙🬚🬛🬜🬝🬞🬟🬠🬡🬢🬣🬤🬥🬦🬧🬨🬩🬪🬫🬬🬭🬮🬯🬰🬱🬲🬳🬴🬵🬶🬷🬸🬹🬺🬻
|
||||
pub const NCBLIT_3x2: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_3x2;
|
||||
|
||||
/// [`NcBlitter`] mode using: four vertical levels
|
||||
/// █▆▄▂
|
||||
pub const NCBLIT_4x1: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_4x1;
|
||||
|
||||
/// [`NcBlitter`] mode using: eight vertical levels
|
||||
/// █▇▆▅▄▃▂▁
|
||||
pub const NCBLIT_8x1: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_8x1;
|
||||
|
||||
/// [`NcBlitter`] mode using: 4 rows, 2 cols (braille)
|
||||
/// ⡀⡄⡆⡇⢀⣀⣄⣆⣇⢠⣠⣤⣦⣧⢰⣰⣴⣶⣷⢸⣸⣼⣾⣿
|
||||
pub const NCBLIT_BRAILLE: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_BRAILLE;
|
||||
|
||||
/// [`NcBlitter`] mode where the blitter is automatically chosen
|
||||
pub const NCBLIT_DEFAULT: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_DEFAULT;
|
||||
|
||||
/// Sixel/Pixel mode
|
||||
///
|
||||
/// NCBLIT_PIXEL
|
||||
///
|
||||
/// See [Sixel in Wikipedia](https://en.wikipedia.org/wiki/Sixel).
|
||||
pub const NCBLIT_PIXEL: NcBlitter = crate::bindings::ffi::ncblitter_e_NCBLIT_PIXEL;
|
||||
|
||||
/// Contains the pixel geometry information as returned by the
|
||||
/// NcPlane.[pixelgeom()][crate::NcPlane#method.pixelgeom] method.
|
||||
///
|
||||
/// If bitmaps are not supported, the fields `max_bitmap_*` will be 0.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NcPixelGeometry {
|
||||
/// Geometry of the display region
|
||||
pub term_y: NcDim,
|
||||
pub term_x: NcDim,
|
||||
pub cell_y: NcDim,
|
||||
pub cell_x: NcDim,
|
||||
pub max_bitmap_y: NcDim,
|
||||
pub max_bitmap_x: NcDim,
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
use core::ptr::null_mut;
|
||||
|
||||
use crate::{
|
||||
cstring, error, error_ref_mut, error_str, ncmenu_create,
|
||||
widgets::{NcMenu, NcMenuOptions},
|
||||
NcInput, NcPlane, NcResult,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::widgets::{NcMenuItem, NcMenuSection};
|
||||
|
||||
/// # `NcMenu` constructors & destructors
|
||||
impl NcMenu {
|
||||
/// Creates an [`NcMenu`] with the specified options.
|
||||
///
|
||||
/// Menus are currently bound to an overall [`Notcurses`][crate::Notcurses]
|
||||
/// object (as opposed to a particular plane), and are implemented as
|
||||
/// [`NcPlane`]s kept atop other NcPlanes.
|
||||
///
|
||||
/// *C style function: [ncmenu_create()][crate::ncmenu_create].*
|
||||
pub fn new<'a>(plane: &mut NcPlane, options: NcMenuOptions) -> NcResult<&'a mut Self> {
|
||||
error_ref_mut![unsafe { ncmenu_create(plane, &options) }, "Creating NcMenu"]
|
||||
}
|
||||
|
||||
/// Destroys an `NcMenu` created with [`new`][NcMenu#method.new].
|
||||
///
|
||||
/// *C style function: [ncmenu_destroy()][crate::ncmenu_destroy].*
|
||||
pub fn destroy(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_destroy(self) }]
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcMenu` methods
|
||||
impl NcMenu {
|
||||
/// Disables or enables an [`NcMenuItem`].
|
||||
///
|
||||
/// *C style function: [ncmenu_item_set_status()][crate::ncmenu_item_set_status].*
|
||||
pub fn item_set_status(&mut self, section: &str, item: &str, enabled: bool) -> NcResult<()> {
|
||||
error![
|
||||
unsafe {
|
||||
crate::ncmenu_item_set_status(self, cstring![section], cstring![item], enabled)
|
||||
},
|
||||
&format!(
|
||||
".item_set_status({:?}, {:?}, {:?}, {})",
|
||||
self, section, item, enabled
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/// Returns the [`NcMenuItem`] description
|
||||
/// corresponding to the mouse `click`.
|
||||
///
|
||||
/// The NcMenuItem must be on an actively unrolled section, and the click
|
||||
/// must be in the area of a valid item.
|
||||
///
|
||||
/// If `ninput` is provided, and the selected item has a shortcut,
|
||||
/// it will be filled in with that shortcut.
|
||||
///
|
||||
/// *C style function: [ncmenu_mouse_selected()][crate::ncmenu_mouse_selected].*
|
||||
pub fn mouse_selected(
|
||||
&self,
|
||||
click: NcInput,
|
||||
shortcut: Option<&mut NcInput>,
|
||||
) -> NcResult<String> {
|
||||
let ninput;
|
||||
if let Some(i) = shortcut {
|
||||
ninput = i as *mut _;
|
||||
} else {
|
||||
ninput = null_mut();
|
||||
}
|
||||
error_str![
|
||||
unsafe { crate::ncmenu_mouse_selected(self, &click, ninput) },
|
||||
"Getting NcMenuItem description"
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves to the next item within the currently unrolled section.
|
||||
///
|
||||
/// If no section is unrolled, the first section will be unrolled.
|
||||
///
|
||||
/// *C style function: [ncmenu_nextitem()][crate::ncmenu_nextitem].*
|
||||
pub fn nextitem(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_nextitem(self) }]
|
||||
}
|
||||
|
||||
/// Unrolls the next section (relative to current unrolled).
|
||||
///
|
||||
/// If no section is unrolled, the first section will be unrolled.
|
||||
///
|
||||
/// *C style function: [ncmenu_nextsection()][crate::ncmenu_nextsection].*
|
||||
pub fn nextsection(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_nextsection(self) }]
|
||||
}
|
||||
|
||||
/// Offers the `input` to this `NcMenu`.
|
||||
///
|
||||
/// If it's relevant, this function returns true,
|
||||
/// and the input ought not be processed further.
|
||||
/// If it's irrelevant to the menu, false is returned.
|
||||
///
|
||||
/// Relevant inputs include:
|
||||
/// - mouse movement over a hidden menu
|
||||
/// - a mouse click on a menu section (the section is unrolled)
|
||||
/// - a mouse click outside of an unrolled menu (the menu is rolled up)
|
||||
/// - left or right on an unrolled menu (navigates among sections)
|
||||
/// - up or down on an unrolled menu (navigates among items)
|
||||
/// - escape on an unrolled menu (the menu is rolled up)
|
||||
///
|
||||
/// *C style function: [ncmenu_offer_input()][crate::ncmenu_offer_input].*
|
||||
pub fn offer_input(&mut self, input: NcInput) -> bool {
|
||||
unsafe { crate::ncmenu_offer_input(self, &input) }
|
||||
}
|
||||
|
||||
/// Returns the [`NcPlane`] backing this `NcMenu`.
|
||||
///
|
||||
/// *C style function: [ncmenu_plane()][crate::ncmenu_plane].*
|
||||
pub fn plane(&mut self) -> NcResult<&NcPlane> {
|
||||
error_ref_mut![
|
||||
unsafe { crate::ncmenu_plane(self) },
|
||||
"Getting the backing NcPlane"
|
||||
]
|
||||
}
|
||||
|
||||
/// Moves to the previous item within the currently unrolled section.
|
||||
///
|
||||
/// If no section is unrolled, the first section will be unrolled.
|
||||
///
|
||||
/// *C style function: [ncmenu_previtem()][crate::ncmenu_previtem].*
|
||||
pub fn previtem(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_previtem(self) }]
|
||||
}
|
||||
|
||||
/// Unrolls the previous section (relative to current unrolled).
|
||||
///
|
||||
/// If no section is unrolled, the first section will be unrolled.
|
||||
///
|
||||
/// *C style function: [ncmenu_prevsection()][crate::ncmenu_prevsection].*
|
||||
pub fn prevsection(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_prevsection(self) }]
|
||||
}
|
||||
|
||||
/// Rolls up any unrolled [`NcMenuSection`]
|
||||
/// and hides this `NcMenu` if using hiding.
|
||||
///
|
||||
/// *C style function: [ncmenu_rollup()][crate::ncmenu_rollup].*
|
||||
pub fn rollup(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_rollup(self) }]
|
||||
}
|
||||
|
||||
/// Returns the selected item description, if there's an unrolled section.
|
||||
///
|
||||
/// If `shortcut` is provided, and the selected item has a shortcut,
|
||||
/// it will be filled in with that shortcut--this can allow faster matching.
|
||||
///
|
||||
/// *C style function: [ncmenu_selected()][crate::ncmenu_selected].*
|
||||
pub fn selected(&mut self, shortcut: Option<&mut NcInput>) -> Option<String> {
|
||||
let ninput;
|
||||
if let Some(i) = shortcut {
|
||||
ninput = i as *mut _;
|
||||
} else {
|
||||
ninput = null_mut();
|
||||
}
|
||||
let res = unsafe { crate::ncmenu_selected(self, ninput) };
|
||||
if !res.is_null() {
|
||||
Some(unsafe { (&*res).to_string() })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Unrolls the specified [`NcMenuSection`],
|
||||
/// making the menu visible if it was invisible
|
||||
/// and rolling up any `NcMenuSection` that is already unrolled.
|
||||
///
|
||||
/// *C style function: [ncmenu_unroll()][crate::ncmenu_unroll].*
|
||||
pub fn unroll(&mut self, sectionindex: u32) -> NcResult<()> {
|
||||
error![unsafe { crate::ncmenu_unroll(self, sectionindex as i32) }]
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
//! `NcMenu*` methods and associated functions.
|
||||
|
||||
use super::{NcMenuItem, NcMenuSection};
|
||||
use crate::{cstring_mut, NcInput};
|
||||
use core::ptr::null_mut;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::widgets::NcMenu;
|
||||
|
||||
mod menu;
|
||||
mod options;
|
||||
|
||||
pub use menu::*;
|
||||
pub use options::*;
|
||||
|
||||
/// # `NcMenuItem` Constructors
|
||||
impl NcMenuItem {
|
||||
/// New NcMenuItem for [`NcMenu`].
|
||||
pub fn new(desc: &str, shortcut: NcInput) -> Self {
|
||||
Self {
|
||||
// utf-8 menu item, NULL for horizontal separator
|
||||
desc: cstring_mut![desc],
|
||||
|
||||
// ´NcInput´ shortcut, all should be distinct
|
||||
shortcut,
|
||||
}
|
||||
}
|
||||
|
||||
/// New empty NcMenuItem for [`NcMenu`].
|
||||
pub fn new_empty() -> Self {
|
||||
Self {
|
||||
desc: null_mut(),
|
||||
shortcut: NcInput::new_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcMenuSection` Constructors
|
||||
///
|
||||
// Must contain at least 1 NcMenuItem.
|
||||
impl NcMenuSection {
|
||||
/// New NcMenuSection for [`NcMenu`].
|
||||
pub fn new(name: &str, items: &mut [NcMenuItem], shortcut: NcInput) -> Self {
|
||||
Self {
|
||||
// utf-8 name string
|
||||
name: cstring_mut![name],
|
||||
|
||||
// array of itemcount `NcMenuItem`s
|
||||
items: items.as_mut_ptr(),
|
||||
|
||||
//
|
||||
itemcount: items.len() as i32,
|
||||
|
||||
// shortcut, will be underlined if present in name
|
||||
shortcut,
|
||||
}
|
||||
}
|
||||
|
||||
/// New NcMenuSection separator for [`NcMenu`].
|
||||
///
|
||||
pub fn new_separator() -> Self {
|
||||
Self {
|
||||
name: null_mut(),
|
||||
items: null_mut(),
|
||||
itemcount: 0,
|
||||
shortcut: NcInput::new_empty(),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
use crate::{
|
||||
widgets::{NcMenuOptions, NcMenuSection},
|
||||
NcChannels,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::widgets::NcMenu;
|
||||
|
||||
/// # `NcMenuOptions` constructors
|
||||
impl NcMenuOptions {
|
||||
/// New NcMenuOptions for [`NcMenu`].
|
||||
///
|
||||
/// `sections` must contain at least 1 [`NcMenuSection`].
|
||||
pub fn new(sections: &mut [NcMenuSection]) -> Self {
|
||||
Self::with_all_args(sections, 0, 0, 0)
|
||||
}
|
||||
|
||||
/// New NcMenuOptions for [`NcMenu`], with all args.
|
||||
///
|
||||
/// `sections` must contain at least 1 [`NcMenuSection`].
|
||||
pub fn with_all_args(
|
||||
sections: &mut [NcMenuSection],
|
||||
style_header: NcChannels,
|
||||
style_sections: NcChannels,
|
||||
flags: u64,
|
||||
) -> Self {
|
||||
assert![!sections.is_empty()];
|
||||
Self {
|
||||
// array of 'sectioncount' `MenuSection`s
|
||||
sections: sections.as_mut_ptr(),
|
||||
|
||||
//
|
||||
sectioncount: sections.len() as i32,
|
||||
|
||||
// styling for header
|
||||
headerchannels: style_header,
|
||||
|
||||
// styling for sections
|
||||
sectionchannels: style_sections,
|
||||
|
||||
// flag word of NCMENU_OPTION_*
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcMenuOptions` methods
|
||||
impl NcMenuOptions {
|
||||
/// Returns the styling for the header.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub const fn header_channels(&self) -> NcChannels {
|
||||
self.headerchannels
|
||||
}
|
||||
|
||||
/// Returns a mutable reference of the styling for the sections.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn header_channels_mut(&mut self) -> &mut NcChannels {
|
||||
&mut self.headerchannels
|
||||
}
|
||||
|
||||
/// Returns the styling for the sections.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub const fn section_channels(&self) -> NcChannels {
|
||||
self.sectionchannels
|
||||
}
|
||||
|
||||
/// Returns a mutable reference of the styling for the sections.
|
||||
///
|
||||
/// *(No equivalent C style function)*
|
||||
pub fn section_channels_mut(&mut self) -> &mut NcChannels {
|
||||
&mut self.sectionchannels
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
//! `NcMenu` widget
|
||||
|
||||
// functions already exported by bindgen : 13
|
||||
// ------------------------------------------
|
||||
// (#) test: 0
|
||||
// (W) wrap: 13
|
||||
// ------------------------------------------
|
||||
//W ncmenu_create
|
||||
//W ncmenu_destroy
|
||||
//W ncmenu_item_set_status
|
||||
//W ncmenu_mouse_selected
|
||||
//W ncmenu_nextitem
|
||||
//W ncmenu_nextsection
|
||||
//W ncmenu_offer_input
|
||||
//W ncmenu_plane
|
||||
//W ncmenu_previtem
|
||||
//W ncmenu_prevsection
|
||||
//W ncmenu_rollup
|
||||
//W ncmenu_selected
|
||||
//W ncmenu_unroll
|
||||
|
||||
mod methods;
|
||||
|
||||
/// menus on the top or bottom rows
|
||||
///
|
||||
/// A [Notcurses][crate::Notcurses] instance supports menu bars on the top or
|
||||
/// bottom row of the true screen.
|
||||
///
|
||||
/// An NcMenu is composed of [NcMenuSection]s, which are in turn composed of
|
||||
/// [NcMenuItem]s.
|
||||
///
|
||||
/// Either no sections are visible, and the menu is rolled up, or exactly one
|
||||
/// section is unrolled.
|
||||
///
|
||||
/// - [rollup()][NcMenu#method.rollup]
|
||||
/// places an `NcMenu` in the rolled up state.
|
||||
/// - [unroll()][NcMenu#method.unroll]
|
||||
/// rolls up any unrolled section and unrolls the specified one.
|
||||
/// - [destroy()][NcMenu#method.destroy]
|
||||
/// removes a menu bar, and frees all associated resources.
|
||||
///
|
||||
/// `type in C: ncmenu (struct)`
|
||||
pub type NcMenu = crate::bindings::ffi::ncmenu;
|
||||
|
||||
/// Options struct for [`NcMenu`].
|
||||
pub type NcMenuOptions = crate::bindings::ffi::ncmenu_options;
|
||||
|
||||
/// Item for [`NcMenu`].
|
||||
pub type NcMenuItem = crate::bindings::ffi::ncmenu_item;
|
||||
|
||||
/// Section for [`NcMenu`].
|
||||
pub type NcMenuSection = crate::bindings::ffi::ncmenu_section;
|
||||
|
||||
/// [NcMenuOptions] flag: Bottom row (as opposed to top row).
|
||||
pub const NCMENU_OPTION_BOTTOM: u64 = crate::bindings::ffi::NCMENU_OPTION_BOTTOM as u64;
|
||||
|
||||
/// [NcMenuOptions] flag: Hide the menu when not unrolled
|
||||
pub const NCMENU_OPTION_HIDING: u64 = crate::bindings::ffi::NCMENU_OPTION_HIDING as u64;
|
@ -1,19 +0,0 @@
|
||||
//! All the notcurses widgets.
|
||||
|
||||
mod menu;
|
||||
mod multiselector;
|
||||
mod plot;
|
||||
mod progbar;
|
||||
mod reader;
|
||||
mod reel;
|
||||
mod selector;
|
||||
mod tree;
|
||||
|
||||
pub use menu::*;
|
||||
pub use multiselector::*;
|
||||
pub use plot::*;
|
||||
pub use progbar::*;
|
||||
pub use reader::*;
|
||||
pub use reel::*;
|
||||
pub use selector::*;
|
||||
pub use tree::*;
|
@ -1,10 +0,0 @@
|
||||
//! `NcMultiSelector` widget.
|
||||
|
||||
/// high-level widget for selecting items from a set
|
||||
pub type NcMultiSelector = crate::bindings::ffi::ncmultiselector;
|
||||
|
||||
/// an item for [`NcMultiSelector`]
|
||||
pub type NcMultiSelectorItem = crate::bindings::ffi::ncmselector_item;
|
||||
|
||||
/// Options structure for [`NcMultiSelector`]
|
||||
pub type NcMultiSelectorOptions = crate::bindings::ffi::ncmultiselector_options;
|
@ -1,27 +0,0 @@
|
||||
//! `NcPlot[F|U]64` widget.
|
||||
|
||||
/// A histogram, bound to an [`NcPlane`][crate::NcPlane]
|
||||
/// (uses non-negative `f64`s)
|
||||
pub type NcPlotF64 = crate::bindings::ffi::ncdplot;
|
||||
|
||||
/// A histogram, bound to an [`NcPlane`][crate::NcPlane] (uses `u64`s)
|
||||
pub type NcPlotU64 = crate::bindings::ffi::ncuplot;
|
||||
|
||||
/// Options struct for
|
||||
/// [`NcPlotF64`] or [`NcPlotU64`]
|
||||
pub type NcPlotOptions = crate::bindings::ffi::ncplot_options;
|
||||
|
||||
/// Use domain detection only for max
|
||||
pub const NCPLOT_OPTION_DETECTMAXONLY: u32 = crate::bindings::ffi::NCPLOT_OPTION_DETECTMAXONLY;
|
||||
|
||||
/// Exponential dependent axis
|
||||
pub const NCPLOT_OPTION_EXPONENTIALD: u32 = crate::bindings::ffi::NCPLOT_OPTION_EXPONENTIALD;
|
||||
|
||||
/// Show labels for dependent axis
|
||||
pub const NCPLOT_OPTION_LABELTICKSD: u32 = crate::bindings::ffi::NCPLOT_OPTION_LABELTICKSD;
|
||||
|
||||
/// Use domain detection only for max
|
||||
pub const NCPLOT_OPTION_NODEGRADE: u32 = crate::bindings::ffi::NCPLOT_OPTION_NODEGRADE;
|
||||
|
||||
/// Independent axis is vertical
|
||||
pub const NCPLOT_OPTION_VERTICALI: u32 = crate::bindings::ffi::NCPLOT_OPTION_VERTICALI;
|
@ -1,68 +0,0 @@
|
||||
//! `NcProgBar` & `NcProgBarOptions` methods and associated functions.
|
||||
|
||||
use super::{NcProgBar, NcProgBarOptions};
|
||||
use crate::{error, NcPlane, NcResult};
|
||||
|
||||
/// # `NcProgBarOptions` Methods
|
||||
impl NcProgBarOptions {
|
||||
/// New NcProgBarOptions for [NcProgBar].
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ulchannel: 0,
|
||||
urchannel: 0,
|
||||
blchannel: 0,
|
||||
brchannel: 0,
|
||||
flags: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcProgBar` Methods
|
||||
impl NcProgBar {
|
||||
/// New NcProgBar.
|
||||
///
|
||||
/// Takes ownership of the `plane`, which will be destroyed by
|
||||
/// [destroy][NcProgBar#method.destroy](). The progress bar is initially at 0%.
|
||||
pub fn new<'a>(plane: &mut NcPlane) -> &'a mut Self {
|
||||
Self::with_options(plane, &NcProgBarOptions::new())
|
||||
}
|
||||
|
||||
/// New NcProgBar. Expects an [NcProgBarOptions] struct.
|
||||
///
|
||||
/// *C style function: [ncprogbar_create()][crate::ncprogbar_create].*
|
||||
pub fn with_options<'a>(plane: &mut NcPlane, options: &NcProgBarOptions) -> &'a mut Self {
|
||||
unsafe { &mut *crate::ncprogbar_create(plane, options) }
|
||||
}
|
||||
|
||||
/// Destroy the progress bar and its underlying ncplane.
|
||||
///
|
||||
/// *C style function: [ncprogbar_destroy()][crate::ncprogbar_destroy].*
|
||||
pub fn destroy(&mut self) {
|
||||
unsafe {
|
||||
crate::ncprogbar_destroy(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a reference to the ncprogbar's underlying ncplane.
|
||||
///
|
||||
/// *C style function: [ncprogbar_plane()][crate::ncprogbar_plane].*
|
||||
pub fn plane(&mut self) -> &mut NcPlane {
|
||||
unsafe { &mut *crate::ncprogbar_plane(self) }
|
||||
}
|
||||
|
||||
/// Get the progress bar's completion, an [f64] on [0, 1].
|
||||
///
|
||||
/// *C style function: [ncprogbar_progress()][crate::ncprogbar_progress].*
|
||||
pub fn progress(&self) -> f64 {
|
||||
unsafe { crate::ncprogbar_progress(self) }
|
||||
}
|
||||
|
||||
/// Sets the progress bar's completion, an 0 <= [f64] <= 1.
|
||||
///
|
||||
/// Returns [NCRESULT_ERR][crate::NCRESULT_ERR] if progress is < 0 || > 1.
|
||||
///
|
||||
/// *C style function: [ncprogbar_set_progress()][crate::ncprogbar_set_progress].*
|
||||
pub fn set_progress(&mut self, progress: f64) -> NcResult<()> {
|
||||
error![unsafe { crate::ncprogbar_set_progress(self, progress) }]
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
//! `NcProgbar` widget.
|
||||
|
||||
// functions already exported by bindgen : 5
|
||||
// -----------------------------------------
|
||||
// (#) test: 0
|
||||
// (W) wrap: 5 / 0
|
||||
// -----------------------------------------
|
||||
//W ncprogbar_create,
|
||||
//W ncprogbar_destroy,
|
||||
//W ncprogbar_plane,
|
||||
//W ncprogbar_progress,
|
||||
//W ncprogbar_set_progress,
|
||||
|
||||
mod methods;
|
||||
|
||||
/// Progress bars. They proceed linearly in any of four directions.
|
||||
///
|
||||
/// The entirety of the plane will be used -- any border should be provided by
|
||||
/// the caller on another plane.
|
||||
///
|
||||
/// The plane will not be erased; text preloaded into the plane will be consumed
|
||||
/// by the progress indicator.
|
||||
///
|
||||
/// The bar is redrawn for each provided progress report (a double between 0
|
||||
/// and 1), and can regress with lower values.
|
||||
///
|
||||
/// The procession will take place along the longer dimension at the time of each
|
||||
/// redraw, with the horizontal length scaled by 2 for purposes of comparison.
|
||||
/// I.e. for a plane of 20 rows and 50 columns, the progress will be to the
|
||||
/// right (50 > 40), or left with [NCPROGBAR_OPTION_RETROGRADE].
|
||||
///
|
||||
/// `type in C: ncprogbar (struct)`
|
||||
///
|
||||
pub type NcProgBar = crate::bindings::ffi::ncprogbar;
|
||||
|
||||
/// Options struct for [`NcProgBar`]
|
||||
///
|
||||
/// `type in C: ncprogbar_options (struct)`
|
||||
///
|
||||
pub type NcProgBarOptions = crate::bindings::ffi::ncprogbar_options;
|
||||
|
||||
/// proceed left/down
|
||||
pub const NCPROGBAR_OPTION_RETROGRADE: u32 = crate::bindings::ffi::NCPROGBAR_OPTION_RETROGRADE;
|
@ -1,35 +0,0 @@
|
||||
//! `NcReader*` methods and associated functions.
|
||||
|
||||
use super::{NcReader, NcReaderOptions};
|
||||
use crate::{error_ref_mut, ncreader_create, NcPlane, NcResult};
|
||||
|
||||
/// # `NcReaderOptions` Constructors
|
||||
impl NcReaderOptions {
|
||||
/// `NcReaderOptions` simple constructor
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
// channels used for input
|
||||
tchannels: 0,
|
||||
// attributes used for input
|
||||
tattrword: 0,
|
||||
// bitfield of NCREADER_OPTION_*
|
||||
flags: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcReader` Constructors
|
||||
impl NcReader {
|
||||
/// `NcReader` simple constructor
|
||||
pub fn new<'a>(plane: &mut NcPlane) -> NcResult<&'a mut Self> {
|
||||
Self::with_options(plane, NcReaderOptions::new())
|
||||
}
|
||||
|
||||
/// `NcReader` constructor with options
|
||||
pub fn with_options<'a>(
|
||||
plane: &mut NcPlane,
|
||||
options: NcReaderOptions,
|
||||
) -> NcResult<&'a mut Self> {
|
||||
error_ref_mut![unsafe { ncreader_create(plane, &options) }]
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
//! `NcReader` widget.
|
||||
|
||||
// functions already exported by bindgen : 11
|
||||
// ------------------------------------------
|
||||
// ncreader_clear
|
||||
// ncreader_contents
|
||||
// ncreader_create
|
||||
// ncreader_destroy
|
||||
// ncreader_move_down
|
||||
// ncreader_move_left
|
||||
// ncreader_move_right
|
||||
// ncreader_move_up
|
||||
// ncreader_offer_input
|
||||
// ncreader_plane
|
||||
// ncreader_write_egc
|
||||
|
||||
mod methods;
|
||||
|
||||
/// Provides a freeform input in a (possibly multiline) region
|
||||
///
|
||||
/// Supports optional readline keybindings (opt out using
|
||||
/// NCREADER_OPTION_NOCMDKEYS flag)
|
||||
///
|
||||
/// Takes ownership of its [`NcPlane`][crate::NcPlane], destroying it on any
|
||||
/// error (`ncreader_destroy`() otherwise destroys the ncplane).
|
||||
///
|
||||
/// `type in C: ncreader (struct)`
|
||||
///
|
||||
pub type NcReader = crate::bindings::ffi::ncreader;
|
||||
|
||||
/// Options struct for [`NcReader`]
|
||||
///
|
||||
/// `type in C: ncreader_options (struct)`
|
||||
///
|
||||
pub type NcReaderOptions = crate::bindings::ffi::ncreader_options;
|
||||
|
||||
/// Make the terminal cursor visible across the lifetime of the ncreader, and
|
||||
/// have the ncreader manage the cursor's placement.
|
||||
pub const NCREADER_OPTION_CURSOR: u32 = crate::bindings::ffi::NCREADER_OPTION_CURSOR;
|
||||
|
||||
/// Enable horizontal scrolling. Virtual lines can then grow arbitrarily long.
|
||||
pub const NCREADER_OPTION_HORSCROLL: u32 = crate::bindings::ffi::NCREADER_OPTION_HORSCROLL;
|
||||
|
||||
/// Disable all editing shortcuts. By default, emacs-style keys are available.
|
||||
pub const NCREADER_OPTION_NOCMDKEYS: u32 = crate::bindings::ffi::NCREADER_OPTION_NOCMDKEYS;
|
||||
|
||||
/// Enable vertical scrolling. You can then use arbitrarily many virtual lines.
|
||||
pub const NCREADER_OPTION_VERSCROLL: u32 = crate::bindings::ffi::NCREADER_OPTION_VERSCROLL;
|
@ -1,32 +0,0 @@
|
||||
//! `NcReel` widget.
|
||||
|
||||
/// A wheel with [`NcTablet`]s on the outside.
|
||||
///
|
||||
/// An `NcReel` is projected onto the 2d rendering area, showing some portion of
|
||||
/// the `NcReel`, and zero or more `NcTablet`s.
|
||||
///
|
||||
/// An `NcReel` is a [`Notcurses`][crate::Notcurses] region devoted to
|
||||
/// displaying zero or more line-oriented, contained [`NcTablet`]s
|
||||
/// between which the user may navigate.
|
||||
///
|
||||
/// If at least one `NcTablet`s exists, there is a "focused tablet".
|
||||
/// As much of the focused tablet as is possible is always displayed.
|
||||
///
|
||||
/// If there is space left over, other tablets are included in the display.
|
||||
/// Tablets can come and go at any time, and can grow or shrink at any time.
|
||||
pub type NcReel = crate::bindings::ffi::ncreel;
|
||||
|
||||
/// Options struct for [`NcReel`]
|
||||
pub type NcReelOptions = crate::bindings::ffi::ncreel_options;
|
||||
|
||||
/// Visual tablet for [`NcReel`]
|
||||
pub type NcTablet = crate::bindings::ffi::nctablet;
|
||||
|
||||
/// is navigation circular (does moving down from the last tablet move to the
|
||||
/// first, and vice versa)? only meaningful when infinitescroll is true. if
|
||||
/// infinitescroll is false, this must be false.
|
||||
pub const NCREEL_OPTION_CIRCULAR: u32 = crate::bindings::ffi::NCREEL_OPTION_CIRCULAR;
|
||||
/// is scrolling infinite (can one move down or up forever, or is an end
|
||||
/// reached?). if true, 'circular' specifies how to handle the special case of
|
||||
/// an incompletely-filled reel.
|
||||
pub const NCREEL_OPTION_INFINITESCROLL: u32 = crate::bindings::ffi::NCREEL_OPTION_INFINITESCROLL;
|
@ -1,10 +0,0 @@
|
||||
//! `NcSelector` widget.
|
||||
|
||||
/// high-level widget for selecting one item from a set
|
||||
pub type NcSelector = crate::bindings::ffi::ncselector;
|
||||
|
||||
/// an item for [`NcSelector`]
|
||||
pub type NcSelectorItem = crate::bindings::ffi::ncselector_item;
|
||||
|
||||
/// Options structur for [`NcSelector`]
|
||||
pub type NcSelectorOptions = crate::bindings::ffi::ncselector_options;
|
@ -1,32 +0,0 @@
|
||||
//! `NcTree*` methods and associated functions.
|
||||
|
||||
mod options;
|
||||
mod tree;
|
||||
|
||||
pub use options::*;
|
||||
pub use tree::*;
|
||||
|
||||
use core::ptr::null_mut;
|
||||
use std::ffi::{c_void, CString};
|
||||
|
||||
use super::NcTreeItem;
|
||||
|
||||
/// # `NcTreeItem` constructor
|
||||
impl NcTreeItem {
|
||||
/// Creates an [NcTreeItem].
|
||||
pub fn new(curry: &str, subs: Option<&mut [NcTreeItem]>, subcount: usize) -> Self {
|
||||
if let Some(subs) = subs {
|
||||
Self {
|
||||
curry: CString::new(curry).unwrap().into_raw() as *mut _ as *mut c_void,
|
||||
subs: subs.as_mut_ptr(),
|
||||
subcount: subcount as u32,
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
curry: CString::new(curry).unwrap().into_raw() as *mut _ as *mut c_void,
|
||||
subs: null_mut(),
|
||||
subcount: subcount as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
use crate::{
|
||||
widgets::{NcTreeItem, NcTreeItemCbUnsafe, NcTreeOptions},
|
||||
NcDim,
|
||||
};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use crate::widgets::NcTree;
|
||||
|
||||
/// # `NcTreeOptions` constructors
|
||||
impl NcTreeOptions {
|
||||
/// New NcTreeOptions for [`NcTree`].
|
||||
pub fn new(items: &[NcTreeItem], indentcols: NcDim) -> Self {
|
||||
Self::with_all_args(items, items.len(), None, indentcols, 0)
|
||||
}
|
||||
|
||||
/// New NcTreeOptions for [`NcTree`], with all args.
|
||||
pub fn with_all_args(
|
||||
// top-level nctree_item array
|
||||
items: &[NcTreeItem],
|
||||
|
||||
// size of |items|
|
||||
count: usize,
|
||||
|
||||
// item callback function
|
||||
// TODO: use NcTreeItemCb and convert to NcTreeItemCbUnsafe
|
||||
nctreecb: Option<NcTreeItemCbUnsafe>,
|
||||
|
||||
// columns to indent per level of hierarchy
|
||||
indentcols: NcDim,
|
||||
|
||||
// bitfield of `NCTREE_OPTION_*` (there's none for now)
|
||||
flags: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
items: items as *const _ as *const NcTreeItem,
|
||||
count: count as u32,
|
||||
nctreecb,
|
||||
indentcols: indentcols as i32,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
use crate::{
|
||||
error, error_ref_mut, nctree_create,
|
||||
widgets::{NcTree, NcTreeItem, NcTreeOptions},
|
||||
NcError, NcInput, NcPlane, NcResult, NCRESULT_ERR,
|
||||
};
|
||||
|
||||
/// # `NcTree` constructors & destructors
|
||||
impl NcTree {
|
||||
/// Creates an [NcTree] with the specified options.
|
||||
///
|
||||
/// *C style function: [nctree_create()][crate::nctree_create].*
|
||||
pub fn new<'a>(plane: &mut NcPlane, options: NcTreeOptions) -> NcResult<&'a mut Self> {
|
||||
error_ref_mut![unsafe { nctree_create(plane, &options) }, "Creating NcTree"]
|
||||
}
|
||||
|
||||
/// Destroys an NcTree created with [new()][NcTree#method.new].
|
||||
///
|
||||
/// *C style function: [nctree_destroy()][crate::nctree_destroy].*
|
||||
pub fn destroy(&mut self) {
|
||||
unsafe { crate::nctree_destroy(self) };
|
||||
}
|
||||
}
|
||||
|
||||
/// # `NcTree` methods
|
||||
impl NcTree {
|
||||
// NOTE: not implemented yet in C API
|
||||
//
|
||||
// /// Goes to the item specified by the array |spec|, terminated by UINT_MAX.
|
||||
// ///
|
||||
// /// If the spec is invalid, returns an error and the depth of the first
|
||||
// /// invalid spec is written to *|failspec|.
|
||||
// ///
|
||||
// /// Otherwise, the true depth is written to *|failspec|,
|
||||
// /// and the curry is returned (|failspec| is necessary because the
|
||||
// /// curry could itself be NULL).
|
||||
// ///
|
||||
// /// *C style function: [nctree_goto()][crate::nctree_goto].*
|
||||
// pub fn goto(&mut self, spec: ... , failspec: ...) -> NcResult<&mut NcTreeItem> {
|
||||
// let res = unsafe { crate::nctree_goto(self) };
|
||||
// if !res.is_null() {
|
||||
// Ok(unsafe { &mut *(res as *mut NcTreeItem) })
|
||||
// } else {
|
||||
// Err(NcError::with_msg(NCRESULT_ERR, "NcTree.goto()"))
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Returns the focused item, if any items are present.
|
||||
///
|
||||
/// This is not a copy; be careful to use it only for the duration of a
|
||||
/// critical section.
|
||||
///
|
||||
/// *C style function: [nctree_focused()][crate::nctree_focused].*
|
||||
pub fn focused(&mut self) -> NcResult<&mut NcTreeItem> {
|
||||
let res = unsafe { crate::nctree_focused(self) };
|
||||
if !res.is_null() {
|
||||
Ok(unsafe { &mut *(res as *mut NcTreeItem) })
|
||||
} else {
|
||||
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.focused()"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the focus to the next item, and returns it.
|
||||
///
|
||||
/// *C style function: [nctree_next()][crate::nctree_next].*
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn next(&mut self) -> NcResult<&mut NcTreeItem> {
|
||||
let res = unsafe { crate::nctree_next(self) };
|
||||
if !res.is_null() {
|
||||
Ok(unsafe { &mut *(res as *mut NcTreeItem) })
|
||||
} else {
|
||||
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.next()"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the focus to the previous item, and returns it.
|
||||
///
|
||||
/// *C style function: [nctree_prev()][crate::nctree_prev].*
|
||||
pub fn prev(&mut self) -> NcResult<&mut NcTreeItem> {
|
||||
let res = unsafe { crate::nctree_prev(self) };
|
||||
if !res.is_null() {
|
||||
Ok(unsafe { &mut *(res as *mut NcTreeItem) })
|
||||
} else {
|
||||
Err(NcError::with_msg(NCRESULT_ERR, "NcTree.prev()"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Offers the `input` to this NcTree.
|
||||
///
|
||||
/// If it's relevant, this function returns true,
|
||||
/// and the input ought not be processed further.
|
||||
/// If it's irrelevant to the tree, false is returned.
|
||||
///
|
||||
/// Relevant inputs include:
|
||||
///
|
||||
/// - a mouse click on an item (focuses item)
|
||||
/// - a mouse scrollwheel event (srolls tree)
|
||||
/// - up, down, pgup, or pgdown (navigates among items)
|
||||
///
|
||||
/// *C style function: [nctree_offer_input()][crate::nctree_offer_input].*
|
||||
pub fn offer_input(&mut self, input: NcInput) -> bool {
|
||||
unsafe { crate::nctree_offer_input(self, &input) }
|
||||
}
|
||||
|
||||
/// Returns the [NcPlane] backing this NcTree.
|
||||
///
|
||||
/// *C style function: [nctree_plane()][crate::nctree_plane].*
|
||||
pub fn plane(&mut self) -> NcResult<&NcPlane> {
|
||||
error_ref_mut![unsafe { crate::nctree_plane(self) }, "NcTree.plane()"]
|
||||
}
|
||||
|
||||
/// Redraws the NcTree in its entirety.
|
||||
///
|
||||
/// The tree will be cleared, and items will be laid out, using the focused
|
||||
/// item as a fulcrum.
|
||||
///
|
||||
/// Item-drawing callbacks will be invoked for each visible item.
|
||||
///
|
||||
/// *C style function: [nctree_redraw()][crate::nctree_redraw].*
|
||||
pub fn redraw(&mut self) -> NcResult<()> {
|
||||
error![unsafe { crate::nctree_redraw(self) }, "NcTree.redraw()"]
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
//! `NcTree` widget
|
||||
|
||||
// functions already exported by bindgen : 13
|
||||
// ------------------------------------------
|
||||
// (#) test: 0
|
||||
// (W) wrap: 13
|
||||
// ------------------------------------------
|
||||
//W nctree_create,
|
||||
//W nctree_destroy,
|
||||
//W nctree_focused,
|
||||
//~ nctree_goto,
|
||||
//W nctree_next,
|
||||
//W nctree_offer_input,
|
||||
//W nctree_plane,
|
||||
//W nctree_prev,
|
||||
//W nctree_redraw,
|
||||
|
||||
use cty::c_int;
|
||||
use std::ffi::c_void;
|
||||
|
||||
use crate::NcPlane;
|
||||
|
||||
mod methods;
|
||||
|
||||
/// High-level hierarchical line-based data.
|
||||
///
|
||||
/// `NcTree`s organize static hierarchical items, and allow them to be browsed.
|
||||
///
|
||||
/// An NcTree cannot be empty, count must be non-zero.
|
||||
///
|
||||
/// - Each item can have arbitrary subitems.
|
||||
/// - Items can be collapsed and expanded.
|
||||
/// - The display supports scrolling and searching.
|
||||
/// - Items cannot be added or removed, however; they must be provided in their
|
||||
/// entirety at creation time.
|
||||
///
|
||||
/// NOTE: `NcTree` shares many properties with `NcReel`. Unlike the latter,
|
||||
/// `NcTree`s support arbitrary hierarchical levels, but they do not allow
|
||||
/// elements to come and go across the lifetime of the widget.
|
||||
///
|
||||
/// `type in C: nctree (struct)`
|
||||
pub type NcTree = crate::bindings::ffi::nctree;
|
||||
|
||||
/// Item for [`NcTree`].
|
||||
///
|
||||
/// each item has a curry, and zero or more subitems.
|
||||
pub type NcTreeItem = crate::bindings::ffi::nctree_item;
|
||||
|
||||
/// Options struct for [`NcTree`].
|
||||
pub type NcTreeOptions = crate::bindings::ffi::nctree_options;
|
||||
|
||||
// e.g.:
|
||||
//
|
||||
// ```c
|
||||
// int treecb(struct ncplane* n, void* curry, int pos){
|
||||
// ncplane_printf_yx(n, 0, 0, "item: %s pos: %d",
|
||||
// static_cast<const char*>(curry), pos);
|
||||
// return 0;
|
||||
// }
|
||||
// ```
|
||||
|
||||
/// An [NcTreeItem] callback function (unsafe).
|
||||
pub type NcTreeItemCbUnsafe = unsafe extern "C" fn(*mut NcPlane, *mut c_void, c_int) -> c_int;
|
||||
|
||||
/// An [NcTreeItem] callback function.
|
||||
pub type NcTreeItemCb = fn(&mut NcPlane, &str, i32);
|
||||
|
||||
// WIP TODO: create callback type and conversion functions
|
||||
//
|
||||
// /// Converts [NcTreeItemCbUnsafe] to [NcTreeItemCb].
|
||||
// pub fn nctreeitemcb_to_rust(resizecb: Option<NcTreeItemCbUnsafe>) -> Option<NcTreeItemCb> {
|
||||
// if let Some(cb) = resizecb {
|
||||
// return Some(unsafe { core::mem::transmute(cb) });
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// Converts [NcTreeItemCb] to [NcTreeItemCbUnsafe].
|
||||
// ///
|
||||
// // waiting for https://github.com/rust-lang/rust/issues/53605
|
||||
// // to make this function const, and then NcPlaneOptions constructors.
|
||||
// pub fn nctreeitemcb_to_c(resizecb: Option<NcTreeItemCb>) -> Option<NcTreeItemCbUnsafe> {
|
||||
// if let Some(cb) = resizecb {
|
||||
// return Some(unsafe { core::mem::transmute(cb) });
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
Loading…
x
Reference in New Issue
Block a user