Icod.DCurses
2.5.0
dotnet add package Icod.DCurses --version 2.5.0
NuGet\Install-Package Icod.DCurses -Version 2.5.0
<PackageReference Include="Icod.DCurses" Version="2.5.0" />
<PackageVersion Include="Icod.DCurses" Version="2.5.0" />
<PackageReference Include="Icod.DCurses" />
paket add Icod.DCurses --version 2.5.0
#r "nuget: Icod.DCurses, 2.5.0"
#:package Icod.DCurses@2.5.0
#addin nuget:?package=Icod.DCurses&version=2.5.0
#tool nuget:?package=Icod.DCurses&version=2.5.0
Icod.DCurses

Icod.DCurses is a managed, cross-platform curses-style terminal UI library for
.NET. It provides retained screens, windows, pads and panels; Unicode-aware text
layout; viewports and geometry; semantic metadata and mixed media; damage-aware
refresh; and deterministic interaction routing without taking ownership of the
application's event loop.
Install
dotnet add package Icod.DCurses
The package targets .NET 8, .NET 9 and .NET 10 and uses C# 13. NuGet restores
the compatible Icod.Terminal dependency; applications do not need a direct
Icod.TermInfo reference for DCurses.
To run the editor-foundation sample from a repository checkout:
dotnet run --project samples/Icod.DCurses.Editor.Sample/Icod.DCurses.Editor.Sample.csproj -c Release -f net10.0
To inspect foreground/background behavior on your own terminal, run the public-only color sample from a repository checkout:
dotnet run --project samples/Icod.DCurses.Color.Sample/Icod.DCurses.Color.Sample.csproj -c Release -f net10.0
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 inputEvent = await session.ReadEventAsync();
The application decides how to interpret inputEvent, when to refresh again,
and when to exit. DCurses does not start a callback dispatcher or a second input
reader.
Color surfaces and fallback
Each CursesCell carries a complete CursesStyle: independently requested
foreground and background CursesColor values plus text attributes. A color
may be terminal-default, indexed, or direct RGB. Logical windows, pads,
viewports, and panels retain the requested style; refresh resolves it against
the current terminal's capabilities. Inspect session.PresentationCapabilities
and choose an application palette that remains legible when a color cannot be
represented:
CursesPresentationCapabilities capabilities = session.PresentationCapabilities;
CursesColor ink = capabilities.SupportsDefaultColorRestoration
&& capabilities.SupportsForegroundColor
&& capabilities.IndexedColorCount >= 8
? CursesColor.Indexed( 7 )
: CursesColor.Default;
CursesColor paper = capabilities.SupportsDefaultColorRestoration
&& capabilities.SupportsBackgroundColor
&& capabilities.IndexedColorCount >= 8
? CursesColor.Indexed( 4 )
: CursesColor.Default;
screen.Write( "Colored text", new CursesStyle( ink, paper ) );
This snippet continues the quick-start session and window above. An unsupported
axis degrades to terminal-default without changing a supported axis; there is
no automatic nearest-color quantization. The terminal's actual appearance can
still depend on its palette and user settings. For a colored surface, set
CursesPanelTransparency.Opaque: blank cells with a styled background then
cover lower panels. BlankCellsTransparent deliberately treats even styled
blanks as transparent. CursesTextAttributes.Reverse is a semantic attribute,
not an interchange of the stored foreground and background colors; display
support is terminal-dependent.
Clipboard and cursor style
Icod.DCurses 2.4 adds explicit, bounded clipboard operations and reversible semantic cursor-style leases over the canonical terminal session:
CursesSessionOptions options = new() {
HideCursor = false,
ClipboardOptions = new CursesClipboardOptions {
MaximumReadBytes = 65_536,
MaximumWriteBytes = 65_536
}
};
await using CursesSession session = await CursesSession.OpenAsync( options );
await using CursesCursorStyleLease caret =
await session.AcquireCursorStyleAsync(
CursesCursorStyle.SteadyBar,
TimeSpan.FromMilliseconds( 250 )
);
await session.WriteClipboardAsync(
CursesClipboardSelection.Clipboard,
"selected text"
);
byte[] payload = await session.ReadClipboardAsync(
CursesClipboardSelection.Clipboard,
TimeSpan.FromMilliseconds( 250 )
);
The default read and write budgets are independently 65,536 bytes and may be configured up to 16 MiB before opening an owned session. They are local safety limits, not a negotiation of remote clipboard capacity. Writes confirm that the complete terminal command was emitted, not that the host accepted it. A read timeout is inconclusive; applications should own fallback content and policy.
Cursor style and visibility are independent. The lease restores the exact observed preceding style in LIFO order. If observation is unsupported, times out or is cancelled, no guessed reset or style mutation is emitted.
Editor foundations
The editor sample is deliberately a public-API composition witness, not a document engine. It demonstrates:
- viewport-local Unicode layout, caret geometry, selection and retained repaint;
- a synthetic ten-million-record source with work bounded to visible records;
- bracketed paste as routed text data and key-release suppression;
- primary-button caret placement and selection with captured outside drag;
- cancellation on release, focus loss, modal activation, resize and disposal;
- a separately hit-tested final-column scrollbar without implicit Tab traversal;
- explicit
Ctrl+C/Ctrl+Vclipboard commands with an application fallback; - a visible caret with a best-effort scoped steady-bar style.
Document storage, undo/redo, revision caches, selection semantics, autoscroll timing, tabs, dialogs and file I/O belong in Icod.Widgets or the application. The complete controls and limitations are documented in the samples guide.
Text layout and retained projection
Source positions are UTF-16 offsets at legal text-element boundaries; visual positions are rows and terminal columns. The application supplies the bounded text slice to lay out and decides which lines to project:
CursesTextLayout layout = CursesTextLayout.Create(
"Hello 👩💻 world",
new CursesTextLayoutOptions( 20 ) {
WrapMode = CursesTextWrapMode.TextElement
}
);
CursesTextPosition afterEmoji =
layout.GetNextPosition( new CursesTextPosition( 6 ) );
CursesTextVisualPosition caret = layout.GetVisualPosition( afterEmoji );
screen.PresentTextLayout( layout, 0, layout.Lines.Count, 0, 0 );
if ( caret.Line < screen.Rows && caret.Column < screen.Columns ) {
screen.Move( caret.Line, caret.Column );
}
await session.RefreshAsync();
HitTest and GetSelectionRectangles use the same Unicode/cell geometry.
Applications should not build file-sized pads or whole-file layouts; keep
document indexing and revision-aware visible-slice caches above DCurses.
Interaction routing
Applications can register semantic key gestures and sequences, inspect the currently effective bindings for help text, and route one normalized input event at a time. Pending sequences have no hidden timer:
CursesKeyGesture g = CursesKeyGesture.ForCharacter( new Rune( 'g' ) );
CursesCommand goTop = new( "document.go-top" );
router.BindGlobalGestureSequence( [ g, g ], goTop );
IReadOnlyList<CursesCommandSequenceBinding> helpBindings =
router.GetEffectiveGestureSequenceBindings();
CursesCommandSequenceResult result = router.ProcessCommandSequence( inputEvent );
if ( result.Kind is CursesCommandSequenceResultKind.Completed ) {
ExecuteApplicationCommand( result.Command! );
} else if ( result.Fallback is not null ) {
HandleOrdinaryRoutingResult( result.Fallback );
}
Focused-region, active-scope and router-global precedence match ordinary routing. The application owns command execution, labels, localization, prefix timeouts, Tab policy and event-loop timing.
Feature inventory
- Retained logical screens, windows, pads, viewports and panels.
- Unicode text-element measurement, wrapping, hit testing and selection geometry.
- Styles, line drawing, semantic hyperlinks and width-two cell coherence.
- Sparse/full damage refresh, synchronized output and physical-state invalidation.
- Geometry, clipping, tracks, docking and prepared bulk cell writes.
- Normalized keyboard, mouse, focus, paste and lifecycle events.
- Interaction regions, modal scopes, focus, pointer capture and command sequences.
- Bounded clipboard access and scoped semantic cursor styles.
- Retained raster resources/placeholders and bounded cell-aligned raster atlases.
- net8.0, net9.0 and net10.0 package assets with portable symbols and XML docs.
Architecture and boundaries
application / Icod.Widgets
document, controls, commands, event loop, files and policy
|
Icod.DCurses
retained cells, layout projection, damage and interaction mechanisms
|
Icod.Terminal
live session, semantic protocols, host I/O and reversible terminal state
|
Icod.TermInfo
immutable capability data and planning
|
terminal / tty
Icod.DCurses does not provide a widget framework, text buffer, callback dispatcher, terminal emulator, PTY host, native clipboard, private protocol parser, automatic raster replay or application policy. Terminal remains the sole owner of protocol framing, query correlation, live identities and physical state.
Compatibility and versioning
The 2.5 color-surface qualification retains the 2.4 public surface, which is
additive over 2.3.1, and keeps AssemblyVersion
2.0.0.0. It has 109 exported types, 857 canonical declared contract lines and
SHA-256 fingerprint
87a3ffe66174634f6db4044b914b05fd31d117b93ecf5b1a151d31d59732e65e.
Version 2.0 changed the public profile/dimensions signatures and advanced
AssemblyVersion to 2.0.0.0; applications upgrading from 1.6 must rebuild.
See the 2.0 migration guide.
Documentation and samples
- 2.5 public API baseline
- 2.5 development roadmap
- Sample guide and runnable commands
- Clipboard integration evidence
- Cursor-style lifecycle evidence
- Viewport measurement
- Editor interaction acceptance
- Changelog
- NuGet package and version history
Support the project
Icod.DCurses and its ecosystem packages are maintained by a solo developer.
Authors
Inspired by Bill Joy (termcap); Ken Arnold (termcap and curses); Mary Ann
(born Mark) Horton (terminfo); Pavel Curtis (pcurses); and Zeyd Ben-Halim,
Eric S. Raymond and Thomas Dickey (libtinfo and ncurses).
Managed .NET implementation by Timothy J. Bruce uniblab@hotmail.com.
License
Icod.DCurses is licensed under the GNU Lesser General Public License, version 3 or later. Samples and tests are licensed under the GNU General Public License, version 3 or later. See the repository license and per-project/source declarations.
| Product | Versions 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. |
-
net10.0
- Icod.Terminal (>= 1.29.0)
-
net8.0
- Icod.Terminal (>= 1.29.0)
-
net9.0
- Icod.Terminal (>= 1.29.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Icod.DCurses:
| Package | Downloads |
|---|---|
|
Icod.Widgets
Reusable terminal UI widgets for .NET, including color themes, Unicode text editing, forms, menus, dialogs, lists, filesystem pickers, and game controls above Icod.DCurses. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.5.0 | 179 | 10/12/2026 |
| 2.4.0 | 135 | 10/11/2026 |
| 2.3.1 | 271 | 10/10/2026 |
| 2.3.0 | 55 | 10/9/2026 |
| 2.2.0 | 452 | 9/25/2026 |
| 2.1.0 | 100 | 9/24/2026 |
| 2.0.0 | 104 | 9/23/2026 |
| 1.6.0 | 392 | 9/17/2026 |
| 1.5.0 | 106 | 9/15/2026 |
| 1.4.0 | 104 | 9/14/2026 |
| 1.3.0 | 111 | 9/12/2026 |
| 1.2.0 | 154 | 9/10/2026 |
| 1.1.0 | 119 | 9/10/2026 |
| 1.0.0 | 108 | 9/9/2026 |
| 0.9.0 | 113 | 9/9/2026 |
| 0.8.0 | 109 | 9/9/2026 |
| 0.7.0 | 115 | 9/9/2026 |
| 0.6.0 | 113 | 9/9/2026 |
| 0.5.0 | 116 | 9/8/2026 |
| 0.4.0 | 112 | 9/8/2026 |
2.5 qualifies existing foreground/background color retention, opaque-panel styled blanks, damage-aware rendition refresh, capability fallback, and lifecycle repaint across .NET 8/9/10; adds a public-only color sample and package consumer. No public API changes. Existing bounded clipboard and cursor-style APIs remain. The sole direct runtime dependency is stable Icod.Terminal 1.29.0.