Skip to content
This is the documentation for xc 0.66. The current documentation describes the newest version.

UXNibV2

UXNibV2 reads the UXNB v2 chunk out of a .rsc file, entirely in portable code.

#use <UXKit> // or #import "UXNibV2.xc"

v1’s chunk is read by libGEM’s C rscload, whose surface UXNib declares. That makes v1 nib loading GEM-only.

v2 is parsed here, from the raw bytes, with no host dependency. Variant selection, logical-id resolution and validation therefore run, and are gated, on every backend, wasm32 included.

A resource format read by one platform’s C library cannot be used by the other six backends, which is why v2 exists.

The magics differ:

magic
UXNBv2 — invisible to the C v1 reader
XGNBv1 — this parser reports it as version 1

A v2 file cannot confuse the old reader. A v1 file handed to this parser is presented per the spec’s compatibility rule: every tree its own single-variant form of class any.

There is no migration step. Old resources keep working, new ones gain variants, and the same code path consumes both.

i32 tree = nib.selectTree(formId, klass, &chosenClass);

A form can carry several variants (a phone layout, a tablet layout, a desktop one). selectTree picks the best available for a requested class by walking a fallback chain of up to four steps.

A nib that only ships a desktop variant still loads on a phone by falling back. A nib that ships both gets the right one with no if in the application.

chosenClass reports which variant was used. This matters when the answer was a fallback rather than the exact match: it separates “there is a phone layout” from “the desktop layout is in use on a phone”.

A form with no usable variant returns -1 rather than guessing.

A phone or tablet layout can also come in portrait and landscape trees. A rotation can re-nest a layout, not just stretch it, so each orientation gets a whole tree of its own, exactly as each form factor does.

i32 tree = nib.selectTreeOriented(formId, gDriver.formFactorClass(),
gDriver.orientation(), &cls, &orient);

Within each class of the fallback chain the order is:

  1. a tree for the current orientation;
  2. a tree with no orientation, drawn to work both ways;
  3. the other orientation’s tree.

Only then does selection move on to the next class. A tablet held upright with only a landscape tablet layout therefore gets that layout, not the desktop’s.

The orientation rides in the top two bits of a variant’s class word (0 none, 1 portrait, 2 landscape). Files written before it existed have 0 there and read unchanged. selectTree masks those bits off, so code that ignores orientation keeps working.

i32 obj = nib.objForLogical(tree, logicalId);
// -1 means the variant genuinely does not have that control

A control is referred to by a logical id instead of its index in a tree, so the same code binds to it in every variant even though the layouts differ.

-1 is a normal answer, not an error:

Borrowing keeps loading a nib cheap: a resource file with hundreds of names costs no allocations to parse.

All multi-byte fields are big-endian, matching the .rsc body. The parser is byte-order-independent, and a resource built on one machine loads on another.

open · parse · version · formCount · formAt · formOffById · formName · selectTree · selectTreeOriented · classOf · orientOf · objForLogical · resolveView · str

static UXNibV2* open(u8* rsc, u32 rscLen)

Finds the chunk in a resource file. The buffer is borrowed; see the caution.

bool parse(void)

Reads the header and the section offsets. Returns false on a malformed chunk. Check this before trusting anything else.

i32 version(void)

1 for a v1 file presented through the compatibility rule, 2 for a real v2 chunk.

i32 formCount(void)
u32 formAt(i32 f)

The byte offset of the i-th form record.

u32 formOffById(i32 formId)

By id rather than by index. 0 when absent.

u8* formName(i32 formId)

Borrowed, like every string here.

i32 selectTree(i32 formId, i32 klass, i32* chosenClass)

The best variant for a form-factor class, ignoring orientation. See above.

i32 selectTreeOriented(i32 formId, i32 klass, i32 orient, i32* chosenClass, i32* chosenOrient)

The best variant for a class held at an orientation (UX_ORIENT_*). See Orientation is a second axis. chosenOrient reports the orientation of the tree that won.

static i32 classOf(u32 word)

The form-factor class in a variant’s class word: its low 14 bits.

static i32 orientOf(u32 word)

The orientation in a variant’s class word: its top two bits.

i32 objForLogical(i32 tree, i32 logicalId)

An object index within a tree, or -1.

i32 resolveView(u32 refAt, i32 tree)

Resolves a reference record to an object. References carry a space saying what they point at: a view by coordinate, a top-level object, the owner, or a view by logical id. This lets a connection survive a variant that moved things around.

u8* str(u32 off)

A string from the chunk’s table, borrowed.

  • UXNib: v1, and the host surface that makes it GEM-only
  • UXViewDriver: formFactorClass, which supplies the class selectTree is asked for
  • UXViewTree: what a loaded nib becomes