libnotcurses_sys/
style.rs

1//!
2
3#[cfg(not(feature = "std"))]
4use alloc::{vec, vec::Vec};
5
6/// A bitmask of styles.
7///
8/// # Flags
9/// - [`Bold`][NcStyle::Bold]
10/// - [`Italic`][NcStyle::Italic]
11/// - [`Struck`][NcStyle::Struck]
12/// - [`Underline`][NcStyle::Underline]
13/// - [`Undercurl`][NcStyle::Undercurl]
14/// - [`None`][NcStyle::None]
15/// - [`Mask`][NcStyle::Mask]
16///
17/// # Default
18/// *[`NcStyle::None`]
19///
20/// # Notes
21/// - if you want reverse video, try [`NcChannels.reverse`]
22/// - if you want blink, try [`NcPlane.pulse`].
23/// - if you want protection, put things on a different [`NcPlane`].
24///
25/// [`NcChannels.reverse`]: crate::NcChannels#method.reverse
26/// [`NcPlane.pulse`]: crate::NcPlane#method.pulse
27/// [`NcPlane`]: crate::NcPlane
28#[repr(transparent)]
29#[derive(Clone, Copy, PartialEq, Eq)]
30pub struct NcStyle(pub c_api::NcStyle_u16);
31
32/// # Flags
33impl NcStyle {
34    /// Bold.
35    pub const Bold: Self = Self(c_api::NCSTYLE_BOLD);
36
37    /// Italic.
38    pub const Italic: Self = Self(c_api::NCSTYLE_ITALIC);
39
40    /// Struck.
41    pub const Struck: Self = Self(c_api::NCSTYLE_STRUCK);
42
43    /// Underline.
44    pub const Underline: Self = Self(c_api::NCSTYLE_UNDERLINE);
45
46    /// Undercurl.
47    pub const Undercurl: Self = Self(c_api::NCSTYLE_UNDERCURL);
48
49    /// None of the styles (all bits set to 0).
50    pub const None: Self = Self(0);
51
52    /// The mask of all styles (all bits set to 1).
53    pub const Mask: Self = Self(c_api::NCSTYLE_MASK);
54}
55
56mod core_impls {
57    use core::fmt;
58
59    #[cfg(not(feature = "std"))]
60    use alloc::string::String;
61
62    use super::{c_api::NcStyle_u16, NcStyle};
63
64    impl Default for NcStyle {
65        fn default() -> Self {
66            Self::None
67        }
68    }
69
70    impl fmt::Display for NcStyle {
71        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72            let mut string = String::new();
73            for s in self.to_vec() {
74                string.push_str(match s {
75                    NcStyle::Italic => "Italic ",
76                    NcStyle::Underline => "Underline ",
77                    NcStyle::Undercurl => "Undercurl ",
78                    NcStyle::Struck => "Struck ",
79                    NcStyle::Bold => "Bold ",
80                    NcStyle::None => "None ",
81                    _ => "",
82                });
83            }
84            let _ = string.pop();
85            write!(f, "{}", string)
86        }
87    }
88    impl fmt::Debug for NcStyle {
89        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90            let mut string = String::new();
91            for s in self.to_vec() {
92                string.push_str(match s {
93                    NcStyle::Italic => "Italic+",
94                    NcStyle::Underline => "Underline+",
95                    NcStyle::Undercurl => "Undercurl+",
96                    NcStyle::Struck => "Struck+",
97                    NcStyle::Bold => "Bold+",
98                    NcStyle::None => "None ",
99                    _ => "",
100                });
101            }
102            let _ = string.pop();
103            write!(f, "NcStyle::{}", string)
104        }
105    }
106
107    crate::from_primitive![NcStyle, NcStyle_u16];
108
109    crate::unit_impl_from![NcStyle, NcStyle_u16];
110
111    // for ncplane_*_styles & ncdirect_*_styles:
112    impl From<NcStyle> for u32 {
113        fn from(style: NcStyle) -> Self {
114            style.0 as u32
115        }
116    }
117
118    crate::unit_impl_ops![bitwise; NcStyle, NcStyle_u16];
119    crate::unit_impl_fmt![bases; NcStyle];
120}
121
122/// # Methods
123impl NcStyle {
124    /// Returns a `Vec` with all the styles contained in the current style.
125    pub fn to_vec(&self) -> Vec<NcStyle> {
126        let mut v = vec![];
127        let styles = [
128            NcStyle::Italic,
129            NcStyle::Underline,
130            NcStyle::Undercurl,
131            NcStyle::Struck,
132            NcStyle::Bold,
133        ];
134        for s in &styles {
135            if self.has(*s) {
136                v.push(*s)
137            }
138        }
139        // only push None if there are no other styles present.
140        if v.is_empty() {
141            v.push(NcStyle::None)
142        }
143        v
144    }
145
146    /// Returns true if the current style has included the `other_style`.
147    #[inline]
148    pub fn has(&self, other: impl Into<NcStyle>) -> bool {
149        let other = other.into();
150        (self.0 & other.0) == other.0
151    }
152
153    /// Sets the `other` style in the current style.
154    #[inline]
155    pub fn set(&mut self, other: impl Into<NcStyle>) {
156        self.0 |= other.into().0
157    }
158
159    /// Unsets the `other` style in the current style.
160    #[inline]
161    pub fn unset(&mut self, other: impl Into<NcStyle>) {
162        self.0 &= !other.into().0
163    }
164}
165
166pub(crate) mod c_api {
167    use crate::c_api::ffi;
168
169    /// Styling attribute flags.
170    ///
171    /// It's recommended to use [`NcStyle`][crate::NcStyle] instead.
172    ///
173    /// # Associated `c_api` constants
174    ///
175    /// - [`NCSTYLE_ITALIC`]
176    /// - [`NCSTYLE_UNDERLINE`]
177    /// - [`NCSTYLE_UNDERCURL`]
178    /// - [`NCSTYLE_STRUCK`]
179    /// - [`NCSTYLE_BOLD`]
180    /// - [`NCSTYLE_NONE`]
181    /// - [`NCSTYLE_MASK`]
182    ///
183    pub type NcStyle_u16 = u16;
184
185    /// [`NcStyle_u16`] Italic.
186    pub const NCSTYLE_ITALIC: u16 = ffi::NCSTYLE_ITALIC as u16;
187
188    /// [`NcStyle_u16`] Underline.
189    pub const NCSTYLE_UNDERLINE: u16 = ffi::NCSTYLE_UNDERLINE as u16;
190
191    /// [`NcStyle_u16`] Undercurl.
192    pub const NCSTYLE_UNDERCURL: u16 = ffi::NCSTYLE_UNDERCURL as u16;
193
194    /// [`NcStyle_u16`] Struck.
195    pub const NCSTYLE_STRUCK: u16 = ffi::NCSTYLE_STRUCK as u16;
196
197    /// [`NcStyle_u16`] Bold.
198    pub const NCSTYLE_BOLD: u16 = ffi::NCSTYLE_BOLD as u16;
199
200    /// [`NcStyle_u16`] None.
201    pub const NCSTYLE_NONE: u16 = ffi::NCSTYLE_NONE as u16;
202
203    /// [`NcStyle_u16`] mask.
204    pub const NCSTYLE_MASK: u16 = ffi::NCSTYLE_MASK as u16;
205}