// * This makes emacs happy -*-Mode: C++;-*-
/****************************************************************************
 * Copyright (c) 1998-2012,2014 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.32 2014/08/09 22:06:11 Adam.Jiang 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 THROW2(NCursesException const, 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 THROW2(NCursesException const, 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 THROW2(NCursesException const, 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 *>(reinterpret_cast<const 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 *>(reinterpret_cast<const 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 *>(reinterpret_cast<const void*>
				     (p_UserData)));
  };

  virtual ~NCursesUserForm() {
  };

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

  inline virtual void setUserData (const T* p_UserData) {
    if (form)
      set_user (const_cast<void *>(reinterpret_cast<const 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 */
