Skip to content

A multi-platform NCurses .NET wrapper with UTF-8 support

License

Notifications You must be signed in to change notification settings

sebaFlame/NippyWard.NCurses

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

82 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NippyWard.NCurses

A multi-platform NCurses .NET wrapper with UTF-8 support

Rationale

After looking for a decent NCurses wrapper supporting Windows and UTF-8, not finding one - except one based on the (back then) outdated PDCurses -, I decided to write my own wrapper.

This project started without any prior experience writing wrappers and during the first months of .NET Core 1.0. It has evolved from using an IL generator to using a source generator today.

Installation

Linux

Ensure NCurses is installed! This should be the default for most if not all distributions. At the time of writing NippyWard.NCurses supports ubuntu.16.04-upwards and Debian-8-upwards.

Any other distribution can be added in

switch ((identifier = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.GetRuntimeIdentifier()))
{
case "win7-x64":
case "win8-x64":
case "win81-x64":
case "win10-x64":
case "win7-x86":
case "win8-x86":
case "win81-x86":
case "win10-x86":
DLLNAME = "libncursesw6";
DLLPANELNAME = "libpanelw6";
SIZEOF_WCHAR_T = 2;
CHTYPE_TYPE = typeof(UInt32);
#if (DEBUG && !DISABLESOURCEGENERATION) || !DEBUG
SingleByteChar = typeof(SingleByteChar_UInt32);
MultiByteChar = typeof(MultiByteChar_SingleByteChar_UInt32_2);
WideChar = typeof(WideChar_2);
MouseEvent = typeof(MouseEvent_SingleByteChar_UInt32);
PanelWrapper = typeof(PanelWrapper_libpanelw6);
NCursesCharWrapper = typeof(NCursesCharWrapper_libncursesw6_MultiByteChar_SingleByteChar_UInt32_2_WideChar_2_SingleByteChar_UInt32_schar_t_MouseEvent_SingleByteChar_UInt32);
NCursesWrapper = typeof(NCursesWrapper_libncursesw6);
#endif
break;
case "ubuntu.16.04-x64":
case "ubuntu.18.04-x64":
case "debian.8-x64":
case "debian.9-x64":
DLLNAME = "libncursesw.so.5.9";
DLLPANELNAME = "libpanelw.so.5.9";
SIZEOF_WCHAR_T = 4;
CHTYPE_TYPE = typeof(UInt64);
#if (DEBUG && !DISABLESOURCEGENERATION) || !DEBUG
SingleByteChar = typeof(SingleByteChar_UInt64);
MultiByteChar = typeof(MultiByteChar_SingleByteChar_UInt64_4);
WideChar = typeof(WideChar_4);
MouseEvent = typeof(MouseEvent_SingleByteChar_UInt64);
PanelWrapper = typeof(PanelWrapper_libpanelw_so_5_9);
NCursesCharWrapper = typeof(NCursesCharWrapper_libncursesw_so_5_9_MultiByteChar_SingleByteChar_UInt64_4_WideChar_4_SingleByteChar_UInt64_schar_t_MouseEvent_SingleByteChar_UInt64);
NCursesWrapper = typeof(NCursesWrapper_libncursesw_so_5_9);
#endif
break;
default:
DLLNAME = "libncursesw.so.6";
DLLPANELNAME = "libpanelw.so.6";
SIZEOF_WCHAR_T = 4;
CHTYPE_TYPE = typeof(UInt32);
#if (DEBUG && !DISABLESOURCEGENERATION) || !DEBUG
SingleByteChar = typeof(SingleByteChar_UInt32);
MultiByteChar = typeof(MultiByteChar_SingleByteChar_UInt32_4);
WideChar = typeof(WideChar_4);
MouseEvent = typeof(MouseEvent_SingleByteChar_UInt32);
PanelWrapper = typeof(PanelWrapper_libpanelw_so_6);
NCursesCharWrapper = typeof(NCursesCharWrapper_libncursesw_so_6_MultiByteChar_SingleByteChar_UInt32_4_WideChar_4_SingleByteChar_UInt32_schar_t_MouseEvent_SingleByteChar_UInt32);
NCursesWrapper = typeof(NCursesWrapper_libncursesw_so_6);
#endif
break;
}
, but most should Just Work™.

Windows

Create and install a NuGet package from runtime.win.NCurses.

Building this package downloads the required DLL files (x86 & x64) from http://invisible-island.net, the official NCurses website.

You're gonna have to manually check the $VERSION the build downloaded in the bin\Debug directory.

Nuget push pushes the NuGet package to your local cache. This way it can be consumed by any project.

cd deps\NippyWard.NCurses.Tasks
dotnet build
cd ..\runtime.win.NCurses
dotnet build
dotnet pack
dotnet nuget push bin\Debug\runtime.win.NCurses.$VERSION.nupkg -s %USERPROFILE%\.nuget\packages

This nuget package should get auto-referenced when on Windows and referencing NippyWard.NCurses. You need to guarantee it's in your cache, because it is not available on NuGet.org.

MacOS

I have no mac.

Usage

The class Ncurses is the starting point of all operations.

A call to NCurses.Start:

  • initilaizes NCurses
  • overrides the current Console
  • returns the Standard Screen.

The Standard Screen (stdscr) is an IWindow which you can use like any window, except that it spans the entire screen.

IWindow stdScr = NCurses.Start();

A window is used to manipulate - write text to - the screen. Windows can be created and destoyed (except the stdscr). These windows can be optimized to only support single byte characters (ASCII). By default multi-byte windows are created unless explicitly stated.

IWindow win1 = NCurses.CreateWindow(20, 20, 0, 0);

Many operations can be used on a window, check IWindow for a full list. The API is very similar to Console, the major difference being a 2nd call to IWindow.Refresh or IWindow.NoOutRefresh/NCurses.Update to actually update the screen.

The NCurses documentation is relevant to some degree. Especially check the sections about refresh to prevent screen flickering.

win1.Write("Hello World");
win1.Refresh(); //update window, screen and render

//update multiple windows
IWindow win2 = NCurses.CreateWindow(20, 20, 20, 20);
win1.Write("Hello Galaxy");
win1.NoOutRefresh(); //update window
win2.Write("Hello Universe");
win2.NoOutRefresh(); //update window
NCurses.Update(); //update screen and render

Check test for more usage examples (e.g. panels, pads). For UTF-8 examples, check MultiByte.

When using UTF-8 on Windows, keep in mind it gets converted to UTF-16 to render.

NippyWard.NCurses is NOT thread-safe, unless locking gets enabled explicitly using NCurses.EnableLocking ! When enabled, a set of operations on 1 ore more windows can be thread-safely grouped using NCurses.CreateThreadSafeDisposable.

Remember to dispose when your're done using the window.

win1.Dispose();

When your program ends, a call to Ncurses.End destroys NCurses and restores the Console.

NCurses.End();

Releases

No releases published

Packages

No packages published

Languages