Home | History | Annotate | Download | only in include
      1 // * This makes emacs happy -*-Mode: C++;-*-
      2 /****************************************************************************
      3  * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc.              *
      4  *                                                                          *
      5  * Permission is hereby granted, free of charge, to any person obtaining a  *
      6  * copy of this software and associated documentation files (the            *
      7  * "Software"), to deal in the Software without restriction, including      *
      8  * without limitation the rights to use, copy, modify, merge, publish,      *
      9  * distribute, distribute with modifications, sublicense, and/or sell       *
     10  * copies of the Software, and to permit persons to whom the Software is    *
     11  * furnished to do so, subject to the following conditions:                 *
     12  *                                                                          *
     13  * The above copyright notice and this permission notice shall be included  *
     14  * in all copies or substantial portions of the Software.                   *
     15  *                                                                          *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
     19  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
     22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
     23  *                                                                          *
     24  * Except as contained in this notice, the name(s) of the above copyright   *
     25  * holders shall not be used in advertising or otherwise to promote the     *
     26  * sale, use or other dealings in this Software without prior written       *
     27  * authorization.                                                           *
     28  ****************************************************************************/
     29 
     30 /****************************************************************************
     31  *   Author: Juergen Pfeifer, 1997                                          *
     32  ****************************************************************************/
     33 
     34 // $Id: cursesf.h,v 1.28 2005/08/13 18:08:24 tom Exp $
     35 
     36 #ifndef NCURSES_CURSESF_H_incl
     37 #define NCURSES_CURSESF_H_incl 1
     38 
     39 #include <cursesp.h>
     40 
     41 #ifndef __EXT_QNX
     42 #include <string.h>
     43 #endif
     44 
     45 extern "C" {
     46 #  include <form.h>
     47 }
     48 //
     49 // -------------------------------------------------------------------------
     50 // The abstract base class for buitin and user defined Fieldtypes.
     51 // -------------------------------------------------------------------------
     52 //
     53 class NCURSES_IMPEXP NCursesFormField; // forward declaration
     54 
     55 // Class to represent builtin field types as well as C++ written new
     56 // fieldtypes (see classes UserDefineFieldType...
     57 class NCURSES_IMPEXP NCursesFieldType
     58 {
     59   friend class NCursesFormField;
     60 
     61 protected:
     62   FIELDTYPE* fieldtype;
     63 
     64   inline void OnError(int err) const THROWS(NCursesFormException) {
     65     if (err!=E_OK)
     66       THROW(new NCursesFormException (err));
     67   }
     68 
     69   NCursesFieldType(FIELDTYPE *f) : fieldtype(f) {
     70   }
     71 
     72   virtual ~NCursesFieldType() {}
     73 
     74   // Set the fields f fieldtype to this one.
     75   virtual void set(NCursesFormField& f) = 0;
     76 
     77 public:
     78   NCursesFieldType()
     79     : fieldtype(STATIC_CAST(FIELDTYPE*)(0))
     80   {
     81   }
     82 
     83   NCursesFieldType& operator=(const NCursesFieldType& rhs)
     84   {
     85     if (this != &rhs) {
     86       *this = rhs;
     87     }
     88     return *this;
     89   }
     90 
     91   NCursesFieldType(const NCursesFieldType& rhs)
     92     : fieldtype(rhs.fieldtype)
     93   {
     94   }
     95 
     96 };
     97 
     98 //
     99 // -------------------------------------------------------------------------
    100 // The class representing a forms field, wrapping the lowlevel FIELD struct
    101 // -------------------------------------------------------------------------
    102 //
    103 class NCURSES_IMPEXP NCursesFormField
    104 {
    105   friend class NCursesForm;
    106 
    107 protected:
    108   FIELD *field;		     // lowlevel structure
    109   NCursesFieldType* ftype;   // Associated field type
    110 
    111   // Error handler
    112   inline void OnError (int err) const THROWS(NCursesFormException) {
    113     if (err != E_OK)
    114       THROW(new NCursesFormException (err));
    115   }
    116 
    117 public:
    118   // Create a 'Null' field. Can be used to delimit a field list
    119   NCursesFormField()
    120     : field(STATIC_CAST(FIELD*)(0)),
    121       ftype(STATIC_CAST(NCursesFieldType*)(0))
    122   {
    123   }
    124 
    125   // Create a new field
    126   NCursesFormField (int rows,
    127 		    int ncols,
    128 		    int first_row = 0,
    129 		    int first_col = 0,
    130 		    int offscreen_rows = 0,
    131 		    int additional_buffers = 0)
    132     : field(0),
    133       ftype(STATIC_CAST(NCursesFieldType*)(0))
    134   {
    135       field = ::new_field(rows, ncols, first_row, first_col,
    136 			  offscreen_rows, additional_buffers);
    137       if (!field)
    138 	OnError(errno);
    139   }
    140 
    141   NCursesFormField& operator=(const NCursesFormField& rhs)
    142   {
    143     if (this != &rhs) {
    144       *this = rhs;
    145     }
    146     return *this;
    147   }
    148 
    149   NCursesFormField(const NCursesFormField& rhs)
    150     : field(rhs.field), ftype(rhs.ftype)
    151   {
    152   }
    153 
    154   virtual ~NCursesFormField ();
    155 
    156   // Duplicate the field at a new position
    157   inline NCursesFormField* dup(int first_row, int first_col)
    158   {
    159     NCursesFormField* f = new NCursesFormField();
    160     if (!f)
    161       OnError(E_SYSTEM_ERROR);
    162     else {
    163       f->ftype = ftype;
    164       f->field = ::dup_field(field,first_row,first_col);
    165       if (!f->field)
    166 	OnError(errno);
    167     }
    168     return f;
    169   }
    170 
    171   // Link the field to a new location
    172   inline NCursesFormField* link(int first_row, int first_col) {
    173     NCursesFormField* f = new NCursesFormField();
    174     if (!f)
    175       OnError(E_SYSTEM_ERROR);
    176     else {
    177       f->ftype = ftype;
    178       f->field = ::link_field(field,first_row,first_col);
    179       if (!f->field)
    180 	OnError(errno);
    181     }
    182     return f;
    183   }
    184 
    185   // Get the lowlevel field representation
    186   inline FIELD* get_field() const {
    187     return field;
    188   }
    189 
    190   // Retrieve info about the field
    191   inline void info(int& rows, int& ncols,
    192 		   int& first_row, int& first_col,
    193 		   int& offscreen_rows, int& additional_buffers) const {
    194     OnError(::field_info(field, &rows, &ncols,
    195 			 &first_row, &first_col,
    196 			 &offscreen_rows, &additional_buffers));
    197   }
    198 
    199   // Retrieve info about the fields dynamic properties.
    200   inline void dynamic_info(int& dynamic_rows, int& dynamic_cols,
    201 			   int& max_growth) const {
    202     OnError(::dynamic_field_info(field, &dynamic_rows, &dynamic_cols,
    203 				 &max_growth));
    204   }
    205 
    206   // For a dynamic field you may set the maximum growth limit.
    207   // A zero means unlimited growth.
    208   inline void set_maximum_growth(int growth = 0) {
    209     OnError(::set_max_field(field,growth));
    210   }
    211 
    212   // Move the field to a new position
    213   inline void move(int row, int col) {
    214     OnError(::move_field(field,row,col));
    215   }
    216 
    217   // Mark the field to start a new page
    218   inline void new_page(bool pageFlag = FALSE) {
    219     OnError(::set_new_page(field,pageFlag));
    220   }
    221 
    222   // Retrieve whether or not the field starts a new page.
    223   inline bool is_new_page() const {
    224     return ::new_page(field);
    225   }
    226 
    227   // Set the justification for the field
    228   inline void set_justification(int just) {
    229     OnError(::set_field_just(field,just));
    230   }
    231 
    232   // Retrieve the fields justification
    233   inline int justification() const {
    234     return ::field_just(field);
    235   }
    236   // Set the foreground attribute for the field
    237   inline void set_foreground(chtype foreground) {
    238     OnError(::set_field_fore(field,foreground));
    239   }
    240 
    241   // Retrieve the fields foreground attribute
    242   inline chtype fore() const {
    243     return ::field_fore(field);
    244   }
    245 
    246   // Set the background attribute for the field
    247   inline void set_background(chtype background) {
    248     OnError(::set_field_back(field,background));
    249   }
    250 
    251   // Retrieve the fields background attribute
    252   inline chtype back() const {
    253     return ::field_back(field);
    254   }
    255 
    256   // Set the padding character for the field
    257   inline void set_pad_character(int padding) {
    258     OnError(::set_field_pad(field, padding));
    259   }
    260 
    261   // Retrieve the fields padding character
    262   inline int pad() const {
    263     return ::field_pad(field);
    264   }
    265 
    266   // Switch on the fields options
    267   inline void options_on (Field_Options opts) {
    268     OnError (::field_opts_on (field, opts));
    269   }
    270 
    271   // Switch off the fields options
    272   inline void options_off (Field_Options opts) {
    273     OnError (::field_opts_off (field, opts));
    274   }
    275 
    276   // Retrieve the fields options
    277   inline Field_Options options () const {
    278     return ::field_opts (field);
    279   }
    280 
    281   // Set the fields options
    282   inline void set_options (Field_Options opts) {
    283     OnError (::set_field_opts (field, opts));
    284   }
    285 
    286   // Mark the field as changed
    287   inline void set_changed(bool changeFlag = TRUE) {
    288     OnError(::set_field_status(field,changeFlag));
    289   }
    290 
    291   // Test whether or not the field is marked as changed
    292   inline bool changed() const {
    293     return ::field_status(field);
    294   }
    295 
    296   // Return the index of the field in the field array of a form
    297   // or -1 if the field is not associated to a form
    298   inline int (index)() const {
    299     return ::field_index(field);
    300   }
    301 
    302   // Store a value in a fields buffer. The default buffer is nr. 0
    303   inline void set_value(const char *val, int buffer = 0) {
    304     OnError(::set_field_buffer(field,buffer,val));
    305   }
    306 
    307   // Retrieve the value of a fields buffer. The default buffer is nr. 0
    308   inline char* value(int buffer = 0) const {
    309     return ::field_buffer(field,buffer);
    310   }
    311 
    312   // Set the validation type of the field.
    313   inline void set_fieldtype(NCursesFieldType& f) {
    314     ftype = &f;
    315     f.set(*this); // A good friend may do that...
    316   }
    317 
    318   // Retrieve the validation type of the field.
    319   inline NCursesFieldType* fieldtype() const {
    320     return ftype;
    321   }
    322 
    323 };
    324 
    325   // This are the built-in hook functions in this C++ binding. In C++ we use
    326   // virtual member functions (see below On_..._Init and On_..._Termination)
    327   // to provide this functionality in an object oriented manner.
    328 extern "C" {
    329   void _nc_xx_frm_init(FORM *);
    330   void _nc_xx_frm_term(FORM *);
    331   void _nc_xx_fld_init(FORM *);
    332   void _nc_xx_fld_term(FORM *);
    333 }
    334 
    335 //
    336 // -------------------------------------------------------------------------
    337 // The class representing a form, wrapping the lowlevel FORM struct
    338 // -------------------------------------------------------------------------
    339 //
    340 class NCURSES_IMPEXP NCursesForm : public NCursesPanel
    341 {
    342 protected:
    343   FORM* form;  // the lowlevel structure
    344 
    345 private:
    346   NCursesWindow* sub;   // the subwindow object
    347   bool b_sub_owner;     // is this our own subwindow?
    348   bool b_framed;	// has the form a border?
    349   bool b_autoDelete;    // Delete fields when deleting form?
    350 
    351   NCursesFormField** my_fields; // The array of fields for this form
    352 
    353   // This structure is used for the form's user data field to link the
    354   // FORM* to the C++ object and to provide extra space for a user pointer.
    355   typedef struct {
    356     void*	       m_user;	    // the pointer for the user's data
    357     const NCursesForm* m_back;      // backward pointer to C++ object
    358     const FORM*	       m_owner;
    359   } UserHook;
    360 
    361   // Get the backward pointer to the C++ object from a FORM
    362   static inline NCursesForm* getHook(const FORM *f) {
    363     UserHook* hook = reinterpret_cast<UserHook*>(::form_userptr(f));
    364     assert(hook != 0 && hook->m_owner==f);
    365     return const_cast<NCursesForm*>(hook->m_back);
    366   }
    367 
    368   friend void _nc_xx_frm_init(FORM *);
    369   friend void _nc_xx_frm_term(FORM *);
    370   friend void _nc_xx_fld_init(FORM *);
    371   friend void _nc_xx_fld_term(FORM *);
    372 
    373   // Calculate FIELD* array for the menu
    374   FIELD** mapFields(NCursesFormField* nfields[]);
    375 
    376 protected:
    377   // internal routines
    378   inline void set_user(void *user) {
    379     UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
    380     assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
    381     uptr->m_user = user;
    382   }
    383 
    384   inline void *get_user() {
    385     UserHook* uptr = reinterpret_cast<UserHook*>(::form_userptr (form));
    386     assert (uptr != 0 && uptr->m_back==this && uptr->m_owner==form);
    387     return uptr->m_user;
    388   }
    389 
    390   void InitForm (NCursesFormField* Fields[],
    391 		 bool with_frame,
    392 		 bool autoDeleteFields);
    393 
    394   inline void OnError (int err) const THROWS(NCursesFormException) {
    395     if (err != E_OK)
    396       THROW(new NCursesFormException (err));
    397   }
    398 
    399   // this wraps the form_driver call.
    400   virtual int driver (int c) ;
    401 
    402   // 'Internal' constructor, builds an object without association to a
    403   // field array.
    404   NCursesForm( int  nlines,
    405 	       int  ncols,
    406 	       int  begin_y = 0,
    407 	       int  begin_x = 0)
    408     : NCursesPanel(nlines, ncols, begin_y, begin_x),
    409       form (STATIC_CAST(FORM*)(0)),
    410       sub(0),
    411       b_sub_owner(0),
    412       b_framed(0),
    413       b_autoDelete(0),
    414       my_fields(0)
    415   {
    416   }
    417 
    418 public:
    419   // Create form for the default panel.
    420   NCursesForm (NCursesFormField* Fields[],
    421 	       bool with_frame=FALSE,	      // reserve space for a frame?
    422 	       bool autoDelete_Fields=FALSE)  // do automatic cleanup?
    423     : NCursesPanel(),
    424       form(0),
    425       sub(0),
    426       b_sub_owner(0),
    427       b_framed(0),
    428       b_autoDelete(0),
    429       my_fields(0)
    430   {
    431     InitForm(Fields, with_frame, autoDelete_Fields);
    432   }
    433 
    434   // Create a form in a panel with the given position and size.
    435   NCursesForm (NCursesFormField* Fields[],
    436 	       int  nlines,
    437 	       int  ncols,
    438 	       int  begin_y,
    439 	       int  begin_x,
    440 	       bool with_frame=FALSE,	     // reserve space for a frame?
    441 	       bool autoDelete_Fields=FALSE) // do automatic cleanup?
    442     : NCursesPanel(nlines, ncols, begin_y, begin_x),
    443       form(0),
    444       sub(0),
    445       b_sub_owner(0),
    446       b_framed(0),
    447       b_autoDelete(0),
    448       my_fields(0)
    449   {
    450       InitForm(Fields, with_frame, autoDelete_Fields);
    451   }
    452 
    453   NCursesForm& operator=(const NCursesForm& rhs)
    454   {
    455     if (this != &rhs) {
    456       *this = rhs;
    457       NCursesPanel::operator=(rhs);
    458     }
    459     return *this;
    460   }
    461 
    462   NCursesForm(const NCursesForm& rhs)
    463     : NCursesPanel(rhs),
    464       form(rhs.form),
    465       sub(rhs.sub),
    466       b_sub_owner(rhs.b_sub_owner),
    467       b_framed(rhs.b_framed),
    468       b_autoDelete(rhs.b_autoDelete),
    469       my_fields(rhs.my_fields)
    470   {
    471   }
    472 
    473   virtual ~NCursesForm();
    474 
    475   // Set the default attributes for the form
    476   virtual void setDefaultAttributes();
    477 
    478   // Retrieve current field of the form.
    479   inline NCursesFormField* current_field() const {
    480     return my_fields[::field_index(::current_field(form))];
    481   }
    482 
    483   // Set the forms subwindow
    484   void setSubWindow(NCursesWindow& sub);
    485 
    486   // Set these fields for the form
    487   inline void setFields(NCursesFormField* Fields[]) {
    488     OnError(::set_form_fields(form,mapFields(Fields)));
    489   }
    490 
    491   // Remove the form from the screen
    492   inline void unpost (void) {
    493     OnError (::unpost_form (form));
    494   }
    495 
    496   // Post the form to the screen if flag is true, unpost it otherwise
    497   inline void post(bool flag = TRUE) {
    498     OnError (flag ? ::post_form(form) : ::unpost_form (form));
    499   }
    500 
    501   // Decorations
    502   inline void frame(const char *title=NULL, const char* btitle=NULL) {
    503     if (b_framed)
    504       NCursesPanel::frame(title,btitle);
    505     else
    506       OnError(E_SYSTEM_ERROR);
    507   }
    508 
    509   inline void boldframe(const char *title=NULL, const char* btitle=NULL) {
    510     if (b_framed)
    511       NCursesPanel::boldframe(title,btitle);
    512     else
    513       OnError(E_SYSTEM_ERROR);
    514   }
    515 
    516   inline void label(const char *topLabel, const char *bottomLabel) {
    517     if (b_framed)
    518       NCursesPanel::label(topLabel,bottomLabel);
    519     else
    520       OnError(E_SYSTEM_ERROR);
    521   }
    522 
    523   // -----
    524   // Hooks
    525   // -----
    526 
    527   // Called after the form gets repositioned in its window.
    528   // This is especially true if the form is posted.
    529   virtual void On_Form_Init();
    530 
    531   // Called before the form gets repositioned in its window.
    532   // This is especially true if the form is unposted.
    533   virtual void On_Form_Termination();
    534 
    535   // Called after the field became the current field
    536   virtual void On_Field_Init(NCursesFormField& field);
    537 
    538   // Called before this field is left as current field.
    539   virtual void On_Field_Termination(NCursesFormField& field);
    540 
    541   // Calculate required window size for the form.
    542   void scale(int& rows, int& ncols) const {
    543     OnError(::scale_form(form,&rows,&ncols));
    544   }
    545 
    546   // Retrieve number of fields in the form.
    547   int count() const {
    548     return ::field_count(form);
    549   }
    550 
    551   // Make the page the current page of the form.
    552   void set_page(int pageNum) {
    553     OnError(::set_form_page(form, pageNum));
    554   }
    555 
    556   // Retrieve current page number
    557   int page() const {
    558     return ::form_page(form);
    559   }
    560 
    561   // Switch on the forms options
    562   inline void options_on (Form_Options opts) {
    563     OnError (::form_opts_on (form, opts));
    564   }
    565 
    566   // Switch off the forms options
    567   inline void options_off (Form_Options opts) {
    568     OnError (::form_opts_off (form, opts));
    569   }
    570 
    571   // Retrieve the forms options
    572   inline Form_Options options () const {
    573     return ::form_opts (form);
    574   }
    575 
    576   // Set the forms options
    577   inline void set_options (Form_Options opts) {
    578     OnError (::set_form_opts (form, opts));
    579   }
    580 
    581   // Are there more data in the current field after the data shown
    582   inline bool data_ahead() const {
    583     return ::data_ahead(form);
    584   }
    585 
    586   // Are there more data in the current field before the data shown
    587   inline bool data_behind() const {
    588     return ::data_behind(form);
    589   }
    590 
    591   // Position the cursor to the current field
    592   inline void position_cursor () {
    593     OnError (::pos_form_cursor (form));
    594   }
    595   // Set the current field
    596   inline void set_current(NCursesFormField& F) {
    597     OnError (::set_current_field(form, F.field));
    598   }
    599 
    600   // Provide a default key virtualization. Translate the keyboard
    601   // code c into a form request code.
    602   // The default implementation provides a hopefully straightforward
    603   // mapping for the most common keystrokes and form requests.
    604   virtual int virtualize(int c);
    605 
    606   // Operators
    607   inline NCursesFormField* operator[](int i) const {
    608     if ( (i < 0) || (i >= ::field_count (form)) )
    609       OnError (E_BAD_ARGUMENT);
    610     return my_fields[i];
    611   }
    612 
    613   // Perform the menu's operation
    614   // Return the field where you left the form.
    615   virtual NCursesFormField* operator()(void);
    616 
    617   // Exception handlers. The default is a Beep.
    618   virtual void On_Request_Denied(int c) const;
    619   virtual void On_Invalid_Field(int c) const;
    620   virtual void On_Unknown_Command(int c) const;
    621 
    622 };
    623 
    624 //
    625 // -------------------------------------------------------------------------
    626 // This is the typical C++ typesafe way to allow to attach
    627 // user data to a field of a form. Its assumed that the user
    628 // data belongs to some class T. Use T as template argument
    629 // to create a UserField.
    630 // -------------------------------------------------------------------------
    631 template<class T> class NCURSES_IMPEXP NCursesUserField : public NCursesFormField
    632 {
    633 public:
    634   NCursesUserField (int rows,
    635 		    int ncols,
    636 		    int first_row = 0,
    637 		    int first_col = 0,
    638 		    const T* p_UserData = STATIC_CAST(T*)(0),
    639 		    int offscreen_rows = 0,
    640 		    int additional_buffers = 0)
    641     : NCursesFormField (rows, ncols,
    642 			first_row, first_col,
    643 			offscreen_rows, additional_buffers) {
    644       if (field)
    645 	OnError(::set_field_userptr(field, STATIC_CAST(void *)(p_UserData)));
    646   }
    647 
    648   virtual ~NCursesUserField() {};
    649 
    650   inline const T* UserData (void) const {
    651     return reinterpret_cast<const T*>(::field_userptr (field));
    652   }
    653 
    654   inline virtual void setUserData(const T* p_UserData) {
    655     if (field)
    656       OnError (::set_field_userptr (field, STATIC_CAST(void *)(p_UserData)));
    657   }
    658 };
    659 //
    660 // -------------------------------------------------------------------------
    661 // The same mechanism is used to attach user data to a form
    662 // -------------------------------------------------------------------------
    663 //
    664 template<class T> class NCURSES_IMPEXP NCursesUserForm : public NCursesForm
    665 {
    666 protected:
    667   // 'Internal' constructor, builds an object without association to a
    668   // field array.
    669   NCursesUserForm( int  nlines,
    670 		   int  ncols,
    671 		   int  begin_y = 0,
    672 		   int  begin_x = 0,
    673 		   const T* p_UserData = STATIC_CAST(T*)(0))
    674     : NCursesForm(nlines,ncols,begin_y,begin_x) {
    675       if (form)
    676 	set_user (const_cast<void *>(p_UserData));
    677   }
    678 
    679 public:
    680   NCursesUserForm (NCursesFormField Fields[],
    681 		   const T* p_UserData = STATIC_CAST(T*)(0),
    682 		   bool with_frame=FALSE,
    683 		   bool autoDelete_Fields=FALSE)
    684     : NCursesForm (Fields, with_frame, autoDelete_Fields) {
    685       if (form)
    686 	set_user (const_cast<void *>(p_UserData));
    687   };
    688 
    689   NCursesUserForm (NCursesFormField Fields[],
    690 		   int nlines,
    691 		   int ncols,
    692 		   int begin_y = 0,
    693 		   int begin_x = 0,
    694 		   const T* p_UserData = STATIC_CAST(T*)(0),
    695 		   bool with_frame=FALSE,
    696 		   bool autoDelete_Fields=FALSE)
    697     : NCursesForm (Fields, nlines, ncols, begin_y, begin_x,
    698 		   with_frame, autoDelete_Fields) {
    699       if (form)
    700 	set_user (const_cast<void *>(p_UserData));
    701   };
    702 
    703   virtual ~NCursesUserForm() {
    704   };
    705 
    706   inline T* UserData (void) const {
    707     return reinterpret_cast<T*>(get_user ());
    708   };
    709 
    710   inline virtual void setUserData (const T* p_UserData) {
    711     if (form)
    712       set_user (const_cast<void *>(p_UserData));
    713   }
    714 
    715 };
    716 //
    717 // -------------------------------------------------------------------------
    718 // Builtin Fieldtypes
    719 // -------------------------------------------------------------------------
    720 //
    721 class NCURSES_IMPEXP Alpha_Field : public NCursesFieldType
    722 {
    723 private:
    724   int min_field_width;
    725 
    726   void set(NCursesFormField& f) {
    727     OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
    728   }
    729 
    730 public:
    731   Alpha_Field(int width)
    732     : NCursesFieldType(TYPE_ALPHA),
    733       min_field_width(width) {
    734   }
    735 };
    736 
    737 class NCURSES_IMPEXP Alphanumeric_Field : public NCursesFieldType
    738 {
    739 private:
    740   int min_field_width;
    741 
    742   void set(NCursesFormField& f) {
    743     OnError(::set_field_type(f.get_field(),fieldtype,min_field_width));
    744   }
    745 
    746 public:
    747   Alphanumeric_Field(int width)
    748     : NCursesFieldType(TYPE_ALNUM),
    749       min_field_width(width) {
    750   }
    751 };
    752 
    753 class NCURSES_IMPEXP Integer_Field : public NCursesFieldType
    754 {
    755 private:
    756   int precision;
    757   long lower_limit, upper_limit;
    758 
    759   void set(NCursesFormField& f) {
    760     OnError(::set_field_type(f.get_field(),fieldtype,
    761 			     precision,lower_limit,upper_limit));
    762   }
    763 
    764 public:
    765   Integer_Field(int prec, long low=0L, long high=0L)
    766     : NCursesFieldType(TYPE_INTEGER),
    767       precision(prec), lower_limit(low), upper_limit(high) {
    768   }
    769 };
    770 
    771 class NCURSES_IMPEXP Numeric_Field : public NCursesFieldType
    772 {
    773 private:
    774   int precision;
    775   double lower_limit, upper_limit;
    776 
    777   void set(NCursesFormField& f) {
    778     OnError(::set_field_type(f.get_field(),fieldtype,
    779 			     precision,lower_limit,upper_limit));
    780   }
    781 
    782 public:
    783   Numeric_Field(int prec, double low=0.0, double high=0.0)
    784     : NCursesFieldType(TYPE_NUMERIC),
    785       precision(prec), lower_limit(low), upper_limit(high) {
    786   }
    787 };
    788 
    789 class NCURSES_IMPEXP Regular_Expression_Field : public NCursesFieldType
    790 {
    791 private:
    792   char* regex;
    793 
    794   void set(NCursesFormField& f) {
    795     OnError(::set_field_type(f.get_field(),fieldtype,regex));
    796   }
    797 
    798   void copy_regex(const char *source)
    799   {
    800     regex = new char[1 + ::strlen(source)];
    801     (::strcpy)(regex, source);
    802   }
    803 
    804 public:
    805   Regular_Expression_Field(const char *expr)
    806     : NCursesFieldType(TYPE_REGEXP),
    807       regex(NULL)
    808   {
    809     copy_regex(expr);
    810   }
    811 
    812   Regular_Expression_Field& operator=(const Regular_Expression_Field& rhs)
    813   {
    814     if (this != &rhs) {
    815       *this = rhs;
    816       copy_regex(rhs.regex);
    817       NCursesFieldType::operator=(rhs);
    818     }
    819     return *this;
    820   }
    821 
    822   Regular_Expression_Field(const Regular_Expression_Field& rhs)
    823     : NCursesFieldType(rhs),
    824       regex(NULL)
    825   {
    826     copy_regex(rhs.regex);
    827   }
    828 
    829   ~Regular_Expression_Field() {
    830     delete[] regex;
    831   }
    832 };
    833 
    834 class NCURSES_IMPEXP Enumeration_Field : public NCursesFieldType
    835 {
    836 private:
    837   const char** list;
    838   int case_sensitive;
    839   int non_unique_matches;
    840 
    841   void set(NCursesFormField& f) {
    842     OnError(::set_field_type(f.get_field(),fieldtype,
    843 			     list,case_sensitive,non_unique_matches));
    844   }
    845 public:
    846   Enumeration_Field(const char* enums[],
    847 		    bool case_sens=FALSE,
    848 		    bool non_unique=FALSE)
    849     : NCursesFieldType(TYPE_ENUM),
    850       list(enums),
    851       case_sensitive(case_sens ? -1 : 0),
    852       non_unique_matches(non_unique ? -1 : 0) {
    853   }
    854 
    855   Enumeration_Field& operator=(const Enumeration_Field& rhs)
    856   {
    857     if (this != &rhs) {
    858       *this = rhs;
    859       NCursesFieldType::operator=(rhs);
    860     }
    861     return *this;
    862   }
    863 
    864   Enumeration_Field(const Enumeration_Field& rhs)
    865     : NCursesFieldType(rhs),
    866       list(rhs.list),
    867       case_sensitive(rhs.case_sensitive),
    868       non_unique_matches(rhs.non_unique_matches)
    869   {
    870   }
    871 };
    872 
    873 class NCURSES_IMPEXP IPV4_Address_Field : public NCursesFieldType
    874 {
    875 private:
    876   void set(NCursesFormField& f) {
    877     OnError(::set_field_type(f.get_field(),fieldtype));
    878   }
    879 
    880 public:
    881   IPV4_Address_Field() : NCursesFieldType(TYPE_IPV4) {
    882   }
    883 };
    884 
    885 extern "C" {
    886   bool _nc_xx_fld_fcheck(FIELD *, const void*);
    887   bool _nc_xx_fld_ccheck(int c, const void *);
    888   void* _nc_xx_fld_makearg(va_list*);
    889 }
    890 
    891 //
    892 // -------------------------------------------------------------------------
    893 // Abstract base class for User-Defined Fieldtypes
    894 // -------------------------------------------------------------------------
    895 //
    896 class NCURSES_IMPEXP UserDefinedFieldType : public NCursesFieldType
    897 {
    898   friend class UDF_Init; // Internal helper to set up statics
    899 private:
    900   // For all C++ defined fieldtypes we need only one generic lowlevel
    901   // FIELDTYPE* element.
    902   static FIELDTYPE* generic_fieldtype;
    903 
    904 protected:
    905   // This are the functions required by the low level libforms functions
    906   // to construct a fieldtype.
    907   friend bool _nc_xx_fld_fcheck(FIELD *, const void*);
    908   friend bool _nc_xx_fld_ccheck(int c, const void *);
    909   friend void* _nc_xx_fld_makearg(va_list*);
    910 
    911   void set(NCursesFormField& f) {
    912     OnError(::set_field_type(f.get_field(),fieldtype,&f));
    913   }
    914 
    915 protected:
    916   // Redefine this function to do a field validation. The argument
    917   // is a reference to the field you should validate.
    918   virtual bool field_check(NCursesFormField& f) = 0;
    919 
    920   // Redefine this function to do a character validation. The argument
    921   // is the character to be validated.
    922   virtual bool char_check (int c) = 0;
    923 
    924 public:
    925   UserDefinedFieldType() : NCursesFieldType(generic_fieldtype) {
    926   }
    927 };
    928 
    929 extern "C" {
    930   bool _nc_xx_next_choice(FIELD*, const void *);
    931   bool _nc_xx_prev_choice(FIELD*, const void *);
    932 }
    933 
    934 //
    935 // -------------------------------------------------------------------------
    936 // Abstract base class for User-Defined Fieldtypes with Choice functions
    937 // -------------------------------------------------------------------------
    938 //
    939 class NCURSES_IMPEXP UserDefinedFieldType_With_Choice : public UserDefinedFieldType
    940 {
    941   friend class UDF_Init; // Internal helper to set up statics
    942 private:
    943   // For all C++ defined fieldtypes with choice functions we need only one
    944   // generic lowlevel FIELDTYPE* element.
    945   static FIELDTYPE* generic_fieldtype_with_choice;
    946 
    947   // This are the functions required by the low level libforms functions
    948   // to construct a fieldtype with choice functions.
    949   friend bool _nc_xx_next_choice(FIELD*, const void *);
    950   friend bool _nc_xx_prev_choice(FIELD*, const void *);
    951 
    952 protected:
    953   // Redefine this function to do the retrieval of the next choice value.
    954   // The argument is a reference to the field tobe examined.
    955   virtual bool next    (NCursesFormField& f) = 0;
    956 
    957   // Redefine this function to do the retrieval of the previous choice value.
    958   // The argument is a reference to the field tobe examined.
    959   virtual bool previous(NCursesFormField& f) = 0;
    960 
    961 public:
    962   UserDefinedFieldType_With_Choice() {
    963     fieldtype = generic_fieldtype_with_choice;
    964   }
    965 };
    966 
    967 #endif /* NCURSES_CURSESF_H_incl */
    968