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

pull/1280/head
nick black 4 years ago
commit 6855c07fd0
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -1606,7 +1606,7 @@ manner.
// play, and fully supports all transparency options. // play, and fully supports all transparency options.
typedef struct nccell { typedef struct nccell {
// These 32 bits, together with the associated plane's associated egcpool, // These 32 bits, together with the associated plane's associated egcpool,
// completely define this nccell's EGC. Unless the EGC requires more than four // completely define this cell's EGC. Unless the EGC requires more than four
// bytes to encode as UTF-8, it will be inlined here. If more than four bytes // bytes to encode as UTF-8, it will be inlined here. If more than four bytes
// are required, it will be spilled into the egcpool. In either case, there's // 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 // a NUL-terminated string available without copying, because (1) the egcpool
@ -1614,19 +1614,38 @@ typedef struct nccell {
// gcluster_backstop field, see below) is guaranteed to be zero, as are any // gcluster_backstop field, see below) is guaranteed to be zero, as are any
// unused bytes in gcluster. // unused bytes in gcluster.
// //
// The gcluster + gcluster_backstop thus form a valid C string of between 0
// and 4 non-NUL bytes. Interpreting them in this fashion requires that
// gcluster be stored as a little-endian number (strings have no byte order).
// This gives rise to three simple rules:
//
// * when storing to gcluster from a numeric, always use htole()
// * when loading from gcluster for numeric use, always use htole()
// * when referencing gcluster as a string, always use a pointer cast
//
// Uses of gcluster ought thus always have exactly one htole() or pointer
// cast associated with them, and we otherwise always work as host-endian.
//
// A spilled EGC is indicated by the value 0x01XXXXXX. This cannot alias a // A spilled EGC is indicated by the value 0x01XXXXXX. This cannot alias a
// true supra-ASCII EGC, because UTF-8 only encodes bytes <= 0x80 when they // true supra-ASCII EGC, because UTF-8 only encodes bytes <= 0x80 when they
// are single-byte ASCII-derived values. The XXXXXX is interpreted as a 24-bit // are single-byte ASCII-derived values. The XXXXXX is interpreted as a 24-bit
// index into the egcpool. These pools may thus be up to 16MB. // index into the egcpool. These pools may thus be up to 16MB.
// //
// The cost of this scheme is that the character 0x01 (SOH) cannot be encoded // The cost of this scheme is that the character 0x01 (SOH) cannot be encoded
// in a nccell, which is absolutely fine because what 70s horseshit is SOH? It // in a nccell, which is absolutely fine because what 70s horseshit is SOH?
// must not be allowed through the API, or havoc will result. // It must not be allowed through the API, or havoc will result.
uint32_t gcluster; // 4B → 4B uint32_t gcluster; // 4B → 4B little endian EGC
uint8_t gcluster_backstop; // 1B → 5B (8 bits of zero) uint8_t gcluster_backstop; // 1B → 5B (8 bits of zero)
uint8_t reserved; // 1B → 6B (8 reserved bits, ought be zero) // 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.
uint8_t width; // 1B → 6B (8 bits of EGC column width)
uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes) uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes)
// (channels & 0x8000000000000000ull): part of a wide glyph // (channels & 0x8000000000000000ull): reserved, must be 0
// (channels & 0x4000000000000000ull): foreground is *not* "default color" // (channels & 0x4000000000000000ull): foreground is *not* "default color"
// (channels & 0x3000000000000000ull): foreground alpha (2 bits) // (channels & 0x3000000000000000ull): foreground alpha (2 bits)
// (channels & 0x0800000000000000ull): foreground uses palette index // (channels & 0x0800000000000000ull): foreground uses palette index
@ -1647,7 +1666,6 @@ typedef struct nccell {
uint64_t channels; // + 8B == 16B uint64_t channels; // + 8B == 16B
} nccell; } nccell;
#define CELL_WIDEASIAN_MASK 0x8000000000000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull #define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_FGDEFAULT_MASK (CELL_BGDEFAULT_MASK << 32u) #define CELL_FGDEFAULT_MASK (CELL_BGDEFAULT_MASK << 32u)
#define CELL_BG_RGB_MASK 0x0000000000ffffffull #define CELL_BG_RGB_MASK 0x0000000000ffffffull
@ -1762,28 +1780,31 @@ cell_off_styles(nccell* c, unsigned stylebits){
c->stylemask &= ~(stylebits & NCSTYLE_MASK); c->stylemask &= ~(stylebits & NCSTYLE_MASK);
} }
// does the cell contain an East Asian Wide codepoint? // Is the cell part of a multicolumn element?
static inline bool static inline bool
cell_double_wide_p(const nccell* c){ cell_double_wide_p(const nccell* c){
return (c->channels & CELL_WIDEASIAN_MASK); return (c->width >= 2);
} }
// Load a 7-bit char 'ch' into the cell 'c'. // Load a 7-bit char 'ch' into the nccell 'c'. Returns the number of bytes
// used, or -1 on error.
static inline int static inline int
cell_load_char(struct ncplane* n, nccell* c, char ch){ cell_load_char(struct ncplane* n, nccell* c, char ch){
cell_release(n, c); char gcluster[2];
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK); gcluster[0] = ch;
c->gcluster = ch; gcluster[1] = '\0';
return 1; return cell_load(n, c, gcluster);
} }
// Load a UTF-8 encoded EGC of up to 4 bytes into the cell 'c'. // 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 static inline int
cell_load_egc32(struct ncplane* n, nccell* c, uint32_t egc){ cell_load_egc32(struct ncplane* n, nccell* c, uint32_t egc){
cell_release(n, c); char gcluster[sizeof(egc) + 1];
c->channels &= ~(CELL_WIDEASIAN_MASK | CELL_NOBACKGROUND_MASK); egc = htole(egc);
c->gcluster = htole(egc); memcpy(gcluster, &egc, sizeof(egc));
return 1; gcluster[4] = '\0';
return cell_load(n, c, gcluster);
} }
// return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer // return a pointer to the NUL-terminated EGC referenced by 'c'. this pointer

@ -15,7 +15,7 @@ notcurses_cell - operations on nccell objects
typedef struct nccell { typedef struct nccell {
uint32_t gcluster; // 4B → 4B uint32_t gcluster; // 4B → 4B
uint8_t gcluster_backstop; // 1B → 5B (8 bits of zero) uint8_t gcluster_backstop; // 1B → 5B (8 bits of zero)
uint8_t reserved; // 1B → 6B (8 reserved bits, ought be zero) uint8_t width; // 1B → 6B (8 bits of column width)
uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes) uint16_t stylemask; // 2B → 8B (16 bits of NCSTYLE_* attributes)
uint64_t channels; uint64_t channels;
} nccell; } nccell;
@ -27,7 +27,6 @@ typedef struct nccell {
#define CELL_INITIALIZER(c, s, chan) \ #define CELL_INITIALIZER(c, s, chan) \
{ .gcluster = (c), .stylemask = (s), .channels = (chan), } { .gcluster = (c), .stylemask = (s), .channels = (chan), }
#define CELL_WIDEASIAN_MASK 0x8000000080000000ull
#define CELL_BGDEFAULT_MASK 0x0000000040000000ull #define CELL_BGDEFAULT_MASK 0x0000000040000000ull
#define CELL_FGDEFAULT_MASK (CELL_BGDEFAULT_MASK << 32u) #define CELL_FGDEFAULT_MASK (CELL_BGDEFAULT_MASK << 32u)
#define CELL_BG_RGB_MASK 0x0000000000ffffffull #define CELL_BG_RGB_MASK 0x0000000000ffffffull

@ -55,7 +55,6 @@ pub use ffi::{
// CELL_FG_PALETTE, // CELL_FG_PALETTE,
// CELL_FG_RGB_MASK, // CELL_FG_RGB_MASK,
// CELL_NOBACKGROUND_MASK, // CELL_NOBACKGROUND_MASK,
// CELL_WIDEASIAN_MASK,
#[doc(inline)] #[doc(inline)]
pub use ffi::{ pub use ffi::{

@ -406,7 +406,7 @@ impl NcCell {
crate::cell_strdup(plane, self) crate::cell_strdup(plane, self)
} }
/// Does this NcCell contain an East Asian Wide codepoint? /// Does this NcCell contain a wide codepoint?
/// ///
/// *C style function: [cell_double_wide_p()][crate::cell_double_wide_p].* /// *C style function: [cell_double_wide_p()][crate::cell_double_wide_p].*
pub fn double_wide_p(&self) -> bool { pub fn double_wide_p(&self) -> bool {
@ -420,7 +420,7 @@ impl NcCell {
crate::cell_wide_right_p(self) crate::cell_wide_right_p(self)
} }
/// Is this the right half of a wide character? /// Is this the right side of a wide character?
/// ///
/// *C style function: [cell_wide_right_p()][crate::cell_wide_right_p].* /// *C style function: [cell_wide_right_p()][crate::cell_wide_right_p].*
pub fn wide_right_p(&self) -> bool { pub fn wide_right_p(&self) -> bool {

@ -272,14 +272,6 @@ pub const NCCELL_FG_RGB_MASK: u64 = crate::bindings::ffi::CELL_FG_RGB_MASK;
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair] /// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::ffi::CELL_NOBACKGROUND_MASK; pub const NCCELL_NOBACKGROUND_MASK: u64 = crate::bindings::ffi::CELL_NOBACKGROUND_MASK;
/// If this bit is set, 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.
///
/// See the detailed diagram at [`NcChannelPair`][crate::NcChannelPair]
pub const NCCELL_WIDEASIAN_MASK: u64 = crate::bindings::ffi::CELL_WIDEASIAN_MASK as u64;
// NcEgc // NcEgc
// //
/// Extended Grapheme Cluster. A 32-bit [`char`]-like type /// Extended Grapheme Cluster. A 32-bit [`char`]-like type

@ -6,7 +6,7 @@ use crate::{
cell_release, cstring, NcAlphaBits, NcCell, NcChannel, NcChannelPair, NcColor, NcEgc, cell_release, cstring, NcAlphaBits, NcCell, NcChannel, NcChannelPair, NcColor, NcEgc,
NcIntResult, NcPaletteIndex, NcPlane, NcRgb, NcStyleMask, NCCELL_ALPHA_OPAQUE, NcIntResult, NcPaletteIndex, NcPlane, NcRgb, NcStyleMask, NCCELL_ALPHA_OPAQUE,
NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE, NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE, NCCELL_BGDEFAULT_MASK, NCCELL_BG_PALETTE, NCCELL_FGDEFAULT_MASK, NCCELL_FG_PALETTE,
NCCELL_NOBACKGROUND_MASK, NCCELL_WIDEASIAN_MASK, NCRESULT_ERR, NCRESULT_OK, NCSTYLE_MASK, NCRESULT_ERR, NCRESULT_OK, NCSTYLE_MASK,
}; };
// Alpha ----------------------------------------------------------------------- // Alpha -----------------------------------------------------------------------
@ -320,7 +320,7 @@ pub fn cell_set_styles(cell: &mut NcCell, stylebits: NcStyleMask) {
// Waiting for: https://github.com/rust-lang/rust-bindgen/issues/1875 // Waiting for: https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline] #[inline]
pub const fn cell_double_wide_p(cell: &NcCell) -> bool { pub const fn cell_double_wide_p(cell: &NcCell) -> bool {
(cell.channels & NCCELL_WIDEASIAN_MASK as NcChannelPair) != 0 cell.width > 0
} }
/// Is this the right half of a wide character? /// Is this the right half of a wide character?
@ -344,7 +344,6 @@ pub const fn cell_wide_left_p(cell: &NcCell) -> bool {
/// *Method: NcCell.[load_char()][NcCell#method.load_char].* /// *Method: NcCell.[load_char()][NcCell#method.load_char].*
// //
// NOTE: Unlike the original C function this doesn't return anything. // NOTE: Unlike the original C function this doesn't return anything.
// REMINDER: remove casting for NCCELL_WIDEASIAN_MASK when fixed:
// Waiting for: https://github.com/rust-lang/rust-bindgen/issues/1875 // Waiting for: https://github.com/rust-lang/rust-bindgen/issues/1875
#[inline] #[inline]
pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcEgc) /* -> i32 */ pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcEgc) /* -> i32 */
@ -352,8 +351,6 @@ pub fn cell_load_char(plane: &mut NcPlane, cell: &mut NcCell, ch: NcEgc) /* -> i
unsafe { unsafe {
crate::cell_release(plane, cell); crate::cell_release(plane, cell);
} }
cell.channels &= !(NCCELL_WIDEASIAN_MASK as NcChannelPair | NCCELL_NOBACKGROUND_MASK);
cell.gcluster = ch as u32;
/* TODO new version: /* TODO new version:

@ -192,7 +192,6 @@ pub type NcAlphaBits = u32;
/// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE] /// - [`NCCELL_FG_PALETTE`][crate::NCCELL_FG_PALETTE]
/// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK] /// - [`NCCELL_FG_RGB_MASK`][crate::NCCELL_FG_RGB_MASK]
/// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK] /// - [`NCCELL_NOBACKGROUND_MASK`][crate::NCCELL_NOBACKGROUND_MASK]
/// - [`NCCELL_WIDEASIAN_MASK`][crate::NCCELL_WIDEASIAN_MASK]
/// ///
pub type NcChannelPair = u64; pub type NcChannelPair = u64;

Loading…
Cancel
Save