1% notcurses_plane(3)
2% nick black <nickblack@linux.com>
3% v3.0.1
4
5# NAME
6
7notcurses_plane - operations on ncplanes
8
9# SYNOPSIS
10
11**#include <notcurses/notcurses.h>**
12
13```c
14#define NCPLANE_OPTION_HORALIGNED   0x0001ull
15#define NCPLANE_OPTION_VERALIGNED   0x0002ull
16#define NCPLANE_OPTION_MARGINALIZED 0x0004ull
17#define NCPLANE_OPTION_FIXED        0x0008ull
18#define NCPLANE_OPTION_AUTOGROW     0x0010ull
19#define NCPLANE_OPTION_VSCROLL      0x0020ull
20
21typedef struct ncplane_options {
22  int y;            // vertical placement relative to parent plane
23  int x;            // horizontal placement relative to parent plane
24  int rows;         // number of rows, must be positive
25  int cols;         // number of columns, must be positive
26  void* userptr;    // user curry, may be NULL
27  const char* name; // name (used only for debugging), may be NULL
28  int (*resizecb)(struct ncplane*); // called on parent resize
29  uint64_t flags;   // closure over NCPLANE_OPTION_*
30  unsigned margin_b, margin_r; // bottom and right margins
31} ncplane_options;
32
33#define NCSTYLE_MASK      0xffffu
34#define NCSTYLE_ITALIC    0x0010u
35#define NCSTYLE_UNDERLINE 0x0008u
36#define NCSTYLE_UNDERCURL 0x0004u
37#define NCSTYLE_BOLD      0x0002u
38#define NCSTYLE_STRUCK    0x0001u
39#define NCSTYLE_NONE      0
40```
41
42**struct ncplane* ncplane_create(struct ncplane* ***n***, const ncplane_options* ***nopts***);**
43
44**struct ncplane* ncpile_create(struct notcurses* ***n***, const ncplane_options* ***nopts***);**
45
46**struct ncplane* ncplane_reparent(struct ncplane* ***n***, struct ncplane* ***newparent***);**
47
48**struct ncplane* ncplane_reparent_family(struct ncplane* ***n***, struct ncplane* ***newparent***);**
49
50**int ncplane_descendant_p(const struct ncplane* ***n***, const struct ncplane* ***ancestor***);**
51
52**int ncplane_resize_realign(struct ncplane* ***n***);**
53
54**int ncplane_resize_maximize(struct ncplane* ***n***);**
55
56**int ncplane_resize_marginalized(struct ncplane* ***n***);**
57
58**int ncplane_resize_placewithin(struct ncplane* ***n***);**
59
60**void ncplane_set_resizecb(struct ncplane* ***n***, int(*resizecb)(struct ncplane*));**
61
62**int (*ncplane_resizecb(const struct ncplane* ***n***))(struct ncplane*);**
63
64**struct ncplane* ncplane_dup(struct ncplane* ***n***, void* ***opaque***);**
65
66**int ncplane_resize(struct ncplane* ***n***, int ***keepy***, int ***keepx***, int ***keepleny***, int ***keeplenx***, int ***yoff***, int ***xoff***, int ***ylen***, int ***xlen***);**
67
68**int ncplane_move_yx(struct ncplane* ***n***, int ***y***, int ***x***);**
69
70**int ncplane_move_rel(struct ncplane* ***n***, int ***y***, int ***x***);**
71
72**void ncplane_yx(const struct ncplane* ***n***, int* restrict ***y***, int* restrict ***x***);**
73
74**int ncplane_y(const struct ncplane* ***n***);**
75
76**int ncplane_x(const struct ncplane* ***n***);**
77
78**void ncplane_abs_yx(const struct ncplane* ***n***, int* ***y***, int* ***x***);**
79
80**int ncplane_abs_y(const struct ncplane* ***n***);**
81
82**int ncplane_abs_x(const struct ncplane* ***n***);**
83
84**struct ncplane* ncplane_parent(struct ncplane* ***n***);**
85
86**const struct ncplane* ncplane_parent_const(const struct ncplane* ***n***);**
87
88**int ncplane_set_base_cell(struct ncplane* ***ncp***, const nccell* ***c***);**
89
90**int ncplane_set_base(struct ncplane* ***ncp***, const char* ***egc***, uint16_t ***stylemask***, uint64_t ***channels***);**
91
92**int ncplane_base(struct ncplane* ***ncp***, nccell* ***c***);**
93
94**static inline void ncplane_move_top(struct ncplane* ***n***);**
95
96**static inline void ncplane_move_bottom(struct ncplane* ***n***);**
97
98**void ncplane_move_family_top(struct ncplane* ***n***);**
99
100**void ncplane_move_family_bottom(struct ncplane* ***n***);**
101
102**int ncplane_move_above(struct ncplane* restrict ***n***, struct ncplane* restrict ***targ***);**
103
104**int ncplane_move_below(struct ncplane* restrict ***n***, struct ncplane* restrict ***targ***);**
105
106**int ncplane_move_family_above(struct ncplane* restrict ***n***, struct ncplane* restrict ***targ***);**
107
108**int ncplane_move_family_below(struct ncplane* restrict ***n***, struct ncplane* restrict ***targ***);**
109
110**struct ncplane* ncplane_below(struct ncplane* ***n***);**
111
112**struct ncplane* ncplane_above(struct ncplane* ***n***);**
113
114**char* ncplane_at_cursor(struct ncplane* ***n***, uint16_t* ***stylemask***, uint64_t* ***channels***);**
115
116**int ncplane_at_cursor_cell(struct ncplane* ***n***, nccell* ***c***);**
117
118**char* ncplane_at_yx(const struct ncplane* ***n***, int ***y***, int ***x***, uint16_t* ***stylemask***, uint64_t* ***channels***);**
119
120**int ncplane_at_yx_cell(struct ncplane* ***n***, int ***y***, int ***x***, nccell* ***c***);**
121
122**uint32_t* ncplane_as_rgba(const struct ncplane* ***nc***, ncblitter_e ***blit***, unsigned ***begy***, unsigned ***begx***, unsigned ***leny***, unsigned ***lenx***, unsigned* ***pxdimy***, unsigned* ***pxdimx***);**
123
124**char* ncplane_contents(const struct ncplane* ***nc***, int ***begy***, int ***begx***, unsigned ***leny***, unsigned ***lenx***);**
125
126**void* ncplane_set_userptr(struct ncplane* ***n***, void* ***opaque***);**
127
128**void* ncplane_userptr(struct ncplane* ***n***);**
129
130**void ncplane_dim_yx(const struct ncplane* ***n***, unsigned* restrict ***rows***, unsigned* restrict ***cols***);**
131
132**static inline unsigned ncplane_dim_y(const struct ncplane* ***n***);**
133
134**static inline unsigned ncplane_dim_x(const struct ncplane* ***n***);**
135
136**void ncplane_cursor_yx(const struct ncplane* ***n***, unsigned* restrict ***y***, unsigned* restrict ***x***);**
137
138**void ncplane_translate(const struct ncplane* ***src***, const struct ncplane* ***dst***, int* restrict ***y***, int* restrict ***x***);**
139
140**bool ncplane_translate_abs(const struct ncplane* ***n***, int* restrict ***y***, int* restrict ***x***);**
141
142**uint64_t ncplane_channels(const struct ncplane* ***n***);**
143
144**void ncplane_set_channels(struct ncplane* ***nc***, uint64_t ***channels***);**
145
146**static inline unsigned ncplane_bchannel(struct ncplane* ***nc***);**
147
148**static inline unsigned ncplane_fchannel(struct ncplane* ***nc***);**
149
150**static inline unsigned ncplane_fg_rgb8(struct ncplane* ***nc***);**
151
152**static inline unsigned ncplane_bg_rgb8(struct ncplane* ***nc***);**
153
154**static inline unsigned ncplane_fg_alpha(struct ncplane* ***nc***);**
155
156**static inline unsigned ncplane_bg_alpha(struct ncplane* ***nc***);**
157
158**static inline unsigned ncplane_fg_rgb8(struct ncplane* ***n***, unsigned* ***r***, unsigned* ***g***, unsigned* ***b***);**
159
160**static inline unsigned ncplane_bg_rgb8(struct ncplane* ***n***, unsigned* ***r***, unsigned* ***g***, unsigned* ***b***);**
161
162**int ncplane_set_fg_rgb8(struct ncplane* ***n***, unsigned ***r***, unsigned ***g***, unsigned ***b***);**
163
164**int ncplane_set_bg_rgb8(struct ncplane* ***n***, unsigned ***r***, unsigned ***g***, unsigned ***b***);**
165
166**void ncplane_set_fg_rgb8_clipped(struct ncplane* ***n***, int ***r***, int ***g***, int ***b***);**
167
168**void ncplane_set_bg_rgb8_clipped(struct ncplane* ***n***, int ***r***, int ***g***, int ***b***);**
169
170**int ncplane_set_fg_rgb8(struct ncplane* ***n***, uint32_t ***channel***);**
171
172**int ncplane_set_bg_rgb8(struct ncplane* ***n***, uint32_t ***channel***);**
173
174**void ncplane_set_fg_default(struct ncplane* ***n***);**
175
176**void ncplane_set_bg_default(struct ncplane* ***n***);**
177
178**int ncplane_set_fg_alpha(struct ncplane* ***n***, unsigned ***alpha***);**
179
180**int ncplane_set_bg_alpha(struct ncplane* ***n***, unsigned ***alpha***);**
181
182**int ncplane_set_fg_palindex(struct ncplane* ***n***, int ***idx***);**
183
184**int ncplane_set_bg_palindex(struct ncplane* ***n***, int ***idx***);**
185
186**uint16_t ncplane_styles(const struct ncplane* ***n***);**
187
188**void ncplane_set_styles(struct ncplane* ***n***, unsigned ***stylebits***);**
189
190**void ncplane_on_styles(struct ncplane* ***n***, unsigned ***stylebits***);**
191
192**void ncplane_off_styles(struct ncplane* ***n***, unsigned ***stylebits***);**
193
194**void ncplane_greyscale(struct ncplane* ***n***);**
195
196**int ncplane_blit_bgrx(struct ncplane* ***nc***, int ***placey***, int ***placex***, int ***linesize***, ncblitter_e ***blitter***, const unsigned char* ***data***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
197
198**int ncplane_blit_rgba(struct ncplane* ***nc***, int ***placey***, int ***placex***, int ***linesize***, ncblitter_e ***blitter***, const unsigned char* ***data***, int ***begy***, int ***begx***, int ***leny***, int ***lenx***);**
199
200**int ncplane_destroy(struct ncplane* ***ncp***);**
201
202**void notcurses_drop_planes(struct notcurses* ***nc***);**
203
204**int ncplane_mergedown(struct ncplane* ***src***, struct ncplane* ***dst***, int ***begsrcy***, int ***begsrcx***, unsigned ***leny***, unsigned ***lenx***, int ***dsty***, int ***dstx***);**
205
206**int ncplane_mergedown_simple(struct ncplane* restrict ***src***, struct ncplane* restrict ***dst***);**
207
208**void ncplane_erase(struct ncplane* ***n***);**
209
210**int ncplane_erase_region(struct ncplane* ***n***, int ***ystart***, int ***xstart***, int ***ylen***, int ***xlen***);**
211
212**bool ncplane_set_scrolling(struct ncplane* ***n***, unsigned ***scrollp***);**
213
214**bool ncplane_scrolling_p(const struct ncplane* ***n***);**
215
216**bool ncplane_set_autogrow(struct ncplane* ***n***, unsigned ***growp***);**
217
218**bool ncplane_autogrow_p(const struct ncplane* ***n***);**
219
220**int ncplane_scrollup(struct ncplane* ***n***, int ***r***);**
221
222**int ncplane_scrollup_child(struct ncplane* ***n***, const struct ncplane* ***child***);**
223
224**int ncplane_rotate_cw(struct ncplane* ***n***);**
225
226**int ncplane_rotate_ccw(struct ncplane* ***n***);**
227
228**void ncplane_pixel_geom(const struct notcurses* ***n***, unsigned* restrict ***pxy***, unsigned* restrict ***pxx***, unsigned* restrict ***celldimy***, unsigned* restrict ***celldimx***, unsigned* restrict ***maxbmapy***, unsigned* restrict ***maxbmapx***);**
229
230**int ncplane_set_name(struct ncplane* ***n***, const char* ***name***);**
231
232**char* ncplane_name(const struct ncplane* ***n***);**
233
234# DESCRIPTION
235
236Ncplanes are the fundamental drawing object of notcurses. All output functions
237take a **struct ncplane** as an argument. They can be any size, and placed
238anywhere. In addition to its framebuffer--a rectilinear matrix of **nccell**s
239(see **notcurses_cell(3)**)--an ncplane is defined by:
240
241* a base **nccell**, used for any cell on the plane without a glyph,
242* the egcpool backing its **nccell**s,
243* a current cursor location,
244* a current style, foreground channel, and background channel,
245* its geometry,
246* a configured user pointer,
247* position relative to the standard plane,
248* the plane, if any, to which it is bound,
249* the next plane bound by the plane to which it is bound,
250* the head of the list of its bound planes,
251* its resize methodology,
252* whether a sprixel (see **notcurses_visual(3)**) is associated,
253* its z-index, and
254* a name (used only for debugging).
255
256New planes can be created with **ncplane_create**. If a plane is bound to
257another, x and y coordinates are relative to the plane to which it is bound,
258and if this latter plane moves, all its bound planes move along with it. When a
259plane is destroyed, all planes bound to it (directly or transitively) are
260destroyed.
261
262If the **NCPLANE_OPTION_HORALIGNED** flag is provided, ***x*** is interpreted
263as an **ncalign_e** rather than an absolute position. If the
264**NCPLANE_OPTION_VERALIGNED** flag is provided, ***y*** is interpreted as an
265**ncalign_e** rather than an absolute postiion. Either way, all positions
266are relative to the parent plane. **ncplane_resize_realign** should usually be
267used together with these flags, so that the plane is automatically realigned
268upon a resize of its parent.
269
270If the **NCPLANE_OPTION_MARGINALIZED** flag is provided, neither
271**NCPLANE_OPTION_HORALIGNED** nor **NCPLANE_OPTION_VERALIGNED** may be
272provided, and ***rows*** and ***cols*** must both be 0. ***y*** and ***x***
273will be interpreted as top and left margins. ***margin_b*** and ***margin_r***
274will be interpreted as bottom and right margins. The plane will take the maximum
275space possible subject to its parent planes and these margins. The plane cannot
276become smaller than 1x1 (the margins are best-effort).
277**ncplane_resize_marginalized** should usually be used together with this flag,
278so that the plane is automatically resized.
279
280**ncplane_reparent** detaches the plane ***n*** from any plane to which it is
281bound, and binds it to ***newparent***. Its children are reparented to its
282previous parent. The standard plane cannot be reparented. If ***newparent*** is
283**NULL**, the plane becomes the root plane of a new, unrendered stack. When
284**ncplane_reparent_family** is used, all planes bound to ***n*** move along with
285it during a reparenting operation. See [Piles][] below.
286
287**ncplane_destroy** destroys a particular ncplane, after which it must not be
288used again. **notcurses_drop_planes** destroys all ncplanes other than the
289stdplane. Any references to such planes are, of course, invalidated. It is
290undefined to destroy a plane concurrently with any other operation involving
291that plane, or any operation involving the z-axis.
292
293It is an error for two threads to concurrently mutate a single ncplane. So long
294as rendering is not taking place, however, multiple threads may safely output
295to multiple ncplanes. So long as all threads are readers, multiple threads may
296work with a single ncplane. A reading function is any which accepts a **const
297struct ncplane**.
298
299A plane can be moved relative to its parent plane's origin with
300**ncplane_move_yx**. If the plane has no parent, the move is relative to
301the rendering area. A plane can be moved off-screen entirely, in which case
302it will not be visible following rasterization; it can also be partially
303off-screen.
304
305A plane has a virtual cursor; Set its new position with **ncplane_cursor_move_yx**.
306Specifying -1 as one or both coordinates will hold that axis constant. You may
307move a cursor relatively to its current position with **ncplane_cursor_move_rel**.
308Unless coordinates are specified for a call, action takes place at the plane's
309virtual cursor, which automatically moves along with output. The current virtual
310cursor location can be acquired with **ncplane_cursor_yx**.
311
312**ncplane_yx** returns the coordinates of the specified plane's origin, relative
313to the plane to which it is bound. Either or both of ***y*** and ***x*** may
314be **NULL**. **ncplane_y** and **ncplane_x** allow a single component of this
315location to be retrieved. **ncplane_abs_yx** returns the coordinates of the
316specified plane's origin relative to its pile.
317
318**ncplane_translate** translates coordinates expressed relative to the plane
319***src***, and writes the coordinates of that cell relative to ***dst***. The cell
320need not intersect with ***dst***, though this will yield coordinates which are
321invalid for writing or reading on ***dst***. If ***dst*** is **NULL**, it is taken
322to refer to the standard plane. **ncplane_translate_abs** takes coordinates
323expressed relative to the standard plane, and returns coordinates relative to
324***dst***, returning **false** if the coordinates are invalid for ***dst***.
325
326**ncplane_mergedown** writes to ***dst*** the frame that would be rendered if only
327***src*** and ***dst*** existed on the z-axis, ad ***dst*** represented the entirety
328of the rendering region. Only those cells where ***src*** intersects with ***dst***
329might see changes. It is an error to merge a plane onto itself.
330
331**ncplane_erase** zeroes out every cell of the plane, dumps the egcpool, and
332homes the cursor. The base cell is preserved, as are the active attributes.
333**ncplane_erase_region** does the same for a subregion of the plane. For the
334latter, supply 0 for ***ylen*** and/or ***xlen*** to erase through that
335dimension, starting at the specified point. Supply -1 for ***ystart*** and/or
336***xstart*** to use the cursor's current position along that axis for a starting
337point. Negative ***ylen*** and ***xlen*** move up and to the left from the starting
338coordinate; positive ***ylen*** and ***xlen*** move down and to the right from same.
339See [BUGS][] below.
340
341When a plane is resized (whether by **ncplane_resize**, **SIGWINCH**, or any
342other mechanism), a depth-first recursion is performed on its children.
343Each child plane having a non-**NULL** **resizecb** will see that callback
344invoked following resizing of its parent's plane. If it returns non-zero, the
345resizing cascade terminates, returning non-zero. Otherwise, resizing proceeds
346recursively.
347
348**ncplane_move_top** and **ncplane_move_bottom** extract their argument
349***n*** from the z-axis, and reinsert it at the top or bottom, respectively,
350of its pile. These functions are both O(1). **ncplane_move_family_top** and
351**ncplane_move_family_bottom** do the same, and move any bound descendants
352along with the plane. Ordering among the plane and its descendants will be
353maintained. For example, assume a pile with A at the top of its z-axis,
354followed by B, C, D, and E, where E is bound to C. Calling
355**ncplane_move_family_top** on C will result in the order CEABD. Calling
356**ncplane_move_family_bottom** on C will result in the order ABDCE. Calling
357**ncplane_move_family_top** or **ncplane_move_top** on E will result in EABCD.
358Calling **ncplane_move_family_bottom** on E is a no-op. These two functions
359are O(N) on the number of planes in the pile.
360
361**ncplane_move_above** and **ncplane_move_below** move the argument ***n***
362above or below, respectively, the argument ***targ***. Both operate in O(1).
363
364**ncplane_at_yx** and **ncplane_at_yx_cell** retrieve the contents of the plane
365at the specified coordinate. The content is returned as it will be used during
366rendering, and thus integrates any base cell as appropriate. If called on the
367secondary columns of a wide glyph, **ncplane_at_yx** returns the EGC, and thus
368cannot be used to distinguish between primary and secondary columns.
369**ncplane_at_yx_cell**, however, preserves this information: retrieving a
370secondary column of a wide glyph with **ncplane_at_yx_cell** will fill in
371the **nccell** argument such that **nccell_extended_gcluster(3)** returns an
372empty string, and **nccell_wide_right_p(3)** returns **true**.
373
374**ncplane_set_name** sets the plane's name, freeing any old name. ***name***
375may be **NULL**. **ncplane_set_name** duplicates the provided name internally.
376
377## Base cells
378
379Each plane has a base cell, initialized to all zeroes. When rendering, the
380cells of the plane are examined in turn. Each cell has three independent
381rendering elements--its EGC, its foreground channel, and its background
382channel. Any default channel is replaced with the corresponding channel from
383that plane's base cell. **ncplane_erase** has no effect on the base cell.
384Calling **ncplane_erase** on a plane whose base cell is a purple 'A' results
385(for rendering purposes) in a plane made up entirely of purple 'A's.
386
387**ncplane_set_base_cell** uses the **nccell** ***c*** (which must be bound to
388the **ncplane** ***ncp***, and must be the first **nccell** of a multicolumn
389sequence) to set the base cell. **ncplane_set_base** does the same with
390***egc***, ***stylemask***, and ***channels***.
391
392## Piles
393
394A single **notcurses** context is made up of one or more piles. A pile is a
395set of one or more **ncplane**s, including the partial orderings made up of
396their binding and z-axis pointers. A pile has a top and bottom **ncplane**
397(this might be a single plane), and one or more root planes (planes which are
398bound to themselves). Multiple threads can concurrently operate on distinct
399piles, even changing one while rendering another.
400
401Each plane is part of one and only one pile. By default, a plane is part of the
402same pile containing that plane to which it is bound. If **ncpile_create** is
403used in the place of **ncplane_create**, the returned plane becomes the root
404plane, top, and bottom of a new pile. As a root plane, it is bound to itself. A
405new pile can also be created by reparenting a plane to itself, though if the
406plane is already a root plane, this is a no-op.
407
408When a plane is moved to a different pile (whether new or preexisting), any
409planes which were bound to it are rebound to its previous parent. If the plane
410was a root plane of some pile, any bound planes become root planes. The new
411plane is placed immediately atop its new parent on its new pile's z-axis.
412When **ncplane_reparent_family** is used, all planes bound to the reparented
413plane are moved along with it. Their relative z-order is maintained.
414
415More information is available from **notcurses_pile(3)**.
416
417## Binding
418
419The planes of a pile make up a directed acyclic forest. Planes bound to
420themselves make up the root planes of the pile. Every plane is either a
421root plane, or bound to some other plane in its pile. A plane and its
422descendants make up a family. When a plane is moved using **ncplane_move_yx**,
423its family is moved along with it.
424
425## Scrolling
426
427All planes, including the standard plane, are created with scrolling disabled.
428Control scrolling on a per-plane basis with **ncplane_set_scrolling**.
429Attempting to print past the end of a line will stop at the plane boundary, and
430indicate an error. On a plane 10 columns wide and two rows high, printing
431"0123456789" at the origin should succeed, but printing "01234567890" will by
432default fail at the eleventh character. In either case, the cursor will be left
433at location 0x10; it must be moved before further printing can take place. If
434scrolling is enabled, the first row will be filled with 01234546789, the second
435row will have 0 written to its first column, and the cursor will end up at 1x1.
436Note that it is still an error to manually attempt to move the cursor
437off-plane, or to specify off-plane output. Box-drawing does not result in
438scrolling; attempting to draw a 2x11 box on our 2x10 plane will result in an
439error and no output. When scrolling is enabled, and output takes place while
440the cursor is past the end of the last row, the first row is discarded, all
441other rows are moved up, the last row is cleared, and output begins at the
442beginning of the last row. This does not take place until output is generated
443(i.e. it is possible to fill a plane when scrolling is enabled).
444
445Creating a plane with the **NCPLANE_OPTION_VSCROLL** flag is equivalent to
446immediately calling **ncplane_set_scrolling** on that plane with an argument
447of **true**.
448
449By default, planes bound to a scrolling plane will scroll along with it, if
450they intersect the plane. This can be disabled by creating them with the
451**NCPLANE_OPTION_FIXED** flag.
452
453## Autogrow
454
455Normally, once output reaches the right boundary of a plane, it is impossible
456to place more output unless the cursor is first moved. If scrolling is
457enabled, the cursor will automatically move down and to the left in this case,
458but upon reaching the bottom right corner of the plane, it is impossible to
459place more output without a scrolling event. If autogrow is in play, the plane
460will automatically be enlarged to accommodate output. If scrolling is disabled,
461growth takes place to the right; it otherwise takes place at the bottom. The
462plane only grows in one dimension. Autogrow cannot be enabled for the standard
463plane.
464
465Creating a plane with the **NCPLANE_OPTION_AUTOGROW** flag is equivalent to
466immediately calling **ncplane_set_autogrow** on that plane with an argument
467of **true**.
468
469## Bitmaps
470
471**ncplane_pixel_geom** retrieves pixel geometry details. **pxy** and **pxx**
472return the size of the plane in pixels. **celldimy** and **celldimx** return
473the size of a cell in pixels (these ought be the same across planes).
474**maxbmapy** and **maxbmapx** describe the largest bitmap which can be
475displayed in the plane. Any parameter (save **n**) may be **NULL**.
476
477When a plane is blitted to using **ncvisual_blit** and **NCBLIT_PIXEL** (see
478**notcurses_visual(3)**), it ceases to accept cell-based output. The sprixel
479will remain associated until a new sprixel is blitted to the plane, the plane
480is resized, the plane is erased, or the plane is destroyed. The base cell of a
481sprixelated plane has no effect; if the sprixel is not even multiples of the
482cell geometry, the "excess plane" is ignored during rendering.
483
484# RETURN VALUES
485
486**ncplane_create** and **ncplane_dup** return a new **struct ncplane** on
487success, or **NULL** on failure.
488
489**ncplane_userptr** returns the configured user pointer for the ncplane, and
490cannot fail.
491
492**ncplane_below** returns the plane below the specified ncplane. If the provided
493plane is the bottommost plane, NULL is returned. It cannot fail.
494
495**ncplane_set_scrolling** returns **true** if scrolling was previously enabled,
496and **false** otherwise.
497
498**ncplane_at_yx** and **ncplane_at_cursor** return a heap-allocated copy of the
499EGC at the relevant cell, or **NULL** if the cell is invalid. The caller should
500free this result. **ncplane_at_yx_cell** and **ncplane_at_cursor_cell** instead
501load these values into an **nccell**, which is invalidated if the associated
502plane is destroyed. The caller should release this **nccell** with
503**nccell_release**.
504
505**ncplane_as_rgba** returns a heap-allocated array of **uint32_t** values,
506each representing a single RGBA pixel, or **NULL** on failure.
507
508**ncplane_erase_region** returns -1 if **ystart** or **xstart** are less than -1,
509or outside the plane.
510
511**ncplane_cursor_move_yx** returns -1 if the coordinates are beyond the
512dimensions of the specified plane (except for the special value -1).
513
514**ncplane_cursor_move_rel** returns -1 if the coordinates are beyond the
515dimensions of the specified plane.
516
517**ncplane_name** returns a heap-allocated copy of the plane's name, or NULL if
518it has no name (or on error).
519
520Functions returning **int** return 0 on success, and non-zero on error.
521
522All other functions cannot fail (and return **void**).
523
524# NOTES
525
526# BUGS
527
528**ncplane_at_yx** doesn't yet account for bitmap-based graphics (see
529**notcurses_visual(3)**). Whatever glyph-based contents existed on the plane when
530the bitmap was blitted will continue to be returned.
531
532When the alternate screen is not used (see **notcurses_init(3)**), the contents
533of the terminal at startup remain present until obliterated on a cell-by-cell
534basis. **ncplane_erase** and **ncplane_erase_region** **cannot** be used to
535clear the terminal of startup content. If you want the screen cleared on
536startup, but do not want to use (or rely on) the alternate screen, use something
537like:
538
539```c
540ncplane_set_base(notcurses_stdplane(nc), " ", 0, 0);
541notcurses_render(nc);
542```
543
544or simply:
545
546```c
547notcurses_refresh(nc);
548```
549
550# SEE ALSO
551
552**notcurses(3)**,
553**notcurses_capabilities(3)**,
554**notcurses_cell(3)**,
555**notcurses_output(3)**,
556**notcurses_pile(3)**,
557**notcurses_stdplane(3)**,
558**notcurses_visual(3)**
559