Icod.DCurses 1.3.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Icod.DCurses --version 1.3.0
                    
NuGet\Install-Package Icod.DCurses -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Icod.DCurses" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Icod.DCurses" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Icod.DCurses" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Icod.DCurses --version 1.3.0
                    
#r "nuget: Icod.DCurses, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Icod.DCurses@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Icod.DCurses&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Icod.DCurses&version=1.3.0
                    
Install as a Cake Tool

Icod.DCurses

Icod TUI Toolchain

PR Staging build Main Release validation

Icod.DCurses is a managed, cross-platform curses-style terminal UI library for .NET.

It sits above Icod.Terminal and Icod.TermInfo:

  • Icod.TermInfo owns immutable terminal capability descriptions and expansion;
  • Icod.Terminal owns the live terminal session, host mode, dimensions, lifecycle, input decoding, semantic terminal protocols, and output serialization;
  • Icod.DCurses owns curses-shaped events, logical screens/windows, pads/viewports, retained panels/layers, cells/styles/metadata, composition, retained refresh policy, and terminal-cell layout primitives.

Status

Current published stable release: Icod.DCurses 1.2.0.

Icod.DCurses 1.3.0 is complete in source and merged to main. The final dependency-qualified source head b90b444556291434bddb9f56d031f09ac1aabfbf passed pull-request workflow #719 / 34708925529 across the package candidate plus Windows/Linux/macOS x64/ARM64. PR #27 was then merged as 18255d59136922b9e246f4113dc6fdb6a9ea24a3, and the resulting main Release workflow #17 / 34709142076 passed. A v1.3.0 tag, GitHub Release, and NuGet publication have not yet been created.

Current source identity:

Version         1.3.0
PackageVersion  1.3.0
AssemblyVersion 1.0.0.0
Icod.Terminal   1.11.1
Icod.TermInfo   1.11.0

Published 1.2 contract:

47 exported types
356 canonical declared contract lines
sha256 4810ebb088764acedbb94aca84b231677886b9c1a1f920d9a30f960cbe1dfce7

Frozen 1.3 contract:

51 exported types
406 canonical declared contract lines
sha256 a655bd85e3c88f5bf38ad0d43a148e3bd06a9e943bbf3e3aa2e21575ffb07424

The four new exported types are CursesRectangle, CursesInsets, CursesDockEdge, and CursesLayout.

Installation

Install the current published package selected by your normal NuGet policy:

dotnet add package Icod.DCurses

Until v1.3.0 is tagged and published, normal package resolution still selects the published 1.2 line. The main branch already contains the fully qualified 1.3.0 source.

Architecture

applications / future widgets / compatibility facades
                         |
                    Icod.DCurses
 windows / pads / panels / cells / semantic metadata
 immutable geometry / pure layout / retained refresh / events
                         |
                    Icod.Terminal
   live session / input / lifecycle / semantic protocols
          capability routing / serialized output
                         |
                    Icod.TermInfo
             immutable capability authority
                         |
                  terminal / tty

Icod.DCurses does not maintain a second terminal capability database, install a competing raw-input loop, own terminal modes independently of Icod.Terminal, emit private OSC/CSI/DCS/APC framing for Terminal-owned protocols, emulate a terminal, or create/manage PTYs.

Version 1.3 also does not add a retained layout tree or automatic layout owner. Geometry remains caller-owned data and layout recomputation remains explicit application policy.

Targets

  • .NET 8
  • .NET 9
  • .NET 10
  • C# 13
  • Windows x64/ARM64
  • Linux x64/ARM64
  • macOS x64/ARM64

Quick start

using Icod.DCurses;

await using CursesSession session = await CursesSession.OpenAsync();
CursesWindow screen = session.StandardScreen;

screen.Clear();
screen.Move(
    0,
    0
);
screen.Write(
    "Hello from Icod.DCurses",
    new CursesStyle(
        CursesColor.Default,
        CursesColor.Default,
        CursesTextAttributes.Bold
    )
);
await session.RefreshAsync();

CursesEvent terminalEvent = await session.ReadEventAsync();

A CursesSession restores the presentation and Terminal-owned state it acquires when disposed. Applications should consume terminal input and lifecycle activity through the curses/Terminal ownership model rather than adding a parallel byte reader.

1.3 geometry, layout, and resize

CursesRectangle and CursesInsets are immutable terminal-cell value types. Empty rectangles are valid geometry results; applying bounds to a window or panel still requires positive dimensions.

CursesLayout is a stateless utility for fixed splits, proportional splits, docking, and clipping:

CursesRectangle bounds = session.Screen.Bounds;

CursesLayout.Dock(
    bounds,
    CursesDockEdge.Top,
    2,
    out CursesRectangle headerBounds,
    out CursesRectangle remaining
);
CursesLayout.SplitColumnsProportional(
    remaining,
    1,
    3,
    out CursesRectangle sidebarBounds,
    out CursesRectangle bodyBounds
);

Geometry is applied explicitly to ordinary windows and retained panels:

header.SetBounds( headerBounds );
sidebar.SetBounds( sidebarBounds );
body.SetBounds( bodyBounds );
dialog.SetBounds(
    bodyBounds.Inset(
        new CursesInsets( 2, 4, 2, 4 )
    )
);

CursesPanel.Resize and SetBounds preserve surviving upper-left retained content and semantic metadata, clamp the retained cursor after shrink, repair width-two footprints at resize boundaries, preserve visibility/z-order/transparency, and validate the final screen-relative rectangle before mutation.

For live resize, DCurses deliberately does not retain layout rules. The application recomputes from the synchronized logical screen:

CursesRectangle current = session.Screen.Bounds;
// derive rectangles from current
// apply them with SetBounds / Resize
await session.RefreshAsync();

The Icod.DCurses.Layout.Sample project demonstrates this explicit lifecycle-driven recomputation model with ordinary windows plus a retained panel.

1.2 retained panels and layers

Ordinary CursesWindow instances remain shared logical views. CursesPanel is intentionally different: it owns an independent retained surface and participates in a deterministic screen-owned z-order stack.

using CursesPanel dialog = session.Screen.CreatePanel(
    row: 3,
    column: 6,
    rows: 8,
    columns: 36
);

dialog.ContentWindow.Write( "Retained dialog content" );
dialog.MoveToTop();
await session.RefreshAsync();

Panels are opaque by default. A panel can instead make ordinary blank cells transparent:

using CursesPanel overlay = session.Screen.CreatePanel(
    row: 2,
    column: 4,
    rows: 3,
    columns: 20
);
overlay.Transparency = CursesPanelTransparency.BlankCellsTransparent;
overlay.ContentWindow.Write( "overlay" );

The published 1.2 panel contract includes independent retained content, show/hide with remembered z-order, movement and relative ordering, clipping, opaque/blank-transparent composition, Unicode width-two and semantic-metadata coherence, damage-bounded recomposition, live session refresh/lifecycle integration, and deterministic one-way Dispose() removal.

Disposal removes a transient panel from its owning screen so repeatedly-created popups/dialogs are not retained for the screen lifetime. A disposed panel cannot be reattached or manipulated.

Version 1.3 extends this published model with retained resizing; it does not replace panel ownership or composition semantics.

Version 1.1 added semantic meaning attached to retained content, beginning with hyperlinks, while keeping visual rendition in CursesStyle.

CursesCellMetadata metadata = new(
    new CursesHyperlink(
        "https://example.test/docs",
        "docs"
    )
);

screen.WriteWithMetadata(
    "documentation",
    metadata
);

Metadata is retained independently of visible glyph/style equality, follows content through supported editing/composition operations, remains coherent across two-column leader/continuation footprints, and is emitted physically through Terminal-owned semantic hyperlink operations. DCurses does not construct OSC 8 directly.

Pads, Unicode, and semantic drawing

CursesPad is an off-screen logical surface that reuses ordinary CursesWindow editing semantics. Multiple viewports may observe one pad independently.

The built-in width provider is pinned to Unicode 17.0.0. East Asian Ambiguous characters are narrow by default and can be made wide explicitly with UnicodeCursesTextWidthProvider.WideAmbiguousInstance.

CursesText.MeasureColumns, TruncateToColumns, and SliceByColumns operate on complete terminal text elements and never return half of a two-column element. Semantic line cells remain distinct from ordinary Unicode box-drawing text.

Concurrency and lifecycle

The library deliberately uses a narrow ownership model rather than pervasive per-cell locking:

  • logical screens, windows, pads, viewports, and panels are single-writer unless documented otherwise;
  • one Terminal-owned event wait may coexist with serialized refresh/output work;
  • caller cancellation does not discard Terminal decoder state;
  • disposal unblocks pending DCurses waits while preserving authoritative restoration;
  • output uncertainty invalidates retained physical knowledge so a later refresh can repaint safely;
  • suspend/resume invalidates physical knowledge but retains logical panel content;
  • lifecycle resize synchronizes the logical screen, while application layout recomputation remains explicit.

Validation and packaging

Local wrappers use Debug configuration. Pull requests use Staging with warnings-as-errors. Pushes to main and release tags use Release.

Runtime validation covers Windows/Linux/macOS x64 and ARM64; the library/test matrix covers net8.0, net9.0, and net10.0.

Package validation verifies .nupkg/.snupkg, package/assembly identity, dependency groups derived from project declarations, README/license/icon/repository metadata, XML documentation, portable symbols, and a fresh NuGet-only consumer. The 1.3 package consumer compiles and executes the rectangle/inset/layout/bounds/panel-resize surface directly from the packed artifact. Package validation does not impose hard-coded sibling dependency versions.

Release documentation

Current authorities:

  • Icod.DCurses-Development-Roadmap.md
  • Icod.DCurses-1.1.0-to-1.4.0-Development-Roadmap.md
  • Icod.DCurses-1.3.0-Development-Roadmap.md
  • docs/Public-API-Fingerprint-1.3.json
  • docs/Public-API-Baseline-1.3.md
  • docs/T1309-Layout-Application-Performance-and-Allocation-Acceptance.md
  • docs/T1310-Public-API-Package-Documentation-and-Regret-Gate.md
  • docs/T1311-RC-and-Stable-Closure.md

Historical 1.0-1.2 closure records remain compatibility authorities and are not rewritten merely to reflect later development state.

Authors

Inspired by original work from Bill Joy, author of the original termcap; Mary Ann (born Mark) Horton, author of terminfo; Pavel Curtis, author of pcurses; and Zeyd Ben-Halim, Eric S. Raymond, and Thomas Dickey, whose work developed and maintained libtinfo and ncurses.

Managed .NET implementation by Timothy J. Bruce uniblab@hotmail.com.

Copyright (c) 2026 Timothy J. Bruce

License

Licensed under the GNU Lesser General Public License v3.0 or later. See LICENSE.

The NuGet package declares license acceptance as required. Package clients which honor NuGet's requireLicenseAcceptance metadata must obtain acceptance of the license terms before installation.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.0 191 9/25/2026
2.1.0 88 9/24/2026
2.0.0 92 9/23/2026
1.6.0 229 9/17/2026
1.5.0 97 9/15/2026
1.4.0 95 9/14/2026
1.3.0 104 9/12/2026
1.2.0 146 9/10/2026
1.1.0 112 9/10/2026
1.0.0 104 9/9/2026
0.9.0 106 9/9/2026
0.8.0 103 9/9/2026
0.7.0 108 9/9/2026
0.6.0 107 9/9/2026
0.5.0 109 9/8/2026
0.4.0 105 9/8/2026
0.3.0 101 9/8/2026
0.2.0 110 9/8/2026
0.1.1 112 9/8/2026
0.1.0 4,704 8/29/2026
Loading failed

1.3.0 adds immutable CursesRectangle/CursesInsets geometry, pure fixed/proportional/docking/clipping layout helpers, screen/window/panel bounds application, retained panel resizing, and explicit live resize recomputation over the published 1.2 panel contract. Runtime dependencies are Icod.Terminal 1.11.1 and Icod.TermInfo 1.11.0; AssemblyVersion remains 1.0.0.0.