libnotcurses_sys/channel/
reimplemented.rs

1//! `ncchannel*_*` reimplemented functions.
2
3use crate::{
4    c_api::{self, NcAlpha_u32, NcChannel_u32, NcChannels_u64, NcResult_i32, NcRgb_u32},
5    NcPaletteIndex,
6};
7
8#[allow(unused_imports)]
9use crate::{NcChannel, NcChannels};
10
11// Alpha -----------------------------------------------------------------------
12
13/// Gets the [`NcAlpha_u32`] from an [`NcChannel_u32`].
14///
15/// It is not shifted down, and can be directly compared to `NCALPHA_*` values.
16///
17/// *Method: NcChannel.[alpha()][NcChannel#method.alpha]*
18#[inline]
19pub fn ncchannel_alpha(channel: impl Into<NcChannel_u32>) -> NcAlpha_u32 {
20    channel.into() & c_api::NC_BG_ALPHA_MASK
21}
22
23/// Sets the [`NcAlpha_u32`] of an [`NcChannel_u32`].
24///
25/// Background channels must not be set to `NCALPHA_HIGHCONTRAST`.
26///
27/// It is an error if alpha contains any bits other than `NCALPHA_*`.
28///
29/// *Method: NcChannel.[set_alpha()][NcChannel#method.set_alpha]*
30#[inline]
31pub fn ncchannel_set_alpha(
32    channel: &mut NcChannel_u32,
33    alpha: impl Into<NcAlpha_u32>,
34) -> NcResult_i32 {
35    let alpha = alpha.into();
36
37    if (alpha & !c_api::NC_BG_ALPHA_MASK) != 0 {
38        return c_api::NCRESULT_ERR;
39    }
40    *channel = alpha | (*channel & !c_api::NC_BG_ALPHA_MASK);
41    if alpha != c_api::NCALPHA_OPAQUE {
42        *channel |= c_api::NC_BGDEFAULT_MASK;
43    }
44    c_api::NCRESULT_OK
45}
46
47/// Gets the foreground [`NcAlpha_u32`] from an [`NcChannels_u64`], shifted to LSBs.
48///
49/// *Method: NcChannels.[fg_alpha()][NcChannels#method.fg_alpha]*
50#[inline]
51pub fn ncchannels_fg_alpha(channels: impl Into<NcChannels_u64>) -> NcAlpha_u32 {
52    ncchannel_alpha(ncchannels_fchannel(channels))
53}
54
55/// Gets the background [`NcAlpha_u32`] from an [`NcChannels_u64`], shifted to LSBs.
56///
57/// *Method: NcChannels.[bg_alpha()][NcChannels#method.bg_alpha]*
58#[inline]
59pub fn ncchannels_bg_alpha(channels: impl Into<NcChannels_u64>) -> NcAlpha_u32 {
60    ncchannel_alpha(ncchannels_bchannel(channels))
61}
62
63/// Sets the [`NcAlpha_u32`] of the foreground [`NcChannel_u32`] of an [`NcChannels_u64`].
64///
65/// *Method: NcChannels.[set_fg_alpha()][NcChannels#method.set_fg_alpha]*
66#[inline]
67pub fn ncchannels_set_fg_alpha(
68    channels: &mut NcChannels_u64,
69    alpha: impl Into<NcAlpha_u32>,
70) -> NcResult_i32 {
71    let mut channel = ncchannels_fchannel(*channels);
72    if ncchannel_set_alpha(&mut channel, alpha.into()) < 0 {
73        return c_api::NCRESULT_ERR;
74    }
75    *channels = (channel as NcChannels_u64) << 32 | *channels & 0xffffffff_u64;
76    c_api::NCRESULT_OK
77}
78
79/// Sets the [`NcAlpha_u32`] of the background [`NcChannel_u32`] of an [`NcChannels_u64`].
80///
81/// *Method: NcChannels.[set_bg_alpha()][NcChannels#method.set_bg_alpha]*
82#[inline]
83pub fn ncchannels_set_bg_alpha(
84    channels: &mut NcChannels_u64,
85    alpha: impl Into<NcAlpha_u32>,
86) -> NcResult_i32 {
87    let alpha = alpha.into();
88    if alpha == c_api::NCALPHA_HIGHCONTRAST {
89        return c_api::NCRESULT_ERR;
90    }
91    let mut channel = ncchannels_bchannel(*channels);
92    if ncchannel_set_alpha(&mut channel, alpha) < 0 {
93        return c_api::NCRESULT_ERR;
94    }
95    ncchannels_set_bchannel(channels, channel);
96    c_api::NCRESULT_OK
97}
98
99// Channels --------------------------------------------------------------------
100
101/// Gets the background alpha and coloring bits as an [`NcChannel_u32`]
102/// from a [`NcChannels_u64`].
103///
104/// *Method: NcChannels.[bchannel()][NcChannels#method.bchannel]*
105#[inline]
106pub fn ncchannels_bchannel(channels: impl Into<NcChannels_u64>) -> NcChannel_u32 {
107    (channels.into()
108        & (c_api::NC_BG_RGB_MASK
109            | c_api::NC_BG_PALETTE
110            | c_api::NC_BGDEFAULT_MASK
111            | c_api::NC_BG_ALPHA_MASK) as NcChannels_u64) as NcChannel_u32
112}
113
114/// Gets the foreground alpha and coloring bits as an [`NcChannel_u32`]
115/// from an [`NcChannels_u64`].
116///
117/// *Method: NcChannels.[fchannel()][NcChannels#method.fchannel]*
118#[inline]
119pub fn ncchannels_fchannel(channels: impl Into<NcChannels_u64>) -> NcChannel_u32 {
120    ncchannels_bchannel(channels.into() >> 32)
121}
122
123/// Gets the alpha and coloring bits as an [`NcChannels_u64`].
124///
125/// *Method: NcChannels.[channels()][NcChannels#method.channels]*
126#[inline]
127pub fn ncchannels_channels(channels: impl Into<NcChannels_u64>) -> NcChannels_u64 {
128    let channels = channels.into();
129    ncchannels_bchannel(channels) as NcChannels_u64
130        | (ncchannels_fchannel(channels) as NcChannels_u64) << 32
131}
132
133/// Sets the background alpha and coloring bits of the [`NcChannels_u64`]
134/// from an [`NcChannel_u32`].
135///
136/// *Method: NcChannels.[set_bchannel()][NcChannels#method.set_bchannel]*
137#[inline]
138pub fn ncchannels_set_bchannel(
139    channels: &mut NcChannels_u64,
140    bchannel: impl Into<NcChannel_u32>,
141) -> NcChannels_u64 {
142    // drop the background color and alpha bit
143    *channels &= (0xffffffff_u64 << 32) | c_api::NC_NOBACKGROUND_MASK;
144    *channels |= bchannel.into() as NcChannels_u64 & !c_api::NC_NOBACKGROUND_MASK;
145    *channels
146}
147
148/// Sets the foreground alpha and coloring bits of the [`NcChannels_u64`]
149/// from an [`NcChannel_u32`].
150///
151/// *Method: NcChannels.[set_fchannel()][NcChannels#method.set_fchannel]*
152#[inline]
153pub fn ncchannels_set_fchannel(
154    channels: &mut NcChannels_u64,
155    fchannel: impl Into<NcChannel_u32>,
156) -> NcChannels_u64 {
157    // drop the background color and alpha bit
158    *channels &= 0xffffffff_u64 | c_api::NC_NOBACKGROUND_MASK << 32;
159    *channels |= (fchannel.into() as NcChannels_u64 & !c_api::NC_NOBACKGROUND_MASK) << 32;
160    *channels
161}
162
163/// Sets the alpha and coloring bits of an [`NcChannels_u64`] from another [`NcChannels_u64`].
164///
165/// *Method: NcChannels.[set_fchannel()][NcChannels#method.set_channels]*
166#[inline]
167pub fn ncchannels_set_channels(
168    channels: &mut NcChannels_u64,
169    other: impl Into<NcChannels_u64>,
170) -> NcChannels_u64 {
171    let other = other.into();
172    ncchannels_set_bchannel(channels, (other & 0xffffffff_u64) as NcChannel_u32);
173    ncchannels_set_fchannel(channels, ((other >> 32) & 0xffffffff_u64) as NcChannel_u32);
174    *channels
175}
176
177/// Combines two [`NcChannel_u32`]s into an [`NcChannels_u64`].
178///
179/// *Method: NcChannels.[combine()][NcChannels#method.combine]*
180#[inline]
181pub fn ncchannels_combine(
182    fchannel: impl Into<NcChannel_u32>,
183    bchannel: impl Into<NcChannel_u32>,
184) -> NcChannels_u64 {
185    let mut channels: NcChannels_u64 = 0;
186    ncchannels_set_fchannel(&mut channels, fchannel.into());
187    ncchannels_set_bchannel(&mut channels, bchannel.into());
188    channels
189}
190
191/// Returns the `NcChannels_u64` with the fore- and background's color information
192/// swapped, but without touching housekeeping bits.
193///
194/// Alpha is retained unless it would lead to an illegal state: `HIGHCONTRAST`,
195/// `TRANSPARENT` and `BLEND` are taken to `OPAQUE` unless the new value is RGB.
196///
197/// *Method: NcChannels.[reverse()][NcChannels#method.reverse]*
198#[inline]
199pub fn ncchannels_reverse(channels: impl Into<NcChannels_u64>) -> NcChannels_u64 {
200    let channels = channels.into();
201    let raw = ((ncchannels_bchannel(channels) as NcChannels_u64) << 32)
202        + ncchannels_fchannel(channels) as NcChannels_u64;
203    let statemask = ((c_api::NC_NOBACKGROUND_MASK | c_api::NC_BG_ALPHA_MASK as NcChannels_u64)
204        << 32)
205        | c_api::NC_NOBACKGROUND_MASK
206        | c_api::NC_BG_ALPHA_MASK as NcChannels_u64;
207    let mut ret = (raw as NcChannels_u64) & !statemask;
208    ret |= channels & statemask;
209    if ncchannels_bg_alpha(ret) != c_api::NCALPHA_OPAQUE && !ncchannels_bg_rgb_p(ret) {
210        ncchannels_set_bg_alpha(&mut ret, c_api::NCALPHA_OPAQUE);
211    }
212    if ncchannels_fg_alpha(ret) != c_api::NCALPHA_OPAQUE && !ncchannels_fg_rgb_p(ret) {
213        ncchannels_set_fg_alpha(&mut ret, c_api::NCALPHA_OPAQUE);
214    }
215    ret
216}
217
218// u8 ---------------------------------------------------------------------
219
220/// Gets the red component from an [`NcChannel_u32`].
221///
222/// Only valid if `ncchannel_rgb_p` would return true for the channel.
223///
224/// *Method: NcChannel.[r()][NcChannel#method.r]*
225#[inline]
226pub fn ncchannel_r(channel: impl Into<NcChannel_u32>) -> u8 {
227    ((channel.into() & 0xff0000) >> 16) as u8
228}
229
230/// Gets the green component from an [`NcChannel_u32`].
231///
232/// Only valid if `ncchannel_rgb_p` would return true for the channel.
233///
234/// *Method: NcChannel.[g()][NcChannel#method.g]*
235#[inline]
236pub fn ncchannel_g(channel: impl Into<NcChannel_u32>) -> u8 {
237    ((channel.into() & 0x00ff00) >> 8) as u8
238}
239
240/// Gets the blue component from an [`NcChannel_u32`].
241///
242/// Only valid if `ncchannel_rgb_p` would return true for the channel.
243///
244/// *Method: NcChannel.[b()][NcChannel#method.b]*
245#[inline]
246pub fn ncchannel_b(channel: impl Into<NcChannel_u32>) -> u8 {
247    (channel.into() & 0x0000ff) as u8
248}
249
250/// Sets the red component of an [`NcChannel_u32`], and returns it.
251///
252/// *Method: NcChannel.[set_r()][NcChannel#method.set_r]*
253//
254// Not in the C API.
255#[inline]
256pub fn ncchannel_set_r(channel: &mut NcChannel_u32, r: u8) -> NcChannel_u32 {
257    *channel = (r as NcChannel_u32) << 16 | (*channel & 0xff00) | (*channel & 0xff);
258    *channel
259}
260
261/// Sets the green component of an [`NcChannel_u32`], and returns it.
262///
263/// *Method: NcChannel.[set_g()][NcChannel#method.set_g]*
264//
265// Not in the C API.
266#[inline]
267pub fn ncchannel_set_g(channel: &mut NcChannel_u32, g: u8) -> NcChannel_u32 {
268    *channel = (*channel & 0xff0000) | (g as NcChannel_u32) << 8 | (*channel & 0xff);
269    *channel
270}
271
272/// Sets the blue component of an [`NcChannel_u32`], and returns it.
273///
274/// *Method: NcChannel.[set_b()][NcChannel#method.set_b]*
275//
276// Not in the C API.
277#[inline]
278pub fn ncchannel_set_b(channel: &mut NcChannel_u32, b: u8) -> NcChannel_u32 {
279    *channel = (*channel & 0xff0000) | (*channel & 0xff00) | (b as NcChannel_u32);
280    *channel
281}
282
283/// Gets the three RGB components from an [`NcChannel_u32`], and returns it.
284///
285/// Only valid if `ncchannel_rgb_p` would return true for the channel.
286///
287/// *Method: NcChannel.[rgb()][NcChannel#method.rgb]*
288#[inline]
289pub fn ncchannel_rgb8(
290    channel: impl Into<NcChannel_u32>,
291    r: &mut u8,
292    g: &mut u8,
293    b: &mut u8,
294) -> NcChannel_u32 {
295    let channel = channel.into();
296    *r = ncchannel_r(channel);
297    *g = ncchannel_g(channel);
298    *b = ncchannel_b(channel);
299    channel
300}
301
302/// Sets the three RGB components an [`NcChannel_u32`], and marks it as NOT using the
303/// "default color", retaining the other bits unchanged.
304///
305/// Note: Unlike the original C function, this one can't fail.
306///
307/// *Method: NcChannel.[set_rgb()][NcChannel#method.set_rgb]*
308#[inline]
309pub fn ncchannel_set_rgb8(channel: &mut NcChannel_u32, r: u8, g: u8, b: u8) {
310    let rgb: NcRgb_u32 =
311        (r as NcChannel_u32) << 16 | (g as NcChannel_u32) << 8 | (b as NcChannel_u32);
312    *channel = (*channel & !(c_api::NC_BG_RGB_MASK | c_api::NC_BG_PALETTE))
313        | c_api::NC_BGDEFAULT_MASK
314        | rgb;
315}
316
317/// Gets the three foreground RGB components from an [`NcChannels_u64`], and
318/// returns the foreground [`NcChannel_u32`] (which can have some extra bits set).
319///
320/// *Method: NcChannels.[fg_rgb()][NcChannels#method.fg_rgb]*
321#[inline]
322pub fn ncchannels_fg_rgb8(
323    channels: impl Into<NcChannels_u64>,
324    r: &mut u8,
325    g: &mut u8,
326    b: &mut u8,
327) -> NcChannel_u32 {
328    ncchannel_rgb8(ncchannels_fchannel(channels.into()), r, g, b)
329}
330
331/// Gets the three background RGB components from an [`NcChannels_u64`], and
332/// returns the background [`NcChannel_u32`] (which can have some extra bits set).
333///
334/// *Method: NcChannels.[bg_rgb()][NcChannels#method.bg_rgb]*
335#[inline]
336pub fn ncchannels_bg_rgb8(
337    channels: impl Into<NcChannels_u64>,
338    r: &mut u8,
339    g: &mut u8,
340    b: &mut u8,
341) -> NcChannel_u32 {
342    ncchannel_rgb8(ncchannels_bchannel(channels.into()), r, g, b)
343}
344
345/// Sets the three foreground RGB components of an [`NcChannels_u64`], and
346/// marks it as NOT using the "default color", retaining the other bits unchanged.
347///
348/// Note: Unlike the original C function, this one returns the new `NcChannels_u64`.
349///
350/// *Method: NcChannels.[set_fg_rgb()][NcChannels#method.set_fg_rgb]*
351#[inline]
352pub fn ncchannels_set_fg_rgb8(
353    channels: &mut NcChannels_u64,
354    r: u8,
355    g: u8,
356    b: u8,
357) -> NcChannels_u64 {
358    let mut channel = ncchannels_fchannel(*channels);
359    ncchannel_set_rgb8(&mut channel, r, g, b);
360    *channels = (channel as NcChannels_u64) << 32 | *channels & 0xffffffff;
361    *channels
362}
363
364/// Sets the three background RGB components of an [`NcChannels_u64`], and
365/// marks it as NOT using the "default color", retaining the other bits unchanged.
366///
367/// Note: Unlike the original C function, this one returns the new `NcChannels_u64`.
368///
369/// *Method: NcChannels.[set_bg_rgb()][NcChannels#method.set_bg_rgb]*
370#[inline]
371pub fn ncchannels_set_bg_rgb8(
372    channels: &mut NcChannels_u64,
373    r: u8,
374    g: u8,
375    b: u8,
376) -> NcChannels_u64 {
377    let mut channel = ncchannels_bchannel(*channels);
378    ncchannel_set_rgb8(&mut channel, r, g, b);
379    ncchannels_set_bchannel(channels, channel);
380    *channels
381}
382
383// NcRgb_u32 -------------------------------------------------------------------
384
385/// Gets the foreground [`NcRgb_u32`] from an [`NcChannels_u64`], shifted to LSBs.
386///
387/// *Method: NcChannels.[fg_rgb()][NcChannels#method.fg_rgb]*
388#[inline]
389pub fn ncchannels_fg_rgb(channels: impl Into<NcChannels_u64>) -> NcRgb_u32 {
390    ncchannels_fchannel(channels.into()) & c_api::NC_BG_RGB_MASK
391}
392
393/// Gets the background [`NcRgb_u32`] from an [`NcChannels_u64`], shifted to LSBs.
394///
395/// *Method: NcChannels.[bg_rgb()][NcChannels#method.bg_rgb]*
396#[inline]
397pub fn ncchannels_bg_rgb(channels: impl Into<NcChannels_u64>) -> NcRgb_u32 {
398    ncchannels_bchannel(channels.into()) & c_api::NC_BG_RGB_MASK
399}
400
401/// Returns true if the foreground channel is set to RGB color.
402///
403/// *Method: NcChannels.[fg_rgb_p()][NcChannels#method.fg_rgb_p]*
404#[inline]
405pub fn ncchannels_fg_rgb_p(channels: impl Into<NcChannels_u64>) -> bool {
406    ncchannel_rgb_p(ncchannels_fchannel(channels.into()))
407}
408
409/// Returns true if the background channel is set to RGB color.
410///
411/// *Method: NcChannels.[bg_rgb_p()][NcChannels#method.bg_rgb_p]*
412#[inline]
413pub fn ncchannels_bg_rgb_p(channels: impl Into<NcChannels_u64>) -> bool {
414    ncchannel_rgb_p(ncchannels_bchannel(channels.into()))
415}
416
417/// Gets the [`NcRgb_u32`] of an [`NcChannel_u32`].
418///
419/// This function basically removes the 4th byte of the `NcChannel_u32`.
420///
421/// *Method: NcChannel.[rgb()][NcChannel#method.rgb]*
422//
423// Not in the C API
424#[inline]
425pub fn ncchannel_rgb(channel: impl Into<NcChannel_u32>) -> NcRgb_u32 {
426    channel.into() & c_api::NC_BG_RGB_MASK
427}
428
429/// Returns true if this `NcChannel_u32` is using RGB color.
430///
431/// *Method: NcChannel.[rgb_p()][NcChannel#method.rgb_p]*
432#[inline]
433pub fn ncchannel_rgb_p(channel: impl Into<NcChannel_u32>) -> bool {
434    let channel = channel.into();
435    !(ncchannel_default_p(channel) | ncchannel_palindex_p(channel))
436}
437
438/// Sets the [`NcRgb_u32`] of an [`NcChannel_u32`], and marks it as NOT using
439/// the "default color", retaining the other bits unchanged.
440///
441/// Note: Unlike the original C function, this one can't fail.
442///
443/// *Method: NcChannel.[set()][NcChannel#method.set]*
444#[inline]
445pub fn ncchannel_set(channel: &mut NcChannel_u32, rgb: impl Into<NcRgb_u32>) {
446    *channel = (*channel & !(c_api::NC_BG_RGB_MASK | c_api::NC_BG_PALETTE))
447        | c_api::NC_BGDEFAULT_MASK
448        | (rgb.into() & 0x00ffffff);
449}
450
451/// Sets the foreground [`NcRgb_u32`] of an [`NcChannels_u64`], and marks it as
452/// NOT using the "default color", retaining the other bits unchanged.
453///
454/// *Method: NcChannels.[set_fg_rgb()][NcChannels#method.set_fg_rgb]*
455#[inline]
456pub fn ncchannels_set_fg_rgb(channels: &mut NcChannels_u64, rgb: impl Into<NcRgb_u32>) {
457    let mut channel = ncchannels_fchannel(*channels);
458    ncchannel_set(&mut channel, rgb.into());
459    *channels = (channel as NcChannels_u64) << 32 | *channels & 0xffffffff;
460}
461
462/// Sets the foreground [`NcRgb_u32`] of an [`NcChannels_u64`], and marks it as NOT using
463/// the "default color", retaining the other bits unchanged.
464///
465/// *Method: NcChannels.[set_bg_rgb()][NcChannels#method.set_bg_rgb]*
466#[inline]
467pub fn ncchannels_set_bg_rgb(channels: &mut NcChannels_u64, rgb: impl Into<NcRgb_u32>) {
468    let mut channel = ncchannels_bchannel(*channels);
469    ncchannel_set(&mut channel, rgb);
470    ncchannels_set_bchannel(channels, channel);
471}
472
473// Default ---------------------------------------------------------------------
474
475/// Is this [`NcChannel_u32`] using the "default color" rather than RGB/palette-indexed?
476///
477/// *Method: NcChannel.[default_p()][NcChannel#method.default_p]*
478#[inline]
479pub fn ncchannel_default_p(channel: impl Into<NcChannel_u32>) -> bool {
480    (channel.into() & c_api::NC_BGDEFAULT_MASK) == 0
481}
482
483/// Marks an [`NcChannel_u32`] as using its "default color". Sets alpha as `OPAQUE`.
484///
485/// *Method: NcChannel.[set_default()][NcChannel#method.set_default]*
486#[inline]
487pub fn ncchannel_set_default(channel: &mut NcChannel_u32) -> NcChannel_u32 {
488    *channel &= !c_api::NC_BGDEFAULT_MASK; // turn off not-default bit
489    ncchannel_set_alpha(channel, c_api::NCALPHA_OPAQUE);
490    *channel
491}
492
493/// Marks an [`NcChannel_u32`] as NOT using its "default color",
494/// retaining the other bits unchanged.
495///
496/// *Method: NcChannel.[set_not_default()][NcChannel#method.set_not_default]*
497//
498// Not in the C API
499#[inline]
500pub fn ncchannel_set_not_default(channel: &mut NcChannel_u32) -> NcChannel_u32 {
501    *channel |= c_api::NC_BGDEFAULT_MASK;
502    *channel
503}
504
505/// Is the foreground of an [`NcChannels_u64`] using the "default foreground color"?
506///
507/// *Method: NcChannels.[fg_default_p()][NcChannels#method.fg_default_p]*
508#[inline]
509pub fn ncchannels_fg_default_p(channels: impl Into<NcChannels_u64>) -> bool {
510    ncchannel_default_p(ncchannels_fchannel(channels.into()))
511}
512
513/// Is the background using the "default background color"?
514///
515/// The "default background color" must generally be used to take advantage of
516/// terminal-effected transparency.
517///
518/// *Method: NcChannels.[bg_default_p()][NcChannels#method.bg_default_p]*
519#[inline]
520pub fn ncchannels_bg_default_p(channels: impl Into<NcChannels_u64>) -> bool {
521    ncchannel_default_p(ncchannels_bchannel(channels.into()))
522}
523
524/// Marks the foreground of an [`NcChannels_u64`] as using its "default color",
525/// which also marks it opaque, and returns the new [`NcChannels_u64`].
526///
527/// *Method: NcChannels.[set_fg_default()][NcChannels#method.set_fg_default]*
528#[inline]
529pub fn ncchannels_set_fg_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
530    let mut channel = ncchannels_fchannel(*channels);
531    ncchannel_set_default(&mut channel);
532    *channels = (channel as NcChannels_u64) << 32 | *channels & 0xffffffff;
533    *channels
534}
535
536/// Marks the foreground of an [`NcChannels_u64`] as NOT using its "default color",
537/// retaining the other bits unchanged, and returns the new [`NcChannels_u64`].
538///
539/// *Method: NcChannels.[set_fg_not_default()][NcChannels#method.set_fg_not_default]*
540//
541// Not in the C API
542#[inline]
543pub fn ncchannels_set_fg_not_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
544    let mut channel = ncchannels_fchannel(*channels);
545    ncchannel_set_not_default(&mut channel);
546    *channels = (channel as NcChannels_u64) << 32 | *channels & 0xffffffff;
547    *channels
548}
549
550/// Marks the background of an [`NcChannels_u64`] as using its "default color",
551/// which also marks it opaque, and returns the new [`NcChannels_u64`].
552///
553/// *Method: NcChannels.[set_bg_default()][NcChannels#method.set_bg_default]*
554#[inline]
555pub fn ncchannels_set_bg_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
556    let mut channel = ncchannels_bchannel(*channels);
557    ncchannel_set_default(&mut channel);
558    ncchannels_set_bchannel(channels, channel);
559    *channels
560}
561
562/// Marks the background of an [`NcChannels_u64`] as NOT using its "default color",
563/// retaining the other bits unchanged, and returns the new [`NcChannels_u64`].
564///
565/// *Method: NcChannels.[set_bg_not_default()][NcChannels#method.set_bg_not_default]*
566//
567// Not in the C API
568#[inline]
569pub fn ncchannels_set_bg_not_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
570    let mut channel = ncchannels_bchannel(*channels);
571    ncchannel_set_not_default(&mut channel);
572    ncchannels_set_bchannel(channels, channel);
573    *channels
574}
575
576/// Marks both the foreground and background of an [`NcChannels_u64`] as using their
577/// "default color", which also marks them opaque, and returns the new [`NcChannels_u64`].
578///
579/// *Method: NcChannels.[set_default()][NcChannels#method.set_default]*
580//
581// Not in the C API
582#[inline]
583pub fn ncchannels_set_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
584    ncchannels_set_bg_default(&mut ncchannels_set_fg_default(channels))
585}
586
587/// Marks both the foreground and background of an [`NcChannels_u64`] as NOT using their
588/// "default color", retaining the other bits unchanged, and returns the new [`NcChannels_u64`].
589///
590/// *Method: NcChannels.[set_not_default()][NcChannels#method.set_not_default]*
591//
592// Not in the C API
593#[inline]
594pub fn ncchannels_set_not_default(channels: &mut NcChannels_u64) -> NcChannels_u64 {
595    ncchannels_set_bg_not_default(&mut ncchannels_set_fg_not_default(channels))
596}
597
598// Palette ---------------------------------------------------------------------
599
600/// Gets the [`NcPaletteIndex`] from the [`NcChannel_u32`].
601///
602/// The channel must be palette-indexed, or the return value is meaningless.
603/// Verify palette indexing with [`ncchannel_palindex_p`].
604///
605/// *Method: NcChannel.[palindex()][NcChannel#method.palindex]*
606pub fn ncchannel_palindex(channel: impl Into<NcChannel_u32>) -> NcPaletteIndex {
607    (channel.into() & 0xFF) as NcPaletteIndex
608}
609
610/// Sets the [`NcPaletteIndex`] of the [`NcChannel_u32`], and the channel into
611/// palette indexed mode.
612///
613/// Note: Unlike the original C function, this one can't fail.
614///
615/// *Method: NcChannel.[set_palindex()][NcChannel#method.set_palindex]*
616pub fn ncchannel_set_palindex(channel: &mut NcChannel_u32, index: impl Into<NcPaletteIndex>) {
617    ncchannel_set_alpha(channel, c_api::NCALPHA_OPAQUE);
618    *channel &= 0xFF000000;
619    *channel |= c_api::NC_BGDEFAULT_MASK | c_api::NC_BG_PALETTE | index.into() as NcChannel_u32;
620}
621
622/// Is this [`NcChannel_u32`] using palette-indexed color rather than RGB?
623///
624/// *Method: NcChannel.[palindex_p()][NcChannel#method.palindex_p]*
625#[inline]
626pub fn ncchannel_palindex_p(channel: impl Into<NcChannel_u32>) -> bool {
627    let channel = channel.into();
628    !ncchannel_default_p(channel) && (channel & c_api::NC_BG_PALETTE) != 0
629}
630
631/// Gets the [`NcPaletteIndex`] from the foreground [`NcChannel_u32`].
632///
633/// *Method: NcChannels.[fg_palindex()][NcChannels#method.fg_palindex]*
634#[inline]
635pub fn ncchannels_fg_palindex(channels: impl Into<NcChannels_u64>) -> NcPaletteIndex {
636    ncchannel_palindex(ncchannels_fchannel(channels.into()))
637}
638
639/// Gets the [`NcPaletteIndex`] from the background [`NcChannel_u32`].
640///
641/// *Method: NcChannels.[bg_palindex()][NcChannels#method.bg_palindex]*
642#[inline]
643pub fn ncchannels_bg_palindex(channels: impl Into<NcChannels_u64>) -> NcPaletteIndex {
644    ncchannel_palindex(ncchannels_bchannel(channels.into()))
645}
646
647/// Is the foreground of an [`NcChannels_u64`] using an [indexed][`NcPaletteIndex`]
648/// [`NcPalette`][crate::NcPalette] color?
649///
650/// *Method: NcChannels.[fg_palindex_p()][NcChannels#method.fg_palindex_p]*
651#[inline]
652pub fn ncchannels_fg_palindex_p(channels: impl Into<NcChannels_u64>) -> bool {
653    ncchannel_palindex_p(ncchannels_fchannel(channels.into()))
654}
655
656/// Is the background of an [`NcChannels_u64`] using an [indexed][`NcPaletteIndex`]
657/// [`NcPalette`][crate::NcPalette] color?
658///
659/// *Method: NcChannels.[bg_palindex_p()][NcChannels#method.bg_palindex_p]*
660#[inline]
661pub fn ncchannels_bg_palindex_p(channels: impl Into<NcChannels_u64>) -> bool {
662    ncchannel_palindex_p(ncchannels_bchannel(channels.into()))
663}
664
665/// Sets the foreground of an [`NcChannels_u64`] as using an
666/// [*indexed*][`NcPaletteIndex`] [`NcPalette`][crate::NcPalette] color.
667///
668/// Note: Unlike the original C function, this one can't fail.
669///
670/// *Method: NcChannels.[set_fg_palindex()][NcChannels#method.set_fg_palindex]*
671#[inline]
672#[allow(clippy::unnecessary_cast)]
673pub fn ncchannels_set_fg_palindex(channels: &mut NcChannels_u64, index: impl Into<NcPaletteIndex>) {
674    let mut channel = ncchannels_fchannel(*channels);
675    ncchannel_set_palindex(&mut channel, index.into());
676    *channels = (channel as NcChannels_u64) << 32 | (*channels & 0xffffffff as NcChannels_u64)
677}
678
679/// Sets the background of an [`NcChannels_u64`] as using an
680/// [*indexed*][`NcPaletteIndex`] [`NcPalette`][crate::NcPalette] color.
681///
682/// Note: Unlike the original C function, this one can't fail.
683///
684/// *Method: NcChannels.[set_bg_palindex()][NcChannels#method.set_bg_palindex]*
685#[inline]
686pub fn ncchannels_set_bg_palindex(channels: &mut NcChannels_u64, index: impl Into<NcPaletteIndex>) {
687    let mut channel = ncchannels_bchannel(*channels);
688    ncchannel_set_palindex(&mut channel, index.into());
689    ncchannels_set_bchannel(channels, channel);
690}