---
name: "notcurses_cell"
section: "3"
platform: "linux"
package: "notcurses"
version: "3.0.17-3"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/notcurses_cell"
---

# notcurses\_cell(3)

operations on nccell objects

## NAME

notcurses\_cell - operations on nccell objects

## SYNOPSIS

**#include \<notcurses/notcurses.h\>**

-

  ```
  // See DESCRIPTION below for information on EGC encoding
  typedef struct nccell {
    uint32_t gcluster;          // 4B → 4B
    uint8_t gcluster_backstop;  // 1B → 5B (8 bits of zero)
    uint8_t width;              // 1B → 6B (8 bits of column width)
    uint16_t stylemask;         // 2B → 8B (16 bits of NCSTYLE_* attributes)
    uint64_t channels;
  } nccell;
  #define NCCELL_TRIVIAL_INITIALIZER \
   { .gcluster = '\0', .stylemask = 0, .channels = 0, }
  #define NCCELL_CHAR_INITIALIZER(c) \
   { .gcluster = (c), .stylemask = 0, .channels = 0, }
  #define NCCELL_INITIALIZER(c, s, chan) \
   { .gcluster = (c), .stylemask = (s), .channels = (chan), }
  #define NCALPHA_HIGHCONTRAST  0x30000000ull
  #define NCALPHA_TRANSPARENT   0x20000000ull
  #define NCALPHA_BLEND         0x10000000ull
  #define NCALPHA_OPAQUE        0x00000000ull
  ```

**void nccell\_init(nccell\*** *c***);**

**int nccell\_load(struct ncplane\*** *n***, nccell\*** *c***, const char\*** *gcluster***);**

**int nccell\_prime(struct ncplane\*** *n***, nccell\*** *c***, const char\*** *gcluster***,** **uint32\_t** *stylemask***, uint64\_t** *channels***);**

**int nccell\_duplicate(struct ncplane\*** *n***, nccell\*** *targ***, const nccell\*** *c***);**

**void nccell\_release(struct ncplane\*** *n***, nccell\*** *c***);**

**int nccell\_cols(const nccell\*** *c***);**

**void nccell\_styles\_set(nccell\*** *c***, unsigned** *stylebits***);**

**unsigned nccell\_styles(const nccell\*** *c***);**

**bool nccellcmp(const struct ncplane\*** *n1***, const** **nccell\*** *c1***, const struct ncplane\*** *n2***, const nccell\*** *c2***);**

**void nccell\_on\_styles(nccell\*** *c***, unsigned** *stylebits***);**

**void nccell\_off\_styles(nccell\*** *c***, unsigned** *stylebits***);**

**void nccell\_set\_fg\_default(nccell\*** *c***);**

**void nccell\_set\_bg\_default(nccell\*** *c***);**

**int nccell\_set\_fg\_alpha(nccell\*** *c***, unsigned** *alpha***);**

**int nccell\_set\_bg\_alpha(nccell\*** *c***, unsigned** *alpha***);**

**bool nccell\_double\_wide\_p(const nccell\*** *c***);**

**const char\* nccell\_extended\_gcluster(const struct ncplane\*** *n***, const nccell\*** *c***);**

**char\* nccell\_strdup(const struct ncplane\*** *n***,** **const nccell\*** *c***);**

**int nccell\_load\_char(struct ncplane\*** *n***, nccell\*** *c***, char** *ch***);**

**int nccell\_load\_egc32(struct ncplane\*** *n***,** **nccell\*** *c***, uint32\_t** *egc***);**

**int nccell\_load\_ucs32(struct ncplane\*** *n***,** **nccell\*** *c***, uint32\_t** *u***);**

**char\* nccell\_extract(const struct ncplane\*** *n***,** **const nccell\*** *c***, uint16\_t\*** *stylemask***, uint64\_t\*** *channels***);**

**uint64\_t nccell\_channels(const nccell\*** *c***);**

**uint32\_t nccell\_bchannel(const nccell\*** *c***);**

**uint32\_t nccell\_fchannel(const nccell\*** *c***);**

**uint64\_t nccell\_set\_channels(nccell\*** *c***,** **uint64\_t** *channels***);**

**uint64\_t nccell\_set\_bchannel(nccell\*** *c***,** **uint32\_t** *channel***);**

**uint64\_t nccell\_set\_fchannel(nccell\*** *c***,** **uint32\_t** *channel***);**

**uint32\_t nccell\_fg\_rgb(const nccell\*** *c***);**

**uint32\_t nccell\_bg\_rgb(const nccell\*** *c***);**

**unsigned nccell\_fg\_alpha(const nccell\*** *c***);**

**unsigned nccell\_bg\_alpha(const nccell\*** *c***);**

**unsigned nccell\_fg\_rgb8(const nccell\*** *c***,** **unsigned\*** *r***, unsigned\*** *g***,** **unsigned\*** *b***);**

**unsigned nccell\_bg\_rgb8(const ncell\*** *c***,** **unsigned\*** *r***, unsigned\*** *g***,** **unsigned\*** *b***);**

**int nccell\_set\_fg\_rgb8(nccell\*** *c***, unsigned** *r***, unsigned** *g***, unsigned** *b***);**

**int nccell\_set\_bg\_rgb8(nccell\*** *c***, unsigned** *r***, unsigned** *g***, unsigned** *b***);**

**void nccell\_set\_fg\_rgb8\_clipped(nccell\*** *c***, int** *r***, int** *g***, int** *b***);**

**void nccell\_set\_bg\_rgb8\_clipped(nccell\*** *c***, int** *r***, int** *g***, int** *b***);**

**int nccell\_set\_fg\_rgb(nccell\*** *c***, uint32\_t** *channel***);**

**int nccell\_set\_bg\_rgb(nccell\*** *c***, uint32\_t** *channel***);**

**bool nccell\_fg\_default\_p(const nccell\*** *c***);**

**bool nccell\_bg\_default\_p(const nccell\*** *c***);**

**int nccell\_set\_fg\_palindex(nccell\*** *cl***, unsigned** *idx***);**

**int nccell\_set\_bg\_palindex(nccell\*** *cl***, unsigned** *idx***);**

**uint32\_t nccell\_fg\_palindex(const nccell\*** *cl***);**

**uint32\_t nccell\_bg\_palindex(const nccell\*** *cl***);**

**bool nccell\_fg\_palindex\_p(const nccell\*** *cl***);**

**bool nccell\_bg\_palindex\_p(const nccell\*** *cl***);**

**int ncstrwidth(const char\*** *text***)**;

**int ncstrwidth\_valid(const char\*** *text***, int\*** *validbytes***, int\*** *validwidth***)**;

## DESCRIPTION

Cells make up the framebuffer associated with each plane, with one cell per addressable coordinate. You should not usually need to interact directly with **nccell**s.

Each **nccell** contains exactly one extended grapheme cluster. If the EGC is encoded in UTF-8 with four or fewer bytes (all Unicode codepoints as of Unicode 13 can be encoded in no more than four UTF-8 bytes), it is encoded directly into the **nccell**'s **gcluster** field, and no additional storage is necessary. Otherwise, the EGC is stored as a nul-terminated UTF-8 string in some backing egcpool. Egcpools are associated with **ncplane**s, so **nccell**s must be considered associated with **ncplane**s. Indeed, **ncplane\_erase** destroys the backing storage for all a plane's cells, invalidating them. This association is formed at the time of **nccell\_load**, **nccell\_prime**, or **nccell\_duplicate**. All of these functions first call **nccell\_release**, as do **nccell\_load\_egc32**, **nccell\_load\_char**, and **nccell\_load\_ucs32**. When done using a **nccell** entirely, call **nccell\_release**. **ncplane\_destroy** will free up the memory used by the **nccell**, but the backing egcpool has a maximum size of 16MiB, and failure to release **nccell**s can eventually block new output. Writing over an **ncplane**'s cells releases them automatically.

**nccell\_extended\_gcluster** provides a nul-terminated handle to the EGC. This ought be considered invalidated by changes to the **nccell** or **egcpool**. The handle is **not** heap-allocated; do **not** attempt to **[free(3)](/free/3.md)** it. A heap-allocated copy can be acquired with **nccell\_strdup**.

**ncstrwidth\_valid** returns the number of columns occupied by a valid UTF-8 string, or -1 if an error is encountered. In either case, the number of valid bytes and columns, respectively, consumed before error into ***validbytes*** and ***validwidth*** (assuming them to not be **NULL**).

**nccell\_fg\_palindex** extracts the palette index from a cell's foreground channel. The channel must be palette-indexed, or the return value is meaningless. Verify palette indexing with **nccell\_fg\_palindex\_p**. A cell's foreground channel can be set to palette-indexed mode (and have the index set) with **nccell\_set\_fg\_palindex**. The index must be less than **NCPALETTESIZE**. Replace **fg** with **bg** to operate on the background channel.

## RETURN VALUES

**nccell\_load** and similar functions return the number of bytes loaded from the EGC, or -1 on failure. They can fail due to either an invalid UTF-8 input, or the backing egcpool reaching its maximum size.

**nccell\_set\_fg\_rgb8** and similar functions will return -1 if provided invalid inputs, and 0 otherwise.

**nccellcmp** returns a negative integer, 0, or a positive integer if ***c1*** is less than, equal to, or more than ***c2***, respectively.

**nccell\_extended\_gcluster** returns **NULL** if called on a sprixel (see **[notcurses\_visual(3)](/notcurses_visual/3.md)**.

**nccell\_cols** returns the number of columns occupied by ***c***, according to **[wcwidth(3)](/wcwidth/3.md)**\*. **ncstrwidth** is an equivalent for strings. **ncstrwidth\_valid** returns the same value as **ncstrwidth**.

## NOTES

**cell** was renamed to **nccell** in Notcurses 2.2.0, so as not to bleed such a common term into the (single, global) C namespace. **cell** will be retained as an alias until Notcurses 3.0. Likewise, many functions prefixed with **cell** have been renamed to start with **nccell**.

## SEE ALSO

**[notcurses(3)](/notcurses/3.md)**, **[notcurses\_channels(3)](/notcurses_channels/3.md)**, **[notcurses\_plane(3)](/notcurses_plane/3.md)**, **[notcurses\_output(3)](/notcurses_output/3.md)**, **[notcurses\_visual(3)](/notcurses_visual/3.md)**, **[wcwidth(3)](/wcwidth/3.md)**, **[utf8(7)](/utf8/7.md)**

## AUTHORS

nick black ⟨nickblack@linux.com⟩\\c.
