Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ CuiSharp binds CUI (C99) to C#. Read these three before changing code, in this o
`docs/ARCHITECTURE.md` is why things are the way they are; read an entry when you are about to change
something that looks odd.

Bumping the CUI submodule has its own runbook: [skills/sync-cui/SKILL.md](skills/sync-cui/SKILL.md)
is the procedure and the error→override table, and `skills/sync-cui/scripts/cui-api-diff.ps1` prints
what upstream added before you read any C. The `sync-cui` agent skill is registered in
`.pi/settings.json`, so `pi` offers it as `/skill:sync-cui`.
Bumping the CUI submodule has its own runbook: [skills/cui-sync/SKILL.md](skills/cui-sync/SKILL.md)
is the procedure, with the binding rules and the error→override table in `skills/cui-sync/references/`.
`skills/cui-sync/scripts/cui-api-diff.ps1` prints what upstream added before you read any C, and
`skills/cui-sync/scripts/sync-status.ps1` says where a sync stands. The `cui-sync` agent skill is
registered in `.pi/settings.json`, so `pi` offers it as `/skill:cui-sync`.

## Hard rules

Expand Down
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,57 @@ Every user-visible change, newest first. Pre-1.0 the minor number carries new su
carries fixes. The section for a tag is what the GitHub release publishes, so the two cannot say
different things.

## [0.4.0] — 2026-11-13

CUI 1.3.1 → 1.4.0. Four functions, four components, and one option array the generator had never
had to express.

### Added

- **CUI's own documentation, wherever it wrote it.** A wrapper used to carry only the sentence above
the declaration, so an options field, an enum constant or a function documented *beside* its
declaration reached C# with nothing at all. The generator now reads all four places upstream
writes in — above the declaration, beside it, above the definition in the C source, and the
component's description above its options struct — and the result is in the package's IntelliSense
file, not just in the source: 1 200 option and struct fields that said `const char * unit` now say
what the field means, 112 wrapped functions gained a sentence (206 down to 94 that have none),
every constant that CUI comments on says what it is for (`AxisUnits.Hours`: *hours shown as a time
of day*), and options structs open with the component's description instead of `cui_split_opts`
(`BlameOpts` now says what Blame is). A section title bar is recognised and dropped rather than
shown as if it were prose, and CUI's notes to its own next reader — `left to right in any
interface: see cui__keep_ltr`, written above fifteen thin wrappers — are recognised as such and
never used as a summary; those wrappers take the description from the header instead.
- **The instruments**: a group of components that read like a panel rather than a page.
`DotChart(id, series, count, opts)` draws values as a grid of dots with the pointer or the arrow
keys reading the value under them, and takes `ChartAnnotation`s drawn over it as lines,
thresholds and labelled points; `EventTrack(id, times, ref count, min, max, ref selected, opts)`
puts moments on a time axis that a click adds to, a double-click removes and a drag moves, and it
lines up under a dot chart of the same width; `Readout(label, value, opts)` is one figure with
its unit and a line of context; `DotDisplay(text, opts)` draws text in a 5 by 7 dot font that
shrinks to fit or scrolls. The gallery's *Instruments* page shows all four on one screen.
- **`CuiAppDesc.AppId`** names the app to a Linux desktop: the window's `WM_CLASS`, and the Wayland
app ID, so the dock, the taskbar and `Alt+Tab` show the app's own name and icon instead of `CUI`.
- **`Ui.DotChart` takes `ReadOnlySpan<DotSeries>`**, the way every other chart takes its series, so a
call site can stack the series inline (`[new(values, "Caffeine", accent: true)]`) and allocate
nothing per frame. The signature change is the one public-surface edit in this release.
- **Generated documentation.** CUI 1.4 documents every field of every options and data struct in
the header, so 208 generated wrappers that could only say the C function's name now say what the
call does, and the option fields carry the header's own words.

### Changed

- **A capacity is the array's length, so it leaves the signature.** `CurveEditor`, `GradientEditor`,
`KvEditor`, `QueryBuilder` and `EventTrack` no longer take a `capacity`: the wrapper passes the
span's length. Supplying both let them disagree, and a capacity larger than the span was a
buffer overrun the type system did not catch.
- **A count beside a record array is now the array's length.** `DotChartOpts.Annotations` and every
other option struct with a record array derive their count, as string and float arrays already
did; the field is no longer public, so the two cannot drift apart.
- **An in-place primitive array is copied back every frame**, not only on the frames the widget
reports a change: native sorts and clamps the array it is given before it draws, and a wrapper
that kept the caller's unsorted copy would disagree with the index it reports. Converting a
record still only happens on a change, because that is the conversion that allocates.

## [0.3.3] — 2026-11-12

### Added
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<!-- Package metadata, inherited by every packable project. -->
<PropertyGroup>
<Version>0.3.3</Version>
<Version>0.4.0</Version>
<Authors>yappologistic</Authors>
<Copyright>Copyright (c) 2026 yappologistic</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ or holding them across an `await`. Nothing can outlive the frame, so nothing can

| | |
|---|---|
| **One executable** | NativeAOT links CUI in statically: no runtime, no `cui.dll`, no VC++ redistributable. The gallery, all twenty-eight pages, is 2.9 MB. |
| **One executable** | NativeAOT links CUI in statically: no runtime, no `cui.dll`, no VC++ redistributable. The gallery, all twenty-nine pages, is 2.9 MB. |
| **No UI framework** | CUI creates the window, owns the message loop and the GL context. `CuiApp.Run` is the entire host. |
| **Sub-millisecond frames** | 0.85 ms mean for the live gallery, software rasterizer, 1240×820 (`--fps 900`). |
| **0 B per frame** | Labels, options and interpolated text come from a per-frame arena. A live chart with a million samples allocates nothing. |
Expand Down Expand Up @@ -306,7 +306,7 @@ src/CuiSharp.CodeFixes/ IDE quick fixes, packed beside the analyzers
src/CuiSharp.Testing/ TestApp: drive a component without a window
src/CuiSharp.Tools/ dotnet cui: the guide and the API offline, plus build, run headless, relay one command
src/CuiSharp.Templates/ dotnet new cui-app / cui-mini
samples/CuiSharp.Gallery/ twenty-eight pages, one file per page
samples/CuiSharp.Gallery/ twenty-nine pages, one file per page
samples/CuiSharp.Gallery.Browser/ the same gallery on a software canvas in WebAssembly
native/ the CUI submodule and the two build scripts
tools/ bindgen.cs, regen.ps1, verify-template.ps1,
Expand Down Expand Up @@ -361,11 +361,11 @@ What changed, per version: [CHANGELOG.md](CHANGELOG.md).

## Status

Pre-1.0: the API may still change. The binding covers all 492 CUI 1.3 functions: 166 option
structs, 100 records, 278 generated wrappers, 169 deliberate hand-written ones, 4 excluded with a
written reason, 0 pending — see [bindings/coverage.txt](bindings/coverage.txt). The gallery ports the
nine core pages, four pages of this binding's own, and CUI 1.3's two developer-tools pages; the other
fifteen extended upstream pages are not yet.
Pre-1.0: the API may still change. The binding covers all 496 CUI 1.4 functions: 170 option
structs, 104 records, 277 generated wrappers, 175 deliberate hand-written ones, 4 excluded with a
written reason, 4 variadic skipped, 0 pending — see [bindings/coverage.txt](bindings/coverage.txt).
The gallery's 29 pages walk the components section by section, light and dark; what is still missing
is the page shape that needs a device — a capture pipeline, an audio stream.

## License

Expand Down
8 changes: 5 additions & 3 deletions bindings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ retained-pointer storage.
| `src/CuiSharp/Ui/Records.g.cs` | Data records used as array items (`Choice`, `Command`, `TableColumn`, `TableSort`): friendly constructor, `ToNative()`, and `FromNative()` where write-back is meaningful. |
| `src/CuiSharp.Tests/OptionMappings.g.cs` | One consolidated test covering every generated option's populated fields, sentinel and null/false defaults. A swapped field is a single generator bug, so it is one test, not one per option. |

Current state: **166** option structs, **100** data records, **278** generated wrappers, **169**
deliberate hand-written ones, **4** excluded, **4** variadic skipped, **0** pending — 492 C
functions, every one with a status. Pointer-heavy options are withheld rather than exposed with guessed
Current state: **170** option structs, **104** data records, **277** generated wrappers, **175**
deliberate hand-written ones, **4** excluded, **4** variadic skipped, **0** pending — 496 C
functions, every one with a status. `pwsh skills/cui-sync/scripts/sync-status.ps1` prints these
numbers from `coverage.txt` and fails when the prose here or in `README.md` disagrees. Pointer-heavy options are withheld rather than exposed with guessed
ownership. Charts, texture handles, text-buffer inputs and reorder are hand-written on purpose, and
`coverage.txt` names the member and the file for every one of them.

Expand Down Expand Up @@ -76,6 +77,7 @@ and missing reasons fail generation.
| `arrayLengths` | `length`, `cast`, `emit`, `why` | A `const T *` parameter whose length is an expression (`rows * cols`) or a differently-named parameter (`size`). `emit: false` means native derives it and the wrapper only checks it. |
| `arrayParams` | `why` | A pointer parameter that is an array although its name is singular, e.g. `const cui_swipe_action *left` (`name@function`). |
| `inOutArrays` | `count`, `why`, `changedWhen` | A record array the widget edits, plus the count it may change: copied in, called, copied back. `changedWhen` is the condition the widget reports an edit by (`__result != 0`, `__result.Changed != 0`, `__result.Flag >= 0`) and the copy back only runs then, because converting a record allocates the strings and fixed arrays it holds. |
| `capacityParams` | `array`, `why` | An `int capacity` the widget writes up to, where the array's length is that number. The wrapper passes the span's length and the parameter leaves the signature: supplying both lets them disagree, and the widget writes past the caller's array. |
| `textFields` | `capacity`, `why` | A `char * buf` pair the caller sees as one `ref string`; the wrapper rents a pooled buffer and reads the text back only when it changed. |
| `optionPointers` | `type`, `why` | An option field that is a pointer to a primitive (`int *`, `_Bool *`), exposed as a `ref` parameter. |
| `optionArrayChecks` | `atLeast`, `why` | An option array whose length is a widget parameter; the wrapper rejects a short array before the call. |
Expand Down
Loading
Loading