1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
//! `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::cell; // 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_BLINK`] /// - [`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_BLINK: u16 = crate::bindings::ffi::NCSTYLE_BLINK 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_BLINK, 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 } }