// * This makes emacs happy -*-Mode: C++;-*-
/****************************************************************************
 * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc.              *
 *                                                                          *
 * Permission is hereby granted, free of charge, to any person obtaining a  *
 * copy of this software and associated documentation files (the            *
 * "Software"), to deal in the Software without restriction, including      *
 * without limitation the rights to use, copy, modify, merge, publish,      *
 * distribute, distribute with modifications, sublicense, and/or sell       *
 * copies of the Software, and to permit persons to whom the Software is    *
 * furnished to do so, subject to the following conditions:                 *
 *                                                                          *
 * The above copyright notice and this permission notice shall be included  *
 * in all copies or substantial portions of the Software.                   *
 *                                                                          *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
 *                                                                          *
 * Except as contained in this notice, the name(s) of the above copyright   *
 * holders shall not be used in advertising or otherwise to promote the     *
 * sale, use or other dealings in this Software without prior written       *
 * authorization.                                                           *
 ****************************************************************************/

/****************************************************************************
 *   Author: Juergen Pfeifer, 1997                                          *
 ****************************************************************************/

// $Id: cursesf.h,v 1.28 2005/08/13 18:08:24 tom Exp $

#ifndef NCURSES_CURSESF_H_incl
#define NCURSES_CURSESF_H_incl 1

#include <cursesp.h>

#ifndef __EXT_QNX
#include <string.h>
#endif

extern "C" {
#  include <form.h>
}
//
// -------------------------------------------------------------------------
// The abstract base class for buitin and user defined Fieldtypes.
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP NCursesFormField; // forward declaration

// Class to represent builtin field types as well as C++ written new
// fieldtypes (see classes UserDefineFieldType...
class NCURSES_IMPEXP NCursesFieldType
{
  friend class NCursesFormField;

protected:
  FIELDTYPE* fieldtype;

  inline void OnError(int err) const THROWS(NCursesFormException) {
    if (err!=E_OK)
      THROW(new NCursesFormException (err));
  }

  NCursesFieldType(FIELDTYPE *f) : fieldtype(f) {
  }

  virtual ~NCursesFieldType() {}

  // Set the fields f fieldtype to this one.
  virtual void set(NCursesFormField& f) = 0;

public:
  NCursesFieldType()
    : fieldtype(STATIC_CAST(FIELDTYPE*)(0))
  {
  }

  NCursesFieldType& operator=(const NCursesFieldType& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
    }
    return *this;
  }

  NCursesFieldType(const NCursesFieldType& rhs)
    : fieldtype(rhs.fieldtype)
  {
  }

};

//
// -------------------------------------------------------------------------
// The class representing a forms field, wrapping the lowlevel FIELD struct
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP NCursesFormField
{
  friend class NCursesForm;

protected:
  FIELD *field;		     // lowlevel structure
  NCursesFieldType* ftype;   // Associated field type

  // Error handler
  inline void OnError (int err) const THROWS(NCursesFormException) {
    if (err != E_OK)
      THROW(new NCursesFormException (err));
  }

public:
  // Create a 'Null' field. Can be used to delimit a field list
  NCursesFormField()
    : field(STATIC_CAST(FIELD*)(0)),
      ftype(STATIC_CAST(NCursesFieldType*)(0))
  {
  }

  // Create a new field
  NCursesFormField (int rows,
		    int ncols,
		    int first_row = 0,
		    int first_col = 0,
		    int offscreen_rows = 0,
		    int additional_buffers = 0)
    : field(0),
      ftype(STATIC_CAST(NCursesFieldType*)(0))
  {
      field = ::new_field(rows, ncols, first_row, first_col,
			  offscreen_rows, additional_buffers);
      if (!field)
	OnError(errno);
  }

  NCursesFormField& operator=(const NCursesFormField& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
    }
    return *this;
  }

  NCursesFormField(const NCursesFormField& rhs)
    : field(rhs.field), ftype(rhs.ftype)
  {
  }

  virtual ~NCursesFormField ();

  // Duplicate the field at a new position
  inline NCursesFormField* dup(int first_row, int first_col)
  {
    NCursesFormField* f = new NCursesFormField();
    if (!f)
      OnError(E_SYSTEM_ERROR);
    else {
      f->ftype = ftype;
      f->field = ::dup_field(field,first_row,first_col);
      if (!f->field)
	OnError(errno);
    }
    return f;
  }

  // Link the field to a new location
  inline NCursesFormField* link(int first_row, int first_col) {
    NCursesFormField* f = new NCursesFormField();
    if (!f)
      OnError(E_SYSTEM_ERROR);
    else {
      f->ftype = ftype;
      f->field = ::link_field(field,first_row,first_col);
      if (!f->field)
	OnError(errno);
    }
    return f;
  }

  // Get the lowlevel field representation
  inline FIELD* get_field() const {
    return field;
  }

  // Retrieve info about the field
  inline void info(int& rows, int& ncols,
		   int& first_row, int& first_col,
		   int& offscreen_rows, int& additional_buffers) const {
    OnError(::field_info(field, &rows, &ncols,
			 &first_row, &first_col,
			 &offscreen_rows, &additional_buffers));
  }

  // Retrieve info about the fields dynamic properties.
  inline void dynamic_info(int& dynamic_rows, int& dynamic_cols,
			   int& max_growth) const {
    OnError(::dynamic_field_info(field, &dynamic_rows, &dynamic_cols,
				 &max_growth));
  }

  // For a dynamic field you may set the maximum growth limit.
  // A zero means unlimited growth.
  inline void set_maximum_growth(int growth = 0) {
    OnError(::set_max_field(field,growth));
  }

  // Move the field to a new position
  inline void move(int row, int col) {
    OnError(::move_field(field,row,col));
  }

  // Mark the field to start a new page
  inline void new_page(bool pageFlag = FALSE) {
    OnError(::set_new_page(field,pageFlag));
  }

  // Retrieve whether or not the field starts a new page.
  inline bool is_new_page() const {
    return ::new_page(field);
  }

  // Set the justification for the field
  inline void set_justification(int just) {
    OnError(::set_field_just(field,just));
  }

  // Retrieve the fields justification
  inline int justification() const {
    return ::field_just(field);
  }
  // Set the foreground attribute for the field
  inline void set_foreground(chtype foreground) {
    OnError(::set_field_fore(field,foreground));
  }

  // Retrieve the fields foreground attribute
  inline chtype fore() const {
    return ::field_fore(field);
  }

  // Set the background attribute for the field
  inline void set_background(chtype background) {
    OnError(::set_field_back(field,background));
  }

  // Retrieve the fields background attribute
  inline chtype back() const {
    return ::field_back(field);
  }

  // Set the padding character for the field
  inline void set_pad_character(int padding) {
    OnError(::set_field_pad(field, padding));
  }

  // Retrieve the fields padding character
  inline int pad() const {
    return ::field_pad(field);
  }

  // Switch on the fields options
  inline void options_on (Field_Options opts) {
    OnError (::field_opts_on (field, opts));
  }

  // Switch off the fields options
  inline void options_off (Field_Options opts) {
    OnError (::field_opts_off (field, opts));
  }

  // Retrieve the fields options
  inline Field_Options options () const {
    return ::field_opts (field);
  }

  // Set the fields options
  inline void set_options (Field_Options opts) {
    OnError (::set_field_opts (field, opts));
  }

  // Mark the field as changed
  inline void set_changed(bool changeFlag = TRUE) {
    OnError(::set_field_status(field,changeFlag));
  }

  // Test whether or not the field is marked as changed
  inline bool changed() const {
    return ::field_status(field);
  }

  // Return the index of the field in the field array of a form
  // or -1 if the field is not associated to a form
  inline int (index)() const {
    return ::field_index(field);
  }

  // Store a value in a fields buffer. The default buffer is nr. 0
  inline void set_value(const char *val, int buffer = 0) {
    OnError(::set_field_buffer(field,buffer,val));
  }

  // Retrieve the value of a fields buffer. The default buffer is nr. 0
  inline char* value(int buffer = 0) const {
    return ::field_buffer(field,buffer);
  }

  // Set the validation type of the field.
  inline void set_fieldtype(NCursesFieldType& f) {
    ftype = &f;
    f.set(*this); // A good friend may do that...
  }

  // Retrieve the validation type of the field.
  inline NCursesFieldType* fieldtype() const {
    return ftype;
  }

};

  // This are the built-in hook functions in this C++ binding. In C++ we use
  // virtual member functions (see below On_..._Init and On_..._Termination)
  // to provide this functionality in an object oriented manner.
extern "C" {
  void _nc_xx_frm_init(FORM *);
  void _nc_xx_frm_term(FORM *);
  void _nc_xx_fld_init(FORM *);
  void _nc_xx_fld_term(FORM *);
}

//
// -------------------------------------------------------------------------
// The class representing a form, wrapping the lowlevel FORM struct
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP NCursesForm : public NCursesPanel
{
protected:
  FORM* form;  // the lowlevel structure

private:
  NCursesWindow* sub;   // the subwindow object
  bool b_sub_owner;     // is this our own subwindow?
  bool b_framed;	// has the form a border?
  bool b_autoDelete;    // Delete fields when deleting form?

  NCursesFormField** my_fields; // The array of fields for this form

  // This structure is used for the form's user data field to link the
  // FORM* to the C++ object and to provide extra space for a user pointer.
  typedef struct {
    void*	       m_user;	    // the pointer for the user's data
    const NCursesForm* m_back;      // backward pointer to C++ object
    const FORM*	       m_owner;
  } UserHook;

  // Get the backward pointer to the C++ object from a FORM
  static inline NCursesForm* getHook(const FORM *f) {
    UserHook* hook = reinterpret_cast<UserHook*>(::form_userptr(f));
    assert(hook != 0 && hook->m_owner==f);
    return const_cast<NCursesForm*>(hook->m_back);
  }

  friend void _nc_xx_frm_init(FORM *);
  friend void _nc_xx_frm_term(FORM *);
  friend void _nc_xx_fld_init(FORM *);
  friend void _nc_xx_fld_term(FORM *);

  // Calculate FIELD* array for the menu
  FIELD** mapFields(NCursesFormField* nfields[]);

protected:
  // internal routines
  inline void set_user(void *user) {
    UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
    assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
    uptr->m_user = user;
  }

  inline void *get_user() {
    UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
    assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
    return uptr->m_user;
  }

  void InitForm (NCursesFormField* Fields[],
		 bool with_frame,
		 bool autoDeleteFields);

  inline void OnError (int err) const THROWS(NCursesFormException) {
    if (err != E_OK)
      THROW(new NCursesFormException (err));
  }

  // this wraps the form_driver call.
  virtual int driver (int c) ;

  // 'Internal' constructor, builds an object without association to a
  // field array.
  NCursesForm( int  nlines,
	       int  ncols,
	       int  begin_y = 0,
	       int  begin_x = 0)
    : NCursesPanel(nlines, ncols, begin_y, begin_x),
      form (STATIC_CAST(FORM*)(0)),
      sub(0),
      b_sub_owner(0),
      b_framed(0),
      b_autoDelete(0),
      my_fields(0)
  {
  }

public:
  // Create form for the default panel.
  NCursesForm (NCursesFormField* Fields[],
	       bool with_frame=FALSE,	      // reserve space for a frame?
	       bool autoDelete_Fields=FALSE)  // do automatic cleanup?
    : NCursesPanel(),
      form(0),
      sub(0),
      b_sub_owner(0),
      b_framed(0),
      b_autoDelete(0),
      my_fields(0)
  {
    InitForm(Fields, with_frame, autoDelete_Fields);
  }

  // Create a form in a panel with the given position and size.
  NCursesForm (NCursesFormField* Fields[],
	       int  nlines,
	       int  ncols,
	       int  begin_y,
	       int  begin_x,
	       bool with_frame=FALSE,	     // reserve space for a frame?
	       bool autoDelete_Fields=FALSE) // do automatic cleanup?
    : NCursesPanel(nlines, ncols, begin_y, begin_x),
      form(0),
      sub(0),
      b_sub_owner(0),
      b_framed(0),
      b_autoDelete(0),
      my_fields(0)
  {
      InitForm(Fields, with_frame, autoDelete_Fields);
  }

  NCursesForm& operator=(const NCursesForm& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
      NCursesPanel::operator=(rhs);
    }
    return *this;
  }

  NCursesForm(const NCursesForm& rhs)
    : NCursesPanel(rhs),
      form(rhs.form),
      sub(rhs.sub),
      b_sub_owner(rhs.b_sub_owner),
      b_framed(rhs.b_framed),
      b_autoDelete(rhs.b_autoDelete),
      my_fields(rhs.my_fields)
  {
  }

  virtual ~NCursesForm();

  // Set the default attributes for the form
  virtual void setDefaultAttributes();

  // Retrieve current field of the form.
  inline NCursesFormField* current_field() const {
    return my_fields[::field_index(::current_field(form))];
  }

  // Set the forms subwindow
  void setSubWindow(NCursesWindow& sub);

  // Set these fields for the form
  inline void setFields(NCursesFormField* Fields[]) {
    OnError(::set_form_fields(form,mapFields(Fields)));
  }

  // Remove the form from the screen
  inline void unpost (void) {
    OnError (::unpost_form (form));
  }

  // Post the form to the screen if flag is true, unpost it otherwise
  inline void post(bool flag = TRUE) {
    OnError (flag ? ::post_form(form) : ::unpost_form (form));
  }

  // Decorations
  inline void frame(const char *title=NULL, const char* btitle=NULL) {
    if (b_framed)
      NCursesPanel::frame(title,btitle);
    else
      OnError(E_SYSTEM_ERROR);
  }

  inline void boldframe(const char *title=NULL, const char* btitle=NULL) {
    if (b_framed)
      NCursesPanel::boldframe(title,btitle);
    else
      OnError(E_SYSTEM_ERROR);
  }

  inline void label(const char *topLabel, const char *bottomLabel) {
    if (b_framed)
      NCursesPanel::label(topLabel,bottomLabel);
    else
      OnError(E_SYSTEM_ERROR);
  }

  // -----
  // Hooks
  // -----

  // Called after the form gets repositioned in its window.
  // This is especially true if the form is posted.
  virtual void On_Form_Init();

  // Called before the form gets repositioned in its window.
  // This is especially true if the form is unposted.
  virtual void On_Form_Termination();

  // Called after the field became the current field
  virtual void On_Field_Init(NCursesFormField& field);

  // Called before this field is left as current field.
  virtual void On_Field_Termination(NCursesFormField& field);

  // Calculate required window size for the form.
  void scale(int& rows, int& ncols) const {
    OnError(::scale_form(form,&rows,&ncols));
  }

  // Retrieve number of fields in the form.
  int count() const {
    return ::field_count(form);
  }

  // Make the page the current page of the form.
  void set_page(int pageNum) {
    OnError(::set_form_page(form, pageNum));
  }

  // Retrieve current page number
  int page() const {
    return ::form_page(form);
  }

  // Switch on the forms options
  inline void options_on (Form_Options opts) {
    OnError (::form_opts_on (form, opts));
  }

  // Switch off the forms options
  inline void options_off (Form_Options opts) {
    OnError (::form_opts_off (form, opts));
  }

  // Retrieve the forms options
  inline Form_Options options () const {
    return ::form_opts (form);
  }

  // Set the forms options
  inline void set_options (Form_Options opts) {
    OnError (::set_form_opts (form, opts));
  }

  // Are there more data in the current field after the data shown
  inline bool data_ahead() const {
    return ::data_ahead(form);
  }

  // Are there more data in the current field before the data shown
  inline bool data_behind() const {
    return ::data_behind(form);
  }

  // Position the cursor to the current field
  inline void position_cursor () {
    OnError (::pos_form_cursor (form));
  }
  // Set the current field
  inline void set_current(NCursesFormField& F) {
    OnError (::set_current_field(form, F.field));
  }

  // Provide a default key virtualization. Translate the keyboard
  // code c into a form request code.
  // The default implementation provides a hopefully straightforward
  // mapping for the most common keystrokes and form requests.
  virtual int virtualize(int c);

  // Operators
  inline NCursesFormField* operator[](int i) const {
    if ( (i < 0) || (i >= ::field_count (form)) )
      OnError (E_BAD_ARGUMENT);
    return my_fields[i];
  }

  // Perform the menu's operation
  // Return the field where you left the form.
  virtual NCursesFormField* operator()(void);

  // Exception handlers. The default is a Beep.
  virtual void On_Request_Denied(int c) const;
  virtual void On_Invalid_Field(int c) const;
  virtual void On_Unknown_Command(int c) const;

};

//
// -------------------------------------------------------------------------
// This is the typical C++ typesafe way to allow to attach
// user data to a field of a form. Its assumed that the user
// data belongs to some class T. Use T as template argument
// to create a UserField.
// -------------------------------------------------------------------------
template<class T> class NCURSES_IMPEXP NCursesUserField : public NCursesFormField
{
public:
  NCursesUserField (int rows,
		    int ncols,
		    int first_row = 0,
		    int first_col = 0,
		    const T* p_UserData = STATIC_CAST(T*)(0),
		    int offscreen_rows = 0,
		    int additional_buffers = 0)
    : NCursesFormField (rows, ncols,
			first_row, first_col,
			offscreen_rows, additional_buffers) {
      if (field)
	OnError(::set_field_userptr(field, STATIC_CAST(void *)(p_UserData)));
  }

  virtual ~NCursesUserField() {};

  inline const T* UserData (void) const {
    return reinterpret_cast<const T*>(::field_userptr (field));
  }

  inline virtual void setUserData(const T* p_UserData) {
    if (field)
      OnError (::set_field_userptr (field, STATIC_CAST(void *)(p_UserData)));
  }
};
//
// -------------------------------------------------------------------------
// The same mechanism is used to attach user data to a form
// -------------------------------------------------------------------------
//
template<class T> class NCURSES_IMPEXP NCursesUserForm : public NCursesForm
{
protected:
  // 'Internal' constructor, builds an object without association to a
  // field array.
  NCursesUserForm( int  nlines,
		   int  ncols,
		   int  begin_y = 0,
		   int  begin_x = 0,
		   const T* p_UserData = STATIC_CAST(T*)(0))
    : NCursesForm(nlines,ncols,begin_y,begin_x) {
      if (form)
	set_user (const_cast<void *>(p_UserData));
  }

public:
  NCursesUserForm (NCursesFormField Fields[],
		   const T* p_UserData = STATIC_CAST(T*)(0),
		   bool with_frame=FALSE,
		   bool autoDelete_Fields=FALSE)
    : NCursesForm (Fields, with_frame, autoDelete_Fields) {
      if (form)
	set_user (const_cast<void *>(p_UserData));
  };

  NCursesUserForm (NCursesFormField Fields[],
		   int nlines,
		   int ncols,
		   int begin_y = 0,
		   int begin_x = 0,
		   const T* p_UserData = STATIC_CAST(T*)(0),
		   bool with_frame=FALSE,
		   bool autoDelete_Fields=FALSE)
    : NCursesForm (Fields, nlines, ncols, begin_y, begin_x,
		   with_frame, autoDelete_Fields) {
      if (form)
	set_user (const_cast<void *>(p_UserData));
  };

  virtual ~NCursesUserForm() {
  };

  inline T* UserData (void) const {
    return reinterpret_cast<T*>(get_user ());
  };

  inline virtual void setUserData (const T* p_UserData) {
    if (form)
      set_user (const_cast<void *>(p_UserData));
  }

};
//
// -------------------------------------------------------------------------
// Builtin Fieldtypes
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP Alpha_Field : public NCursesFieldType
{
private:
  int min_field_width;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
  }

public:
  Alpha_Field(int width)
    : NCursesFieldType(TYPE_ALPHA),
      min_field_width(width) {
  }
};

class NCURSES_IMPEXP Alphanumeric_Field : public NCursesFieldType
{
private:
  int min_field_width;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
  }

public:
  Alphanumeric_Field(int width)
    : NCursesFieldType(TYPE_ALNUM),
      min_field_width(width) {
  }
};

class NCURSES_IMPEXP Integer_Field : public NCursesFieldType
{
private:
  int precision;
  long lower_limit, upper_limit;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,
			     precision,lower_limit,upper_limit));
  }

public:
  Integer_Field(int prec, long low=0L, long high=0L)
    : NCursesFieldType(TYPE_INTEGER),
      precision(prec), lower_limit(low), upper_limit(high) {
  }
};

class NCURSES_IMPEXP Numeric_Field : public NCursesFieldType
{
private:
  int precision;
  double lower_limit, upper_limit;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,
			     precision,lower_limit,upper_limit));
  }

public:
  Numeric_Field(int prec, double low=0.0, double high=0.0)
    : NCursesFieldType(TYPE_NUMERIC),
      precision(prec), lower_limit(low), upper_limit(high) {
  }
};

class NCURSES_IMPEXP Regular_Expression_Field : public NCursesFieldType
{
private:
  char* regex;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,regex));
  }

  void copy_regex(const char *source)
  {
    regex = new char[1 + ::strlen(source)];
    (::strcpy)(regex, source);
  }

public:
  Regular_Expression_Field(const char *expr)
    : NCursesFieldType(TYPE_REGEXP),
      regex(NULL)
  {
    copy_regex(expr);
  }

  Regular_Expression_Field& operator=(const Regular_Expression_Field& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
      copy_regex(rhs.regex);
      NCursesFieldType::operator=(rhs);
    }
    return *this;
  }

  Regular_Expression_Field(const Regular_Expression_Field& rhs)
    : NCursesFieldType(rhs),
      regex(NULL)
  {
    copy_regex(rhs.regex);
  }

  ~Regular_Expression_Field() {
    delete[] regex;
  }
};

class NCURSES_IMPEXP Enumeration_Field : public NCursesFieldType
{
private:
  const char** list;
  int case_sensitive;
  int non_unique_matches;

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,
			     list,case_sensitive,non_unique_matches));
  }
public:
  Enumeration_Field(const char* enums[],
		    bool case_sens=FALSE,
		    bool non_unique=FALSE)
    : NCursesFieldType(TYPE_ENUM),
      list(enums),
      case_sensitive(case_sens ? -1 : 0),
      non_unique_matches(non_unique ? -1 : 0) {
  }

  Enumeration_Field& operator=(const Enumeration_Field& rhs)
  {
    if (this != &rhs) {
      *this = rhs;
      NCursesFieldType::operator=(rhs);
    }
    return *this;
  }

  Enumeration_Field(const Enumeration_Field& rhs)
    : NCursesFieldType(rhs),
      list(rhs.list),
      case_sensitive(rhs.case_sensitive),
      non_unique_matches(rhs.non_unique_matches)
  {
  }
};

class NCURSES_IMPEXP IPV4_Address_Field : public NCursesFieldType
{
private:
  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype));
  }

public:
  IPV4_Address_Field() : NCursesFieldType(TYPE_IPV4) {
  }
};

extern "C" {
  bool _nc_xx_fld_fcheck(FIELD *, const void*);
  bool _nc_xx_fld_ccheck(int c, const void *);
  void* _nc_xx_fld_makearg(va_list*);
}

//
// -------------------------------------------------------------------------
// Abstract base class for User-Defined Fieldtypes
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP UserDefinedFieldType : public NCursesFieldType
{
  friend class UDF_Init; // Internal helper to set up statics
private:
  // For all C++ defined fieldtypes we need only one generic lowlevel
  // FIELDTYPE* element.
  static FIELDTYPE* generic_fieldtype;

protected:
  // This are the functions required by the low level libforms functions
  // to construct a fieldtype.
  friend bool _nc_xx_fld_fcheck(FIELD *, const void*);
  friend bool _nc_xx_fld_ccheck(int c, const void *);
  friend void* _nc_xx_fld_makearg(va_list*);

  void set(NCursesFormField& f) {
    OnError(::set_field_type(f.get_field(),fieldtype,&f));
  }

protected:
  // Redefine this function to do a field validation. The argument
  // is a reference to the field you should validate.
  virtual bool field_check(NCursesFormField& f) = 0;

  // Redefine this function to do a character validation. The argument
  // is the character to be validated.
  virtual bool char_check (int c) = 0;

public:
  UserDefinedFieldType() : NCursesFieldType(generic_fieldtype) {
  }
};

extern "C" {
  bool _nc_xx_next_choice(FIELD*, const void *);
  bool _nc_xx_prev_choice(FIELD*, const void *);
}

//
// -------------------------------------------------------------------------
// Abstract base class for User-Defined Fieldtypes with Choice functions
// -------------------------------------------------------------------------
//
class NCURSES_IMPEXP UserDefinedFieldType_With_Choice : public UserDefinedFieldType
{
  friend class UDF_Init; // Internal helper to set up statics
private:
  // For all C++ defined fieldtypes with choice functions we need only one
  // generic lowlevel FIELDTYPE* element.
  static FIELDTYPE* generic_fieldtype_with_choice;

  // This are the functions required by the low level libforms functions
  // to construct a fieldtype with choice functions.
  friend bool _nc_xx_next_choice(FIELD*, const void *);
  friend bool _nc_xx_prev_choice(FIELD*, const void *);

protected:
  // Redefine this function to do the retrieval of the next choice value.
  // The argument is a reference to the field tobe examined.
  virtual bool next    (NCursesFormField& f) = 0;

  // Redefine this function to do the retrieval of the previous choice value.
  // The argument is a reference to the field tobe examined.
  virtual bool previous(NCursesFormField& f) = 0;

public:
  UserDefinedFieldType_With_Choice() {
    fieldtype = generic_fieldtype_with_choice;
  }
};

#endif /* NCURSES_CURSESF_H_incl */
