# Ada95 Binding for ncurses

The ncurses Ada95 binding is © 1996 by Jürgen Pfeifer.

Permission is hereby granted to reproduce and distribute this binding by any means and for any fee, whether alone or as part of a larger distribution, in source or in binary form, PROVIDED this notice is included with any such distribution, and is not removed from any of its header files. Mention of ncurses and the author of this binding in any applications linked with it is highly appreciated.
This binding comes AS IS with no warranty, implied or expressed.

## General Remarks

- Although I like Ada95 very much (thanks to GNAT), I'm not really a poweruser of it, because at work we don't use it :-(.
  So I can use it only at home for my small private projects :-).
  So any comments of the real Ada Gurus about design flaws are really appreciated.
- This document describes Version 00.91 of the binding.
- The functionality is modelled to be compatible with the ncurses package, a clone of the SVr4 curses model.
  I did the development on an Intel box running Linux 1.3.x and 2.0, ncurses-1.9.9g and the GNU Ada Translator gnat-3.05. For any older versions of ncurses and gnat it will not work.
- You must have the m4 macroprocessor to build this package. If you don't have this program, you can get the FSF version here.
- Ada programs are supposed to be readable. One of my favourite methods to make code readable is to use expressive names for the identifiers. You can find a list of a mapping of the cryptic curses names to the Ada names in this table.
- This is not a typical one-2-one interface mapping. It is close to one-2-one on the functional level. Each (n)curses function has it's counterpart with a more or less similar formal parameter list in the binding. I make use of Ada's overloading mechanisms. This means, that sometimes different C functions are represented by the same Ada procedure/function name, but with different formal parameter lists.
  The mapping is not one-2-one with respect to the datatypes. I tried to make records out of the flat chtype and similar structures, so you don't have to do bit operations to mark an attributed character as bold. Just make the boolean member bold of the record true. The binding also hides the structures like WINDOW, PANEL, MENU, FORM etc. !
- I try to do as much error checking as possible and feasible in the binding. I will raise an Ada exception when something went wrong in the low-level curses. This has the effect that - at least first time in my life - (n)curses programs have now a very rigid error checking, but - thanks to Ada - you don't have to code the orgiastic error checking style of C.
- Support for wide characters is currently not in the binding, as it is not really in ncurses at this point in time.

## Directory organization and the build process

The toplevel directory of the Ada95 binding contains only the README, TODO and the Makefile. All the rest are subdirectories containing various parts of the binding. All of this is configured during the configure process of the ncurses package, as long as the configure script detects the right version of GNAT. It must be 3.05 or above.

The subdirectories are

Directory | Content
--- | ---
gen | Generation templates and Generator
html | Documentation in HTML format
ada_include | Binding specification and body files
ada_objects | Binding object files (after compilation)
objects | Temporary object files created during compilation
samples | Sample programs for the binding.

The top level Makefile first visits the gen directory and makes the targets there. The main purpose of this directory is to create and run a helper program named gen. gen is compiled with the current headers and libraries of this ncurses package. It is used to generate various constants and data structures into several Ada95 package specifications. Several ncurses datatypes are int's used as bitmaps. To model this as Ada95 records, one has to provide a representation clause that guarantees the correct mapping, because this depends on the endianess of the machines architecture.
The gen program is called with two single letters as argument and generates then output depending on the arguments on the standard output channel. This output is then included into the various template files by the m4 macroprocessor. The templates all have the name pattern terminal_*.m4. If you cut the .m4 extension you have the names of the files that are generated.
For more details which letter combinations are allowed as arguments, about there meanings and how the output is merged into the templates please consult the sourcefile gen.c and the Makefile in the gen directory.
You should never edit the generated sources. Use the templates and run the generator again.

After the generation of the specifications, the ada_include directory is entered. This now contains the complete library source for the Ada95 binding to ncurses. The make in this directory now creates the associated object files and linker information files in the ada_objects directory.
Finally the samples directory is entered. There is currently only one sample program. The executables name is tour. The purpose of the sample is simply to give a coding sample for the binding and not so much to provide a demo of all ncurses features.

## Limitations

- I provide no SCREEN datatype and functions to set a new screen. If you need this (mostly for debugging I guess), write a small C routine doing all this and import it into your Ada program.
- I provide no functions to switch on/off curses tracing options. Same suggestion as above.
- Although Ada95 is an OO Language, this binding doesn't provide an OO abstraction of the (n)curses functionality. As mentioned above it's a thin binding for the (n)curses functions. But without any doubt it would be nice to build on top of this an OO abstraction of (n)curses functionality.
- If you use the user-pointer mechanism for most of the ncurses structures in a mixed language environemt, i.e. Ada95 and C routines operate on the same objects, care must be taken because the Ada binding itself uses the user pointer mechanism for it's own purposes. See the corresponding section in implementention details.
- I currently do not support the link_fieldtype functionality of the forms subsystem.
- The *_IO packages are currently output only.

## Installation

After you have successfully built the whole ncurses package including this binding, you will find in the Ada95 directory two subdirectoried:

- ada_include
- ada_objects

You can copy them to the place were you usually store your ada libraries or just leave them here. You have to use the -p option of the cp command. You have to add these directories to the ADA_INCLUDE_PATH or ADA_OBJECTS_PATH environment variables.

If you use the --srcdir option when configuring your ncurses, the ada_include directory is actually splitted across two directory trees. One ada_include directory is part of the Ada95 subtree of the ncurses source tree. It contains those package specifications and bodies which are not generated on the fly. In the Ada95 subdirectory of your build tree you'll find the other part of ada_include, which contains those specfications and bodies that are generated. You must copy both subdirectories into one common target directory where you store your GNAT libraries.

If you perform the install step of the ncurses global Makefile (or the install.libs step), a library named libncwrap.a will be installed in your selected library target directory. This is a tiny C wrapper library required by the binding to encapsulate a few functions of (n)curses. We plan to integrate these wrappers into the ncurses main library so that this wrapper is no longer required in the future.

## Hierarchy of packages

- Terminal_Interface
  - Curses
    - Mouse
    - Panels
      - User_Data
    - Menus
      - Menu_User_Data
      - Item_User_Data
    - Forms
      - Form_User_Data
      - Field_User_Data
      - Field_Types
      - Choice_Field_Types
    - Text_IO
      - Integer_IO
      - Float_IO
      - Fixed_IO
      - Decimal_IO
      - Modular_IO
      - Enumeration_IO
      - Complex_IO

## Implementation Details

#### Behind the abstraction

All the new types like Window, Panel, Menu, Form etc. are just opaque representations of the pointers to the corresponding low level (n)curses structures like WINDOW *, PANEL *, MENU * or FORM *. So you can safely pass them to C routines that expect a pointer to one of those structures.

#### Item and Field Arrays

In C you have to pass the item and field arrays to define menus or forms terminated by a null item or null field. This is not necessary in this binding. The binding routines will construct from an Ada95 style array of Item or Field objects internally the properly terminated array of C structure pointers. See the examples for more details.

#### Extended ripoffline() usage

The official documentation of (n)curses says, that the line parameter determines only whether or not exactly one line is stolen from the top or bottom of the screen. So essentially only the sign of the parameter is evaluated. ncurses has internally implemented it in a way, that uses the line parameter also to control the amount of lines to steal. This mechanism is used in the Rip_Off_Lines routine of the binding.

#### User Pointer mechanism

TBD

#### How user defined field types work

TBD

#### Enumeration fields handling

The (n)curses documentation says, that the String arrays to be passed to an TYPE_ENUM fieldtype must not be automatic variables. This is not true in this binding, because it is internally arranged to safely copy these values.

#### Using other Ada compilers

This should basically not be a problem, but you have to replace a code sequence in the package body of Terminal_Interface.Curses.Forms that uses a hashing package supplied with the GNAT runtime, which is not part of the Standard Ada runtimes. This should not be too hard. I intend to remove this dependency in the future.

#### Port to other curses implementations

Basically it should not be too hard to make all this run on a regular SVr4 implementation of curses. The problems are probably these:

- ncurses has some additional features which are presented in this binding. You have two choices to deal with this:
  - Emulate the feature in this binding
  - Raise an exception for non implemented features
  Most likely you will follow a mixed approach. Some features are easy to simulate, others will be hard if not impossible.
- For menu items, the name and descriptions are internally copied by ncurses. So the binding doesn't care for the lifetime of the strings passed to the construction routine for items. This assumption is not true in most other implementations of the menu library. In this case you have to modify the binding routine New_Item to safestore the strings.

I'm quite sure I forgot something.