Bläddra i källkod

Adding form library.

Berk Geveci 24 år sedan
förälder
incheckning
cd7297781d
47 ändrade filer med 10081 tillägg och 0 borttagningar
  1. 46 0
      Source/CursesDialog/form/CMakeLists.txt
  2. 15 0
      Source/CursesDialog/form/READ.ME
  3. 52 0
      Source/CursesDialog/form/eti.h
  4. 91 0
      Source/CursesDialog/form/fld_arg.c
  5. 111 0
      Source/CursesDialog/form/fld_attr.c
  6. 124 0
      Source/CursesDialog/form/fld_current.c
  7. 346 0
      Source/CursesDialog/form/fld_def.c
  8. 97 0
      Source/CursesDialog/form/fld_dup.c
  9. 62 0
      Source/CursesDialog/form/fld_ftchoice.c
  10. 83 0
      Source/CursesDialog/form/fld_ftlink.c
  11. 91 0
      Source/CursesDialog/form/fld_info.c
  12. 81 0
      Source/CursesDialog/form/fld_just.c
  13. 90 0
      Source/CursesDialog/form/fld_link.c
  14. 74 0
      Source/CursesDialog/form/fld_max.c
  15. 62 0
      Source/CursesDialog/form/fld_move.c
  16. 125 0
      Source/CursesDialog/form/fld_newftyp.c
  17. 124 0
      Source/CursesDialog/form/fld_opts.c
  18. 78 0
      Source/CursesDialog/form/fld_pad.c
  19. 76 0
      Source/CursesDialog/form/fld_page.c
  20. 73 0
      Source/CursesDialog/form/fld_stat.c
  21. 92 0
      Source/CursesDialog/form/fld_type.c
  22. 67 0
      Source/CursesDialog/form/fld_user.c
  23. 389 0
      Source/CursesDialog/form/form.h
  24. 128 0
      Source/CursesDialog/form/form.priv.h
  25. 66 0
      Source/CursesDialog/form/frm_cursor.c
  26. 181 0
      Source/CursesDialog/form/frm_data.c
  27. 376 0
      Source/CursesDialog/form/frm_def.c
  28. 3843 0
      Source/CursesDialog/form/frm_driver.c
  29. 140 0
      Source/CursesDialog/form/frm_hook.c
  30. 116 0
      Source/CursesDialog/form/frm_opts.c
  31. 100 0
      Source/CursesDialog/form/frm_page.c
  32. 117 0
      Source/CursesDialog/form/frm_post.c
  33. 163 0
      Source/CursesDialog/form/frm_req_name.c
  34. 63 0
      Source/CursesDialog/form/frm_scale.c
  35. 69 0
      Source/CursesDialog/form/frm_sub.c
  36. 67 0
      Source/CursesDialog/form/frm_user.c
  37. 70 0
      Source/CursesDialog/form/frm_win.c
  38. 137 0
      Source/CursesDialog/form/fty_alnum.c
  39. 138 0
      Source/CursesDialog/form/fty_alpha.c
  40. 295 0
      Source/CursesDialog/form/fty_enum.c
  41. 160 0
      Source/CursesDialog/form/fty_int.c
  42. 81 0
      Source/CursesDialog/form/fty_ipv4.c
  43. 195 0
      Source/CursesDialog/form/fty_num.c
  44. 257 0
      Source/CursesDialog/form/fty_regex.c
  45. 694 0
      Source/CursesDialog/form/llib-lform
  46. 93 0
      Source/CursesDialog/form/mf_common.h
  47. 83 0
      Source/CursesDialog/form/nc_alloc.h

+ 46 - 0
Source/CursesDialog/form/CMakeLists.txt

@@ -0,0 +1,46 @@
+PROJECT(CMAKE_FORM)
+
+SOURCE_FILES(FORM_SRCS
+             fld_arg.c
+             fld_attr.c
+             fld_current.c
+             fld_def.c
+             fld_dup.c
+             fld_ftchoice.c
+             fld_ftlink.c
+             fld_info.c
+             fld_just.c
+             fld_link.c
+             fld_max.c
+             fld_move.c
+             fld_newftyp.c
+             fld_opts.c
+             fld_pad.c
+             fld_page.c
+             fld_stat.c
+             fld_type.c
+             fld_user.c
+             frm_cursor.c
+             frm_data.c
+             frm_def.c
+             frm_driver.c
+             frm_hook.c
+             frm_opts.c
+             frm_page.c
+             frm_post.c
+             frm_req_name.c
+             frm_scale.c
+             frm_sub.c
+             frm_user.c
+             frm_win.c
+             fty_alnum.c
+             fty_alpha.c
+             fty_enum.c
+             fty_int.c
+             fty_ipv4.c
+             fty_num.c
+             fty_regex.c
+	     )
+             
+INCLUDE_DIRECTORIES(${CMAKE_FORM_SOURCE_DIR})
+ADD_LIBRARY(cmForm FORM_SRCS)

+ 15 - 0
Source/CursesDialog/form/READ.ME

@@ -0,0 +1,15 @@
+This is a clone of the form library that is available with typical
+System V curses implementations (ETI).
+
+It is modelled after the documentation that comes for this library with
+a 386 based SVR4 implementation (ESIX).  
+
+The development environment was and is an ELF based Linux system.
+
+For things that still need doing, see the TO-DO file in the top-level 
+directory.
+
+Juergen Pfeifer
+
+eMail: [email protected]
+

+ 52 - 0
Source/CursesDialog/form/eti.h

@@ -0,0 +1,52 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#ifndef _ETI_ERRNO_H_
+#define _ETI_ERRNO_H_
+
+#define	E_OK			(0)
+#define	E_SYSTEM_ERROR	 	(-1)
+#define	E_BAD_ARGUMENT	 	(-2)
+#define	E_POSTED	 	(-3)
+#define	E_CONNECTED	 	(-4)
+#define	E_BAD_STATE	 	(-5)
+#define	E_NO_ROOM	 	(-6)
+#define	E_NOT_POSTED		(-7)
+#define	E_UNKNOWN_COMMAND	(-8)
+#define	E_NO_MATCH		(-9)
+#define	E_NOT_SELECTABLE	(-10)
+#define	E_NOT_CONNECTED	        (-11)
+#define	E_REQUEST_DENIED	(-12)
+#define	E_INVALID_FIELD	        (-13)
+#define	E_CURRENT		(-14)
+
+#endif

+ 91 - 0
Source/CursesDialog/form/fld_arg.c

@@ -0,0 +1,91 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_fieldtype_arg(
+|                            FIELDTYPE *typ,
+|                            void * (* const make_arg)(va_list *),
+|                            void * (* const copy_arg)(const void *),
+|                            void   (* const free_arg)(void *) )
+|   
+|   Description   :  Connects to the type additional arguments necessary
+|                    for a set_field_type call. The various function pointer
+|                    arguments are:
+|                       make_arg : allocates a structure for the field
+|                                  specific parameters.
+|                       copy_arg : duplicate the structure created by
+|                                  make_arg
+|                       free_arg : Release the memory allocated by make_arg
+|                                  or copy_arg
+|
+|                    At least make_arg must be non-NULL.
+|                    You may pass NULL for copy_arg and free_arg if your
+|                    make_arg function doesn't allocate memory and your
+|                    arg fits into the storage for a (void*).
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+int set_fieldtype_arg(FIELDTYPE * typ,
+		      void * (* const make_arg)(va_list *),
+		      void * (* const copy_arg)(const void *),
+		      void   (* const free_arg)(void *))
+{
+  if ( !typ || !make_arg )
+    RETURN(E_BAD_ARGUMENT);
+
+  typ->status |= _HAS_ARGS;
+  typ->makearg = make_arg;
+  typ->copyarg = copy_arg;
+  typ->freearg = free_arg;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  void *field_arg(const FIELD *field)
+|   
+|   Description   :  Retrieve pointer to the fields argument structure.
+|
+|   Return Values :  Pointer to structure or NULL if none is defined.
++--------------------------------------------------------------------------*/
+void *field_arg(const FIELD * field)
+{
+  return Normalize_Field(field)->arg;
+}
+
+/* fld_arg.c ends here */

+ 111 - 0
Source/CursesDialog/form/fld_attr.c

@@ -0,0 +1,111 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*----------------------------------------------------------------------------
+  Field-Attribute manipulation routines
+  --------------------------------------------------------------------------*/
+/* "Template" macro to generate a function to set a fields attribute */
+#define GEN_FIELD_ATTR_SET_FCT( name ) \
+int set_field_ ## name (FIELD * field, chtype attr)\
+{\
+   int res = E_BAD_ARGUMENT;\
+   if ( attr==A_NORMAL || ((attr & A_ATTRIBUTES)==attr) )\
+     {\
+       Normalize_Field( field );\
+       if ((field -> name) != attr)\
+         {\
+           field -> name = attr;\
+           res = _nc_Synchronize_Attributes( field );\
+         }\
+       else\
+	 res = E_OK;\
+     }\
+   RETURN(res);\
+}
+
+/* "Template" macro to generate a function to get a fields attribute */
+#define GEN_FIELD_ATTR_GET_FCT( name ) \
+chtype field_ ## name (const FIELD * field)\
+{\
+   return ( A_ATTRIBUTES & (Normalize_Field( field ) -> name) );\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_fore(FIELD *field, chtype attr)
+|   
+|   Description   :  Sets the foreground of the field used to display the
+|                    field contents.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid attributes
+|                    E_SYSTEM_ERROR   - system error
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_SET_FCT( fore )
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  chtype field_fore(const FIELD *)
+|   
+|   Description   :  Retrieve fields foreground attribute
+|
+|   Return Values :  The foreground attribute
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_GET_FCT( fore )
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_back(FIELD *field, chtype attr)
+|   
+|   Description   :  Sets the background of the field used to display the
+|                    fields extend.
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid attributes
+|                    E_SYSTEM_ERROR   - system error
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_SET_FCT( back )
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  chtype field_back(const 
+|   
+|   Description   :  Retrieve fields background attribute
+|
+|   Return Values :  The background attribute
++--------------------------------------------------------------------------*/
+GEN_FIELD_ATTR_GET_FCT( back )
+
+/* fld_attr.c ends here */

+ 124 - 0
Source/CursesDialog/form/fld_current.c

@@ -0,0 +1,124 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_current_field(FORM  * form,FIELD * field)
+|   
+|   Description   :  Set the current field of the form to the specified one.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form or field pointer
+|                    E_REQUEST_DENIED  - field not selectable
+|                    E_BAD_STATE       - called from a hook routine
+|                    E_INVALID_FIELD   - current field can't be left
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+int set_current_field(FORM  * form, FIELD * field)
+{
+  int err = E_OK;
+
+  if ( !form || !field )
+    RETURN(E_BAD_ARGUMENT);
+
+  if ( (form != field->form) || Field_Is_Not_Selectable(field) )
+    RETURN(E_REQUEST_DENIED);
+
+  if (!(form->status & _POSTED))
+    {
+      form->current = field;
+      form->curpage = field->page;
+  }
+  else
+    {
+      if (form->status & _IN_DRIVER) 
+	err = E_BAD_STATE;
+      else
+	{
+	  if (form->current != field)
+	    {
+	      if (!_nc_Internal_Validation(form)) 
+	       err = E_INVALID_FIELD;
+	      else
+		{
+		  Call_Hook(form,fieldterm);
+		  if (field->page != form->curpage)
+		    {
+		      Call_Hook(form,formterm);
+		      err = _nc_Set_Form_Page(form,field->page,field);
+		      Call_Hook(form,forminit);
+		    } 
+		  else 
+		    {
+		      err = _nc_Set_Current_Field(form,field);
+		    }
+		  Call_Hook(form,fieldinit);
+		  _nc_Refresh_Current_Field(form);
+		}
+	    }
+	}
+    }
+  RETURN(err);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD *current_field(const FORM * form)
+|   
+|   Description   :  Return the current field.
+|
+|   Return Values :  Pointer to the current field.
++--------------------------------------------------------------------------*/
+FIELD *current_field(const FORM * form)
+{
+  return Normalize_Form(form)->current;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_index(const FIELD * field)
+|   
+|   Description   :  Return the index of the field in the field-array of
+|                    the form.
+|
+|   Return Values :  >= 0   : field index
+|                    -1     : fieldpointer invalid or field not connected
++--------------------------------------------------------------------------*/
+int field_index(const FIELD * field)
+{
+  return ( (field && field->form) ? field->index : -1 );
+}
+
+/* fld_current.c ends here */

+ 346 - 0
Source/CursesDialog/form/fld_def.c

@@ -0,0 +1,346 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/* this can't be readonly */
+static FIELD default_field = {
+  0,                       /* status */
+  0,                       /* rows   */
+  0,                       /* cols   */
+  0,                       /* frow   */
+  0,                       /* fcol   */
+  0,                       /* drows  */
+  0,                       /* dcols  */
+  0,                       /* maxgrow*/
+  0,                       /* nrow   */
+  0,                       /* nbuf   */
+  NO_JUSTIFICATION,        /* just   */
+  0,                       /* page   */
+  0,                       /* index  */
+  (int)' ',                /* pad    */
+  A_NORMAL,                /* fore   */
+  A_NORMAL,                /* back   */
+  ALL_FIELD_OPTS,          /* opts   */
+  (FIELD *)0,              /* snext  */
+  (FIELD *)0,              /* sprev  */
+  (FIELD *)0,              /* link   */
+  (FORM *)0,               /* form   */
+  (FIELDTYPE *)0,          /* type   */
+  (char *)0,               /* arg    */ 
+  (char *)0,               /* buf    */
+  (char *)0                /* usrptr */
+};
+
+FIELD *_nc_Default_Field = &default_field;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  TypeArgument *_nc_Make_Argument(
+|                              const FIELDTYPE *typ,
+|                              va_list *ap,
+|                              int *err )
+|   
+|   Description   :  Create an argument structure for the specified type.
+|                    Use the type-dependant argument list to construct
+|                    it.
+|
+|   Return Values :  Pointer to argument structure. Maybe NULL.
+|                    In case of an error in *err an errorcounter is increased. 
++--------------------------------------------------------------------------*/
+TypeArgument*
+_nc_Make_Argument(const FIELDTYPE *typ, va_list *ap, int *err)
+{
+  TypeArgument *res = (TypeArgument *)0; 
+  TypeArgument *p;
+
+  if (typ && (typ->status & _HAS_ARGS))
+    {
+      assert(err && ap);
+      if (typ->status & _LINKED_TYPE)
+	{
+	  p = (TypeArgument *)malloc(sizeof(TypeArgument));
+	  if (p) 
+	    {
+	      p->left  = _nc_Make_Argument(typ->left ,ap,err);
+	      p->right = _nc_Make_Argument(typ->right,ap,err);
+	      return p;
+	    }
+	  else
+	    *err += 1;
+      } else 
+	{
+	  assert(typ->makearg);
+	  if ( !(res=(TypeArgument *)typ->makearg(ap)) ) 
+	    *err += 1;
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  TypeArgument *_nc_Copy_Argument(const FIELDTYPE *typ,
+|                                                    const TypeArgument *argp,
+|                                                    int *err )
+|   
+|   Description   :  Create a copy of an argument structure for the specified 
+|                    type.
+|
+|   Return Values :  Pointer to argument structure. Maybe NULL.
+|                    In case of an error in *err an errorcounter is increased. 
++--------------------------------------------------------------------------*/
+TypeArgument*
+_nc_Copy_Argument(const FIELDTYPE *typ,
+		  const TypeArgument *argp, int *err)
+{
+  TypeArgument *res = (TypeArgument *)0;
+  TypeArgument *p;
+
+  if ( typ && (typ->status & _HAS_ARGS) )
+    {
+      assert(err && argp);
+      if (typ->status & _LINKED_TYPE)
+	{
+	  p = (TypeArgument *)malloc(sizeof(TypeArgument));
+	  if (p)
+	    {
+	      p->left  = _nc_Copy_Argument(typ,argp->left ,err);
+	      p->right = _nc_Copy_Argument(typ,argp->right,err);
+	      return p;
+	    }
+	  *err += 1;
+      } 
+      else 
+	{
+	  if (typ->copyarg)
+	    {
+	      if (!(res = (TypeArgument *)(typ->copyarg((const void *)argp)))) 
+		*err += 1;
+	    }
+	  else
+	    res = (TypeArgument *)argp;
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  void _nc_Free_Argument(const FIELDTYPE *typ,
+|                                           TypeArgument * argp )
+|   
+|   Description   :  Release memory associated with the argument structure
+|                    for the given fieldtype.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+void
+_nc_Free_Argument(const FIELDTYPE * typ, TypeArgument * argp)
+{
+  if (!typ || !(typ->status & _HAS_ARGS)) 
+    return;
+  
+  if (typ->status & _LINKED_TYPE)
+    {
+      assert(argp);
+      _nc_Free_Argument(typ->left ,argp->left );
+      _nc_Free_Argument(typ->right,argp->right);
+      free(argp);
+    } 
+  else 
+    {
+      if (typ->freearg)
+	typ->freearg((void *)argp);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool _nc_Copy_Type( FIELD *dst, FIELD const *src )
+|   
+|   Description   :  Copy argument structure of field src to field dst
+|
+|   Return Values :  TRUE       - copy worked
+|                    FALSE      - error occured
++--------------------------------------------------------------------------*/
+bool
+_nc_Copy_Type(FIELD *dst, FIELD const *src)
+{
+  int err = 0;
+
+  assert(dst && src);
+
+  dst->type = src->type;
+  dst->arg  = (void *)_nc_Copy_Argument(src->type,(TypeArgument *)(src->arg),&err);
+
+  if (err)
+    {
+      _nc_Free_Argument(dst->type,(TypeArgument *)(dst->arg));
+      dst->type = (FIELDTYPE *)0;
+      dst->arg  = (void *)0;
+      return FALSE;
+    }
+  else
+    {
+      if (dst->type) 
+	dst->type->ref++;
+      return TRUE;
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  void _nc_Free_Type( FIELD *field )
+|   
+|   Description   :  Release Argument structure for this field
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+void
+_nc_Free_Type(FIELD *field)
+{
+  assert(field);
+  if (field->type) 
+    field->type->ref--;
+  _nc_Free_Argument(field->type,(TypeArgument *)(field->arg));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD *new_field( int rows, int cols, 
+|                                      int frow, int fcol,
+|                                      int nrow, int nbuf )
+|   
+|   Description   :  Create a new field with this many 'rows' and 'cols',
+|                    starting at 'frow/fcol' in the subwindow of the form.
+|                    Allocate 'nrow' off-screen rows and 'nbuf' additional
+|                    buffers. If an error occurs, errno is set to
+|                    
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure.
++--------------------------------------------------------------------------*/
+FIELD *new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf)
+{
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  if (rows>0  && 
+      cols>0  && 
+      frow>=0 && 
+      fcol>=0 && 
+      nrow>=0 && 
+      nbuf>=0 &&
+      ((err = E_SYSTEM_ERROR) != 0) && /* trick: this resets the default error */
+      (New_Field=(FIELD *)malloc(sizeof(FIELD))) )
+    {
+      *New_Field       = default_field;
+      New_Field->rows  = rows;
+      New_Field->cols  = cols;
+      New_Field->drows = rows + nrow;
+      New_Field->dcols = cols;
+      New_Field->frow  = frow;
+      New_Field->fcol  = fcol;
+      New_Field->nrow  = nrow;
+      New_Field->nbuf  = nbuf;
+      New_Field->link  = New_Field;
+
+      if (_nc_Copy_Type(New_Field,&default_field))
+	{
+	  size_t len;
+
+	  len = Total_Buffer_Size(New_Field);
+	  if ((New_Field->buf = (char *)malloc(len)))
+	    {
+	      /* Prefill buffers with blanks and insert terminating zeroes
+		 between buffers */
+	      int i;
+
+	      memset(New_Field->buf,' ',len);
+	      for(i=0;i<=New_Field->nbuf;i++)
+		{
+		  New_Field->buf[(New_Field->drows*New_Field->cols+1)*(i+1)-1]
+		    = '\0';
+		}
+	      return New_Field;
+	    }
+	}
+    }
+
+  if (New_Field) 
+    free_field(New_Field);
+  
+  SET_ERROR( err );
+  return (FIELD *)0;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int free_field( FIELD *field )
+|   
+|   Description   :  Frees the storage allocated for the field.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer
+|                    E_CONNECTED    - field is connected
++--------------------------------------------------------------------------*/
+int free_field(FIELD * field)
+{
+  if (!field) 
+    RETURN(E_BAD_ARGUMENT);
+
+  if (field->form)
+    RETURN(E_CONNECTED);
+  
+  if (field == field->link)
+    {
+      if (field->buf) 
+	free(field->buf);
+    }
+  else 
+    {
+      FIELD *f;
+
+      for(f=field;f->link != field;f = f->link) 
+	{}
+      f->link = field->link;
+    }
+  _nc_Free_Type(field);
+  free(field);
+  RETURN(E_OK);
+}
+
+/* fld_def.c ends here */

+ 97 - 0
Source/CursesDialog/form/fld_dup.c

@@ -0,0 +1,97 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD *dup_field(FIELD *field, int frow, int fcol)
+|   
+|   Description   :  Duplicates the field at the specified position. All
+|                    field attributes and the buffers are copied.
+|                    If an error occurs, errno is set to
+|                    
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure
++--------------------------------------------------------------------------*/
+FIELD *dup_field(FIELD * field, int frow, int fcol)
+{
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  if (field && (frow>=0) && (fcol>=0) && 
+      ((err=E_SYSTEM_ERROR) != 0) && /* trick : this resets the default error */
+      (New_Field=(FIELD *)malloc(sizeof(FIELD))) )
+    {
+      *New_Field         = *_nc_Default_Field;
+      New_Field->frow    = frow;
+      New_Field->fcol    = fcol;
+      New_Field->link    = New_Field;
+      New_Field->rows    = field->rows;
+      New_Field->cols    = field->cols;
+      New_Field->nrow    = field->nrow;
+      New_Field->drows   = field->drows;
+      New_Field->dcols   = field->dcols;
+      New_Field->maxgrow = field->maxgrow;
+      New_Field->nbuf    = field->nbuf;
+      New_Field->just    = field->just;
+      New_Field->fore    = field->fore;
+      New_Field->back    = field->back;
+      New_Field->pad     = field->pad;
+      New_Field->opts    = field->opts;
+      New_Field->usrptr  = field->usrptr;
+
+      if (_nc_Copy_Type(New_Field,field))
+	{
+	  size_t len;
+
+	  len = Total_Buffer_Size(New_Field);
+	  if ( (New_Field->buf=(char *)malloc(len)) )
+	    {
+	      memcpy(New_Field->buf,field->buf,len);
+	      return New_Field;
+	    }
+	}
+    }
+
+  if (New_Field) 
+    free_field(New_Field);
+
+  SET_ERROR(err);
+  return (FIELD *)0;
+}
+
+/* fld_dup.c ends here */

+ 62 - 0
Source/CursesDialog/form/fld_ftchoice.c

@@ -0,0 +1,62 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_fieldtype_choice(
+|                          FIELDTYPE *typ,
+|                          bool (* const next_choice)(FIELD *,const void *),
+|                          bool (* const prev_choice)(FIELD *,const void *))
+|
+|   Description   :  Define implementation of enumeration requests.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid arguments
++--------------------------------------------------------------------------*/
+int set_fieldtype_choice(FIELDTYPE * typ,
+			 bool (* const next_choice) (FIELD *,const void *),
+			 bool (* const prev_choice) (FIELD *,const void *))
+{
+  if ( !typ || !next_choice || !prev_choice ) 
+    RETURN(E_BAD_ARGUMENT);
+
+  typ->status |= _HAS_CHOICE;
+  typ->next = next_choice;
+  typ->prev = prev_choice;
+  RETURN(E_OK);
+}
+
+/* fld_ftchoice.c ends here */

+ 83 - 0
Source/CursesDialog/form/fld_ftlink.c

@@ -0,0 +1,83 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELDTYPE *link_fieldtype(
+|                                FIELDTYPE *type1,
+|                                FIELDTYPE *type2)
+|   
+|   Description   :  Create a new fieldtype built from the two given types.
+|                    They are connected by an logical 'OR'.
+|                    If an error occurs, errno is set to                    
+|                       E_BAD_ARGUMENT  - invalid arguments
+|                       E_SYSTEM_ERROR  - system error (no memory)
+|
+|   Return Values :  Fieldtype pointer or NULL if error occured.
++--------------------------------------------------------------------------*/
+FIELDTYPE *link_fieldtype(FIELDTYPE * type1, FIELDTYPE * type2)
+{
+  FIELDTYPE *nftyp = (FIELDTYPE *)0;
+
+  if ( type1 && type2 )
+    {
+      nftyp = (FIELDTYPE *)malloc(sizeof(FIELDTYPE));
+      if (nftyp)
+	{
+	  *nftyp = *_nc_Default_FieldType;
+	  nftyp->status |= _LINKED_TYPE;
+	  if ((type1->status & _HAS_ARGS) || (type2->status & _HAS_ARGS) )
+	    nftyp->status |= _HAS_ARGS;
+	  if ((type1->status & _HAS_CHOICE) || (type2->status & _HAS_CHOICE) )
+	    nftyp->status |= _HAS_CHOICE;
+	  nftyp->left  = type1;
+	  nftyp->right = type2; 
+	  type1->ref++;
+	  type2->ref++;
+	}
+      else
+	{
+	  SET_ERROR( E_SYSTEM_ERROR );
+	}
+    }
+  else
+    {
+      SET_ERROR( E_BAD_ARGUMENT );
+    }
+  return nftyp;
+}
+
+/* fld_ftlink.c ends here */

+ 91 - 0
Source/CursesDialog/form/fld_info.c

@@ -0,0 +1,91 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_info(const FIELD *field,
+|                                   int *rows, int *cols,
+|                                   int *frow, int *fcol,
+|                                   int *nrow, int *nbuf)
+|   
+|   Description   :  Retrieve infos about the fields creation parameters.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer
++--------------------------------------------------------------------------*/
+int field_info(const FIELD *field,
+	       int *rows, int *cols, 
+	       int *frow, int *fcol, 
+	       int *nrow, int *nbuf)
+{
+  if (!field) 
+    RETURN(E_BAD_ARGUMENT);
+
+  if (rows) *rows = field->rows;
+  if (cols) *cols = field->cols;
+  if (frow) *frow = field->frow;
+  if (fcol) *fcol = field->fcol;
+  if (nrow) *nrow = field->nrow;
+  if (nbuf) *nbuf = field->nbuf;
+  RETURN(E_OK);
+}
+	
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int dynamic_field_info(const FIELD *field,
+|                                           int *drows, int *dcols,
+|                                           int *maxgrow)
+|   
+|   Description   :  Retrieve informations about a dynamic fields current
+|                    dynamic parameters.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+int dynamic_field_info(const FIELD *field,
+		       int *drows, int *dcols, int *maxgrow)
+{
+  if (!field)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (drows)   *drows   = field->drows;
+  if (dcols)   *dcols   = field->dcols;
+  if (maxgrow) *maxgrow = field->maxgrow;
+
+  RETURN(E_OK);
+}
+
+/* fld_info.c ends here */

+ 81 - 0
Source/CursesDialog/form/fld_just.c

@@ -0,0 +1,81 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_just(FIELD *field, int just)
+|   
+|   Description   :  Set the fields type of justification.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - one of the arguments was incorrect
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+int set_field_just(FIELD * field, int just)
+{
+  int res = E_BAD_ARGUMENT;
+
+  if ((just==NO_JUSTIFICATION)  ||
+      (just==JUSTIFY_LEFT)	||
+      (just==JUSTIFY_CENTER)	||
+      (just==JUSTIFY_RIGHT)	)
+    {
+      Normalize_Field( field );
+      if (field->just != just)
+	{
+	  field->just = just;
+	  res = _nc_Synchronize_Attributes( field );
+	}
+      else
+	res = E_OK;
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_just( const FIELD *field )
+|   
+|   Description   :  Retrieve the fields type of justification
+|
+|   Return Values :  The justification type.
++--------------------------------------------------------------------------*/
+int field_just(const FIELD * field)
+{
+  return Normalize_Field( field )->just;
+}
+
+/* fld_just.c ends here */

+ 90 - 0
Source/CursesDialog/form/fld_link.c

@@ -0,0 +1,90 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD *link_field(FIELD *field, int frow, int fcol)  
+|   
+|   Description   :  Duplicates the field at the specified position. The
+|                    new field shares its buffers with the original one,
+|                    the attributes are independent.
+|                    If an error occurs, errno is set to
+|                    
+|                    E_BAD_ARGUMENT - invalid argument
+|                    E_SYSTEM_ERROR - system error
+|
+|   Return Values :  Pointer to the new field or NULL if failure
++--------------------------------------------------------------------------*/
+FIELD *link_field(FIELD * field, int frow, int fcol)
+{
+  FIELD *New_Field = (FIELD *)0;
+  int err = E_BAD_ARGUMENT;
+
+  if (field && (frow>=0) && (fcol>=0) &&
+      ((err=E_SYSTEM_ERROR) != 0) && /* trick: this resets the default error */
+      (New_Field = (FIELD *)malloc(sizeof(FIELD))) )
+    {
+      *New_Field        = *_nc_Default_Field;
+      New_Field->frow   = frow;
+      New_Field->fcol   = fcol;
+      New_Field->link   = field->link;
+      field->link       = New_Field;
+      New_Field->buf    = field->buf;
+      New_Field->rows   = field->rows;
+      New_Field->cols   = field->cols;
+      New_Field->nrow   = field->nrow;
+      New_Field->nbuf   = field->nbuf;
+      New_Field->drows  = field->drows;
+      New_Field->dcols  = field->dcols;
+      New_Field->maxgrow= field->maxgrow;
+      New_Field->just   = field->just;
+      New_Field->fore   = field->fore;
+      New_Field->back   = field->back;
+      New_Field->pad    = field->pad;
+      New_Field->opts   = field->opts;
+      New_Field->usrptr = field->usrptr;
+      if (_nc_Copy_Type(New_Field,field)) 
+	return New_Field;
+    }
+
+  if (New_Field) 
+    free_field(New_Field);
+
+  SET_ERROR( err );
+  return (FIELD *)0;
+}
+
+/* fld_link.c ends here */

+ 74 - 0
Source/CursesDialog/form/fld_max.c

@@ -0,0 +1,74 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_max_field(FIELD *field, int maxgrow)
+|   
+|   Description   :  Set the maximum growth for a dynamic field. If maxgrow=0
+|                    the field may grow to any possible size.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid argument
++--------------------------------------------------------------------------*/
+int set_max_field(FIELD *field, int maxgrow)
+{
+  if (!field || (maxgrow<0))
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      bool single_line_field = Single_Line_Field(field);
+
+      if (maxgrow>0)
+	{
+	  if (( single_line_field && (maxgrow < field->dcols)) ||
+	      (!single_line_field && (maxgrow < field->drows)))
+	    RETURN(E_BAD_ARGUMENT);
+	}
+      field->maxgrow = maxgrow;
+      field->status &= ~_MAY_GROW;
+      if (!(field->opts & O_STATIC))
+	{
+	  if ((maxgrow==0) ||
+	      ( single_line_field && (field->dcols < maxgrow)) ||
+	      (!single_line_field && (field->drows < maxgrow)))
+	    field->status |= _MAY_GROW;
+	}
+    }
+  RETURN(E_OK);
+}
+		  
+/* fld_max.c ends here */

+ 62 - 0
Source/CursesDialog/form/fld_move.c

@@ -0,0 +1,62 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int move_field(FIELD *field,int frow, int fcol)
+|   
+|   Description   :  Moves the disconnected field to the new location in
+|                    the forms subwindow.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid argument passed
+|                    E_CONNECTED     - field is connected
++--------------------------------------------------------------------------*/
+int move_field(FIELD *field, int frow, int fcol)
+{
+  if ( !field || (frow<0) || (fcol<0) ) 
+    RETURN(E_BAD_ARGUMENT);
+
+  if (field->form) 
+    RETURN(E_CONNECTED);
+
+  field->frow = frow;
+  field->fcol = fcol;
+  RETURN(E_OK);
+}
+
+/* fld_move.c ends here */
+

+ 125 - 0
Source/CursesDialog/form/fld_newftyp.c

@@ -0,0 +1,125 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+static FIELDTYPE const default_fieldtype = {
+  0,                   /* status                                      */
+  0L,                  /* reference count                             */
+  (FIELDTYPE *)0,      /* pointer to left  operand                    */
+  (FIELDTYPE *)0,      /* pointer to right operand                    */
+  NULL,                /* makearg function                            */
+  NULL,                /* copyarg function                            */
+  NULL,                /* freearg function                            */
+  NULL,                /* field validation function                   */
+  NULL,                /* Character check function                    */
+  NULL,                /* enumerate next function                     */
+  NULL                 /* enumerate previous function                 */
+};
+
+const FIELDTYPE* _nc_Default_FieldType = &default_fieldtype;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELDTYPE *new_fieldtype(
+|                       bool (* const field_check)(FIELD *,const void *),
+|                       bool (* const char_check) (int, const void *) ) 
+|   
+|   Description   :  Create a new fieldtype. The application programmer must
+|                    write a field_check and a char_check function and give
+|                    them as input to this call.
+|                    If an error occurs, errno is set to                    
+|                       E_BAD_ARGUMENT  - invalid arguments
+|                       E_SYSTEM_ERROR  - system error (no memory)
+|
+|   Return Values :  Fieldtype pointer or NULL if error occured
++--------------------------------------------------------------------------*/
+FIELDTYPE *new_fieldtype(
+ bool (* const field_check)(FIELD *,const void *),
+ bool (* const char_check) (int,const void *) )
+{
+  FIELDTYPE *nftyp = (FIELDTYPE *)0;
+  
+  if ( (field_check) || (char_check) )
+    {
+      nftyp = (FIELDTYPE *)malloc(sizeof(FIELDTYPE));
+      if (nftyp)
+	{
+	  *nftyp = default_fieldtype;
+	  nftyp->fcheck = field_check;
+	  nftyp->ccheck = char_check;
+	}
+      else
+	{
+	  SET_ERROR( E_SYSTEM_ERROR );
+	}
+    }
+  else
+    {
+      SET_ERROR( E_BAD_ARGUMENT );
+    }
+  return nftyp;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int free_fieldtype(FIELDTYPE *typ)
+|   
+|   Description   :  Release the memory associated with this fieldtype.
+|
+|   Return Values :  E_OK            - success
+|                    E_CONNECTED     - there are fields referencing the type
+|                    E_BAD_ARGUMENT  - invalid fieldtype pointer
++--------------------------------------------------------------------------*/
+int free_fieldtype(FIELDTYPE *typ)
+{
+  if (!typ)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (typ->ref!=0)
+    RETURN(E_CONNECTED);
+
+  if (typ->status & _RESIDENT)
+    RETURN(E_CONNECTED);
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      if (typ->left ) typ->left->ref--;
+      if (typ->right) typ->right->ref--;
+    }
+  free(typ);
+  RETURN(E_OK);
+}
+
+/* fld_newftyp.c ends here */

+ 124 - 0
Source/CursesDialog/form/fld_opts.c

@@ -0,0 +1,124 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*----------------------------------------------------------------------------
+  Field-Options manipulation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_opts(FIELD *field, Field_Options opts)
+|   
+|   Description   :  Turns on the named options for this field and turns
+|                    off all the remaining options.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+int set_field_opts(FIELD * field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    res = _nc_Synchronize_Options( Normalize_Field(field), opts );
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Field_Options field_opts(const FIELD *field)
+|   
+|   Description   :  Retrieve the fields options.
+|
+|   Return Values :  The options.
++--------------------------------------------------------------------------*/
+Field_Options field_opts(const FIELD * field)
+{
+  return ALL_FIELD_OPTS & Normalize_Field( field )->opts;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_opts_on(FIELD *field, Field_Options opts)
+|   
+|   Description   :  Turns on the named options for this field and all the 
+|                    remaining options are unchanged.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+int field_opts_on(FIELD * field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    {
+      Normalize_Field( field );
+      res = _nc_Synchronize_Options( field, field->opts | opts );
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_opts_off(FIELD *field, Field_Options opts)
+|   
+|   Description   :  Turns off the named options for this field and all the 
+|                    remaining options are unchanged.
+|
+|   Return Values :  E_OK            - success
+|                    E_CURRENT       - the field is the current field
+|                    E_BAD_ARGUMENT  - invalid options
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+int field_opts_off(FIELD  * field, Field_Options opts)
+{
+  int res = E_BAD_ARGUMENT;
+
+  opts &= ALL_FIELD_OPTS;
+  if (!(opts & ~ALL_FIELD_OPTS))
+    {
+      Normalize_Field( field );
+      res = _nc_Synchronize_Options( field, field->opts & ~opts );
+    }
+  RETURN(res);
+}	
+
+/* fld_opts.c ends here */

+ 78 - 0
Source/CursesDialog/form/fld_pad.c

@@ -0,0 +1,78 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_pad(FIELD *field, int ch)
+|   
+|   Description   :  Set the pad character used to fill the field. This must
+|                    be a printable character.
+|
+|   Return Values :  E_OK           - success
+|                    E_BAD_ARGUMENT - invalid field pointer or pad character
+|                    E_SYSTEM_ERROR - system error
++--------------------------------------------------------------------------*/
+int set_field_pad(FIELD  * field, int ch)
+{
+  int res = E_BAD_ARGUMENT;
+
+  Normalize_Field( field );
+  if (isprint((unsigned char)ch))
+    {
+      if (field->pad != ch)
+	{
+	  field->pad = ch;
+	  res = _nc_Synchronize_Attributes( field );
+	}
+      else
+	res = E_OK;
+    }
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_pad(const FIELD *field)
+|   
+|   Description   :  Retrieve the fields pad character.
+|
+|   Return Values :  The pad character.
++--------------------------------------------------------------------------*/
+int field_pad(const FIELD * field)
+{
+  return Normalize_Field( field )->pad;
+}
+
+/* fld_pad.c ends here */

+ 76 - 0
Source/CursesDialog/form/fld_page.c

@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_new_page(FIELD *field, bool new_page_flag)
+|   
+|   Description   :  Marks the field as the beginning of a new page of 
+|                    the form.
+|
+|   Return Values :  E_OK         - success
+|                    E_CONNECTED  - field is connected
++--------------------------------------------------------------------------*/
+int set_new_page(FIELD * field, bool new_page_flag)
+{
+  Normalize_Field(field);
+  if (field->form) 
+    RETURN(E_CONNECTED);
+
+  if (new_page_flag) 
+    field->status |= _NEWPAGE;
+  else
+    field->status &= ~_NEWPAGE;
+
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool new_page(const FIELD *field)
+|   
+|   Description   :  Retrieve the info whether or not the field starts a
+|                    new page on the form.
+|
+|   Return Values :  TRUE  - field starts a new page
+|                    FALSE - field doesn't start a new page
++--------------------------------------------------------------------------*/
+bool new_page(const FIELD * field)
+{
+  return (Normalize_Field(field)->status & _NEWPAGE)  ? TRUE : FALSE;
+}
+
+/* fld_page.c ends here */

+ 73 - 0
Source/CursesDialog/form/fld_stat.c

@@ -0,0 +1,73 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_status(FIELD *field, bool status)
+|   
+|   Description   :  Set or clear the 'changed' indication flag for that
+|                    fields primary buffer.
+|
+|   Return Values :  E_OK            - success
++--------------------------------------------------------------------------*/
+int set_field_status(FIELD * field, bool status)
+{
+  Normalize_Field( field );
+
+  if (status)
+    field->status |= _CHANGED;
+  else
+    field->status &= ~_CHANGED;
+
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool field_status(const FIELD *field)
+|   
+|   Description   :  Retrieve the value of the 'changed' indication flag
+|                    for that fields primary buffer. 
+|
+|   Return Values :  TRUE  - buffer has been changed
+|                    FALSE - buffer has not been changed
++--------------------------------------------------------------------------*/
+bool field_status(const FIELD * field)
+{
+  return ((Normalize_Field(field)->status & _CHANGED) ? TRUE : FALSE);
+}
+
+/* fld_stat.c ends here */

+ 92 - 0
Source/CursesDialog/form/fld_type.c

@@ -0,0 +1,92 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_type(FIELD *field, FIELDTYPE *type,...)
+|   
+|   Description   :  Associate the specified fieldtype with the field.
+|                    Certain field types take additional arguments. Look
+|                    at the spec of the field types !
+|
+|   Return Values :  E_OK           - success
+|                    E_SYSTEM_ERROR - system error
++--------------------------------------------------------------------------*/
+int set_field_type(FIELD *field,FIELDTYPE *type, ...)
+{
+  va_list ap;
+  int res = E_SYSTEM_ERROR;
+  int err = 0;
+
+  va_start(ap,type);
+
+  Normalize_Field(field);
+  _nc_Free_Type(field);
+
+  field->type = type;
+  field->arg  = (void *)_nc_Make_Argument(field->type,&ap,&err);
+
+  if (err)
+    {
+      _nc_Free_Argument(field->type,(TypeArgument *)(field->arg));
+      field->type = (FIELDTYPE *)0;
+      field->arg  = (void *)0;
+    }
+  else
+    {
+      res = E_OK;
+      if (field->type) 
+	field->type->ref++;
+    }
+
+  va_end(ap);
+  RETURN(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELDTYPE *field_type(const FIELD *field)
+|   
+|   Description   :  Retrieve the associated fieldtype for this field.
+|
+|   Return Values :  Pointer to fieldtype of NULL if none is defined.
++--------------------------------------------------------------------------*/
+FIELDTYPE *field_type(const FIELD * field)
+{
+  return Normalize_Field(field)->type;
+}
+
+/* fld_type.c ends here */

+ 67 - 0
Source/CursesDialog/form/fld_user.c

@@ -0,0 +1,67 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_userptr(FIELD *field, void *usrptr)
+|   
+|   Description   :  Set the pointer that is reserved in any field to store
+|                    application relevant informations
+|
+|   Return Values :  E_OK         - on success
++--------------------------------------------------------------------------*/
+int set_field_userptr(FIELD * field, void  *usrptr)
+{
+  Normalize_Field( field )->usrptr = usrptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  void *field_userptr(const FIELD *field)
+|   
+|   Description   :  Return the pointer that is reserved in any field to
+|                    store application relevant informations.
+|
+|   Return Values :  Value of pointer. If no such pointer has been set,
+|                    NULL is returned
++--------------------------------------------------------------------------*/
+void *field_userptr(const FIELD *field)
+{
+  return Normalize_Field( field )->usrptr;
+}
+
+/* fld_user.c ends here */

+ 389 - 0
Source/CursesDialog/form/form.h

@@ -0,0 +1,389 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#ifndef FORM_H
+#define FORM_H
+
+#include <curses.h>
+#include <eti.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+typedef int Form_Options;
+typedef int Field_Options;
+
+	/**********
+	*  _PAGE  *
+	**********/
+
+typedef struct {
+  short	pmin;	  /* index of first field on page            */
+  short	pmax;	  /* index of last field on page             */
+  short	smin;	  /* index of top leftmost field on page     */
+  short	smax;	  /* index of bottom rightmost field on page */
+} _PAGE;
+
+	/**********
+	*  FIELD  *
+	**********/
+
+typedef struct fieldnode {
+  unsigned short       	status;	  /* flags		        */
+  short			rows;	  /* size in rows		*/
+  short			cols;	  /* size in cols		*/
+  short			frow;	  /* first row		        */
+  short			fcol;	  /* first col		        */
+  int                   drows;    /* dynamic rows               */
+  int                   dcols;    /* dynamic cols               */
+  int                   maxgrow;  /* maximum field growth       */
+  int			nrow;	  /* offscreen rows	        */
+  short			nbuf;	  /* additional buffers	        */
+  short			just;	  /* justification	        */
+  short			page;	  /* page on form		*/
+  short			index;	  /* into form -> field	        */
+  int			pad;	  /* pad character	        */
+  chtype		fore;	  /* foreground attribute	*/
+  chtype		back;	  /* background attribute	*/
+  Field_Options		opts;	  /* options		        */
+  struct fieldnode *	snext;	  /* sorted order pointer	*/
+  struct fieldnode *	sprev;	  /* sorted order pointer	*/
+  struct fieldnode *	link;	  /* linked field chain	        */
+  struct formnode *	form;	  /* containing form	        */
+  struct typenode *	type;	  /* field type		        */
+  void *		arg;	  /* argument for type	        */
+  char *		buf;	  /* field buffers	        */
+  void *		usrptr;	  /* user pointer		*/
+} FIELD;
+
+	/**************
+	*  FIELDTYPE  *
+	**************/
+
+typedef struct typenode {
+  unsigned short	status;	               /* flags		       */
+  long			ref;	               /* reference count      */
+  struct typenode *	left;	               /* ptr to operand for | */
+  struct typenode *	right;	               /* ptr to operand for | */
+
+  void* (*makearg)(va_list *);                 /* make fieldtype arg   */
+  void* (*copyarg)(const void *);              /* copy fieldtype arg   */
+  void  (*freearg)(void *);                    /* free fieldtype arg   */
+
+  bool	(*fcheck)(FIELD *,const void *);       /* field validation     */
+  bool	(*ccheck)(int,const void *);           /* character validation */
+
+  bool	(*next)(FIELD *,const void *);         /* enumerate next value */
+  bool	(*prev)(FIELD *,const void *);         /* enumerate prev value */
+
+} FIELDTYPE;
+
+	/*********
+	*  FORM  *
+	*********/
+
+typedef struct formnode {
+  unsigned short	status;	  /* flags		        */
+  short			rows;	  /* size in rows		*/
+  short			cols;	  /* size in cols		*/
+  int			currow;	  /* current row in field window*/
+  int			curcol;	  /* current col in field window*/
+  int			toprow;	  /* in scrollable field window	*/
+  int                   begincol; /* in horiz. scrollable field */
+  short			maxfield; /* number of fields	        */
+  short			maxpage;  /* number of pages	        */
+  short			curpage;  /* index into page	        */
+  Form_Options		opts;	  /* options		        */
+  WINDOW *		win;	  /* window		        */
+  WINDOW *		sub;	  /* subwindow		        */
+  WINDOW *		w;	  /* window for current field	*/
+  FIELD **		field;	  /* field [maxfield]	        */
+  FIELD *		current;  /* current field	        */
+  _PAGE *		page;	  /* page [maxpage]	        */
+  void *		usrptr;	  /* user pointer		*/
+
+  void                  (*forminit)(struct formnode *);
+  void                  (*formterm)(struct formnode *);
+  void                  (*fieldinit)(struct formnode *);
+  void                  (*fieldterm)(struct formnode *);
+
+} FORM;
+
+typedef void (*Form_Hook)(FORM *);
+
+	/***************************
+	*  miscellaneous #defines  *
+	***************************/
+
+/* field justification */
+#define NO_JUSTIFICATION	(0)
+#define JUSTIFY_LEFT		(1)
+#define JUSTIFY_CENTER		(2)
+#define JUSTIFY_RIGHT		(3)
+
+/* field options */
+#define O_VISIBLE		(0x0001)
+#define O_ACTIVE		(0x0002)
+#define O_PUBLIC		(0x0004)
+#define O_EDIT			(0x0008)
+#define O_WRAP			(0x0010)
+#define O_BLANK			(0x0020)
+#define O_AUTOSKIP		(0x0040)
+#define O_NULLOK		(0x0080)
+#define O_PASSOK		(0x0100)
+#define O_STATIC                (0x0200)
+
+/* form options */
+#define O_NL_OVERLOAD		(0x0001)
+#define O_BS_OVERLOAD		(0x0002)
+
+/* form driver commands */
+#define REQ_NEXT_PAGE	 (KEY_MAX + 1)	/* move to next page		*/
+#define REQ_PREV_PAGE	 (KEY_MAX + 2)	/* move to previous page	*/
+#define REQ_FIRST_PAGE	 (KEY_MAX + 3)	/* move to first page		*/
+#define REQ_LAST_PAGE	 (KEY_MAX + 4)	/* move to last page		*/
+
+#define REQ_NEXT_FIELD	 (KEY_MAX + 5)	/* move to next field		*/
+#define REQ_PREV_FIELD	 (KEY_MAX + 6)	/* move to previous field	*/
+#define REQ_FIRST_FIELD	 (KEY_MAX + 7)	/* move to first field		*/
+#define REQ_LAST_FIELD	 (KEY_MAX + 8)	/* move to last field		*/
+#define REQ_SNEXT_FIELD	 (KEY_MAX + 9)	/* move to sorted next field	*/
+#define REQ_SPREV_FIELD	 (KEY_MAX + 10)	/* move to sorted prev field	*/
+#define REQ_SFIRST_FIELD (KEY_MAX + 11)	/* move to sorted first field	*/
+#define REQ_SLAST_FIELD	 (KEY_MAX + 12)	/* move to sorted last field	*/
+#define REQ_LEFT_FIELD	 (KEY_MAX + 13)	/* move to left to field	*/
+#define REQ_RIGHT_FIELD	 (KEY_MAX + 14)	/* move to right to field	*/
+#define REQ_UP_FIELD	 (KEY_MAX + 15)	/* move to up to field		*/
+#define REQ_DOWN_FIELD	 (KEY_MAX + 16)	/* move to down to field	*/
+
+#define REQ_NEXT_CHAR	 (KEY_MAX + 17)	/* move to next char in field	*/
+#define REQ_PREV_CHAR	 (KEY_MAX + 18)	/* move to prev char in field	*/
+#define REQ_NEXT_LINE	 (KEY_MAX + 19)	/* move to next line in field	*/
+#define REQ_PREV_LINE	 (KEY_MAX + 20)	/* move to prev line in field	*/
+#define REQ_NEXT_WORD	 (KEY_MAX + 21)	/* move to next word in field	*/
+#define REQ_PREV_WORD	 (KEY_MAX + 22)	/* move to prev word in field	*/
+#define REQ_BEG_FIELD	 (KEY_MAX + 23)	/* move to first char in field	*/
+#define REQ_END_FIELD	 (KEY_MAX + 24)	/* move after last char in fld	*/
+#define REQ_BEG_LINE	 (KEY_MAX + 25)	/* move to beginning of line	*/
+#define REQ_END_LINE	 (KEY_MAX + 26)	/* move after last char in line	*/
+#define REQ_LEFT_CHAR	 (KEY_MAX + 27)	/* move left in field		*/
+#define REQ_RIGHT_CHAR	 (KEY_MAX + 28)	/* move right in field		*/
+#define REQ_UP_CHAR	 (KEY_MAX + 29)	/* move up in field		*/
+#define REQ_DOWN_CHAR	 (KEY_MAX + 30)	/* move down in field		*/
+
+#define REQ_NEW_LINE	 (KEY_MAX + 31)	/* insert/overlay new line	*/
+#define REQ_INS_CHAR	 (KEY_MAX + 32)	/* insert blank char at cursor	*/
+#define REQ_INS_LINE	 (KEY_MAX + 33)	/* insert blank line at cursor	*/
+#define REQ_DEL_CHAR	 (KEY_MAX + 34)	/* delete char at cursor	*/
+#define REQ_DEL_PREV	 (KEY_MAX + 35)	/* delete char before cursor	*/
+#define REQ_DEL_LINE	 (KEY_MAX + 36)	/* delete line at cursor	*/
+#define REQ_DEL_WORD	 (KEY_MAX + 37)	/* delete line at cursor	*/
+#define REQ_CLR_EOL	 (KEY_MAX + 38)	/* clear to end of line		*/
+#define REQ_CLR_EOF	 (KEY_MAX + 39)	/* clear to end of field	*/
+#define REQ_CLR_FIELD	 (KEY_MAX + 40)	/* clear entire field		*/
+#define REQ_OVL_MODE	 (KEY_MAX + 41)	/* begin overlay mode		*/
+#define REQ_INS_MODE	 (KEY_MAX + 42)	/* begin insert mode		*/
+#define REQ_SCR_FLINE	 (KEY_MAX + 43)	/* scroll field forward a line	*/
+#define REQ_SCR_BLINE	 (KEY_MAX + 44)	/* scroll field backward a line	*/
+#define REQ_SCR_FPAGE	 (KEY_MAX + 45)	/* scroll field forward a page	*/
+#define REQ_SCR_BPAGE	 (KEY_MAX + 46)	/* scroll field backward a page	*/
+#define REQ_SCR_FHPAGE   (KEY_MAX + 47) /* scroll field forward  half page */
+#define REQ_SCR_BHPAGE   (KEY_MAX + 48) /* scroll field backward half page */
+#define REQ_SCR_FCHAR    (KEY_MAX + 49) /* horizontal scroll char          */
+#define REQ_SCR_BCHAR    (KEY_MAX + 50) /* horizontal scroll char          */
+#define REQ_SCR_HFLINE   (KEY_MAX + 51) /* horizontal scroll line          */
+#define REQ_SCR_HBLINE   (KEY_MAX + 52) /* horizontal scroll line          */
+#define REQ_SCR_HFHALF   (KEY_MAX + 53) /* horizontal scroll half line     */
+#define REQ_SCR_HBHALF   (KEY_MAX + 54) /* horizontal scroll half line     */
+
+#define REQ_VALIDATION	 (KEY_MAX + 55)	/* validate field		*/
+#define REQ_NEXT_CHOICE	 (KEY_MAX + 56)	/* display next field choice	*/
+#define REQ_PREV_CHOICE	 (KEY_MAX + 57)	/* display prev field choice	*/
+
+#define MIN_FORM_COMMAND (KEY_MAX + 1)	/* used by form_driver		*/
+#define MAX_FORM_COMMAND (KEY_MAX + 57)	/* used by form_driver		*/
+
+#if defined(MAX_COMMAND)
+#  if (MAX_FORM_COMMAND > MAX_COMMAND)
+#    error Something is wrong -- MAX_FORM_COMMAND is greater than MAX_COMMAND
+#  elif (MAX_COMMAND != (KEY_MAX + 128))
+#    error Something is wrong -- MAX_COMMAND is already inconsistently defined.
+#  endif
+#else
+#  define MAX_COMMAND (KEY_MAX + 128)
+#endif
+
+	/*************************
+	*  standard field types  *
+	*************************/
+extern FIELDTYPE *TYPE_ALPHA,
+                 *TYPE_ALNUM,
+                 *TYPE_ENUM,
+                 *TYPE_INTEGER,
+                 *TYPE_NUMERIC,
+                 *TYPE_REGEXP;
+
+        /************************************
+	*  built-in additional field types  *
+        *  They are not defined in SVr4     *
+	************************************/
+extern FIELDTYPE *TYPE_IPV4;      /* Internet IP Version 4 address */
+
+        /*********************** 
+        *   Default objects    *
+        ***********************/ 
+extern FORM  *_nc_Default_Form;
+extern FIELD *_nc_Default_Field;
+
+
+	/***********************
+	*  FIELDTYPE routines  *
+	***********************/
+extern FIELDTYPE 
+                *new_fieldtype(
+		    bool (* const field_check)(FIELD *,const void *),
+		    bool (* const char_check)(int,const void *)),
+                *link_fieldtype(FIELDTYPE *,FIELDTYPE *);
+
+extern int      free_fieldtype(FIELDTYPE *),
+                set_fieldtype_arg(FIELDTYPE *,
+		    void * (* const make_arg)(va_list *),
+		    void * (* const copy_arg)(const void *),
+		    void (* const free_arg)(void *)),
+                set_fieldtype_choice (FIELDTYPE *,
+		    bool (* const next_choice)(FIELD *,const void *),
+	      	    bool (* const prev_choice)(FIELD *,const void *));
+
+	/*******************
+	*  FIELD routines  *
+	*******************/
+extern FIELD    *new_field(int,int,int,int,int,int),
+                *dup_field(FIELD *,int,int),
+                *link_field(FIELD *,int,int);
+
+extern int      free_field(FIELD *),
+                field_info(const FIELD *,int *,int *,int *,int *,int *,int *),
+                dynamic_field_info(const FIELD *,int *,int *,int *),
+                set_max_field( FIELD *,int),
+                move_field(FIELD *,int,int),
+                set_field_type(FIELD *,FIELDTYPE *,...),
+                set_new_page(FIELD *,bool),
+                set_field_just(FIELD *,int),
+                field_just(const FIELD *),
+                set_field_fore(FIELD *,chtype),
+                set_field_back(FIELD *,chtype),
+                set_field_pad(FIELD *,int),
+                field_pad(const FIELD *),
+                set_field_buffer(FIELD *,int,const char *),
+                set_field_status(FIELD *,bool),
+                set_field_userptr(FIELD *, void *),
+                set_field_opts(FIELD *,Field_Options),
+                field_opts_on(FIELD *,Field_Options),
+                field_opts_off(FIELD *,Field_Options);
+
+extern chtype   field_fore(const FIELD *),
+                field_back(const FIELD *);
+
+extern bool     new_page(const FIELD *),
+                field_status(const FIELD *);
+
+extern void     *field_arg(const FIELD *);
+
+extern void     *field_userptr(const FIELD *);
+
+extern FIELDTYPE
+                *field_type(const FIELD *);
+
+extern char*    field_buffer(const FIELD *,int);
+
+extern Field_Options  
+                field_opts(const FIELD *);
+
+	/******************
+	*  FORM routines  *
+	******************/
+extern FORM     *new_form(FIELD **);
+
+extern FIELD    **form_fields(const FORM *),
+                *current_field(const FORM *);
+
+extern WINDOW   *form_win(const FORM *),
+                *form_sub(const FORM *);
+
+extern Form_Hook
+                form_init(const FORM *),
+                form_term(const FORM *),
+                field_init(const FORM *),
+                field_term(const FORM *);
+
+extern int      free_form(FORM *),
+                set_form_fields(FORM *,FIELD **),
+                field_count(const FORM *),
+                set_form_win(FORM *,WINDOW *),
+                set_form_sub(FORM *,WINDOW *),
+                set_current_field(FORM *,FIELD *),
+                field_index(const FIELD *),
+                set_form_page(FORM *,int),
+                form_page(const FORM *),
+                scale_form(const FORM *,int *,int *),
+                set_form_init(FORM *,Form_Hook),
+                set_form_term(FORM *,Form_Hook),
+                set_field_init(FORM *,Form_Hook),
+                set_field_term(FORM *,Form_Hook),
+                post_form(FORM *),
+                unpost_form(FORM *),
+                pos_form_cursor(FORM *),
+                form_driver(FORM *,int),
+                set_form_userptr(FORM *,void *),
+                set_form_opts(FORM *,Form_Options),
+                form_opts_on(FORM *,Form_Options),
+                form_opts_off(FORM *,Form_Options),
+                form_request_by_name(const char *);
+
+extern const char
+                *form_request_name(int);
+
+extern void     *form_userptr(const FORM *);
+
+extern Form_Options
+                form_opts(const FORM *);
+
+extern bool     data_ahead(const FORM *),
+                data_behind(const FORM *);
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif	/* FORM_H */

+ 128 - 0
Source/CursesDialog/form/form.priv.h

@@ -0,0 +1,128 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "mf_common.h"
+#include "form.h"
+
+/* form  status values */
+#define _OVLMODE         (0x04) /* Form is in overlay mode                */
+#define _WINDOW_MODIFIED (0x10) /* Current field window has been modified */
+#define _FCHECK_REQUIRED (0x20) /* Current field needs validation         */
+
+/* field status values */
+#define _CHANGED         (0x01) /* Field has been changed                 */
+#define _NEWTOP          (0x02) /* Vertical scrolling occured             */
+#define _NEWPAGE	 (0x04) /* field begins new page of form          */
+#define _MAY_GROW        (0x08) /* dynamic field may still grow           */
+
+/* fieldtype status values */
+#define _LINKED_TYPE     (0x01) /* Type is a linked type                  */
+#define _HAS_ARGS        (0x02) /* Type has arguments                     */
+#define _HAS_CHOICE      (0x04) /* Type has choice methods                */
+#define _RESIDENT        (0x08) /* Type is builtin                        */
+
+/* This are the field options required to be a selectable field in field
+   navigation requests */
+#define O_SELECTABLE (O_ACTIVE | O_VISIBLE)
+
+/* If form is NULL replace form argument by default-form */
+#define Normalize_Form(form)  ((form)=(form)?(form):_nc_Default_Form)
+
+/* If field is NULL replace field argument by default-field */
+#define Normalize_Field(field)  ((field)=(field)?(field):_nc_Default_Field)
+
+/* Retrieve forms window */
+#define Get_Form_Window(form) \
+  ((form)->sub?(form)->sub:((form)->win?(form)->win:stdscr))
+
+/* Calculate the size for a single buffer for this field */
+#define Buffer_Length(field) ((field)->drows * (field)->dcols)
+
+/* Calculate the total size of all buffers for this field */
+#define Total_Buffer_Size(field) \
+   ( (Buffer_Length(field) + 1) * (1+(field)->nbuf) )
+
+/* Logic to determine whether or not a field is single lined */
+#define Single_Line_Field(field) \
+   (((field)->rows + (field)->nrow) == 1)
+
+/* Logic to determine whether or not a field is selectable */
+#define Field_Is_Selectable(f)     (((f)->opts & O_SELECTABLE)==O_SELECTABLE)
+#define Field_Is_Not_Selectable(f) (((f)->opts & O_SELECTABLE)!=O_SELECTABLE)
+
+typedef struct typearg {
+  struct typearg *left;
+  struct typearg *right;
+} TypeArgument;
+
+/* This is a dummy request code (normally invalid) to be used internally
+   with the form_driver() routine to position to the first active field
+   on the form
+*/
+#define FIRST_ACTIVE_MAGIC (-291056)
+
+#define ALL_FORM_OPTS  (                \
+			O_NL_OVERLOAD  |\
+			O_BS_OVERLOAD   )
+
+#define ALL_FIELD_OPTS (           \
+			O_VISIBLE |\
+			O_ACTIVE  |\
+			O_PUBLIC  |\
+			O_EDIT    |\
+			O_WRAP    |\
+			O_BLANK   |\
+			O_AUTOSKIP|\
+			O_NULLOK  |\
+			O_PASSOK  |\
+			O_STATIC   )
+
+
+#define C_BLANK ' '
+#define is_blank(c) ((c)==C_BLANK)
+
+extern const FIELDTYPE* _nc_Default_FieldType;
+
+extern TypeArgument* _nc_Make_Argument(const FIELDTYPE*,va_list*,int*);
+extern TypeArgument *_nc_Copy_Argument(const FIELDTYPE*,const TypeArgument*, int*);
+extern void _nc_Free_Argument(const FIELDTYPE*,TypeArgument*);
+extern bool _nc_Copy_Type(FIELD*, FIELD const *);
+extern void _nc_Free_Type(FIELD *);
+
+extern int _nc_Synchronize_Attributes(FIELD*);
+extern int _nc_Synchronize_Options(FIELD*,Field_Options);
+extern int _nc_Set_Form_Page(FORM*,int,FIELD*);
+extern int _nc_Refresh_Current_Field(FORM*);
+extern FIELD* _nc_First_Active_Field(FORM*);
+extern bool _nc_Internal_Validation(FORM*);
+extern int _nc_Set_Current_Field(FORM*,FIELD*);
+extern int _nc_Position_Form_Cursor(FORM*);

+ 66 - 0
Source/CursesDialog/form/frm_cursor.c

@@ -0,0 +1,66 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int pos_form_cursor(FORM * form)
+|   
+|   Description   :  Moves the form window cursor to the location required
+|                    by the form driver to resume form processing. This may
+|                    be needed after the application calls a curses library
+|                    I/O routine that modifies the cursor position.
+|
+|   Return Values :  E_OK                      - Success
+|                    E_SYSTEM_ERROR            - System error.
+|                    E_BAD_ARGUMENT            - Invalid form pointer
+|                    E_NOT_POSTED              - Form is not posted
++--------------------------------------------------------------------------*/
+int pos_form_cursor(FORM * form)
+{
+  int res;
+
+  if (!form)
+   res = E_BAD_ARGUMENT;
+  else
+    {
+      if (!(form->status & _POSTED))
+        res = E_NOT_POSTED;
+      else
+	res = _nc_Position_Form_Cursor(form);
+    }
+  RETURN(res);
+}
+
+/* frm_cursor.c ends here */

+ 181 - 0
Source/CursesDialog/form/frm_data.c

@@ -0,0 +1,181 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool data_behind(const FORM *form)
+|   
+|   Description   :  Check for off-screen data behind. This is nearly trivial
+|                    becose the begin of a field is fixed.
+|
+|   Return Values :  TRUE   - there are off-screen data behind
+|                    FALSE  - there are no off-screen data behind
++--------------------------------------------------------------------------*/
+bool data_behind(const FORM *form)
+{
+  bool result = FALSE;
+
+  if (form && (form->status & _POSTED) && form->current)
+    {
+      FIELD *field;
+
+      field = form->current;
+      if (!Single_Line_Field(field))
+	{
+	  result = (form->toprow==0) ? FALSE : TRUE;
+	}
+      else
+	{
+	  result = (form->begincol==0) ? FALSE : TRUE;
+	}
+    }
+  return(result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static char * After_Last_Non_Pad_Position(
+|                                    char *buffer,
+|                                    int len,
+|                                    int pad)
+|   
+|   Description   :  Find the last position in the buffer that doesn't
+|                    contain a padding character.
+|
+|   Return Values :  The pointer to this position 
++--------------------------------------------------------------------------*/
+INLINE 
+static char * After_Last_Non_Pad_Position(char *buffer, int len, int pad)
+{
+  char *end = buffer + len;
+
+  assert(buffer && len>=0);
+  while ( (buffer < end) && (*(end-1)==pad) )
+    end--;
+
+  return end;
+}
+
+#define SMALL_BUFFER_SIZE (80)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool data_ahead(const FORM *form)
+|   
+|   Description   :  Check for off-screen data ahead. This is more difficult
+|                    because a dynamic field has a variable end. 
+|
+|   Return Values :  TRUE   - there are off-screen data ahead
+|                    FALSE  - there are no off-screen data ahead
++--------------------------------------------------------------------------*/
+bool data_ahead(const FORM *form)
+{
+  bool result = FALSE;
+
+  if (form && (form->status & _POSTED) && form->current)
+    {
+      static char buffer[SMALL_BUFFER_SIZE + 1];
+      FIELD *field;
+      bool large_buffer;
+      bool cursor_moved = FALSE;
+      char *bp;
+      char *found_content;
+      int pos;
+
+      field = form->current;
+      assert(form->w);
+
+      large_buffer = (field->cols > SMALL_BUFFER_SIZE);
+      if (large_buffer)
+	bp = (char *)malloc((size_t)(field->cols) + 1);
+      else
+	bp = buffer;
+
+      assert(bp);
+      
+      if (Single_Line_Field(field))
+	{
+	  int check_len;
+
+	  pos = form->begincol + field->cols;
+	  while (pos < field->dcols)
+	    {
+	      check_len = field->dcols - pos;
+	      if ( check_len >= field->cols )
+		check_len = field->cols;
+	      cursor_moved = TRUE;
+	      wmove(form->w,0,pos);
+	      winnstr(form->w,bp,check_len);
+	      found_content = 
+		After_Last_Non_Pad_Position(bp,check_len,field->pad);
+	      if (found_content==bp)
+		  pos += field->cols;		  
+	      else
+		{
+		  result = TRUE;
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  pos = form->toprow + field->rows;
+	  while (pos < field->drows)
+	    {
+	      cursor_moved = TRUE;
+	      wmove(form->w,pos,0);
+	      pos++;
+	      winnstr(form->w,bp,field->cols);
+	      found_content = 
+		After_Last_Non_Pad_Position(bp,field->cols,field->pad);
+	      if (found_content!=bp)
+		{
+		  result = TRUE;
+		  break;
+		}
+	    }
+	}
+
+      if (large_buffer)
+	free(bp);
+
+      if (cursor_moved)
+	wmove(form->w,form->currow,form->curcol);
+    }
+  return(result);
+}
+
+/* frm_data.c ends here */

+ 376 - 0
Source/CursesDialog/form/frm_def.c

@@ -0,0 +1,376 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/* this can't be readonly */
+static FORM default_form = {
+  0,                                    /* status     */
+  0,                                    /* rows       */
+  0,                                    /* cols       */
+  0,                                    /* currow     */
+  0,                                    /* curcol     */
+  0,                                    /* toprow     */
+  0,                                    /* begincol   */
+  -1,                                   /* maxfield   */
+  -1,                                   /* maxpage    */
+  -1,                                   /* curpage    */
+  ALL_FORM_OPTS,                        /* opts       */
+  (WINDOW *)0,                          /* win        */
+  (WINDOW *)0,                          /* sub        */
+  (WINDOW *)0,                          /* w          */
+  (FIELD **)0,                          /* field      */
+  (FIELD *)0,                           /* current    */
+  (_PAGE *)0,                           /* page       */
+  (char *)0,                            /* usrptr     */
+  NULL,			                /* forminit   */
+  NULL,                                 /* formterm   */
+  NULL,                                 /* fieldinit  */
+  NULL                                  /* fieldterm  */
+};
+
+FORM *_nc_Default_Form = &default_form;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Insert_Field_By_Position(
+|                                     FIELD *new_field, 
+|                                     FIELD *head )
+|   
+|   Description   :  Insert new_field into sorted fieldlist with head "head"
+|                    and return new head of sorted fieldlist. Sorting
+|                    criteria is (row,column). This is a circular list.
+|
+|   Return Values :  New head of sorted fieldlist
++--------------------------------------------------------------------------*/
+static FIELD *Insert_Field_By_Position(FIELD *newfield, FIELD *head)
+{
+  FIELD *current, *newhead;
+  
+  assert(newfield);
+
+  if (!head)
+    { /* empty list is trivial */
+      newhead = newfield->snext = newfield->sprev = newfield;
+    }
+  else
+    {
+      newhead = current = head;
+      while((current->frow < newfield->frow) || 
+	    ((current->frow==newfield->frow) && 
+	     (current->fcol < newfield->fcol)) )
+	{
+	  current = current->snext;
+	  if (current==head)
+	    { /* We cycled through. Reset head to indicate that */
+	      head = (FIELD *)0;
+	      break;
+	    }
+	}
+      /* we leave the loop with current pointing to the field after newfield*/
+      newfield->snext	 = current;
+      newfield->sprev	 = current->sprev;
+      newfield->snext->sprev = newfield;
+      newfield->sprev->snext = newfield;
+      if (current==head) 
+	newhead = newfield;
+    }
+  return(newhead);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Disconnect_Fields(FORM *form)
+|   
+|   Description   :  Break association between form and array of fields.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Disconnect_Fields( FORM * form )
+{
+  if (form->field)
+    {
+      FIELD **fields;
+
+      for(fields=form->field;*fields;fields++)
+	{
+	  if (form == (*fields)->form) 
+	    (*fields)->form = (FORM *)0;
+	}
+      
+      form->rows = form->cols = 0;
+      form->maxfield = form->maxpage = -1;
+      form->field = (FIELD **)0;
+      if (form->page) 
+	free(form->page);
+      form->page = (_PAGE *)0;
+    }	
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Connect_Fields(FORM *form, FIELD **fields)
+|   
+|   Description   :  Set association between form and array of fields.
+|
+|   Return Values :  E_OK            - no error
+|                    E_CONNECTED     - a field is already connected
+|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
+|                    E_SYSTEM_ERROR  - not enough memory
++--------------------------------------------------------------------------*/
+static int Connect_Fields(FORM  * form, FIELD ** fields)
+{
+  int field_cnt, j;
+  int page_nr;
+  int maximum_row_in_field, maximum_col_in_field;
+  _PAGE *pg;
+  
+  assert(form);
+
+  form->field    = fields;
+  form->maxfield = 0;
+  form->maxpage  = 0;
+
+  if (!fields)
+    RETURN(E_OK);
+  
+  page_nr = 0;
+  /* store formpointer in fields and count pages */
+  for(field_cnt=0;fields[field_cnt];field_cnt++)
+    {
+      if (fields[field_cnt]->form) 
+	RETURN(E_CONNECTED);
+      if ( field_cnt==0 || 
+	  (fields[field_cnt]->status & _NEWPAGE)) 
+	page_nr++;
+      fields[field_cnt]->form = form;
+    }	
+  if (field_cnt==0)
+    RETURN(E_BAD_ARGUMENT);
+  
+  /* allocate page structures */
+  if ( (pg = (_PAGE *)malloc(page_nr * sizeof(_PAGE))) != (_PAGE *)0 )
+    {
+      form->page = pg;
+    }
+  else
+    RETURN(E_SYSTEM_ERROR);
+  
+  /* Cycle through fields and calculate page boundaries as well as
+     size of the form */
+  for(j=0;j<field_cnt;j++)
+    {
+      if (j==0) 
+	pg->pmin = j;
+      else
+	{
+	  if (fields[j]->status & _NEWPAGE)
+	    {
+	      pg->pmax = j-1;
+	      pg++;
+	      pg->pmin = j;
+	    }
+	}
+      
+      maximum_row_in_field = fields[j]->frow + fields[j]->rows;
+      maximum_col_in_field = fields[j]->fcol + fields[j]->cols;
+      
+      if (form->rows < maximum_row_in_field) 
+	form->rows = maximum_row_in_field;
+      if (form->cols < maximum_col_in_field) 
+	form->cols = maximum_col_in_field;
+    }
+  
+  pg->pmax       = field_cnt-1;
+  form->maxfield = field_cnt;
+  form->maxpage  = page_nr; 
+  
+  /* Sort fields on form pages */
+  for(page_nr = 0;page_nr < form->maxpage; page_nr++)
+    {
+      FIELD *fld = (FIELD *)0;
+      for(j = form->page[page_nr].pmin;j <= form->page[page_nr].pmax;j++)
+	{
+	  fields[j]->index = j;
+	  fields[j]->page  = page_nr;
+	  fld = Insert_Field_By_Position(fields[j],fld);
+	}
+      form->page[page_nr].smin = fld->index;
+      form->page[page_nr].smax = fld->sprev->index;
+    }
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Associate_Fields(FORM *form, FIELD **fields)
+|   
+|   Description   :  Set association between form and array of fields. 
+|                    If there are fields, position to first active field.
+|
+|   Return Values :  E_OK            - success
+|                    any other       - error occured
++--------------------------------------------------------------------------*/
+INLINE static int Associate_Fields(FORM  *form, FIELD **fields)
+{
+  int res = Connect_Fields(form,fields);
+  if (res == E_OK)
+    {
+      if (form->maxpage>0)
+	{
+	  form->curpage = 0;
+	  form_driver(form,FIRST_ACTIVE_MAGIC);
+	}
+      else
+	{
+	  form->curpage = -1;
+	  form->current = (FIELD *)0;
+	} 
+    }
+  return(res);
+}
+			    
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FORM *new_form( FIELD **fields )
+|   
+|   Description   :  Create new form with given array of fields.
+|
+|   Return Values :  Pointer to form. NULL if error occured.
++--------------------------------------------------------------------------*/
+FORM *new_form(FIELD ** fields)
+{	
+  int err = E_SYSTEM_ERROR;
+
+  FORM *form = (FORM *)malloc(sizeof(FORM));
+  
+  if (form)
+    {
+      *form = *_nc_Default_Form;
+      if ((err=Associate_Fields(form,fields))!=E_OK)
+	{
+	  free_form(form);
+	  form = (FORM *)0;
+	}
+    }
+
+  if (!form)
+    SET_ERROR(err);
+  
+  return(form);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int free_form( FORM *form )
+|   
+|   Description   :  Release internal memory associated with form.
+|
+|   Return Values :  E_OK           - no error
+|                    E_BAD_ARGUMENT - invalid form pointer
+|                    E_POSTED       - form is posted
++--------------------------------------------------------------------------*/
+int free_form(FORM * form)
+{
+  if ( !form )	
+    RETURN(E_BAD_ARGUMENT);
+
+  if ( form->status & _POSTED)  
+    RETURN(E_POSTED);
+  
+  Disconnect_Fields( form );
+  if (form->page) 
+    free(form->page);
+  free(form);
+  
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_fields( FORM *form, FIELD **fields )
+|   
+|   Description   :  Set a new association of an array of fields to a form
+|
+|   Return Values :  E_OK              - no error
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_POSTED          - form is posted
++--------------------------------------------------------------------------*/
+int set_form_fields(FORM  * form, FIELD ** fields)
+{
+  FIELD **old;
+  int res;
+  
+  if ( !form )	
+    RETURN(E_BAD_ARGUMENT);
+
+  if ( form->status & _POSTED )	
+    RETURN(E_POSTED);
+  
+  old = form->field;
+  Disconnect_Fields( form );
+  
+  if( (res = Associate_Fields( form, fields )) != E_OK )
+    Connect_Fields( form, old );
+  
+  RETURN(res);
+}
+	
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD **form_fields( const FORM *form )
+|   
+|   Description   :  Retrieve array of fields
+|
+|   Return Values :  Pointer to field array
++--------------------------------------------------------------------------*/
+FIELD **form_fields(const FORM * form)
+{
+  return (Normalize_Form( form )->field);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int field_count( const FORM *form )
+|   
+|   Description   :  Retrieve number of fields
+|
+|   Return Values :  Number of fields, -1 if none are defined
++--------------------------------------------------------------------------*/
+int field_count(const FORM * form)
+{
+  return (Normalize_Form( form )->maxfield);
+}
+
+/* frm_def.c ends here */

+ 3843 - 0
Source/CursesDialog/form/frm_driver.c

@@ -0,0 +1,3843 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*----------------------------------------------------------------------------
+  This is the core module of the form library. It contains the majority
+  of the driver routines as well as the form_driver function. 
+
+  Essentially this module is nearly the whole library. This is because
+  all the functions in this module depends on some others in the module,
+  so it makes no sense to split them into separate files because they
+  will always be linked together. The only acceptable concern is turnaround
+  time for this module, but now we have all Pentiums or Riscs, so what!
+
+  The driver routines are grouped into nine generic categories:
+
+   a)   Page Navigation            ( all functions prefixed by PN_ )
+        The current page of the form is left and some new page is
+        entered.
+   b)   Inter-Field Navigation     ( all functions prefixed by FN_ )
+        The current field of the form is left and some new field is
+        entered.
+   c)   Intra-Field Navigation     ( all functions prefixed by IFN_ )
+        The current position in the current field is changed. 
+   d)   Vertical Scrolling         ( all functions prefixed by VSC_ )
+        Esseantially this is a specialization of Intra-Field navigation.
+        It has to check for a multi-line field.
+   e)   Horizontal Scrolling       ( all functions prefixed by HSC_ )
+        Esseantially this is a specialization of Intra-Field navigation.
+        It has to check for a single-line field.
+   f)   Field Editing              ( all functions prefixed by FE_ )
+        The content of the current field is changed
+   g)   Edit Mode requests         ( all functions prefixed by EM_ )
+        Switching between insert and overlay mode
+   h)   Field-Validation requests  ( all functions prefixed by FV_ )
+        Perform verifications of the field.
+   i)   Choice requests            ( all functions prefixed by CR_ )
+        Requests to enumerate possible field values
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Some remarks on the placements of assert() macros :
+  I use them only on "strategic" places, i.e. top level entries where
+  I want to make sure that things are set correctly. Throughout subordinate
+  routines I omit them mostly.
+  --------------------------------------------------------------------------*/
+
+/*
+Some options that may effect compatibility in behavior to SVr4 forms,
+but they are here to allow a more intuitive and user friendly behaviour of
+our form implementation. This doesn't affect the API, so we feel it is
+uncritical.
+
+The initial implementation tries to stay very close with the behaviour
+of the original SVr4 implementation, although in some areas it is quite
+clear that this isn't the most appropriate way. As far as possible this
+sources will allow you to build a forms lib that behaves quite similar
+to SVr4, but now and in the future we will give you better options. 
+Perhaps at some time we will make this configurable at runtime.
+*/
+
+/* Implement a more user-friendly previous/next word behaviour */
+#define FRIENDLY_PREV_NEXT_WORD (1)
+/* Fix the wrong behaviour for forms with all fields inactive */
+#define FIX_FORM_INACTIVE_BUG (1)
+/* Allow dynamic field growth also when navigating past the end */
+#define GROW_IF_NAVIGATE (1)
+
+/*----------------------------------------------------------------------------
+  Forward references to some internally used static functions
+  --------------------------------------------------------------------------*/
+static int Inter_Field_Navigation ( int (* const fct) (FORM *), FORM * form );
+static int FN_Next_Field (FORM * form);
+static int FN_Previous_Field (FORM * form);
+static int FE_New_Line(FORM *);
+static int FE_Delete_Previous(FORM *);
+
+/*----------------------------------------------------------------------------
+  Macro Definitions.
+
+  Some Remarks on that: I use the convention to use UPPERCASE for constants
+  defined by Macros. If I provide a macro as a kind of inline routine to
+  provide some logic, I use my Upper_Lower case style.
+  --------------------------------------------------------------------------*/
+
+/* Calculate the position of a single row in a field buffer */
+#define Position_Of_Row_In_Buffer(field,row) ((row)*(field)->dcols)
+
+/* Calculate start address for the fields buffer# N */
+#define Address_Of_Nth_Buffer(field,N) \
+  ((field)->buf + (N)*(1+Buffer_Length(field)))
+
+/* Calculate the start address of the row in the fields specified buffer# N */
+#define Address_Of_Row_In_Nth_Buffer(field,N,row) \
+  (Address_Of_Nth_Buffer(field,N) + Position_Of_Row_In_Buffer(field,row))
+
+/* Calculate the start address of the row in the fields primary buffer */
+#define Address_Of_Row_In_Buffer(field,row) \
+  Address_Of_Row_In_Nth_Buffer(field,0,row)
+
+/* Calculate the start address of the row in the forms current field
+   buffer# N */
+#define Address_Of_Current_Row_In_Nth_Buffer(form,N) \
+   Address_Of_Row_In_Nth_Buffer((form)->current,N,(form)->currow)
+
+/* Calculate the start address of the row in the forms current field
+   primary buffer */
+#define Address_Of_Current_Row_In_Buffer(form) \
+   Address_Of_Current_Row_In_Nth_Buffer(form,0)
+
+/* Calculate the address of the cursor in the forms current field
+   primary buffer */
+#define Address_Of_Current_Position_In_Nth_Buffer(form,N) \
+   (Address_Of_Current_Row_In_Nth_Buffer(form,N) + (form)->curcol)
+
+/* Calculate the address of the cursor in the forms current field
+   buffer# N */
+#define Address_Of_Current_Position_In_Buffer(form) \
+  Address_Of_Current_Position_In_Nth_Buffer(form,0)
+
+/* Logic to decide wether or not a field is actually a field with
+   vertical or horizontal scrolling */
+#define Is_Scroll_Field(field)          \
+   (((field)->drows > (field)->rows) || \
+    ((field)->dcols > (field)->cols))
+
+/* Logic to decide whether or not a field needs to have an individual window
+   instead of a derived window because it contains invisible parts.
+   This is true for non-public fields and for scrollable fields. */
+#define Has_Invisible_Parts(field)     \
+  (!((field)->opts & O_PUBLIC)      || \
+   Is_Scroll_Field(field))
+
+/* Logic to decide whether or not a field needs justification */
+#define Justification_Allowed(field)        \
+   (((field)->just != NO_JUSTIFICATION)  && \
+    (Single_Line_Field(field))           && \
+    (((field)->dcols == (field)->cols)   && \
+    ((field)->opts & O_STATIC))             )
+
+/* Logic to determine whether or not a dynamic field may still grow */
+#define Growable(field) ((field)->status & _MAY_GROW)
+
+/* Macro to set the attributes for a fields window */
+#define Set_Field_Window_Attributes(field,win) \
+(  wbkgdset((win),(chtype)((field)->pad | (field)->back)), \
+   wattrset((win),(field)->fore) )
+
+/* Logic to decide whether or not a field really appears on the form */
+#define Field_Really_Appears(field)         \
+  ((field->form)                          &&\
+   (field->form->status & _POSTED)        &&\
+   (field->opts & O_VISIBLE)              &&\
+   (field->page == field->form->curpage))
+
+/* Logic to determine whether or not we are on the first position in the
+   current field */
+#define First_Position_In_Current_Field(form) \
+  (((form)->currow==0) && ((form)->curcol==0))
+
+
+#define Minimum(a,b) (((a)<=(b)) ? (a) : (b))
+#define Maximum(a,b) (((a)>=(b)) ? (a) : (b))
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static char *Get_Start_Of_Data(char * buf, int blen)
+|   
+|   Description   :  Return pointer to first non-blank position in buffer.
+|                    If buffer is empty return pointer to buffer itself.
+|
+|   Return Values :  Pointer to first non-blank position in buffer
++--------------------------------------------------------------------------*/
+INLINE static char *Get_Start_Of_Data(char * buf, int blen)
+{
+  char *p   = buf;
+  char *end = &buf[blen];
+
+  assert(buf && blen>=0);
+  while( (p < end) && is_blank(*p) ) 
+    p++;
+  return( (p==end) ? buf : p );
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static char *After_End_Of_Data(char * buf, int blen)
+|   
+|   Description   :  Return pointer after last non-blank position in buffer.
+|                    If buffer is empty, return pointer to buffer itself.
+|
+|   Return Values :  Pointer to position after last non-blank position in 
+|                    buffer.
++--------------------------------------------------------------------------*/
+INLINE static char *After_End_Of_Data(char * buf,int blen)
+{
+  char *p   = &buf[blen];
+  
+  assert(buf && blen>=0);
+  while( (p>buf) && is_blank(p[-1]) ) 
+    p--;
+  return( p );
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static char *Get_First_Whitespace_Character(
+|                                     char * buf, int   blen)
+|   
+|   Description   :  Position to the first whitespace character.
+|
+|   Return Values :  Pointer to first whitespace character in buffer.
++--------------------------------------------------------------------------*/
+INLINE static char *Get_First_Whitespace_Character(char * buf, int blen)
+{
+  char *p   = buf;
+  char *end = &p[blen];
+  
+  assert(buf && blen>=0);
+  while( (p < end) && !is_blank(*p)) 
+    p++;
+  return( (p==end) ? buf : p );
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static char *After_Last_Whitespace_Character(
+|                                     char * buf, int blen)
+|   
+|   Description   :  Get the position after the last whitespace character.
+|
+|   Return Values :  Pointer to position after last whitespace character in 
+|                    buffer.
++--------------------------------------------------------------------------*/
+INLINE static char *After_Last_Whitespace_Character(char * buf, int blen)
+{
+  char *p   = &buf[blen];
+  
+  assert(buf && blen>=0);
+  while( (p>buf) && !is_blank(p[-1]) ) 
+    p--;
+  return( p );
+}
+
+/* Set this to 1 to use the div_t version. This is a good idea if your
+   compiler has an intrinsic div() support. Unfortunately GNU-C has it
+   not yet. 
+   N.B.: This only works if form->curcol follows immediately form->currow
+         and both are of type int. 
+*/
+#define USE_DIV_T (0)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Adjust_Cursor_Position(
+|                                       FORM * form, const char * pos)
+|   
+|   Description   :  Set current row and column of the form to values 
+|                    corresponding to the buffer position.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+INLINE static void Adjust_Cursor_Position(FORM * form, const char * pos)
+{
+  FIELD *field;
+  int idx;
+
+  field = form->current;
+  assert( pos >= field->buf && field->dcols > 0);
+  idx = (int)( pos - field->buf );
+#if USE_DIV_T
+  *((div_t *)&(form->currow)) = div(idx,field->dcols);
+#else
+  form->currow = idx / field->dcols;
+  form->curcol = idx - field->cols * form->currow;
+#endif  
+  if ( field->drows < form->currow )
+    form->currow = 0;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Buffer_To_Window(
+|                                      const FIELD  * field,
+|                                      WINDOW * win)
+|   
+|   Description   :  Copy the buffer to the window. If its a multiline
+|                    field, the buffer is split to the lines of the
+|                    window without any editing.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Buffer_To_Window(const FIELD  * field, WINDOW * win)
+{
+  int width, height;
+  int len;
+  int row;
+  char *pBuffer;
+
+  assert(win && field);
+
+  width  = getmaxx(win);
+  height = getmaxy(win);
+
+  for(row=0, pBuffer=field->buf; 
+      row < height; 
+      row++, pBuffer += width )
+    {
+      if ((len = (int)( After_End_Of_Data( pBuffer, width ) - pBuffer )) > 0)
+	{
+	  wmove( win, row, 0 );
+	  waddnstr( win, pBuffer, len );
+	}
+    }	
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Window_To_Buffer(
+|                                          WINDOW * win,
+|                                          FIELD  * field)
+|   
+|   Description   :  Copy the content of the window into the buffer.
+|                    The multiple lines of a window are simply
+|                    concatenated into the buffer. Pad characters in
+|                    the window will be replaced by blanks in the buffer.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Window_To_Buffer(WINDOW * win, FIELD  * field)
+{
+  int pad;
+  int len = 0;
+  char *p;
+  int row, height;
+  
+  assert(win && field && field->buf );
+
+  pad = field->pad;
+  p = field->buf;
+  height = getmaxy(win);
+
+  for(row=0; (row < height) && (row < field->drows); row++ )
+    {
+      wmove( win, row, 0 );
+      len += winnstr( win, p+len, field->dcols );
+    }
+  p[len] = '\0';
+
+  /* replace visual padding character by blanks in buffer */
+  if (pad != C_BLANK)
+    {
+      int i;
+      for(i=0; i<len; i++, p++)
+	{
+	  if (*p==pad) 
+	    *p = C_BLANK;
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Synchronize_Buffer(FORM * form)
+|   
+|   Description   :  If there was a change, copy the content of the
+|                    window into the buffer, so the buffer is synchronized
+|                    with the windows content. We have to indicate that the
+|                    buffer needs validation due to the change.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+INLINE static void Synchronize_Buffer(FORM * form)
+{
+  if (form->status & _WINDOW_MODIFIED)
+    {
+      form->status &= ~_WINDOW_MODIFIED;
+      form->status |=  _FCHECK_REQUIRED;
+      Window_To_Buffer(form->w,form->current);
+      wmove(form->w,form->currow,form->curcol);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Field_Grown( FIELD *field, int amount)
+|   
+|   Description   :  This function is called for growable dynamic fields
+|                    only. It has to increase the buffers and to allocate
+|                    a new window for this field.
+|                    This function has the side effect to set a new
+|                    field-buffer pointer, the dcols and drows values
+|                    as well as a new current Window for the field.
+|
+|   Return Values :  TRUE     - field successfully increased
+|                    FALSE    - there was some error
++--------------------------------------------------------------------------*/
+static bool Field_Grown(FIELD * field, int amount)
+{
+  bool result = FALSE;
+
+  if (field && Growable(field))
+    {
+      bool single_line_field = Single_Line_Field(field);
+      int old_buflen = Buffer_Length(field);
+      int new_buflen;
+      int old_dcols = field->dcols;
+      int old_drows = field->drows;
+      char *oldbuf  = field->buf;
+      char *newbuf;
+
+      int growth;
+      FORM *form = field->form;
+      bool need_visual_update = ((form != (FORM *)0)      &&
+				 (form->status & _POSTED) &&
+				 (form->current==field));
+      
+      if (need_visual_update)
+	Synchronize_Buffer(form);
+      
+      if (single_line_field)
+	{
+	  growth = field->cols * amount;
+	  if (field->maxgrow)
+	    growth = Minimum(field->maxgrow - field->dcols,growth);
+	  field->dcols += growth;
+	  if (field->dcols == field->maxgrow)
+	    field->status &= ~_MAY_GROW;
+	}
+      else
+	{
+	  growth = (field->rows + field->nrow) * amount;
+	  if (field->maxgrow)
+	    growth = Minimum(field->maxgrow - field->drows,growth);
+	  field->drows += growth;
+	  if (field->drows == field->maxgrow)
+	    field->status &= ~_MAY_GROW;
+	}
+      /* drows, dcols changed, so we get really the new buffer length */
+      new_buflen = Buffer_Length(field);
+      newbuf=(char *)malloc((size_t)Total_Buffer_Size(field));
+      if (!newbuf)
+	{ /* restore to previous state */
+	  field->dcols = old_dcols;
+	  field->drows = old_drows;
+	  if (( single_line_field && (field->dcols!=field->maxgrow)) ||
+	      (!single_line_field && (field->drows!=field->maxgrow)))
+	    field->status |= _MAY_GROW;
+	  return FALSE;
+	}
+      else
+	{ /* Copy all the buffers. This is the reason why we can't
+	     just use realloc().
+	     */
+	  int i;
+	  char *old_bp;
+	  char *new_bp;
+	  
+	  field->buf = newbuf;
+	  for(i=0;i<=field->nbuf;i++)
+	    {
+	      new_bp = Address_Of_Nth_Buffer(field,i);
+	      old_bp = oldbuf + i*(1+old_buflen);
+	      memcpy(new_bp,old_bp,(size_t)old_buflen);
+	      if (new_buflen > old_buflen)
+		memset(new_bp + old_buflen,C_BLANK,
+		       (size_t)(new_buflen - old_buflen));
+	      *(new_bp + new_buflen) = '\0';
+	    }
+
+	  if (need_visual_update)
+	    { 	      
+	      WINDOW *new_window = newpad(field->drows,field->dcols);
+	      if (!new_window)
+		{ /* restore old state */
+		  field->dcols = old_dcols;
+		  field->drows = old_drows;
+		  field->buf   = oldbuf;
+		  if (( single_line_field              && 
+			(field->dcols!=field->maxgrow)) ||
+		      (!single_line_field              && 
+		       (field->drows!=field->maxgrow)))
+		    field->status |= _MAY_GROW;
+		  free( newbuf );
+		  return FALSE;
+		}
+	      assert(form!=(FORM *)0);
+	      delwin(form->w);
+	      form->w = new_window;
+	      Set_Field_Window_Attributes(field,form->w);
+	      werase(form->w);
+	      Buffer_To_Window(field,form->w);
+	      untouchwin(form->w);
+	      wmove(form->w,form->currow,form->curcol);
+	    }
+
+	  free(oldbuf);
+	  /* reflect changes in linked fields */
+	  if (field != field->link)
+	    {
+	      FIELD *linked_field;
+	      for(linked_field = field->link;
+		  linked_field!= field;
+		  linked_field = linked_field->link)
+		{
+		  linked_field->buf   = field->buf;
+		  linked_field->drows = field->drows;
+		  linked_field->dcols = field->dcols;
+		}
+	    }
+	  result = TRUE;
+	}	
+    }
+  return(result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Position_Form_Cursor(FORM * form)
+|   
+|   Description   :  Position the cursor in the window for the current
+|                    field to be in sync. with the currow and curcol 
+|                    values.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - form has no current field or
+|                                        field-window
++--------------------------------------------------------------------------*/
+int
+_nc_Position_Form_Cursor(FORM * form)
+{
+  FIELD  *field;
+  WINDOW *formwin;
+  
+  if (!form)
+    return(E_BAD_ARGUMENT);
+
+  if (!form->w || !form->current) 
+    return(E_SYSTEM_ERROR);
+
+  field    = form->current;
+  formwin  = Get_Form_Window(form);
+
+  wmove( form->w, form->currow, form->curcol );
+  if ( Has_Invisible_Parts(field) )
+    {
+      /* in this case fieldwin isn't derived from formwin, so we have
+	 to move the cursor in formwin by hand... */
+      wmove(formwin,
+	    field->frow + form->currow - form->toprow,
+	    field->fcol + form->curcol - form->begincol);
+      wcursyncup(formwin);
+    }
+  else 
+    wcursyncup(form->w);
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Refresh_Current_Field(FORM * form)
+|   
+|   Description   :  Propagate the changes in the fields window to the
+|                    window of the form.
+|
+|   Return Values :  E_OK              - on success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_SYSTEM_ERROR    - general error
++--------------------------------------------------------------------------*/
+int
+_nc_Refresh_Current_Field(FORM * form)
+{
+  WINDOW *formwin;
+  FIELD  *field;
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!form->w || !form->current) 
+    RETURN(E_SYSTEM_ERROR);
+
+  field    = form->current;
+  formwin  = Get_Form_Window(form);
+
+  if (field->opts & O_PUBLIC)
+    {
+      if (Is_Scroll_Field(field))
+	{
+	  /* Again, in this case the fieldwin isn't derived from formwin,
+	     so we have to perform a copy operation. */
+	  if (Single_Line_Field(field))
+	    { /* horizontal scrolling */
+	      if (form->curcol < form->begincol)
+		  form->begincol = form->curcol;
+	      else
+		{
+		  if (form->curcol >= (form->begincol + field->cols))
+		      form->begincol = form->curcol - field->cols + 1;
+		}
+	      copywin(form->w,
+		      formwin,
+		      0,
+		      form->begincol,
+		      field->frow,
+		      field->fcol,
+		      field->frow,
+		      field->cols + field->fcol - 1,
+		      0);
+	    }
+	  else
+	    { /* A multiline, i.e. vertical scrolling field */
+	      int row_after_bottom,first_modified_row,first_unmodified_row;
+
+	      if (field->drows > field->rows)
+		{
+		  row_after_bottom = form->toprow + field->rows;
+		  if (form->currow < form->toprow)
+		    {
+		      form->toprow = form->currow;
+		      field->status |= _NEWTOP;
+		    }
+		  if (form->currow >= row_after_bottom)
+		    {
+		      form->toprow = form->currow - field->rows + 1;
+		      field->status |= _NEWTOP;
+		    }
+		  if (field->status & _NEWTOP)
+		    { /* means we have to copy whole range */
+		      first_modified_row = form->toprow;
+		      first_unmodified_row = first_modified_row + field->rows;
+		      field->status &= ~_NEWTOP;
+		    }
+		  else 
+		    { /* we try to optimize : finding the range of touched
+                         lines */
+		      first_modified_row = form->toprow;
+		      while(first_modified_row < row_after_bottom)
+			{
+			  if (is_linetouched(form->w,first_modified_row)) 
+			    break;
+			  first_modified_row++;
+			}
+		      first_unmodified_row = first_modified_row;
+		      while(first_unmodified_row < row_after_bottom)
+			{
+			  if (!is_linetouched(form->w,first_unmodified_row)) 
+			    break;
+			  first_unmodified_row++;
+			}
+		    }
+		}
+	      else
+		{
+		  first_modified_row   = form->toprow;
+		  first_unmodified_row = first_modified_row + field->rows;
+		}
+	      if (first_unmodified_row != first_modified_row)
+		copywin(form->w,
+			formwin,
+			first_modified_row,
+			0,
+			field->frow + first_modified_row - form->toprow,
+			field->fcol,
+			field->frow + first_unmodified_row - form->toprow - 1,
+			field->cols + field->fcol - 1,
+			0);
+	    }
+	  wsyncup(formwin);
+	}
+      else
+	{ /* if the field-window is simply a derived window, i.e. contains
+	     no invisible parts, the whole thing is trivial 
+	  */
+	  wsyncup(form->w);
+	}
+    }
+  untouchwin(form->w);
+  return _nc_Position_Form_Cursor(form);
+}
+	
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Perform_Justification(
+|                                        FIELD  * field,
+|                                        WINDOW * win)
+|   
+|   Description   :  Output field with requested justification 
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Perform_Justification(FIELD  * field, WINDOW * win)
+{
+  char *bp;
+  int len;
+  int col  = 0;
+
+  bp  = Get_Start_Of_Data(field->buf,Buffer_Length(field));
+  len = (int)(After_End_Of_Data(field->buf,Buffer_Length(field)) - bp);
+
+  if (len>0)
+    {
+      assert(win && (field->drows == 1) && (field->dcols == field->cols));
+
+      switch(field->just)
+	{
+	case JUSTIFY_LEFT:
+	  break;
+	case JUSTIFY_CENTER:
+	  col = (field->cols - len)/2;
+	  break;
+	case JUSTIFY_RIGHT:
+	  col = field->cols - len;
+	  break;
+	default:
+	  break;
+	}
+
+      wmove(win,0,col);
+      waddnstr(win,bp,len);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Undo_Justification(
+|                                     FIELD  * field,
+|                                     WINDOW * win)
+|   
+|   Description   :  Display field without any justification, i.e.
+|                    left justified
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Undo_Justification(FIELD  * field, WINDOW * win)
+{
+  char *bp;
+  int len;
+
+  bp  = Get_Start_Of_Data(field->buf,Buffer_Length(field));
+  len = (int)(After_End_Of_Data(field->buf,Buffer_Length(field))-bp);
+
+  if (len>0)
+    {
+      assert(win);
+      wmove(win,0,0);
+      waddnstr(win,bp,len);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Char(
+|                                           FIELDTYPE * typ,
+|                                           int ch,
+|                                           TypeArgument *argp)
+|   
+|   Description   :  Perform a single character check for character ch
+|                    according to the fieldtype instance.  
+|
+|   Return Values :  TRUE             - Character is valid
+|                    FALSE            - Character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Char(FIELDTYPE * typ, int ch, TypeArgument *argp)
+{
+  if (typ) 
+    {
+      if (typ->status & _LINKED_TYPE)
+	{
+	  assert(argp);
+	  return(
+	    Check_Char(typ->left ,ch,argp->left ) ||
+	    Check_Char(typ->right,ch,argp->right) );
+	} 
+      else 
+	{
+	  if (typ->ccheck)
+	    return typ->ccheck(ch,(void *)argp);
+	}
+    }
+  return (isprint((unsigned char)ch) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Display_Or_Erase_Field(
+|                                           FIELD * field,
+|                                           bool bEraseFlag)
+|   
+|   Description   :  Create a subwindow for the field and display the
+|                    buffer contents (apply justification if required)
+|                    or simply erase the field.
+|
+|   Return Values :  E_OK           - on success
+|                    E_SYSTEM_ERROR - some error (typical no memory)
++--------------------------------------------------------------------------*/
+static int Display_Or_Erase_Field(FIELD * field, bool bEraseFlag)
+{
+  WINDOW *win;
+  WINDOW *fwin;
+
+  if (!field)
+    return E_SYSTEM_ERROR;
+
+  fwin = Get_Form_Window(field->form);
+  win  = derwin(fwin,
+		field->rows,field->cols,field->frow,field->fcol);
+
+  if (!win) 
+    return E_SYSTEM_ERROR;
+  else
+    {
+      if (field->opts & O_VISIBLE)
+	Set_Field_Window_Attributes(field,win);
+      else
+	wattrset(win,getattrs(fwin));
+      werase(win);
+    }
+
+  if (!bEraseFlag)
+    {
+      if (field->opts & O_PUBLIC)
+	{
+	  if (Justification_Allowed(field))
+	    Perform_Justification(field,win);
+	  else
+	    Buffer_To_Window(field,win);
+	}
+      field->status &= ~_NEWTOP;
+    }
+  wsyncup(win);
+  delwin(win);
+  return E_OK;
+}
+
+/* Macros to preset the bEraseFlag */
+#define Display_Field(field) Display_Or_Erase_Field(field,FALSE)
+#define Erase_Field(field)   Display_Or_Erase_Field(field,TRUE)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Synchronize_Field(FIELD * field)
+|   
+|   Description   :  Synchronize the windows content with the value in
+|                    the buffer.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer 
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+static int Synchronize_Field(FIELD * field)
+{
+  FORM *form;
+  int res = E_OK;
+
+  if (!field)
+    return(E_BAD_ARGUMENT);
+
+  if (((form=field->form) != (FORM *)0)
+      && Field_Really_Appears(field))
+    {
+      if (field == form->current)
+	{ 
+	  form->currow  = form->curcol = form->toprow = form->begincol = 0;
+	  werase(form->w);
+      
+	  if ( (field->opts & O_PUBLIC) && Justification_Allowed(field) )
+	    Undo_Justification( field, form->w );
+	  else
+	    Buffer_To_Window( field, form->w );
+	  
+	  field->status |= _NEWTOP;
+	  res = _nc_Refresh_Current_Field( form );
+	}
+      else
+	res = Display_Field( field );
+    }
+  field->status |= _CHANGED;
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Synchronize_Linked_Fields(FIELD * field)
+|   
+|   Description   :  Propagate the Synchronize_Field function to all linked
+|                    fields. The first error that occurs in the sequence
+|                    of updates is the returnvalue.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer 
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+static int Synchronize_Linked_Fields(FIELD * field)
+{
+  FIELD *linked_field;
+  int res = E_OK;
+  int syncres;
+
+  if (!field)
+    return(E_BAD_ARGUMENT);
+
+  if (!field->link)
+    return(E_SYSTEM_ERROR);
+
+  for(linked_field = field->link; 
+      linked_field!= field;
+      linked_field = linked_field->link )
+    {
+      if (((syncres=Synchronize_Field(linked_field)) != E_OK) &&
+	  (res==E_OK))
+	res = syncres;
+    }
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Synchronize_Attributes(FIELD * field)
+|   
+|   Description   :  If a fields visual attributes have changed, this
+|                    routine is called to propagate those changes to the
+|                    screen.  
+|
+|   Return Values :  E_OK             - success
+|                    E_BAD_ARGUMENT   - invalid field pointer
+|                    E_SYSTEM_ERROR   - some severe basic error
++--------------------------------------------------------------------------*/
+int _nc_Synchronize_Attributes(FIELD * field)
+{
+  FORM *form;
+  int res = E_OK;
+  WINDOW *formwin;
+
+  if (!field)
+    return(E_BAD_ARGUMENT);
+
+  if (((form=field->form) != (FORM *)0)
+      && Field_Really_Appears(field))
+    {    
+      if (form->current==field)
+	{
+	  Synchronize_Buffer(form);
+	  Set_Field_Window_Attributes(field,form->w);
+	  werase(form->w);
+	  if (field->opts & O_PUBLIC)
+	    {
+	      if (Justification_Allowed(field))
+		Undo_Justification(field,form->w);
+	      else 
+		Buffer_To_Window(field,form->w);
+	    }
+	  else 
+	    {
+	      formwin = Get_Form_Window(form); 
+	      copywin(form->w,formwin,
+		      0,0,
+		      field->frow,field->fcol,
+		      field->rows-1,field->cols-1,0);
+	      wsyncup(formwin);
+	      Buffer_To_Window(field,form->w);
+	      field->status |= _NEWTOP; /* fake refresh to paint all */
+	      _nc_Refresh_Current_Field(form);
+	    }
+	}
+      else 
+	{
+	  res = Display_Field(field);
+	}
+    }
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Synchronize_Options(FIELD * field,
+|                                                Field_Options newopts)
+|   
+|   Description   :  If a fields options have changed, this routine is
+|                    called to propagate these changes to the screen and
+|                    to really change the behaviour of the field.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid field pointer 
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+int
+_nc_Synchronize_Options(FIELD *field, Field_Options newopts)
+{
+  Field_Options oldopts;
+  Field_Options changed_opts;
+  FORM *form;
+  int res = E_OK;
+
+  if (!field)
+    return(E_BAD_ARGUMENT);
+
+  oldopts      = field->opts;
+  changed_opts = oldopts ^ newopts;
+  field->opts  = newopts;
+  form         = field->form;
+
+  if (form)
+    {
+      if (form->current == field)
+	{
+	  field->opts = oldopts;
+	  return(E_CURRENT);
+	}
+
+      if (form->status & _POSTED)
+	{
+	  if ((form->curpage == field->page))
+	    {
+	      if (changed_opts & O_VISIBLE)
+		{
+		  if (newopts & O_VISIBLE)
+		    res = Display_Field(field);
+		  else
+		    res = Erase_Field(field);
+		}
+	      else
+		{
+		  if ((changed_opts & O_PUBLIC) &&
+		      (newopts & O_VISIBLE))
+		    res = Display_Field(field);
+		}
+	    }
+	}
+    }
+
+  if (changed_opts & O_STATIC)
+    {
+      bool single_line_field = Single_Line_Field(field);
+      int res2 = E_OK;
+
+      if (newopts & O_STATIC)
+	{ /* the field becomes now static */
+	  field->status &= ~_MAY_GROW;
+	  /* if actually we have no hidden columns, justification may
+	     occur again */
+	  if (single_line_field                 &&
+	      (field->cols == field->dcols)     &&
+	      (field->just != NO_JUSTIFICATION) &&
+	      Field_Really_Appears(field))
+	    {
+	      res2 = Display_Field(field);
+	    }
+	}
+      else
+	{ /* field is no longer static */
+	  if ((field->maxgrow==0) ||
+	      ( single_line_field && (field->dcols < field->maxgrow)) ||
+	      (!single_line_field && (field->drows < field->maxgrow)))
+	    {
+	      field->status |= _MAY_GROW;
+	      /* a field with justification now changes its behaviour,
+		 so we must redisplay it */
+	      if (single_line_field                 &&
+		  (field->just != NO_JUSTIFICATION) &&
+		  Field_Really_Appears(field))
+		{
+		  res2 = Display_Field(field);
+		}	 
+	    }     
+	}
+      if (res2 != E_OK)
+	res = res2;
+    }
+
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Set_Current_Field(FORM  * form,
+|                                              FIELD * newfield)
+|   
+|   Description   :  Make the newfield the new current field.
+|
+|   Return Values :  E_OK                - success
+|                    E_BAD_ARGUMENT      - invalid form or field pointer 
+|                    E_SYSTEM_ERROR      - some severe basic error
++--------------------------------------------------------------------------*/
+int
+_nc_Set_Current_Field(FORM  *form, FIELD *newfield)
+{
+  FIELD  *field;
+  WINDOW *new_window;
+
+  if (!form || !newfield || !form->current || (newfield->form!=form))
+    return(E_BAD_ARGUMENT);
+
+  if ( (form->status & _IN_DRIVER) )
+    return(E_BAD_STATE);
+
+  if (!(form->field))
+    return(E_NOT_CONNECTED);
+
+  field = form->current;
+ 
+  if ((field!=newfield) || 
+      !(form->status & _POSTED))
+    {
+      if ((form->w) && 
+	  (field->opts & O_VISIBLE) &&
+	  (field->form->curpage == field->page))
+	{
+	  _nc_Refresh_Current_Field(form);
+	  if (field->opts & O_PUBLIC)
+	    {
+	      if (field->drows > field->rows)
+		{
+		  if (form->toprow==0)
+		    field->status &= ~_NEWTOP;
+		  else 
+		    field->status |= _NEWTOP;
+		} 
+	      else 
+		{
+		  if (Justification_Allowed(field))
+		    {
+		      Window_To_Buffer(form->w,field);
+		      werase(form->w);
+		      Perform_Justification(field,form->w);
+		      wsyncup(form->w);
+		    }
+		}
+	    }
+	  delwin(form->w);
+	}
+      
+      field = newfield;
+
+      if (Has_Invisible_Parts(field))
+	new_window = newpad(field->drows,field->dcols);
+      else 
+	new_window = derwin(Get_Form_Window(form),
+			    field->rows,field->cols,field->frow,field->fcol);
+
+      if (!new_window) 
+	return(E_SYSTEM_ERROR);
+
+      form->current = field;
+      form->w       = new_window;
+      form->status &= ~_WINDOW_MODIFIED;
+      Set_Field_Window_Attributes(field,form->w);
+
+      if (Has_Invisible_Parts(field))
+	{
+	  werase(form->w);
+	  Buffer_To_Window(field,form->w);
+	} 
+      else 
+	{
+	  if (Justification_Allowed(field))
+	    {
+	      werase(form->w);
+	      Undo_Justification(field,form->w);
+	      wsyncup(form->w);
+	    }
+	}
+
+      untouchwin(form->w);
+    }
+
+  form->currow = form->curcol = form->toprow = form->begincol = 0;
+  return(E_OK);
+}
+
+/*----------------------------------------------------------------------------
+  Intra-Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Next_Character(FORM * form)
+|   
+|   Description   :  Move to the next character in the field. In a multiline
+|                    field this wraps at the end of the line.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the rightmost position
++--------------------------------------------------------------------------*/
+static int IFN_Next_Character(FORM * form)
+{
+  FIELD *field = form->current;
+  
+  if ((++(form->curcol))==field->dcols)
+    {
+      if ((++(form->currow))==field->drows)
+	{
+#if GROW_IF_NAVIGATE
+	  if (!Single_Line_Field(field) && Field_Grown(field,1)) {
+	    form->curcol = 0;
+	    return(E_OK);
+	  }
+#endif
+	  form->currow--;
+#if GROW_IF_NAVIGATE
+	  if (Single_Line_Field(field) && Field_Grown(field,1))
+	    return(E_OK);
+#endif
+	  form->curcol--;
+	  return(E_REQUEST_DENIED);
+	}
+      form->curcol = 0;
+    }
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Previous_Character(FORM * form)
+|   
+|   Description   :  Move to the previous character in the field. In a 
+|                    multiline field this wraps and the beginning of the 
+|                    line.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the leftmost position
++--------------------------------------------------------------------------*/
+static int IFN_Previous_Character(FORM * form)
+{
+  if ((--(form->curcol))<0)
+    {
+      if ((--(form->currow))<0)
+	{
+	  form->currow++;
+	  form->curcol++;
+	  return(E_REQUEST_DENIED);
+	}
+      form->curcol = form->current->dcols - 1;
+    }
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Next_Line(FORM * form)
+|   
+|   Description   :  Move to the beginning of the next line in the field
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the last line
++--------------------------------------------------------------------------*/
+static int IFN_Next_Line(FORM * form)
+{
+  FIELD *field = form->current;
+
+  if ((++(form->currow))==field->drows)
+    {
+#if GROW_IF_NAVIGATE
+      if (!Single_Line_Field(field) && Field_Grown(field,1))
+	return(E_OK);
+#endif
+      form->currow--;
+      return(E_REQUEST_DENIED);
+    }
+  form->curcol = 0;
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Previous_Line(FORM * form)
+|   
+|   Description   :  Move to the beginning of the previous line in the field
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - at the first line
++--------------------------------------------------------------------------*/
+static int IFN_Previous_Line(FORM * form)
+{
+  if ( (--(form->currow)) < 0 )
+    {
+      form->currow++;
+      return(E_REQUEST_DENIED);
+    }
+  form->curcol = 0;
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Next_Word(FORM * form)
+|   
+|   Description   :  Move to the beginning of the next word in the field.
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - there is no next word
++--------------------------------------------------------------------------*/
+static int IFN_Next_Word(FORM * form)
+{
+  FIELD *field = form->current;
+  char  *bp    = Address_Of_Current_Position_In_Buffer(form);
+  char  *s;
+  char  *t;
+
+  /* We really need access to the data, so we have to synchronize */
+  Synchronize_Buffer(form);
+
+  /* Go to the first whitespace after the current position (including
+     current position). This is then the startpoint to look for the
+    next non-blank data */
+  s = Get_First_Whitespace_Character(bp,Buffer_Length(field) -
+				     (int)(bp - field->buf));
+
+  /* Find the start of the next word */
+  t = Get_Start_Of_Data(s,Buffer_Length(field) -
+			(int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+  if (s==t) 
+    return(E_REQUEST_DENIED);
+  else
+#endif
+    {
+      Adjust_Cursor_Position(form,t);
+      return(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Previous_Word(FORM * form)
+|   
+|   Description   :  Move to the beginning of the previous word in the field.
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - there is no previous word
++--------------------------------------------------------------------------*/
+static int IFN_Previous_Word(FORM * form)
+{
+  FIELD *field = form->current;
+  char  *bp    = Address_Of_Current_Position_In_Buffer(form);
+  char  *s;
+  char  *t;
+  bool  again = FALSE;
+
+  /* We really need access to the data, so we have to synchronize */
+  Synchronize_Buffer(form);
+
+  s = After_End_Of_Data(field->buf,(int)(bp-field->buf));
+  /* s points now right after the last non-blank in the buffer before bp.
+     If bp was in a word, s equals bp. In this case we must find the last
+     whitespace in the buffer before bp and repeat the game to really find
+     the previous word! */
+  if (s==bp)
+    again = TRUE;
+  
+  /* And next call now goes backward to look for the last whitespace
+     before that, pointing right after this, so it points to the begin
+     of the previous word. 
+  */
+  t = After_Last_Whitespace_Character(field->buf,(int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+  if (s==t) 
+    return(E_REQUEST_DENIED);
+#endif
+  if (again)
+    { /* and do it again, replacing bp by t */
+      s = After_End_Of_Data(field->buf,(int)(t - field->buf));
+      t = After_Last_Whitespace_Character(field->buf,(int)(s - field->buf));
+#if !FRIENDLY_PREV_NEXT_WORD
+      if (s==t) 
+	return(E_REQUEST_DENIED);
+#endif
+    }
+  Adjust_Cursor_Position(form,t);
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Beginning_Of_Field(FORM * form)
+|   
+|   Description   :  Place the cursor at the first non-pad character in
+|                    the field. 
+|
+|   Return Values :  E_OK             - success            
++--------------------------------------------------------------------------*/
+static int IFN_Beginning_Of_Field(FORM * form)
+{
+  FIELD *field = form->current;
+
+  Synchronize_Buffer(form);
+  Adjust_Cursor_Position(form,
+		 Get_Start_Of_Data(field->buf,Buffer_Length(field)));
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_End_Of_Field(FORM * form)
+|   
+|   Description   :  Place the cursor after the last non-pad character in
+|                    the field. If the field occupies the last position in
+|                    the buffer, the cursos is positioned on the last 
+|                    character.
+|
+|   Return Values :  E_OK              - success
++--------------------------------------------------------------------------*/
+static int IFN_End_Of_Field(FORM * form)
+{
+  FIELD *field = form->current;
+  char *pos;
+
+  Synchronize_Buffer(form);
+  pos = After_End_Of_Data(field->buf,Buffer_Length(field));
+  if (pos==(field->buf + Buffer_Length(field)))
+    pos--;
+  Adjust_Cursor_Position(form,pos);
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Beginning_Of_Line(FORM * form)
+|   
+|   Description   :  Place the cursor on the first non-pad character in
+|                    the current line of the field.
+|
+|   Return Values :  E_OK         - success
++--------------------------------------------------------------------------*/
+static int IFN_Beginning_Of_Line(FORM * form)
+{
+  FIELD *field = form->current;
+
+  Synchronize_Buffer(form);
+  Adjust_Cursor_Position(form,
+		 Get_Start_Of_Data(Address_Of_Current_Row_In_Buffer(form),
+				   field->dcols));
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_End_Of_Line(FORM * form)
+|   
+|   Description   :  Place the cursor after the last non-pad character in the
+|                    current line of the field. If the field occupies the 
+|                    last column in the line, the cursor is positioned on the
+|                    last character of the line.
+|
+|   Return Values :  E_OK        - success
++--------------------------------------------------------------------------*/
+static int IFN_End_Of_Line(FORM * form)
+{
+  FIELD *field = form->current;
+  char *pos;
+  char *bp;
+
+  Synchronize_Buffer(form);
+  bp  = Address_Of_Current_Row_In_Buffer(form); 
+  pos = After_End_Of_Data(bp,field->dcols);
+  if (pos == (bp + field->dcols))
+    pos--;
+  Adjust_Cursor_Position(form,pos);
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Left_Character(FORM * form)
+|   
+|   Description   :  Move one character to the left in the current line.
+|                    This doesn't cycle.  
+|
+|   Return Values :  E_OK             - success
+|                    E_REQUEST_DENIED - already in first column
++--------------------------------------------------------------------------*/
+static int IFN_Left_Character(FORM * form)
+{
+  if ( (--(form->curcol)) < 0 )
+    {
+      form->curcol++;
+      return(E_REQUEST_DENIED);
+    }
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Right_Character(FORM * form)
+|   
+|   Description   :  Move one character to the right in the current line.
+|                    This doesn't cycle.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int IFN_Right_Character(FORM * form)
+{
+  if ( (++(form->curcol)) == form->current->dcols )
+    {
+#if GROW_IF_NAVIGATE
+      FIELD *field = form->current;
+      if (Single_Line_Field(field) && Field_Grown(field,1))
+	return(E_OK);
+#endif
+      --(form->curcol);
+      return(E_REQUEST_DENIED);
+    }
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Up_Character(FORM * form)
+|   
+|   Description   :  Move one line up. This doesn't cycle through the lines
+|                    of the field.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int IFN_Up_Character(FORM * form)
+{
+  if ( (--(form->currow)) < 0 )
+    {
+      form->currow++;
+      return(E_REQUEST_DENIED);
+    }
+  return(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int IFN_Down_Character(FORM * form)
+|   
+|   Description   :  Move one line down. This doesn't cycle through the
+|                    lines of the field.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - already in last column
++--------------------------------------------------------------------------*/
+static int IFN_Down_Character(FORM * form)
+{
+  FIELD *field = form->current;
+
+  if ( (++(form->currow)) == field->drows )
+    {
+#if GROW_IF_NAVIGATE
+      if (!Single_Line_Field(field) && Field_Grown(field,1))
+	return(E_OK);
+#endif
+      --(form->currow);
+      return(E_REQUEST_DENIED);
+    }
+  return(E_OK);
+}
+/*----------------------------------------------------------------------------
+  END of Intra-Field Navigation routines 
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Vertical scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Generic(FORM *form, int lines)
+|
+|   Description   :  Scroll multi-line field forward (lines>0) or
+|                    backward (lines<0) this many lines.
+|
+|   Return Values :  E_OK              - success 
+|                    E_REQUEST_DENIED  - can't scroll
++--------------------------------------------------------------------------*/
+static int VSC_Generic(FORM *form, int lines)
+{
+  FIELD *field = form->current;
+  int res = E_REQUEST_DENIED;
+  int rows_to_go = (lines > 0 ? lines : -lines);
+
+  if (lines > 0)
+    {
+      if ( (rows_to_go + form->toprow) > (field->drows - field->rows) )
+	rows_to_go = (field->drows - field->rows - form->toprow);
+
+      if (rows_to_go > 0)
+	{
+	  form->currow += rows_to_go;
+	  form->toprow += rows_to_go;
+	  res = E_OK;
+	}
+    }
+  else
+    {
+      if (rows_to_go > form->toprow)
+	rows_to_go = form->toprow;
+      
+      if (rows_to_go > 0)
+	{
+	  form->currow -= rows_to_go;
+	  form->toprow -= rows_to_go;
+	  res = E_OK;
+	}
+    }
+  return(res);
+}
+/*----------------------------------------------------------------------------
+  End of Vertical scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Vertical scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Vertical_Scrolling(
+|                                           int (* const fct) (FORM *),
+|                                           FORM * form)
+|   
+|   Description   :  Performs the generic vertical scrolling routines. 
+|                    This has to check for a multi-line field and to set
+|                    the _NEWTOP flag if scrolling really occured.
+|
+|   Return Values :  Propagated error code from low-level driver calls
++--------------------------------------------------------------------------*/
+static int Vertical_Scrolling(int (* const fct) (FORM *), FORM * form)
+{
+  int res = E_REQUEST_DENIED;
+
+  if (!Single_Line_Field(form->current))
+    {
+      res = fct(form);
+      if (res == E_OK)
+	form->current->status |= _NEWTOP;
+    }
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Line_Forward(FORM * form)
+|   
+|   Description   :  Scroll multi-line field forward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Line_Forward(FORM * form)
+{
+  return VSC_Generic(form,1);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Line_Backward(FORM * form)
+|   
+|   Description   :  Scroll multi-line field backward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Line_Backward(FORM * form)
+{
+  return VSC_Generic(form,-1);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Page_Forward(FORM * form)
+|   
+|   Description   :  Scroll a multi-line field forward a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data ahead
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Page_Forward(FORM * form)
+{
+  return VSC_Generic(form,form->current->rows);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Half_Page_Forward(FORM * form)
+|   
+|   Description   :  Scroll a multi-line field forward half a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data ahead
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Half_Page_Forward(FORM * form)
+{
+  return VSC_Generic(form,(form->current->rows + 1)/2);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Page_Backward(FORM * form)
+|   
+|   Description   :  Scroll a multi-line field backward a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data behind
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Page_Backward(FORM * form)
+{
+  return VSC_Generic(form, -(form->current->rows));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int VSC_Scroll_Half_Page_Backward(FORM * form)
+|   
+|   Description   :  Scroll a multi-line field backward half a page
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - no data behind
++--------------------------------------------------------------------------*/
+static int VSC_Scroll_Half_Page_Backward(FORM * form)
+{
+  return VSC_Generic(form, -((form->current->rows + 1)/2));
+}
+/*----------------------------------------------------------------------------
+  End of Vertical scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Horizontal scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Generic(FORM *form, int columns)
+|
+|   Description   :  Scroll single-line field forward (columns>0) or
+|                    backward (columns<0) this many columns.
+|
+|   Return Values :  E_OK              - success 
+|                    E_REQUEST_DENIED  - can't scroll
++--------------------------------------------------------------------------*/
+static int HSC_Generic(FORM *form, int columns)
+{
+  FIELD *field = form->current;
+  int res = E_REQUEST_DENIED;
+  int cols_to_go = (columns > 0 ? columns : -columns);
+
+  if (columns > 0)
+    {
+      if ((cols_to_go + form->begincol) > (field->dcols - field->cols))
+	cols_to_go = field->dcols - field->cols - form->begincol;
+      
+      if (cols_to_go > 0)
+	{
+	  form->curcol   += cols_to_go;
+	  form->begincol += cols_to_go;
+	  res = E_OK;
+	}
+    }
+  else
+    {
+      if ( cols_to_go > form->begincol )
+	cols_to_go = form->begincol;
+
+      if (cols_to_go > 0)
+	{
+	  form->curcol   -= cols_to_go;
+	  form->begincol -= cols_to_go;
+	  res = E_OK;
+	}
+    }
+  return(res);
+}
+/*----------------------------------------------------------------------------
+  End of Horizontal scrolling helper routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Horizontal scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Horizontal_Scrolling(
+|                                          int (* const fct) (FORM *),
+|                                          FORM * form)
+|   
+|   Description   :  Performs the generic horizontal scrolling routines. 
+|                    This has to check for a single-line field.
+|
+|   Return Values :  Propagated error code from low-level driver calls
++--------------------------------------------------------------------------*/
+static int Horizontal_Scrolling(int (* const fct) (FORM *), FORM * form)
+{
+  if (Single_Line_Field(form->current))
+    return fct(form);
+  else
+    return(E_REQUEST_DENIED);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Scroll_Char_Forward(FORM * form)
+|   
+|   Description   :  Scroll single-line field forward a character
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int HSC_Scroll_Char_Forward(FORM *form)
+{
+  return HSC_Generic(form,1);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Scroll_Char_Backward(FORM * form)
+|   
+|   Description   :  Scroll single-line field backward a character
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int HSC_Scroll_Char_Backward(FORM *form)
+{
+  return HSC_Generic(form,-1);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Horizontal_Line_Forward(FORM* form)
+|   
+|   Description   :  Scroll single-line field forward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data ahead
++--------------------------------------------------------------------------*/
+static int HSC_Horizontal_Line_Forward(FORM * form)
+{
+  return HSC_Generic(form,form->current->cols);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Horizontal_Half_Line_Forward(FORM* form)
+|   
+|   Description   :  Scroll single-line field forward half a line
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - no data ahead
++--------------------------------------------------------------------------*/
+static int HSC_Horizontal_Half_Line_Forward(FORM * form)
+{
+  return HSC_Generic(form,(form->current->cols + 1)/2);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Horizontal_Line_Backward(FORM* form)
+|   
+|   Description   :  Scroll single-line field backward a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int HSC_Horizontal_Line_Backward(FORM * form)
+{
+  return HSC_Generic(form,-(form->current->cols));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int HSC_Horizontal_Half_Line_Backward(FORM* form)
+|   
+|   Description   :  Scroll single-line field backward half a line
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - no data behind
++--------------------------------------------------------------------------*/
+static int HSC_Horizontal_Half_Line_Backward(FORM * form)
+{
+  return HSC_Generic(form,-((form->current->cols + 1)/2));
+}
+
+/*----------------------------------------------------------------------------
+  End of Horizontal scrolling routines
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Field Editing
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Is_There_Room_For_A_Line(FORM * form)
+|   
+|   Description   :  Check whether or not there is enough room in the
+|                    buffer to enter a whole line.
+|
+|   Return Values :  TRUE   - there is enough space
+|                    FALSE  - there is not enough space
++--------------------------------------------------------------------------*/
+INLINE static bool Is_There_Room_For_A_Line(FORM * form)
+{
+  FIELD *field = form->current;
+  char *begin_of_last_line, *s;
+  
+  Synchronize_Buffer(form);
+  begin_of_last_line = Address_Of_Row_In_Buffer(field,(field->drows-1));
+  s  = After_End_Of_Data(begin_of_last_line,field->dcols);
+  return ((s==begin_of_last_line) ? TRUE : FALSE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Is_There_Room_For_A_Char_In_Line(FORM * form)
+|   
+|   Description   :  Checks whether or not there is room for a new character
+|                    in the current line.
+|
+|   Return Values :  TRUE    - there is room
+|                    FALSE   - there is not enough room (line full)
++--------------------------------------------------------------------------*/
+INLINE static bool Is_There_Room_For_A_Char_In_Line(FORM * form)
+{
+  int last_char_in_line;
+
+  wmove(form->w,form->currow,form->current->dcols-1);
+  last_char_in_line  = (int)(winch(form->w) & A_CHARTEXT);
+  wmove(form->w,form->currow,form->curcol);
+  return (((last_char_in_line == form->current->pad) ||
+	   is_blank(last_char_in_line)) ? TRUE : FALSE);
+}
+
+#define There_Is_No_Room_For_A_Char_In_Line(f) \
+  !Is_There_Room_For_A_Char_In_Line(f)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Insert_String(
+|                                             FORM * form,
+|                                             int row,
+|                                             char *txt,
+|                                             int  len )
+|   
+|   Description   :  Insert the 'len' characters beginning at pointer 'txt'
+|                    into the 'row' of the 'form'. The insertion occurs
+|                    on the beginning of the row, all other characters are
+|                    moved to the right. After the text a pad character will 
+|                    be inserted to separate the text from the rest. If
+|                    necessary the insertion moves characters on the next
+|                    line to make place for the requested insertion string.
+|
+|   Return Values :  E_OK              - success 
+|                    E_REQUEST_DENIED  -
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+static int Insert_String(FORM *form, int row, char *txt, int len)
+{ 
+  FIELD  *field    = form->current;
+  char *bp         = Address_Of_Row_In_Buffer(field,row);
+  int datalen      = (int)(After_End_Of_Data(bp,field->dcols) - bp);
+  int freelen      = field->dcols - datalen;
+  int requiredlen  = len+1;
+  char *split;
+  int result = E_REQUEST_DENIED;
+  const char *Space = " ";
+
+  if (freelen >= requiredlen)
+    {
+      wmove(form->w,row,0);
+      winsnstr(form->w,txt,len);
+      wmove(form->w,row,len);
+      winsnstr(form->w,Space,1);
+      return E_OK;
+    }
+  else
+    { /* we have to move characters on the next line. If we are on the
+	 last line this may work, if the field is growable */
+      if ((row == (field->drows - 1)) && Growable(field))
+	{
+	  if (!Field_Grown(field,1))
+	    return(E_SYSTEM_ERROR);
+	  /* !!!Side-Effect : might be changed due to growth!!! */
+	  bp = Address_Of_Row_In_Buffer(field,row); 
+	}
+
+      if (row < (field->drows - 1)) 
+	{ 
+	  split = After_Last_Whitespace_Character(bp,
+		    (int)(Get_Start_Of_Data(bp + field->dcols - requiredlen ,
+					    requiredlen) - bp));
+	  /* split points now to the first character of the portion of the
+	     line that must be moved to the next line */
+	  datalen = (int)(split-bp); /* + freelen has to stay on this line   */
+	  freelen = field->dcols - (datalen + freelen); /* for the next line */
+
+	  if ((result=Insert_String(form,row+1,split,freelen))==E_OK) 
+	    {
+	      wmove(form->w,row,datalen);
+	      wclrtoeol(form->w);
+	      wmove(form->w,row,0);
+	      winsnstr(form->w,txt,len);
+	      wmove(form->w,row,len);
+	      winsnstr(form->w,Space,1);
+	      return E_OK;
+	    }
+	}
+      return(result);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Wrapping_Not_Necessary_Or_Wrapping_Ok(
+|                                             FORM * form)
+|   
+|   Description   :  If a character has been entered into a field, it may
+|                    be that wrapping has to occur. This routine checks
+|                    whether or not wrapping is required and if so, performs
+|                    the wrapping.
+|
+|   Return Values :  E_OK              - no wrapping required or wrapping
+|                                        was successfull
+|                    E_REQUEST_DENIED  -
+|                    E_SYSTEM_ERROR    - some system error
++--------------------------------------------------------------------------*/
+static int Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM * form)
+{
+  FIELD  *field = form->current;
+  int result = E_REQUEST_DENIED;
+  bool Last_Row = ((field->drows - 1) == form->currow);
+
+  if ( (field->opts & O_WRAP)                     &&  /* wrapping wanted     */
+      (!Single_Line_Field(field))                 &&  /* must be multi-line  */
+      (There_Is_No_Room_For_A_Char_In_Line(form)) &&  /* line is full        */
+      (!Last_Row || Growable(field))               )  /* there are more lines*/
+    {
+      char *bp;
+      char *split;
+      int chars_to_be_wrapped;
+      int chars_to_remain_on_line;
+      if (Last_Row)
+	{ /* the above logic already ensures, that in this case the field
+	     is growable */
+	  if (!Field_Grown(field,1))
+	    return E_SYSTEM_ERROR;
+	}
+      bp = Address_Of_Current_Row_In_Buffer(form);
+      Window_To_Buffer(form->w,field);
+      split = After_Last_Whitespace_Character(bp,field->dcols);
+      /* split points to the first character of the sequence to be brought
+         on the next line */
+      chars_to_remain_on_line = (int)(split - bp);
+      chars_to_be_wrapped     = field->dcols - chars_to_remain_on_line;
+      if (chars_to_remain_on_line > 0)
+	{
+	  if ((result=Insert_String(form,form->currow+1,split,
+				    chars_to_be_wrapped)) == E_OK)
+	    {
+	      wmove(form->w,form->currow,chars_to_remain_on_line);
+	      wclrtoeol(form->w);
+	      if (form->curcol >= chars_to_remain_on_line)
+		{
+		  form->currow++;
+		  form->curcol -= chars_to_remain_on_line;
+		}
+	      return E_OK;
+	    }
+	}
+      else
+	return E_OK;
+      if (result!=E_OK)
+	{
+	  wmove(form->w,form->currow,form->curcol);
+	  wdelch(form->w);
+	  Window_To_Buffer(form->w,field);
+	  result = E_REQUEST_DENIED;
+	}
+    }
+  else
+    result = E_OK; /* wrapping was not necessary */
+  return(result);
+}
+
+/*----------------------------------------------------------------------------
+  Field Editing routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Field_Editing(
+|                                    int (* const fct) (FORM *),
+|                                    FORM * form)
+|   
+|   Description   :  Generic routine for field editing requests. The driver
+|                    routines are only called for editable fields, the
+|                    _WINDOW_MODIFIED flag is set if editing occured.
+|                    This is somewhat special due to the overload semantics
+|                    of the NEW_LINE and DEL_PREV requests.
+|
+|   Return Values :  Error code from low level drivers.
++--------------------------------------------------------------------------*/
+static int Field_Editing(int (* const fct) (FORM *), FORM * form)
+{
+  int res = E_REQUEST_DENIED;
+
+  /* We have to deal here with the specific case of the overloaded 
+     behaviour of New_Line and Delete_Previous requests.
+     They may end up in navigational requests if we are on the first
+     character in a field. But navigation is also allowed on non-
+     editable fields.
+  */ 
+  if ((fct==FE_Delete_Previous)            && 
+      (form->opts & O_BS_OVERLOAD)         &&
+      First_Position_In_Current_Field(form) )
+    {
+      res = Inter_Field_Navigation(FN_Previous_Field,form);
+    }
+  else
+    {
+      if (fct==FE_New_Line)
+	{
+	  if ((form->opts & O_NL_OVERLOAD)         &&
+	      First_Position_In_Current_Field(form))
+	    {
+	      res = Inter_Field_Navigation(FN_Next_Field,form);
+	    }
+	  else
+	    /* FE_New_Line deals itself with the _WINDOW_MODIFIED flag */
+	    res = fct(form);
+	}
+      else
+	{
+	  /* From now on, everything must be editable */
+	  if (form->current->opts & O_EDIT)
+	    {
+	      res = fct(form);
+	      if (res==E_OK)
+		form->status |= _WINDOW_MODIFIED;
+	    }
+	}
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_New_Line(FORM * form)
+|   
+|   Description   :  Perform a new line request. This is rather complex
+|                    compared to other routines in this code due to the 
+|                    rather difficult to understand description in the
+|                    manuals.
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - new line not allowed
+|                    E_SYSTEM_ERROR     - system error
++--------------------------------------------------------------------------*/
+static int FE_New_Line(FORM * form)
+{
+  FIELD  *field = form->current;
+  char *bp, *t;
+  bool Last_Row = ((field->drows - 1)==form->currow);
+  
+  if (form->status & _OVLMODE) 
+    {
+      if (Last_Row && 
+	  (!(Growable(field) && !Single_Line_Field(field))))
+	{
+	  if (!(form->opts & O_NL_OVERLOAD))
+	    return(E_REQUEST_DENIED);
+	  wclrtoeol(form->w);
+	  /* we have to set this here, although it is also
+	     handled in the generic routine. The reason is,
+	     that FN_Next_Field may fail, but the form is
+	     definitively changed */
+	  form->status |= _WINDOW_MODIFIED;
+	  return Inter_Field_Navigation(FN_Next_Field,form);
+	}
+      else 
+	{
+	  if (Last_Row && !Field_Grown(field,1))
+	    { /* N.B.: due to the logic in the 'if', LastRow==TRUE
+		 means here that the field is growable and not
+		 a single-line field */
+	      return(E_SYSTEM_ERROR);
+	    }
+	  wclrtoeol(form->w);
+	  form->currow++;
+	  form->curcol = 0;
+	  form->status |= _WINDOW_MODIFIED;
+	  return(E_OK);
+	}
+    }
+  else 
+    { /* Insert Mode */
+      if (Last_Row &&
+	  !(Growable(field) && !Single_Line_Field(field)))
+	{
+	  if (!(form->opts & O_NL_OVERLOAD))
+	    return(E_REQUEST_DENIED);
+	  return Inter_Field_Navigation(FN_Next_Field,form);
+	}
+      else 
+	{
+	  bool May_Do_It = !Last_Row && Is_There_Room_For_A_Line(form);
+	  
+	  if (!(May_Do_It || Growable(field)))
+	    return(E_REQUEST_DENIED);
+	  if (!May_Do_It && !Field_Grown(field,1))
+	    return(E_SYSTEM_ERROR);
+	  
+	  bp= Address_Of_Current_Position_In_Buffer(form);
+	  t = After_End_Of_Data(bp,field->dcols - form->curcol);
+	  wclrtoeol(form->w);
+	  form->currow++;
+	  form->curcol=0;
+	  wmove(form->w,form->currow,form->curcol);
+	  winsertln(form->w);
+	  waddnstr(form->w,bp,(int)(t-bp));
+	  form->status |= _WINDOW_MODIFIED;
+	  return E_OK;
+	}
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Insert_Character(FORM * form)
+|   
+|   Description   :  Insert blank character at the cursor position
+|
+|   Return Values :  E_OK
+|                    E_REQUEST_DENIED
++--------------------------------------------------------------------------*/
+static int FE_Insert_Character(FORM * form)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  if (Check_Char(field->type,(int)C_BLANK,(TypeArgument *)(field->arg)))
+    {
+      bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
+
+      if (There_Is_Room ||
+	  ((Single_Line_Field(field) && Growable(field))))
+	{
+	  if (!There_Is_Room && !Field_Grown(field,1))
+	    result =  E_SYSTEM_ERROR;
+	  else
+	    {
+	      winsch(form->w,(chtype)C_BLANK);
+	      result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form);
+	    }
+	}
+    }
+  return result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Insert_Line(FORM * form)
+|   
+|   Description   :  Insert a blank line at the cursor position
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - line can not be inserted
++--------------------------------------------------------------------------*/
+static int FE_Insert_Line(FORM * form)
+{
+  FIELD *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  if (Check_Char(field->type,(int)C_BLANK,(TypeArgument *)(field->arg)))
+    {
+      bool Maybe_Done = (form->currow!=(field->drows-1)) && 
+	                Is_There_Room_For_A_Line(form);
+
+      if (!Single_Line_Field(field) &&
+	  (Maybe_Done || Growable(field)))
+	{
+	  if (!Maybe_Done && !Field_Grown(field,1))
+	    result = E_SYSTEM_ERROR;
+	  else
+	    {
+	      form->curcol = 0;
+	      winsertln(form->w);
+	      result = E_OK;
+	    }
+	}
+    }
+  return result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Delete_Character(FORM * form)
+|   
+|   Description   :  Delete character at the cursor position
+|
+|   Return Values :  E_OK    - success
++--------------------------------------------------------------------------*/
+static int FE_Delete_Character(FORM * form)
+{
+  wdelch(form->w);
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Delete_Previous(FORM * form)
+|   
+|   Description   :  Delete character before cursor. Again this is a rather
+|                    difficult piece compared to others due to the overloading
+|                    semantics of backspace.
+|                    N.B.: The case of overloaded BS on first field position
+|                          is already handled in the generic routine.
+|
+|   Return Values :  E_OK                - success
+|                    E_REQUEST_DENIED    - Character can't be deleted
++--------------------------------------------------------------------------*/
+static int FE_Delete_Previous(FORM * form)
+{
+  FIELD  *field = form->current;
+  
+  if (First_Position_In_Current_Field(form))
+    return E_REQUEST_DENIED;
+
+  if ( (--(form->curcol))<0 )
+    {
+      char *this_line, *prev_line, *prev_end, *this_end;
+      
+      form->curcol++;
+      if (form->status & _OVLMODE) 
+	return E_REQUEST_DENIED;
+      
+      prev_line = Address_Of_Row_In_Buffer(field,(form->currow-1));
+      this_line = Address_Of_Row_In_Buffer(field,(form->currow));
+      Synchronize_Buffer(form);
+      prev_end = After_End_Of_Data(prev_line,field->dcols);
+      this_end = After_End_Of_Data(this_line,field->dcols);
+      if ((int)(this_end-this_line) > 
+	  (field->cols-(int)(prev_end-prev_line))) 
+	return E_REQUEST_DENIED;
+      wdeleteln(form->w);
+      Adjust_Cursor_Position(form,prev_end);
+      wmove(form->w,form->currow,form->curcol);
+      waddnstr(form->w,this_line,(int)(this_end-this_line));
+    } 
+  else 
+    {
+      wmove(form->w,form->currow,form->curcol);
+      wdelch(form->w);
+    }
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Delete_Line(FORM * form)
+|   
+|   Description   :  Delete line at cursor position.
+|
+|   Return Values :  E_OK  - success
++--------------------------------------------------------------------------*/
+static int FE_Delete_Line(FORM * form)
+{
+  form->curcol = 0;
+  wdeleteln(form->w);
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Delete_Word(FORM * form)
+|   
+|   Description   :  Delete word at cursor position
+|
+|   Return Values :  E_OK               - success
+|                    E_REQUEST_DENIED   - failure
++--------------------------------------------------------------------------*/
+static int FE_Delete_Word(FORM * form)
+{
+  FIELD  *field = form->current;
+  char   *bp = Address_Of_Current_Row_In_Buffer(form);
+  char   *ep = bp + field->dcols;
+  char   *cp = bp + form->curcol;
+  char *s;
+  
+  Synchronize_Buffer(form);
+  if (is_blank(*cp)) 
+    return E_REQUEST_DENIED; /* not in word */
+
+  /* move cursor to begin of word and erase to end of screen-line */
+  Adjust_Cursor_Position(form,
+			 After_Last_Whitespace_Character(bp,form->curcol)); 
+  wmove(form->w,form->currow,form->curcol);
+  wclrtoeol(form->w);
+
+  /* skip over word in buffer */
+  s = Get_First_Whitespace_Character(cp,(int)(ep-cp)); 
+  /* to begin of next word    */
+  s = Get_Start_Of_Data(s,(int)(ep - s));
+  if ( (s!=cp) && !is_blank(*s))
+    {
+      /* copy remaining line to window */
+      waddnstr(form->w,s,(int)(s - After_End_Of_Data(s,(int)(ep - s))));
+    }
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Clear_To_End_Of_Line(FORM * form)
+|   
+|   Description   :  Clear to end of current line.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int FE_Clear_To_End_Of_Line(FORM * form)
+{
+  wclrtoeol(form->w);
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Clear_To_End_Of_Form(FORM * form)
+|   
+|   Description   :  Clear to end of form.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int FE_Clear_To_End_Of_Form(FORM * form)
+{
+  wclrtobot(form->w);
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FE_Clear_Field(FORM * form)
+|   
+|   Description   :  Clear entire field.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int FE_Clear_Field(FORM * form)
+{
+  form->currow = form->curcol = 0;
+  werase(form->w);
+  return E_OK;
+}
+/*----------------------------------------------------------------------------
+  END of Field Editing routines 
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Edit Mode routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int EM_Overlay_Mode(FORM * form)
+|   
+|   Description   :  Switch to overlay mode.
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int EM_Overlay_Mode(FORM * form)
+{
+  form->status |= _OVLMODE;
+  return E_OK;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int EM_Insert_Mode(FORM * form)
+|   
+|   Description   :  Switch to insert mode
+|
+|   Return Values :  E_OK   - success
++--------------------------------------------------------------------------*/
+static int EM_Insert_Mode(FORM * form)
+{
+  form->status &= ~_OVLMODE;
+  return E_OK;
+}
+
+/*----------------------------------------------------------------------------
+  END of Edit Mode routines 
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Next_Choice(
+|                                            FIELDTYPE * typ,
+|                                            FIELD * field,
+|                                            TypeArgument *argp)
+|   
+|   Description   :  Get the next field choice. For linked types this is
+|                    done recursively.
+|
+|   Return Values :  TRUE    - next choice successfully retrieved
+|                    FALSE   - couldn't retrieve next choice
++--------------------------------------------------------------------------*/
+static bool Next_Choice(FIELDTYPE * typ, FIELD *field, TypeArgument *argp)
+{
+  if (!typ || !(typ->status & _HAS_CHOICE)) 
+    return FALSE;
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      assert(argp);
+      return(
+	     Next_Choice(typ->left ,field,argp->left) ||
+	     Next_Choice(typ->right,field,argp->right) );
+    } 
+  else
+    {
+      assert(typ->next);
+      return typ->next(field,(void *)argp);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Previous_Choice(
+|                                                FIELDTYPE * typ,
+|                                                FIELD * field,
+|                                                TypeArgument *argp)
+|   
+|   Description   :  Get the previous field choice. For linked types this
+|                    is done recursively.
+|
+|   Return Values :  TRUE    - previous choice successfully retrieved
+|                    FALSE   - couldn't retrieve previous choice
++--------------------------------------------------------------------------*/
+static bool Previous_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+{
+  if (!typ || !(typ->status & _HAS_CHOICE)) 
+    return FALSE;
+
+  if (typ->status & _LINKED_TYPE)
+    {
+      assert(argp);
+      return(
+	     Previous_Choice(typ->left ,field,argp->left) ||
+	     Previous_Choice(typ->right,field,argp->right));
+    } 
+  else 
+    {
+      assert(typ->prev);
+      return typ->prev(field,(void *)argp);
+    }
+}
+/*----------------------------------------------------------------------------
+  End of Helper routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int CR_Next_Choice(FORM * form)
+|   
+|   Description   :  Get the next field choice.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - next choice couldn't be retrieved
++--------------------------------------------------------------------------*/
+static int CR_Next_Choice(FORM * form)
+{
+  FIELD *field = form->current;
+  Synchronize_Buffer(form);
+  return ((Next_Choice(field->type,field,(TypeArgument *)(field->arg))) ? 
+	  E_OK : E_REQUEST_DENIED);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int CR_Previous_Choice(FORM * form)
+|   
+|   Description   :  Get the previous field choice.
+|
+|   Return Values :  E_OK              - success
+|                    E_REQUEST_DENIED  - prev. choice couldn't be retrieved
++--------------------------------------------------------------------------*/
+static int CR_Previous_Choice(FORM * form)
+{
+  FIELD *field = form->current;
+  Synchronize_Buffer(form);
+  return ((Previous_Choice(field->type,field,(TypeArgument *)(field->arg))) ? 
+	  E_OK : E_REQUEST_DENIED);
+}
+/*----------------------------------------------------------------------------
+  End of Routines for Choice Requests
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Field Validations.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Field(
+|                                            FIELDTYPE * typ,
+|                                            FIELD * field,
+|                                            TypeArgument * argp)
+|   
+|   Description   :  Check the field according to its fieldtype and its
+|                    actual arguments. For linked fieldtypes this is done
+|                    recursively.
+|
+|   Return Values :  TRUE       - field is valid
+|                    FALSE      - field is invalid.
++--------------------------------------------------------------------------*/
+static bool Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp)
+{
+  if (typ)
+    {
+      if (field->opts & O_NULLOK)
+	{
+	  char *bp = field->buf;
+	  assert(bp);
+	  while(is_blank(*bp))
+	    { bp++; }
+	  if (*bp == '\0') 
+	    return TRUE;
+	}
+
+      if (typ->status & _LINKED_TYPE)
+	{
+	  assert(argp);
+	  return( 
+		 Check_Field(typ->left ,field,argp->left ) ||
+		 Check_Field(typ->right,field,argp->right) );
+	}
+      else 
+	{
+	  if (typ->fcheck)
+	    return typ->fcheck(field,(void *)argp);
+	}
+    }
+  return TRUE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  bool _nc_Internal_Validation(FORM * form )
+|   
+|   Description   :  Validate the current field of the form.  
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+bool
+_nc_Internal_Validation(FORM *form)
+{
+  FIELD *field;
+
+  field = form->current; 
+  
+  Synchronize_Buffer(form);
+  if ((form->status & _FCHECK_REQUIRED) ||
+      (!(field->opts & O_PASSOK)))
+    {
+      if (!Check_Field(field->type,field,(TypeArgument *)(field->arg)))
+	return FALSE;
+      form->status  &= ~_FCHECK_REQUIRED;
+      field->status |= _CHANGED;
+      Synchronize_Linked_Fields(field);
+    }
+  return TRUE;
+}
+/*----------------------------------------------------------------------------
+  End of Helper routines for Field Validations.
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Routines for Field Validation.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FV_Validation(FORM * form)
+|   
+|   Description   :  Validate the current field of the form.
+|
+|   Return Values :  E_OK             - field valid
+|                    E_INVALID_FIELD  - field not valid
++--------------------------------------------------------------------------*/
+static int FV_Validation(FORM * form)
+{
+  if (_nc_Internal_Validation(form))
+    return E_OK;
+  else
+    return E_INVALID_FIELD;
+}
+/*----------------------------------------------------------------------------
+  End of routines for Field Validation.
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Inter-Field Navigation
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Next_Field_On_Page(FIELD * field)
+|   
+|   Description   :  Get the next field after the given field on the current 
+|                    page. The order of fields is the one defined by the
+|                    fields array. Only visible and active fields are
+|                    counted.
+|
+|   Return Values :  Pointer to the next field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Next_Field_On_Page(FIELD * field)
+{
+  FORM  *form = field->form;
+  FIELD **field_on_page = &form->field[field->index];
+  FIELD **first_on_page = &form->field[form->page[form->curpage].pmin];
+  FIELD **last_on_page  = &form->field[form->page[form->curpage].pmax];
+
+  do
+    {
+      field_on_page = 
+	(field_on_page==last_on_page) ? first_on_page : field_on_page + 1;
+      if (Field_Is_Selectable(*field_on_page))
+	break;
+    } while(field!=(*field_on_page));  
+  return(*field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  FIELD* _nc_First_Active_Field(FORM * form)
+|   
+|   Description   :  Get the first active field on the current page,
+|                    if there are such. If there are none, get the first
+|                    visible field on the page. If there are also none,
+|                    we return the first field on page and hope the best.
+|
+|   Return Values :  Pointer to calculated field.
++--------------------------------------------------------------------------*/
+FIELD*
+_nc_First_Active_Field(FORM * form)
+{
+  FIELD **last_on_page = &form->field[form->page[form->curpage].pmax];
+  FIELD *proposed = Next_Field_On_Page(*last_on_page);
+
+  if (proposed == *last_on_page)
+    { /* there might be the special situation, where there is no 
+	 active and visible field on the current page. We then select
+	 the first visible field on this readonly page
+      */
+      if (Field_Is_Not_Selectable(proposed))
+	{
+	  FIELD **field = &form->field[proposed->index];
+	  FIELD **first = &form->field[form->page[form->curpage].pmin];
+
+	  do
+	    {
+	      field = (field==last_on_page) ? first : field + 1;
+	      if (((*field)->opts & O_VISIBLE))
+		break;
+	    } while(proposed!=(*field));
+	  
+	  proposed = *field;
+
+	  if ((proposed == *last_on_page) && !(proposed->opts&O_VISIBLE))
+	    { /* This means, there is also no visible field on the page.
+		 So we propose the first one and hope the very best... 
+		 Some very clever user has designed a readonly and invisible
+		 page on this form.
+	       */
+	      proposed = *first;
+	    }
+	}
+    }
+  return(proposed);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Previous_Field_On_Page(FIELD * field)
+|   
+|   Description   :  Get the previous field before the given field on the 
+|                    current page. The order of fields is the one defined by 
+|                    the fields array. Only visible and active fields are
+|                    counted.
+|
+|   Return Values :  Pointer to the previous field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Previous_Field_On_Page(FIELD * field)
+{
+  FORM  *form   = field->form;
+  FIELD **field_on_page = &form->field[field->index];
+  FIELD **first_on_page = &form->field[form->page[form->curpage].pmin];
+  FIELD **last_on_page  = &form->field[form->page[form->curpage].pmax];
+  
+  do
+    {
+      field_on_page = 
+	(field_on_page==first_on_page) ? last_on_page : field_on_page - 1;
+      if (Field_Is_Selectable(*field_on_page))
+	break;
+    } while(field!=(*field_on_page));
+  
+  return (*field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Sorted_Next_Field(FIELD * field)
+|   
+|   Description   :  Get the next field after the given field on the current 
+|                    page. The order of fields is the one defined by the
+|                    (row,column) geometry, rows are major.
+|
+|   Return Values :  Pointer to the next field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Sorted_Next_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+
+  do
+    {
+      field_on_page = field_on_page->snext;
+      if (Field_Is_Selectable(field_on_page))
+	break;
+    } while(field_on_page!=field);
+  
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Sorted_Previous_Field(FIELD * field)
+|   
+|   Description   :  Get the previous field before the given field on the 
+|                    current page. The order of fields is the one defined 
+|                    by the (row,column) geometry, rows are major.
+|
+|   Return Values :  Pointer to the previous field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Sorted_Previous_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+
+  do
+    {
+      field_on_page = field_on_page->sprev;
+      if (Field_Is_Selectable(field_on_page))
+	break;
+    } while(field_on_page!=field);
+  
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Left_Neighbour_Field(FIELD * field)
+|   
+|   Description   :  Get the left neighbour of the field on the same line
+|                    and the same page. Cycles through the line.
+|
+|   Return Values :  Pointer to left neighbour field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Left_Neighbour_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+
+  /* For a field that has really a left neighbour, the while clause
+     immediately fails and the loop is left, positioned at the right
+     neighbour. Otherwise we cycle backwards through the sorted fieldlist
+     until we enter the same line (from the right end).
+  */
+  do
+    {
+      field_on_page = Sorted_Previous_Field(field_on_page);
+    } while(field_on_page->frow != field->frow);
+  
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Right_Neighbour_Field(FIELD * field)
+|   
+|   Description   :  Get the right neighbour of the field on the same line
+|                    and the same page.
+|
+|   Return Values :  Pointer to right neighbour field.
++--------------------------------------------------------------------------*/
+INLINE static FIELD *Right_Neighbour_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+
+  /* See the comments on Left_Neighbour_Field to understand how it works */
+  do
+    {
+      field_on_page = Sorted_Next_Field(field_on_page);
+    } while(field_on_page->frow != field->frow);
+  
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Upper_Neighbour_Field(FIELD * field)
+|   
+|   Description   :  Because of the row-major nature of sorting the fields,
+|                    its more difficult to define whats the upper neighbour
+|                    field really means. We define that it must be on a
+|                    'previous' line (cyclic order!) and is the rightmost
+|                    field laying on the left side of the given field. If
+|                    this set is empty, we take the first field on the line.
+|
+|   Return Values :  Pointer to the upper neighbour field.
++--------------------------------------------------------------------------*/
+static FIELD *Upper_Neighbour_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+  int frow = field->frow;
+  int fcol = field->fcol;
+
+  /* Walk back to the 'previous' line. The second term in the while clause
+     just guarantees that we stop if we cycled through the line because
+     there might be no 'previous' line if the page has just one line.
+  */
+  do
+    {
+      field_on_page = Sorted_Previous_Field(field_on_page);
+    } while(field_on_page->frow==frow && field_on_page->fcol!=fcol);
+  
+  if (field_on_page->frow!=frow)
+    { /* We really found a 'previous' line. We are positioned at the
+         rightmost field on this line */
+      frow = field_on_page->frow; 
+
+      /* We walk to the left as long as we are really right of the 
+	 field. */
+      while(field_on_page->frow==frow && field_on_page->fcol>fcol)
+	field_on_page = Sorted_Previous_Field(field_on_page);
+
+      /* If we wrapped, just go to the right which is the first field on 
+	 the row */
+      if (field_on_page->frow!=frow)
+	field_on_page = Sorted_Next_Field(field_on_page);
+    }
+  
+  return (field_on_page);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static FIELD *Down_Neighbour_Field(FIELD * field)
+|   
+|   Description   :  Because of the row-major nature of sorting the fields,
+|                    its more difficult to define whats the down neighbour
+|                    field really means. We define that it must be on a
+|                    'next' line (cyclic order!) and is the leftmost
+|                    field laying on the right side of the given field. If
+|                    this set is empty, we take the last field on the line.
+|
+|   Return Values :  Pointer to the upper neighbour field.
++--------------------------------------------------------------------------*/
+static FIELD *Down_Neighbour_Field(FIELD * field)
+{
+  FIELD *field_on_page = field;
+  int frow = field->frow;
+  int fcol = field->fcol;
+
+  /* Walk forward to the 'next' line. The second term in the while clause
+     just guarantees that we stop if we cycled through the line because
+     there might be no 'next' line if the page has just one line.
+  */
+  do
+    {
+      field_on_page = Sorted_Next_Field(field_on_page);
+    } while(field_on_page->frow==frow && field_on_page->fcol!=fcol);
+
+  if (field_on_page->frow!=frow)
+    { /* We really found a 'next' line. We are positioned at the rightmost
+         field on this line */
+      frow = field_on_page->frow;
+
+      /* We walk to the right as long as we are really left of the 
+	 field. */
+      while(field_on_page->frow==frow && field_on_page->fcol<fcol)
+	field_on_page = Sorted_Next_Field(field_on_page);
+
+      /* If we wrapped, just go to the left which is the last field on 
+	 the row */
+      if (field_on_page->frow!=frow)
+	field_on_page = Sorted_Previous_Field(field_on_page);
+    }
+  
+  return(field_on_page);
+}
+
+/*----------------------------------------------------------------------------
+  Inter-Field Navigation routines
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Inter_Field_Navigation(
+|                                           int (* const fct) (FORM *),
+|                                           FORM * form)
+|   
+|   Description   :  Generic behaviour for changing the current field, the
+|                    field is left and a new field is entered. So the field
+|                    must be validated and the field init/term hooks must
+|                    be called.
+|
+|   Return Values :  E_OK                - success
+|                    E_INVALID_FIELD     - field is invalid
+|                    some other          - error from subordinate call
++--------------------------------------------------------------------------*/
+static int Inter_Field_Navigation(int (* const fct) (FORM *),FORM *form)
+{
+  int res;
+
+  if (!_nc_Internal_Validation(form)) 
+    res = E_INVALID_FIELD;
+  else
+    {
+      Call_Hook(form,fieldterm);
+      res = fct(form);
+      Call_Hook(form,fieldinit);
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Next_Field(FORM * form)
+|   
+|   Description   :  Move to the next field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Next_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Next_Field_On_Page(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Previous_Field(FORM * form)
+|   
+|   Description   :  Move to the previous field on the current page of the 
+|                    form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Previous_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Previous_Field_On_Page(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_First_Field(FORM * form)
+|   
+|   Description   :  Move to the first field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_First_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+      Next_Field_On_Page(form->field[form->page[form->curpage].pmax]));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Last_Field(FORM * form)
+|   
+|   Description   :  Move to the last field on the current page of the form
+|
+|   Return Values :  E_OK                 - success
+|                    != E_OK              - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Last_Field(FORM * form)
+{
+  return 
+    _nc_Set_Current_Field(form,
+       Previous_Field_On_Page(form->field[form->page[form->curpage].pmin]));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Sorted_Next_Field(FORM * form)
+|   
+|   Description   :  Move to the sorted next field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Sorted_Next_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Sorted_Next_Field(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Sorted_Previous_Field(FORM * form)
+|   
+|   Description   :  Move to the sorted previous field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Sorted_Previous_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Sorted_Previous_Field(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Sorted_First_Field(FORM * form)
+|   
+|   Description   :  Move to the sorted first field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Sorted_First_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+	      Sorted_Next_Field(form->field[form->page[form->curpage].smax]));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Sorted_Last_Field(FORM * form)
+|   
+|   Description   :  Move to the sorted last field on the current page
+|                    of the form.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Sorted_Last_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+	   Sorted_Previous_Field(form->field[form->page[form->curpage].smin]));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Left_Field(FORM * form)
+|   
+|   Description   :  Get the field on the left of the current field on the
+|                    same line and the same page. Cycles through the line.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Left_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Left_Neighbour_Field(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Right_Field(FORM * form)
+|   
+|   Description   :  Get the field on the right of the current field on the
+|                    same line and the same page. Cycles through the line.
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Right_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Right_Neighbour_Field(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Up_Field(FORM * form)
+|   
+|   Description   :  Get the upper neighbour of the current field. This
+|                    cycles through the page. See the comments of the
+|                    Upper_Neighbour_Field function to understand how
+|                    'upper' is defined. 
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Up_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Upper_Neighbour_Field(form->current));
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int FN_Down_Field(FORM * form)
+|   
+|   Description   :  Get the down neighbour of the current field. This
+|                    cycles through the page. See the comments of the
+|                    Down_Neighbour_Field function to understand how
+|                    'down' is defined. 
+|
+|   Return Values :  E_OK            - success
+|                    != E_OK         - error from subordinate call
++--------------------------------------------------------------------------*/
+static int FN_Down_Field(FORM * form)
+{
+  return _nc_Set_Current_Field(form,
+			       Down_Neighbour_Field(form->current));
+}
+/*----------------------------------------------------------------------------
+  END of Field Navigation routines 
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for Page Navigation
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_Set_Form_Page(FORM * form,
+|                                          int page,
+|                                          FIELD * field)
+|   
+|   Description   :  Make the given page nr. the current page and make
+|                    the given field the current field on the page. If
+|                    for the field NULL is given, make the first field on
+|                    the page the current field. The routine acts only
+|                    if the requested page is not the current page.
+|
+|   Return Values :  E_OK                - success
+|                    != E_OK             - error from subordinate call
++--------------------------------------------------------------------------*/
+int
+_nc_Set_Form_Page(FORM * form, int page, FIELD * field)
+{
+  int res = E_OK;
+
+  if ((form->curpage!=page))
+    {
+      FIELD *last_field, *field_on_page;
+
+      werase(Get_Form_Window(form));
+      form->curpage = page;
+      last_field = field_on_page = form->field[form->page[page].smin];
+      do
+	{
+	  if (field_on_page->opts & O_VISIBLE)
+	    if ((res=Display_Field(field_on_page))!=E_OK) 
+	      return(res);
+	  field_on_page = field_on_page->snext;
+	} while(field_on_page != last_field);
+
+      if (field)
+	res = _nc_Set_Current_Field(form,field);
+      else
+	/* N.B.: we don't encapsulate this by Inter_Field_Navigation(),
+	   because this is already executed in a page navigation
+	   context that contains field navigation 
+	 */
+	res = FN_First_Field(form);
+    }
+  return(res);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Next_Page_Number(const FORM * form)
+|   
+|   Description   :  Calculate the page number following the current page
+|                    number. This cycles if the highest page number is
+|                    reached.  
+|
+|   Return Values :  The next page number
++--------------------------------------------------------------------------*/
+INLINE static int Next_Page_Number(const FORM * form)
+{
+  return (form->curpage + 1) % form->maxpage;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Previous_Page_Number(const FORM * form)
+|   
+|   Description   :  Calculate the page number before the current page
+|                    number. This cycles if the first page number is
+|                    reached.  
+|
+|   Return Values :  The previous page number
++--------------------------------------------------------------------------*/
+INLINE static int Previous_Page_Number(const FORM * form)
+{
+  return (form->curpage!=0 ? form->curpage - 1 : form->maxpage - 1);
+}
+
+/*----------------------------------------------------------------------------
+  Page Navigation routines 
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Page_Navigation(
+|                                               int (* const fct) (FORM *),
+|                                               FORM * form)
+|   
+|   Description   :  Generic behaviour for changing a page. This means
+|                    that the field is left and a new field is entered.
+|                    So the field must be validated and the field init/term
+|                    hooks must be called. Because also the page is changed,
+|                    the forms init/term hooks must be called also.
+|
+|   Return Values :  E_OK                - success
+|                    E_INVALID_FIELD     - field is invalid
+|                    some other          - error from subordinate call
++--------------------------------------------------------------------------*/
+static int Page_Navigation(int (* const fct) (FORM *), FORM * form)
+{
+  int res;
+
+  if (!_nc_Internal_Validation(form)) 
+    res = E_INVALID_FIELD;
+  else
+    {
+      Call_Hook(form,fieldterm);
+      Call_Hook(form,formterm);
+      res = fct(form);
+      Call_Hook(form,forminit);
+      Call_Hook(form,fieldinit);
+    }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int PN_Next_Page(FORM * form)
+|   
+|   Description   :  Move to the next page of the form
+|
+|   Return Values :  E_OK                - success
+|                    != E_OK             - error from subordinate call
++--------------------------------------------------------------------------*/
+static int PN_Next_Page(FORM * form)
+{ 
+  return _nc_Set_Form_Page(form,Next_Page_Number(form),(FIELD *)0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int PN_Previous_Page(FORM * form)
+|   
+|   Description   :  Move to the previous page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int PN_Previous_Page(FORM * form)
+{
+  return _nc_Set_Form_Page(form,Previous_Page_Number(form),(FIELD *)0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int PN_First_Page(FORM * form)
+|   
+|   Description   :  Move to the first page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int PN_First_Page(FORM * form)
+{
+  return _nc_Set_Form_Page(form,0,(FIELD *)0);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int PN_Last_Page(FORM * form)
+|   
+|   Description   :  Move to the last page of the form
+|
+|   Return Values :  E_OK              - success
+|                    != E_OK           - error from subordinate call
++--------------------------------------------------------------------------*/
+static int PN_Last_Page(FORM * form)
+{
+  return _nc_Set_Form_Page(form,form->maxpage-1,(FIELD *)0);
+}
+/*----------------------------------------------------------------------------
+  END of Field Navigation routines 
+  --------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  Helper routines for the core form driver.
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Data_Entry(FORM * form,int c)
+|   
+|   Description   :  Enter character c into at the current position of the
+|                    current field of the form.
+|
+|   Return Values :  E_OK              -
+|                    E_REQUEST_DENIED  -
+|                    E_SYSTEM_ERROR    -
++--------------------------------------------------------------------------*/
+static int Data_Entry(FORM * form, int c)
+{
+  FIELD  *field = form->current;
+  int result = E_REQUEST_DENIED;
+
+  if ( (field->opts & O_EDIT) 
+#if FIX_FORM_INACTIVE_BUG
+       && (field->opts & O_ACTIVE) 
+#endif
+       )
+    {
+      if ( (field->opts & O_BLANK) &&
+	   First_Position_In_Current_Field(form) &&
+	   !(form->status & _FCHECK_REQUIRED) && 
+	   !(form->status & _WINDOW_MODIFIED) )
+	werase(form->w);
+
+      if (form->status & _OVLMODE)
+	{
+	  waddch(form->w,(chtype)c);
+	} 
+      else /* no _OVLMODE */ 
+	{
+	  bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form);
+
+	  if (!(There_Is_Room ||
+		((Single_Line_Field(field) && Growable(field)))))
+	      return E_REQUEST_DENIED;
+
+	  if (!There_Is_Room && !Field_Grown(field,1))
+	    return E_SYSTEM_ERROR;
+
+	  winsch(form->w,(chtype)c);
+	}
+
+      if ((result=Wrapping_Not_Necessary_Or_Wrapping_Ok(form))==E_OK)
+	{
+	  bool End_Of_Field= (((field->drows-1)==form->currow) &&
+			      ((field->dcols-1)==form->curcol));
+	  form->status |= _WINDOW_MODIFIED;
+	  if (End_Of_Field && !Growable(field) && (field->opts & O_AUTOSKIP))
+	    result = Inter_Field_Navigation(FN_Next_Field,form);
+	  else
+	    {
+	      if (End_Of_Field && Growable(field) && !Field_Grown(field,1))
+		result = E_SYSTEM_ERROR;
+	      else
+		{
+		  IFN_Next_Character(form);
+		  result = E_OK;
+		}
+	    }
+	}
+    }
+  return result;
+}
+
+/* Structure to describe the binding of a request code to a function.
+   The member keycode codes the request value as well as the generic
+   routine to use for the request. The code for the generic routine
+   is coded in the upper 16 Bits while the request code is coded in
+   the lower 16 bits. 
+
+   In terms of C++ you might think of a request as a class with a
+   virtual method "perform". The different types of request are
+   derived from this base class and overload (or not) the base class
+   implementation of perform.
+*/
+typedef struct {
+  int keycode;           /* must be at least 32 bit: hi:mode, lo: key */
+  int (*cmd)(FORM *);    /* low level driver routine for this key     */
+} Binding_Info;
+
+/* You may see this is the class-id of the request type class */
+#define ID_PN    (0x00000000)    /* Page navigation           */
+#define ID_FN    (0x00010000)    /* Inter-Field navigation    */
+#define ID_IFN   (0x00020000)    /* Intra-Field navigation    */
+#define ID_VSC   (0x00030000)    /* Vertical Scrolling        */
+#define ID_HSC   (0x00040000)    /* Horizontal Scrolling      */
+#define ID_FE    (0x00050000)    /* Field Editing             */
+#define ID_EM    (0x00060000)    /* Edit Mode                 */
+#define ID_FV    (0x00070000)    /* Field Validation          */
+#define ID_CH    (0x00080000)    /* Choice                    */
+#define ID_Mask  (0xffff0000)
+#define Key_Mask (0x0000ffff)
+#define ID_Shft  (16)
+
+/* This array holds all the Binding Infos */
+static const Binding_Info bindings[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] = 
+{
+  { REQ_NEXT_PAGE    |ID_PN  ,PN_Next_Page},
+  { REQ_PREV_PAGE    |ID_PN  ,PN_Previous_Page},
+  { REQ_FIRST_PAGE   |ID_PN  ,PN_First_Page},
+  { REQ_LAST_PAGE    |ID_PN  ,PN_Last_Page},
+  
+  { REQ_NEXT_FIELD   |ID_FN  ,FN_Next_Field},
+  { REQ_PREV_FIELD   |ID_FN  ,FN_Previous_Field},
+  { REQ_FIRST_FIELD  |ID_FN  ,FN_First_Field},
+  { REQ_LAST_FIELD   |ID_FN  ,FN_Last_Field},
+  { REQ_SNEXT_FIELD  |ID_FN  ,FN_Sorted_Next_Field},
+  { REQ_SPREV_FIELD  |ID_FN  ,FN_Sorted_Previous_Field},
+  { REQ_SFIRST_FIELD |ID_FN  ,FN_Sorted_First_Field},
+  { REQ_SLAST_FIELD  |ID_FN  ,FN_Sorted_Last_Field},
+  { REQ_LEFT_FIELD   |ID_FN  ,FN_Left_Field},
+  { REQ_RIGHT_FIELD  |ID_FN  ,FN_Right_Field},
+  { REQ_UP_FIELD     |ID_FN  ,FN_Up_Field},
+  { REQ_DOWN_FIELD   |ID_FN  ,FN_Down_Field},
+  
+  { REQ_NEXT_CHAR    |ID_IFN ,IFN_Next_Character},
+  { REQ_PREV_CHAR    |ID_IFN ,IFN_Previous_Character},
+  { REQ_NEXT_LINE    |ID_IFN ,IFN_Next_Line},
+  { REQ_PREV_LINE    |ID_IFN ,IFN_Previous_Line},
+  { REQ_NEXT_WORD    |ID_IFN ,IFN_Next_Word},
+  { REQ_PREV_WORD    |ID_IFN ,IFN_Previous_Word},
+  { REQ_BEG_FIELD    |ID_IFN ,IFN_Beginning_Of_Field},
+  { REQ_END_FIELD    |ID_IFN ,IFN_End_Of_Field},
+  { REQ_BEG_LINE     |ID_IFN ,IFN_Beginning_Of_Line},
+  { REQ_END_LINE     |ID_IFN ,IFN_End_Of_Line},
+  { REQ_LEFT_CHAR    |ID_IFN ,IFN_Left_Character},
+  { REQ_RIGHT_CHAR   |ID_IFN ,IFN_Right_Character},
+  { REQ_UP_CHAR      |ID_IFN ,IFN_Up_Character},
+  { REQ_DOWN_CHAR    |ID_IFN ,IFN_Down_Character},
+  
+  { REQ_NEW_LINE     |ID_FE  ,FE_New_Line},
+  { REQ_INS_CHAR     |ID_FE  ,FE_Insert_Character},
+  { REQ_INS_LINE     |ID_FE  ,FE_Insert_Line},
+  { REQ_DEL_CHAR     |ID_FE  ,FE_Delete_Character},
+  { REQ_DEL_PREV     |ID_FE  ,FE_Delete_Previous},
+  { REQ_DEL_LINE     |ID_FE  ,FE_Delete_Line},
+  { REQ_DEL_WORD     |ID_FE  ,FE_Delete_Word},
+  { REQ_CLR_EOL      |ID_FE  ,FE_Clear_To_End_Of_Line},
+  { REQ_CLR_EOF      |ID_FE  ,FE_Clear_To_End_Of_Form},
+  { REQ_CLR_FIELD    |ID_FE  ,FE_Clear_Field},
+  
+  { REQ_OVL_MODE     |ID_EM  ,EM_Overlay_Mode},
+  { REQ_INS_MODE     |ID_EM  ,EM_Insert_Mode},
+  
+  { REQ_SCR_FLINE    |ID_VSC ,VSC_Scroll_Line_Forward},
+  { REQ_SCR_BLINE    |ID_VSC ,VSC_Scroll_Line_Backward},
+  { REQ_SCR_FPAGE    |ID_VSC ,VSC_Scroll_Page_Forward},
+  { REQ_SCR_BPAGE    |ID_VSC ,VSC_Scroll_Page_Backward},
+  { REQ_SCR_FHPAGE   |ID_VSC ,VSC_Scroll_Half_Page_Forward},
+  { REQ_SCR_BHPAGE   |ID_VSC ,VSC_Scroll_Half_Page_Backward},
+  
+  { REQ_SCR_FCHAR    |ID_HSC ,HSC_Scroll_Char_Forward},
+  { REQ_SCR_BCHAR    |ID_HSC ,HSC_Scroll_Char_Backward},
+  { REQ_SCR_HFLINE   |ID_HSC ,HSC_Horizontal_Line_Forward},
+  { REQ_SCR_HBLINE   |ID_HSC ,HSC_Horizontal_Line_Backward},
+  { REQ_SCR_HFHALF   |ID_HSC ,HSC_Horizontal_Half_Line_Forward},
+  { REQ_SCR_HBHALF   |ID_HSC ,HSC_Horizontal_Half_Line_Backward},
+  
+  { REQ_VALIDATION   |ID_FV  ,FV_Validation},
+
+  { REQ_NEXT_CHOICE  |ID_CH  ,CR_Next_Choice},
+  { REQ_PREV_CHOICE  |ID_CH  ,CR_Previous_Choice}
+};
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int form_driver(FORM * form,int  c)
+|   
+|   Description   :  This is the workhorse of the forms system. It checks
+|                    to determine whether the character c is a request or
+|                    data. If it is a request, the form driver executes
+|                    the request and returns the result. If it is data
+|                    (printable character), it enters the data into the
+|                    current position in the current field. If it is not
+|                    recognized, the form driver assumes it is an application
+|                    defined command and returns E_UNKNOWN_COMMAND.
+|                    Application defined command should be defined relative
+|                    to MAX_FORM_COMMAND, the maximum value of a request.
+|
+|   Return Values :  E_OK              - success
+|                    E_SYSTEM_ERROR    - system error
+|                    E_BAD_ARGUMENT    - an argument is incorrect
+|                    E_NOT_POSTED      - form is not posted
+|                    E_INVALID_FIELD   - field contents are invalid
+|                    E_BAD_STATE       - called from inside a hook routine
+|                    E_REQUEST_DENIED  - request failed
+|                    E_UNKNOWN_COMMAND - command not known
++--------------------------------------------------------------------------*/
+int form_driver(FORM * form, int  c)
+{
+  const Binding_Info* BI = (Binding_Info *)0;
+  int res = E_UNKNOWN_COMMAND;
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->field))
+    RETURN(E_NOT_CONNECTED);
+  
+  assert(form->page);
+  
+  if (c==FIRST_ACTIVE_MAGIC)
+    {
+      form->current = _nc_First_Active_Field(form);
+      return E_OK;
+    }
+  
+  assert(form->current && 
+	 form->current->buf && 
+	 (form->current->form == form)
+	);
+  
+  if ( form->status & _IN_DRIVER )
+    RETURN(E_BAD_STATE);
+
+  if ( !( form->status & _POSTED ) ) 
+    RETURN(E_NOT_POSTED);
+  
+  if ((c>=MIN_FORM_COMMAND && c<=MAX_FORM_COMMAND) &&
+      ((bindings[c-MIN_FORM_COMMAND].keycode & Key_Mask) == c))
+    BI = &(bindings[c-MIN_FORM_COMMAND]);
+  
+  if (BI)
+    {
+      typedef int (*Generic_Method)(int (* const)(FORM *),FORM *);
+      static const Generic_Method Generic_Methods[] = 
+	{
+	  Page_Navigation,         /* overloaded to call field&form hooks */
+	  Inter_Field_Navigation,  /* overloaded to call field hooks      */
+	  NULL,                    /* Intra-Field is generic              */
+	  Vertical_Scrolling,      /* Overloaded to check multi-line      */
+	  Horizontal_Scrolling,    /* Overloaded to check single-line     */
+	  Field_Editing,           /* Overloaded to mark modification     */
+	  NULL,                    /* Edit Mode is generic                */
+	  NULL,                    /* Field Validation is generic         */
+	  NULL                     /* Choice Request is generic           */
+	};
+      size_t nMethods = (sizeof(Generic_Methods)/sizeof(Generic_Methods[0]));
+      size_t method   = ((BI->keycode & ID_Mask) >> ID_Shft) & 0xffff;
+      
+      if ( (method >= nMethods) || !(BI->cmd) )
+	res = E_SYSTEM_ERROR;
+      else
+	{
+	  Generic_Method fct = Generic_Methods[method];
+	  if (fct)
+	    res = fct(BI->cmd,form);
+	  else
+	    res = (BI->cmd)(form);
+	}
+    } 
+  else 
+    {
+      if (!(c & (~(int)MAX_REGULAR_CHARACTER)) &&
+	  isprint((unsigned char)c) &&                      
+	  Check_Char(form->current->type,c,
+		     (TypeArgument *)(form->current->arg)))
+	res = Data_Entry(form,c);
+    }
+  _nc_Refresh_Current_Field(form);
+  RETURN(res);
+}
+
+/*----------------------------------------------------------------------------
+  Field-Buffer manipulation routines.
+  The effects of setting a buffer is tightly coupled to the core of the form
+  driver logic. This is especially true in the case of growable fields.
+  So I don't separate this into an own module. 
+  --------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_buffer(FIELD *field,
+|                                         int buffer, char *value)
+|   
+|   Description   :  Set the given buffer of the field to the given value.
+|                    Buffer 0 stores the displayed content of the field.
+|                    For dynamic fields this may grow the fieldbuffers if
+|                    the length of the value exceeds the current buffer
+|                    length. For buffer 0 only printable values are allowed.
+|                    For static fields, the value needs not to be zero ter-
+|                    minated. It is copied up to the length of the buffer.   
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid argument
+|                    E_SYSTEM_ERROR  - system error
++--------------------------------------------------------------------------*/
+int set_field_buffer(FIELD * field, int buffer, const char * value)
+{
+  char *s, *p;
+  int res = E_OK;
+  unsigned int len;
+
+  if ( !field || !value || ((buffer < 0)||(buffer > field->nbuf)) )
+    RETURN(E_BAD_ARGUMENT);
+
+  len  = Buffer_Length(field);
+
+  if (buffer==0)
+    {
+      const char *v;
+      unsigned int i = 0;
+
+      for(v=value; *v && (i<len); v++,i++)
+	{
+	  if (!isprint((unsigned char)*v))
+	    RETURN(E_BAD_ARGUMENT);
+	}
+    }
+
+  if (Growable(field))
+    {
+      /* for a growable field we must assume zero terminated strings, because
+	 somehow we have to detect the length of what should be copied.
+      */
+      unsigned int vlen = strlen(value);
+      if (vlen > len)
+	{
+	  if (!Field_Grown(field,
+			   (int)(1 + (vlen-len)/((field->rows+field->nrow)*field->cols))))
+	    RETURN(E_SYSTEM_ERROR);
+
+	  /* in this case we also have to check, wether or not the remaining
+	     characters in value are also printable for buffer 0. */
+	  if (buffer==0)
+	    {
+	      unsigned int i;
+	  
+	      for(i=len; i<vlen; i++)
+		if (!isprint(value[i]))
+		  RETURN(E_BAD_ARGUMENT);
+	    }
+	  len = vlen;
+	}
+    }
+  
+  p   = Address_Of_Nth_Buffer(field,buffer);
+
+#if HAVE_MEMCCPY
+  s = memccpy(p,value,0,len);
+#else
+  for(s=(char *)value; *s && (s < (value+len)); s++)
+    p[s-value] = *s;
+  if (s < (value+len))
+    {
+      p[s-value] = *s++;
+      s = p + (s-value);
+    }
+  else 
+    s=(char *)0;
+#endif
+
+  if (s) 
+    { /* this means, value was null terminated and not greater than the
+	 buffer. We have to pad with blanks. Please note that due to memccpy
+	 logic s points after the terminating null. */
+      s--; /* now we point to the terminator. */
+      assert(len >= (unsigned int)(s-p));
+      if (len > (unsigned int)(s-p))
+	memset(s,C_BLANK,len-(unsigned int)(s-p));
+    }
+
+  if (buffer==0)
+    {
+      int syncres;
+      if (((syncres=Synchronize_Field( field ))!=E_OK) && 
+	  (res==E_OK))
+	res = syncres;
+      if (((syncres=Synchronize_Linked_Fields(field ))!=E_OK) &&
+	  (res==E_OK))
+	res = syncres;
+    }
+  RETURN(res);
+}		
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  char *field_buffer(const FIELD *field,int buffer)
+|   
+|   Description   :  Return the address of the buffer for the field.
+|
+|   Return Values :  Pointer to buffer or NULL if arguments were invalid.
++--------------------------------------------------------------------------*/
+char *field_buffer(const FIELD * field, int  buffer)
+{
+  if (field && (buffer >= 0) && (buffer <= field->nbuf))
+    return Address_Of_Nth_Buffer(field,buffer);
+  else
+    return (char *)0;
+}
+
+/* frm_driver.c ends here */

+ 140 - 0
Source/CursesDialog/form/frm_hook.c

@@ -0,0 +1,140 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/* "Template" macro to generate function to set application specific hook */
+#define GEN_HOOK_SET_FUNCTION( typ, name ) \
+int set_ ## typ ## _ ## name (FORM *form, Form_Hook func)\
+{\
+   (Normalize_Form( form ) -> typ ## name) = func ;\
+   RETURN(E_OK);\
+}
+
+/* "Template" macro to generate function to get application specific hook */
+#define GEN_HOOK_GET_FUNCTION( typ, name ) \
+Form_Hook typ ## _ ## name ( const FORM *form )\
+{\
+   return ( Normalize_Form( form ) -> typ ## name );\
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_init(FORM *form, Form_Hook f)
+|   
+|   Description   :  Assigns an application defined initialization function
+|                    to be called when the form is posted and just after
+|                    the current field changes.
+|
+|   Return Values :  E_OK      - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(field,init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Form_Hook field_init(const FORM *form)
+|   
+|   Description   :  Retrieve field initialization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(field,init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_field_term(FORM *form, Form_Hook f)
+|   
+|   Description   :  Assigns an application defined finalization function
+|                    to be called when the form is unposted and just before
+|                    the current field changes.
+|
+|   Return Values :  E_OK      - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(field,term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Form_Hook field_term(const FORM *form)
+|   
+|   Description   :  Retrieve field finalization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(field,term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_init(FORM *form, Form_Hook f)
+|   
+|   Description   :  Assigns an application defined initialization function
+|                    to be called when the form is posted and just after
+|                    a page change.
+|
+|   Return Values :  E_OK       - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(form,init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Form_Hook form_init(const FORM *form)
+|   
+|   Description   :  Retrieve form initialization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(form,init)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_term(FORM *form, Form_Hook f)
+|   
+|   Description   :  Assigns an application defined finalization function
+|                    to be called when the form is unposted and just before
+|                    a page change.
+|
+|   Return Values :  E_OK       - success
++--------------------------------------------------------------------------*/
+GEN_HOOK_SET_FUNCTION(form,term)
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Form_Hook form_term(const FORM *form)
+|   
+|   Description   :  Retrieve form finalization routine address.
+|
+|   Return Values :  The address or NULL if no hook defined.
++--------------------------------------------------------------------------*/
+GEN_HOOK_GET_FUNCTION(form,term)
+
+/* frm_hook.c ends here */

+ 116 - 0
Source/CursesDialog/form/frm_opts.c

@@ -0,0 +1,116 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_opts(FORM *form, Form_Options opts)
+|   
+|   Description   :  Turns on the named options and turns off all the
+|                    remaining options for that form.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid options
++--------------------------------------------------------------------------*/
+int set_form_opts(FORM * form, Form_Options  opts)
+{
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form( form )->opts = opts;
+      RETURN(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  Form_Options form_opts(const FORM *)
+|   
+|   Description   :  Retrieves the current form options.
+|
+|   Return Values :  The option flags.
++--------------------------------------------------------------------------*/
+Form_Options form_opts(const FORM * form)
+{
+  return (Normalize_Form(form)->opts & ALL_FORM_OPTS);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int form_opts_on(FORM *form, Form_Options opts)
+|   
+|   Description   :  Turns on the named options; no other options are 
+|                    changed.
+|
+|   Return Values :  E_OK            - success 
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+int form_opts_on(FORM * form, Form_Options opts)
+{
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form( form )->opts |= opts;	
+      RETURN(E_OK);
+    }
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int form_opts_off(FORM *form, Form_Options opts)
+|   
+|   Description   :  Turns off the named options; no other options are 
+|                    changed.
+|
+|   Return Values :  E_OK            - success 
+|                    E_BAD_ARGUMENT  - invalid options
++--------------------------------------------------------------------------*/
+int form_opts_off(FORM * form, Form_Options opts)
+{
+  opts &= ALL_FORM_OPTS;
+  if (opts & ~ALL_FORM_OPTS)
+    RETURN(E_BAD_ARGUMENT);
+  else
+    {
+      Normalize_Form(form)->opts &= ~opts;
+      RETURN(E_OK);
+    }
+}
+
+/* frm_opts.c ends here */

+ 100 - 0
Source/CursesDialog/form/frm_page.c

@@ -0,0 +1,100 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_page(FORM * form,int  page)
+|   
+|   Description   :  Set the page number of the form.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer or page number
+|                    E_BAD_STATE       - called from a hook routine
+|                    E_INVALID_FIELD   - current field can't be left
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+int set_form_page(FORM * form, int page)
+{
+  int err = E_OK;
+
+  if ( !form || (page<0) || (page>=form->maxpage) )
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->status & _POSTED))
+    {
+      form->curpage = page;
+      form->current = _nc_First_Active_Field(form);
+  }
+  else
+    {
+      if (form->status & _IN_DRIVER) 
+	err = E_BAD_STATE;
+      else
+	{
+	  if (form->curpage != page)
+	    {
+	      if (!_nc_Internal_Validation(form)) 
+		err = E_INVALID_FIELD;
+	      else
+		{
+		  Call_Hook(form,fieldterm);
+		  Call_Hook(form,formterm);
+		  err = _nc_Set_Form_Page(form,page,(FIELD *)0);
+		  Call_Hook(form,forminit);
+		  Call_Hook(form,fieldinit);
+		  _nc_Refresh_Current_Field(form);
+		}
+	    }
+	}
+    }
+  RETURN(err);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int form_page(const FORM * form)
+|   
+|   Description   :  Return the current page of the form.
+|
+|   Return Values :  >= 0  : current page number
+|                    -1    : invalid form pointer
++--------------------------------------------------------------------------*/
+int form_page(const FORM * form)
+{
+  return Normalize_Form(form)->curpage;
+}
+
+/* frm_page.c ends here */

+ 117 - 0
Source/CursesDialog/form/frm_post.c

@@ -0,0 +1,117 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int post_form(FORM * form)
+|   
+|   Description   :  Writes the form into its associated subwindow.
+|
+|   Return Values :  E_OK              - success
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_POSTED          - form already posted
+|                    E_NOT_CONNECTED   - no fields connected to form
+|                    E_NO_ROOM         - form doesn't fit into subwindow
+|                    E_SYSTEM_ERROR    - system error
++--------------------------------------------------------------------------*/
+int post_form(FORM * form)
+{
+  WINDOW *formwin;
+  int err;
+  int page;
+
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (form->status & _POSTED)   
+    RETURN(E_POSTED);
+
+  if (!(form->field))
+    RETURN(E_NOT_CONNECTED);
+  
+  formwin = Get_Form_Window(form);
+  if ((form->cols > getmaxx(formwin)) || (form->rows > getmaxy(formwin))) 
+    RETURN(E_NO_ROOM);
+
+  /* reset form->curpage to an invald value. This forces Set_Form_Page
+     to do the page initialization which is required by post_form.
+  */
+  page = form->curpage;
+  form->curpage = -1;
+  if ((err = _nc_Set_Form_Page(form,page,form->current))!=E_OK)
+    RETURN(err);
+
+  form->status |= _POSTED;
+
+  Call_Hook(form,forminit);
+  Call_Hook(form,fieldinit);
+
+  _nc_Refresh_Current_Field(form);
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int unpost_form(FORM * form)
+|   
+|   Description   :  Erase form from its associated subwindow.
+|
+|   Return Values :  E_OK            - success
+|                    E_BAD_ARGUMENT  - invalid form pointer
+|                    E_NOT_POSTED    - form isn't posted
+|                    E_BAD_STATE     - called from a hook routine
++--------------------------------------------------------------------------*/
+int unpost_form(FORM * form)
+{
+  if (!form)
+    RETURN(E_BAD_ARGUMENT);
+
+  if (!(form->status & _POSTED)) 
+    RETURN(E_NOT_POSTED);
+
+  if (form->status & _IN_DRIVER) 
+    RETURN(E_BAD_STATE);
+
+  Call_Hook(form,fieldterm);
+  Call_Hook(form,formterm);
+
+  werase(Get_Form_Window(form));
+  delwin(form->w);
+  form->w = (WINDOW *)0;
+  form->status &= ~_POSTED;
+  RETURN(E_OK);
+}
+
+/* frm_post.c ends here */

+ 163 - 0
Source/CursesDialog/form/frm_req_name.c

@@ -0,0 +1,163 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+/***************************************************************************
+* Module form_request_name                                                 *
+* Routines to handle external names of menu requests                       *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+static const char *request_names[ MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1 ] = {
+  "NEXT_PAGE"	 ,
+  "PREV_PAGE"	 ,
+  "FIRST_PAGE"	 ,
+  "LAST_PAGE"	 ,
+
+  "NEXT_FIELD"	 ,
+  "PREV_FIELD"	 ,
+  "FIRST_FIELD"	 ,
+  "LAST_FIELD"	 ,
+  "SNEXT_FIELD"	 ,
+  "SPREV_FIELD"	 ,
+  "SFIRST_FIELD" ,
+  "SLAST_FIELD"	 ,
+  "LEFT_FIELD"	 ,
+  "RIGHT_FIELD"	 ,
+  "UP_FIELD"	 ,
+  "DOWN_FIELD"	 ,
+
+  "NEXT_CHAR"	 ,
+  "PREV_CHAR"	 ,
+  "NEXT_LINE"	 ,
+  "PREV_LINE"	 ,
+  "NEXT_WORD"	 ,
+  "PREV_WORD"	 ,
+  "BEG_FIELD"	 ,
+  "END_FIELD"	 ,
+  "BEG_LINE"	 ,
+  "END_LINE"	 ,
+  "LEFT_CHAR"	 ,
+  "RIGHT_CHAR"	 ,
+  "UP_CHAR"	 ,
+  "DOWN_CHAR"	 ,
+
+  "NEW_LINE"	 ,
+  "INS_CHAR"	 ,
+  "INS_LINE"	 ,
+  "DEL_CHAR"	 ,
+  "DEL_PREV"	 ,
+  "DEL_LINE"	 ,
+  "DEL_WORD"	 ,
+  "CLR_EOL"	 ,
+  "CLR_EOF"	 ,
+  "CLR_FIELD"	 ,
+  "OVL_MODE"	 ,
+  "INS_MODE"	 ,
+  "SCR_FLINE"	 ,
+  "SCR_BLINE"	 ,
+  "SCR_FPAGE"	 ,
+  "SCR_BPAGE"	 ,
+  "SCR_FHPAGE"   ,
+  "SCR_BHPAGE"   ,
+  "SCR_FCHAR"    ,
+  "SCR_BCHAR"    ,
+  "SCR_HFLINE"   ,
+  "SCR_HBLINE"   ,
+  "SCR_HFHALF"   ,
+  "SCR_HBHALF"   ,
+
+  "VALIDATION"	 ,
+  "NEXT_CHOICE"	 ,
+  "PREV_CHOICE"	 
+};
+#define A_SIZE (sizeof(request_names)/sizeof(request_names[0]))
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  const char * form_request_name (int request);
+|   
+|   Description   :  Get the external name of a form request.
+|
+|   Return Values :  Pointer to name      - on success
+|                    NULL                 - on invalid request code
++--------------------------------------------------------------------------*/
+const char *form_request_name( int request )
+{
+  if ( (request < MIN_FORM_COMMAND) || (request > MAX_FORM_COMMAND) )
+    {
+      SET_ERROR (E_BAD_ARGUMENT);
+      return (const char *)0;
+    }
+  else
+    return request_names[ request - MIN_FORM_COMMAND ];
+}
+
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int form_request_by_name (const char *str);
+|   
+|   Description   :  Search for a request with this name.
+|
+|   Return Values :  Request Id       - on success
+|                    E_NO_MATCH       - request not found
++--------------------------------------------------------------------------*/
+int form_request_by_name( const char *str )
+{ 
+  /* because the table is so small, it doesn't really hurt
+     to run sequentially through it.
+  */
+  unsigned int i = 0;
+  char buf[16];
+  
+  if (str)
+    {
+      strncpy(buf,str,sizeof(buf));
+      while( (i<sizeof(buf)) && (buf[i] != '\0') )
+	{
+	  buf[i] = toupper(buf[i]);
+	  i++;
+	}
+      
+      for (i=0; i < A_SIZE; i++)
+	{
+	  if (strncmp(request_names[i],buf,sizeof(buf))==0)
+	    return MIN_FORM_COMMAND + i;
+	} 
+    }
+  RETURN(E_NO_MATCH);
+}
+
+/* frm_req_name.c ends here */

+ 63 - 0
Source/CursesDialog/form/frm_scale.c

@@ -0,0 +1,63 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int scale_form( const FORM *form, int *rows, int *cols )
+|   
+|   Description   :  Retrieve size of form
+|
+|   Return Values :  E_OK              - no error
+|                    E_BAD_ARGUMENT    - invalid form pointer
+|                    E_NOT_CONNECTED   - no fields connected to form
++--------------------------------------------------------------------------*/
+int scale_form(const FORM * form, int * rows, int * cols)
+{
+  if ( !form )
+    RETURN(E_BAD_ARGUMENT);
+
+  if ( !(form->field) )
+    RETURN(E_NOT_CONNECTED);
+  
+  if (rows) 
+    *rows = form->rows;
+  if (cols) 
+    *cols = form->cols;
+  
+  RETURN(E_OK);
+}
+
+/* frm_scale.c ends here */

+ 69 - 0
Source/CursesDialog/form/frm_sub.c

@@ -0,0 +1,69 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_sub(FORM *form, WINDOW *win)
+|   
+|   Description   :  Set the subwindow of the form to win. 
+|
+|   Return Values :  E_OK       - success
+|                    E_POSTED   - form is posted
++--------------------------------------------------------------------------*/
+int set_form_sub(FORM * form, WINDOW * win)
+{
+  if (form && (form->status & _POSTED))	
+    RETURN(E_POSTED);
+
+  Normalize_Form( form )->sub = win;
+  RETURN(E_OK);
+}	
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  WINDOW *form_sub(const FORM *)
+|   
+|   Description   :  Retrieve the window of the form.
+|
+|   Return Values :  The pointer to the Subwindow.
++--------------------------------------------------------------------------*/
+WINDOW *form_sub(const FORM * form)
+{
+  const FORM* f = Normalize_Form( form );
+  return Get_Form_Window(f);
+}
+
+/* frm_sub.c ends here */

+ 67 - 0
Source/CursesDialog/form/frm_user.c

@@ -0,0 +1,67 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_userptr(FORM *form, void *usrptr)
+|   
+|   Description   :  Set the pointer that is reserved in any form to store
+|                    application relevant informations
+|
+|   Return Values :  E_OK         - on success
++--------------------------------------------------------------------------*/
+int set_form_userptr(FORM * form, void *usrptr)
+{
+  Normalize_Form(form)->usrptr = usrptr;
+  RETURN(E_OK);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  void *form_userptr(const FORM *form)
+|   
+|   Description   :  Return the pointer that is reserved in any form to
+|                    store application relevant informations.
+|
+|   Return Values :  Value of pointer. If no such pointer has been set,
+|                    NULL is returned
++--------------------------------------------------------------------------*/
+void *form_userptr(const FORM * form)
+{
+  return Normalize_Form(form)->usrptr;
+}
+
+/* frm_user.c ends here */

+ 70 - 0
Source/CursesDialog/form/frm_win.c

@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (c) 1998 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int set_form_win(FORM *form,WINDOW *win)
+|   
+|   Description   :  Set the window of the form to win. 
+|
+|   Return Values :  E_OK       - success
+|                    E_POSTED   - form is posted
++--------------------------------------------------------------------------*/
+int set_form_win(FORM * form, WINDOW * win)
+{
+  if (form && (form->status & _POSTED))	
+    RETURN(E_POSTED);
+
+  Normalize_Form( form )->win = win;
+  RETURN(E_OK);
+}	
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  WINDOW *form_win(const FORM *)
+|   
+|   Description   :  Retrieve the window of the form.
+|
+|   Return Values :  The pointer to the Window or stdscr if there is none.
++--------------------------------------------------------------------------*/
+WINDOW *form_win(const FORM * form)
+{
+  const FORM* f = Normalize_Form( form );
+  return (f->win ? f->win : stdscr);
+}
+
+/* frm_win.c ends here */
+

+ 137 - 0
Source/CursesDialog/form/fty_alnum.c

@@ -0,0 +1,137 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+typedef struct {
+  int width;
+} alnumARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Make_AlphaNumeric_Type(va_list *ap)
+|   
+|   Description   :  Allocate structure for alphanumeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_AlphaNumeric_Type(va_list * ap)
+{
+  alnumARG *argp = (alnumARG *)malloc(sizeof(alnumARG));
+
+  if (argp)
+    argp->width = va_arg(*ap,int);
+
+  return ((void *)argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Copy_AlphaNumericType(const void *argp)
+|   
+|   Description   :  Copy structure for alphanumeric type argument.  
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_AlphaNumeric_Type(const void *argp)
+{
+  const alnumARG *ap = (const alnumARG *)argp;
+  alnumARG *result = (alnumARG *)malloc(sizeof(alnumARG));
+
+  if (result)
+    *result = *ap;
+
+  return ((void *)result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Free_AlphaNumeric_Type(void *argp)
+|   
+|   Description   :  Free structure for alphanumeric type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_AlphaNumeric_Type(void * argp)
+{
+  if (argp) 
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_AlphaNumeric_Field(
+|                                      FIELD *field,
+|                                      const void *argp)
+|   
+|   Description   :  Validate buffer content to be a valid alphanumeric value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_AlphaNumeric_Field(FIELD * field, const void * argp)
+{
+  int width = ((const alnumARG *)argp)->width;
+  unsigned char *bp  = (unsigned char *)field_buffer(field,0);
+  int  l = -1;
+  unsigned char *s;
+
+  while(*bp && *bp==' ') 
+    bp++;
+  if (*bp)
+    {
+      s = bp;
+      while(*bp && isalnum(*bp)) 
+	bp++;
+      l = (int)(bp-s);
+      while(*bp && *bp==' ') 
+	bp++;
+    }
+  return ((*bp || (l < width)) ? FALSE : TRUE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_AlphaNumeric_Character(
+|                                      int c, 
+|                                      const void *argp )
+|   
+|   Description   :  Check a character for the alphanumeric type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_AlphaNumeric_Character(int c, const void * argp)
+{
+  return (isalnum(c) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeALNUM = {
+  _HAS_ARGS | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_AlphaNumeric_Type,
+  Copy_AlphaNumeric_Type,
+  Free_AlphaNumeric_Type,
+  Check_AlphaNumeric_Field,
+  Check_AlphaNumeric_Character,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_ALNUM = &typeALNUM;
+
+/* fty_alnum.c ends here */

+ 138 - 0
Source/CursesDialog/form/fty_alpha.c

@@ -0,0 +1,138 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+typedef struct {
+  int width;
+} alphaARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Make_Alpha_Type(va_list *ap)
+|   
+|   Description   :  Allocate structure for alpha type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_Alpha_Type(va_list * ap)
+{
+  alphaARG *argp = (alphaARG *)malloc(sizeof(alphaARG));
+  if (argp)
+    {
+      argp->width = va_arg(*ap,int);
+    }
+  return ((void *)argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Copy_Alpha_Type(const void * argp)
+|   
+|   Description   :  Copy structure for alpha type argument.  
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_Alpha_Type(const void * argp)
+{
+  const alphaARG *ap = (const alphaARG *)argp;
+  alphaARG *result = (alphaARG *)malloc(sizeof(alphaARG));
+  
+  if (result)
+    {
+      *result = *ap;
+    }
+  return ((void *)result);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Free_Alpha_Type( void * argp )
+|   
+|   Description   :  Free structure for alpha type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_Alpha_Type(void * argp)
+{
+  if (argp) 
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Alpha_Field(
+|                                      FIELD * field,
+|                                      const void * argp)
+|   
+|   Description   :  Validate buffer content to be a valid alpha value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Alpha_Field(FIELD * field, const void * argp)
+{
+  int width = ((const alphaARG *)argp)->width;
+  unsigned char *bp  = (unsigned char *)field_buffer(field,0);
+  int  l = -1;
+  unsigned char *s;
+
+  while(*bp && *bp==' ') 
+    bp++;
+  if (*bp)
+    {
+      s = bp;
+      while(*bp && isalpha(*bp)) 
+	bp++;
+      l = (int)(bp-s);
+      while(*bp && *bp==' ') 
+	bp++;
+    }
+  return ((*bp || (l < width)) ? FALSE : TRUE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Alpha_Character(
+|                                      int c,
+|                                      const void * argp)
+|   
+|   Description   :  Check a character for the alpha type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Alpha_Character(int c, const void * argp)
+{
+  return (isalpha(c) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeALPHA = {
+  _HAS_ARGS | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_Alpha_Type,
+  Copy_Alpha_Type,
+  Free_Alpha_Type,
+  Check_Alpha_Field,
+  Check_Alpha_Character,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_ALPHA = &typeALPHA;
+
+/* fty_alpha.c ends here */

+ 295 - 0
Source/CursesDialog/form/fty_enum.c

@@ -0,0 +1,295 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+typedef struct {
+  char **kwds;
+  int  count;
+  bool checkcase;
+  bool checkunique;
+} enumARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Make_Enum_Type( va_list * ap )
+|   
+|   Description   :  Allocate structure for enumeration type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_Enum_Type(va_list * ap)
+{
+  enumARG *argp = (enumARG *)malloc(sizeof(enumARG));
+
+  if (argp)
+    {
+      int cnt = 0;
+      char **kp = (char **)0;
+      int ccase, cunique;
+
+      argp->kwds        = va_arg(*ap,char **);
+      ccase             = va_arg(*ap,int);
+      cunique           = va_arg(*ap,int);
+      argp->checkcase   = ccase   ? TRUE : FALSE;
+      argp->checkunique = cunique ? TRUE : FALSE;
+
+      kp = argp->kwds;
+      while( kp && (*kp++) ) cnt++;
+      argp->count = cnt;
+    }
+  return (void *)argp;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Copy_Enum_Type( const void * argp )
+|   
+|   Description   :  Copy structure for enumeration type argument.  
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_Enum_Type(const void * argp)
+{
+  enumARG *result = (enumARG *)0;
+
+  if (argp)
+    {
+      const enumARG *ap = (const enumARG *)argp;
+
+      result = (enumARG *)malloc(sizeof(enumARG));
+      if (result)
+	*result = *ap;
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Free_Enum_Type( void * argp )
+|   
+|   Description   :  Free structure for enumeration type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_Enum_Type(void * argp)
+{
+  if (argp) 
+    free(argp);
+}
+
+#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
+#define NOMATCH 0
+#define PARTIAL 1
+#define EXACT   2
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static int Compare(const unsigned char * s,  
+|                                       const unsigned char * buf,
+|                                       bool  ccase )
+|   
+|   Description   :  Check wether or not the text in 'buf' matches the
+|                    text in 's', at least partial.
+|
+|   Return Values :  NOMATCH   - buffer doesn't match
+|                    PARTIAL   - buffer matches partially
+|                    EXACT     - buffer matches exactly
++--------------------------------------------------------------------------*/
+static int Compare(const unsigned char *s, const unsigned char *buf, 
+		   bool ccase)
+{
+  SKIP_SPACE(buf); /* Skip leading spaces in both texts */
+  SKIP_SPACE(s);
+
+  if (*buf=='\0')
+    {
+      return (((*s)!='\0') ? NOMATCH : EXACT);
+    } 
+  else 
+    {
+      if (ccase)
+	{
+	  while(*s++ == *buf)
+	    {
+	      if (*buf++=='\0') return EXACT;
+	    } 
+	} 
+      else 
+	{
+	  while(toupper(*s++)==toupper(*buf))
+	    {
+	      if (*buf++=='\0') return EXACT;
+	    }
+	}
+    }
+  /* At this location buf points to the first character where it no longer
+     matches with s. So if only blanks are following, we have a partial
+     match otherwise there is no match */
+  SKIP_SPACE(buf);
+  if (*buf) 
+    return NOMATCH;
+
+  /* If it happens that the reference buffer is at its end, the partial
+     match is actually an exact match. */
+  return ((s[-1]!='\0') ? PARTIAL : EXACT);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Enum_Field(
+|                                      FIELD * field,
+|                                      const void  * argp)
+|   
+|   Description   :  Validate buffer content to be a valid enumeration value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Enum_Field(FIELD * field, const void  * argp)
+{
+  char **kwds       = ((const enumARG *)argp)->kwds;
+  bool ccase        = ((const enumARG *)argp)->checkcase;
+  bool unique       = ((const enumARG *)argp)->checkunique;
+  unsigned char *bp = (unsigned char *)field_buffer(field,0);
+  char *s, *t, *p;
+  int res;
+  
+  while( kwds && (s=(*kwds++)) )
+    {
+      if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)
+	{
+	  p=t=s; /* t is at least a partial match */
+	  if ((unique && res!=EXACT)) 
+	    {
+	      while( kwds && (p = *kwds++) )
+		{
+		  if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)
+		    {
+		      if (res==EXACT)
+			{
+			  t = p;
+			  break;
+			}
+		      else
+			t = (char *)0;
+		    }
+		}
+	    }	  
+	  if (t)
+	    {
+	      set_field_buffer(field,0,t);
+	      return TRUE;
+	    }
+	  if (!p)
+	    break;
+	}
+    }
+  return FALSE;
+}
+
+static const char *dummy[] = { (char *)0 };
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Next_Enum(FIELD * field,
+|                                          const void * argp)
+|   
+|   Description   :  Check for the next enumeration value
+|
+|   Return Values :  TRUE  - next value found and loaded
+|                    FALSE - no next value loaded
++--------------------------------------------------------------------------*/
+static bool Next_Enum(FIELD * field, const void * argp)
+{
+  const enumARG *args = (const enumARG *)argp;
+  char **kwds       = args->kwds;
+  bool ccase        = args->checkcase;
+  int cnt           = args->count;
+  unsigned char *bp = (unsigned char *)field_buffer(field,0);
+
+  if (kwds) {
+    while(cnt--)
+      {
+	if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT) 
+	  break;
+      }
+    if (cnt<=0)
+      kwds = args->kwds;
+    if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
+      {
+	set_field_buffer(field,0,*kwds);
+	return TRUE;
+      }
+  }
+  return FALSE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Previous_Enum(
+|                                          FIELD * field,
+|                                          const void * argp)
+|   
+|   Description   :  Check for the previous enumeration value
+|
+|   Return Values :  TRUE  - previous value found and loaded
+|                    FALSE - no previous value loaded
++--------------------------------------------------------------------------*/
+static bool Previous_Enum(FIELD * field, const void * argp)
+{
+  const enumARG *args = (const enumARG *)argp;
+  int cnt       = args->count;
+  char **kwds   = &args->kwds[cnt-1];
+  bool ccase    = args->checkcase;
+  unsigned char *bp = (unsigned char *)field_buffer(field,0);
+
+  if (kwds) {
+    while(cnt--)
+      {
+	if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT) 
+	  break;
+      }
+    
+    if (cnt<=0)
+      kwds  = &args->kwds[args->count-1];
+    
+    if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
+      {
+	set_field_buffer(field,0,*kwds);
+	return TRUE;
+      }
+  }
+  return FALSE;
+}
+
+
+static FIELDTYPE typeENUM = {
+  _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_Enum_Type,
+  Copy_Enum_Type,
+  Free_Enum_Type,
+  Check_Enum_Field,
+  NULL,
+  Next_Enum,
+  Previous_Enum
+};
+
+FIELDTYPE* TYPE_ENUM = &typeENUM;
+
+/* fty_enum.c ends here */

+ 160 - 0
Source/CursesDialog/form/fty_int.c

@@ -0,0 +1,160 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+typedef struct {
+  int precision;
+  long low;
+  long high;
+} integerARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Make_Integer_Type( va_list * ap )
+|   
+|   Description   :  Allocate structure for integer type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_Integer_Type(va_list * ap)
+{
+  integerARG *argp = (integerARG *)malloc(sizeof(integerARG));
+
+  if (argp)
+    {
+      argp->precision = va_arg(*ap,int);
+      argp->low       = va_arg(*ap,long);
+      argp->high      = va_arg(*ap,long);
+    }
+  return (void *)argp;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Copy_Integer_Type(const void * argp)
+|   
+|   Description   :  Copy structure for integer type argument.  
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_Integer_Type(const void * argp)
+{
+  const integerARG *ap = (const integerARG *)argp;
+  integerARG *result = (integerARG *)0;
+
+  if (argp)
+    {
+      result = (integerARG *)malloc(sizeof(integerARG));
+      if (result)
+	*result = *ap;
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Free_Integer_Type(void * argp)
+|   
+|   Description   :  Free structure for integer type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_Integer_Type(void * argp)
+{
+  if (argp) 
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Integer_Field(
+|                                                    FIELD * field,
+|                                                    const void * argp)
+|   
+|   Description   :  Validate buffer content to be a valid integer value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Integer_Field(FIELD * field, const void * argp)
+{
+  const integerARG *argi = (const integerARG *)argp;
+  long low          = argi->low;
+  long high         = argi->high;
+  int prec          = argi->precision;
+  unsigned char *bp = (unsigned char *)field_buffer(field,0);
+  char *s           = (char *)bp;
+  long val;
+  char buf[100];
+
+  while( *bp && *bp==' ') bp++;
+  if (*bp)
+    {
+      if (*bp=='-') bp++;
+      while (*bp)
+	{
+	  if (!isdigit(*bp)) break;
+	  bp++;
+	}
+      while(*bp && *bp==' ') bp++;
+      if (*bp=='\0')
+	{
+	  val = atol(s);
+	  if (low<high)
+	    {
+	      if (val<low || val>high) return FALSE;
+	    }
+	  sprintf(buf,"%.*ld",(prec>0?prec:0),val);
+	  set_field_buffer(field,0,buf);
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Integer_Character(
+|                                      int c,
+|                                      const void * argp)
+|   
+|   Description   :  Check a character for the integer type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Integer_Character(int c, const void * argp)
+{
+  return ((isdigit(c) || (c=='-')) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeINTEGER = {
+  _HAS_ARGS | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_Integer_Type,
+  Copy_Integer_Type,
+  Free_Integer_Type,
+  Check_Integer_Field,
+  Check_Integer_Character,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_INTEGER = &typeINTEGER;
+
+/* fty_int.c ends here */

+ 81 - 0
Source/CursesDialog/form/fty_ipv4.c

@@ -0,0 +1,81 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Per Foreby, [email protected]                                    *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_IPV4_Field(
+|                                      FIELD * field,
+|                                      const void * argp)
+|   
+|   Description   :  Validate buffer content to be a valid IP number (Ver. 4)
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_IPV4_Field(FIELD * field, const void * argp)
+{
+  char *bp = field_buffer(field,0);
+  int num = 0, len;
+  unsigned int d1, d2, d3, d4;
+
+  if(isdigit(*bp))              /* Must start with digit */
+    {
+      num = sscanf(bp, "%u.%u.%u.%u%n", &d1, &d2, &d3, &d4, &len);
+      if (num == 4)
+        {
+          bp += len;            /* Make bp point to what sscanf() left */
+          while (*bp && isspace(*bp))
+            bp++;               /* Allow trailing whitespace */
+        }
+    }
+  return ((num != 4 || *bp || d1 > 255 || d2 > 255
+                           || d3 > 255 || d4 > 255) ? FALSE : TRUE);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_IPV4_Character(
+|                                      int c, 
+|                                      const void *argp )
+|   
+|   Description   :  Check a character for unsigned type or period.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_IPV4_Character(int c, const void * argp)
+{
+  return ((isdigit(c) || (c=='.')) ? TRUE : FALSE);
+}
+
+static FIELDTYPE typeIPV4 = {
+  _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  NULL,
+  NULL,
+  NULL,
+  Check_IPV4_Field,
+  Check_IPV4_Character,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_IPV4 = &typeIPV4;
+
+/* fty_ipv4.c ends here */

+ 195 - 0
Source/CursesDialog/form/fty_num.c

@@ -0,0 +1,195 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+#if HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+typedef struct {
+  int    precision;
+  double low;
+  double high;
+  struct lconv* L;
+} numericARG;
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Make_Numeric_Type(va_list * ap)
+|   
+|   Description   :  Allocate structure for numeric type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_Numeric_Type(va_list * ap)
+{
+  numericARG *argn = (numericARG *)malloc(sizeof(numericARG));
+
+  if (argn)
+    {
+      argn->precision = va_arg(*ap,int);
+      argn->low       = va_arg(*ap,double);
+      argn->high      = va_arg(*ap,double);
+#if HAVE_LOCALE_H
+      argn->L         = localeconv();
+#else
+      argn->L         = NULL;
+#endif
+    }
+  return (void *)argn;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Copy_Numeric_Type(const void * argp)
+|   
+|   Description   :  Copy structure for numeric type argument.  
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_Numeric_Type(const void * argp)
+{
+  const numericARG *ap = (const numericARG *)argp;
+  numericARG *result = (numericARG *)0;
+
+  if (argp)
+    {
+      result = (numericARG *)malloc(sizeof(numericARG));
+      if (result)
+	*result  = *ap;
+    }
+  return (void *)result;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void Free_Numeric_Type(void * argp)
+|   
+|   Description   :  Free structure for numeric type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_Numeric_Type(void * argp)
+{
+  if (argp) 
+    free(argp);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Numeric_Field(FIELD * field,
+|                                                    const void * argp)
+|   
+|   Description   :  Validate buffer content to be a valid numeric value
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Numeric_Field(FIELD * field, const void * argp)
+{
+  const numericARG *argn = (const numericARG *)argp;
+  double low          = argn->low;
+  double high         = argn->high;
+  int prec            = argn->precision;
+  unsigned char *bp   = (unsigned char *)field_buffer(field,0);
+  char *s             = (char *)bp;
+  double val          = 0.0;
+  struct lconv* L     = argn->L;
+  char buf[64];
+
+  while(*bp && *bp==' ') bp++;
+  if (*bp)
+    {
+      if (*bp=='-' || *bp=='+')
+	bp++;
+      while(*bp)
+	{
+	  if (!isdigit(*bp)) break;
+	  bp++;
+	}
+      if (*bp==(
+#if HAVE_LOCALE_H
+		(L && L->decimal_point) ? *(L->decimal_point) :
+#endif
+		'.'))
+	{
+	  bp++;
+	  while(*bp)
+	    {
+	      if (!isdigit(*bp)) break;
+	      bp++;
+	    }
+	}
+      while(*bp && *bp==' ') bp++;
+      if (*bp=='\0')
+	{
+	  val = atof(s);
+	  if (low<high)
+	    {
+	      if (val<low || val>high) return FALSE;
+	    }
+	  sprintf(buf,"%.*f",(prec>0?prec:0),val);
+	  set_field_buffer(field,0,buf);
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static bool Check_Numeric_Character(
+|                                      int c,
+|                                      const void * argp)
+|   
+|   Description   :  Check a character for the numeric type.
+|
+|   Return Values :  TRUE  - character is valid
+|                    FALSE - character is invalid
++--------------------------------------------------------------------------*/
+static bool Check_Numeric_Character(int c, const void * argp)
+{
+  const numericARG *argn = (const numericARG *)argp;
+  struct lconv* L  = argn->L;  
+
+  return (isdigit(c)  || 
+	  c == '+'    || 
+	  c == '-'    || 
+	  c == (
+#if HAVE_LOCALE_H
+		(L && L->decimal_point) ? *(L->decimal_point) :
+#endif
+		'.')
+	  ) ? TRUE : FALSE;
+}
+
+static FIELDTYPE typeNUMERIC = {
+  _HAS_ARGS | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_Numeric_Type,
+  Copy_Numeric_Type,
+  Free_Numeric_Type,
+  Check_Numeric_Field,
+  Check_Numeric_Character,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_NUMERIC = &typeNUMERIC;
+
+/* fty_num.c ends here */

+ 257 - 0
Source/CursesDialog/form/fty_regex.c

@@ -0,0 +1,257 @@
+
+/*
+ * THIS CODE IS SPECIFICALLY EXEMPTED FROM THE NCURSES PACKAGE COPYRIGHT.
+ * You may freely copy it for use as a template for your own field types.
+ * If you develop a field type that might be of general use, please send
+ * it back to the ncurses maintainers for inclusion in the next version.
+ */
+/***************************************************************************
+*                                                                          *
+*  Author : Juergen Pfeifer, [email protected]                       *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id$")
+
+#if HAVE_REGEX_H_FUNCS	/* We prefer POSIX regex */
+#include <regex.h>
+
+typedef struct
+{
+  regex_t *pRegExp;
+  unsigned long *refCount;
+} RegExp_Arg;
+
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+#undef RETURN
+static int reg_errno;
+
+static char *RegEx_Init(char *instring)
+{
+	reg_errno = 0;
+	return instring;
+}
+
+static char *RegEx_Error(int code)
+{
+	reg_errno = code;
+	return 0;
+}
+
+#define INIT 		register char *sp = RegEx_Init(instring);
+#define GETC()		(*sp++)
+#define PEEKC()		(*sp)
+#define UNGETC(c)	(--sp)
+#define RETURN(c)	return(c)
+#define ERROR(c)	return RegEx_Error(c)
+
+#if HAVE_REGEXP_H_FUNCS
+#include <regexp.h>
+#else
+#include <regexpr.h>
+#endif
+
+typedef struct
+{
+  char *compiled_expression;
+  unsigned long *refCount;
+} RegExp_Arg;
+
+/* Maximum Length we allow for a compiled regular expression */
+#define MAX_RX_LEN   (2048)
+#define RX_INCREMENT (256)
+
+#endif
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Make_RegularExpression_Type(va_list * ap)
+|
+|   Description   :  Allocate structure for regex type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error
++--------------------------------------------------------------------------*/
+static void *Make_RegularExpression_Type(va_list * ap)
+{
+#if HAVE_REGEX_H_FUNCS
+  char *rx = va_arg(*ap,char *);
+  RegExp_Arg *preg;
+
+  preg = (RegExp_Arg*)malloc(sizeof(RegExp_Arg));
+  if (preg)
+    {
+      if (((preg->pRegExp = (regex_t*)malloc(sizeof(regex_t))) != (regex_t*)0)
+       && !regcomp(preg->pRegExp,rx,
+		   (REG_EXTENDED | REG_NOSUB | REG_NEWLINE) ))
+	{
+	  preg->refCount = (unsigned long *)malloc(sizeof(unsigned long));
+	  *(preg->refCount) = 1;
+	}
+      else
+	{
+	  if (preg->pRegExp)
+	    free(preg->pRegExp);
+	  free(preg);
+	  preg = (RegExp_Arg*)0;
+	}
+    }
+  return((void *)preg);
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  char *rx = va_arg(*ap,char *);
+  RegExp_Arg *pArg;
+
+  pArg = (RegExp_Arg *)malloc(sizeof(RegExp_Arg));
+
+  if (pArg)
+    {
+      int blen = RX_INCREMENT;
+      pArg->compiled_expression = NULL;
+      pArg->refCount = (unsigned long *)malloc(sizeof(unsigned long));
+      *(pArg->refCount) = 1;
+
+      do {
+	char *buf = (char *)malloc(blen);
+	if (buf)
+	  {
+#if HAVE_REGEXP_H_FUNCS
+	    char *last_pos = compile (rx, buf, &buf[blen], '\0');
+#else /* HAVE_REGEXPR_H_FUNCS */
+	    char *last_pos = compile (rx, buf, &buf[blen]);
+#endif
+	    if (reg_errno)
+	      {
+		free(buf);
+		if (reg_errno==50)
+		  blen += RX_INCREMENT;
+		else
+		  {
+		    free(pArg);
+		    pArg = NULL;
+		    break;
+		  }
+	      }
+	    else
+	      {
+		pArg->compiled_expression = buf;
+		break;
+	      }
+	  }
+      } while( blen <= MAX_RX_LEN );
+    }
+  if (pArg && !pArg->compiled_expression)
+    {
+      free(pArg);
+      pArg = NULL;
+    }
+  return (void *)pArg;
+#else
+  return 0;
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void *Copy_RegularExpression_Type(
+|                                      const void * argp)
+|
+|   Description   :  Copy structure for regex type argument.
+|
+|   Return Values :  Pointer to argument structure or NULL on error.
++--------------------------------------------------------------------------*/
+static void *Copy_RegularExpression_Type(const void * argp)
+{
+#if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS)
+  const RegExp_Arg *ap = (const RegExp_Arg *)argp;
+  const RegExp_Arg *result = (const RegExp_Arg *)0;
+
+  if (ap)
+    {
+      *(ap->refCount) += 1;
+      result = ap;
+    }
+  return (void *)result;
+#else
+  return 0;
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static void Free_RegularExpression_Type(void * argp)
+|
+|   Description   :  Free structure for regex type argument.
+|
+|   Return Values :  -
++--------------------------------------------------------------------------*/
+static void Free_RegularExpression_Type(void * argp)
+{
+#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  RegExp_Arg *ap = (RegExp_Arg *)argp;
+  if (ap)
+    {
+      if (--(*(ap->refCount)) == 0)
+	{
+#if HAVE_REGEX_H_FUNCS
+	  if (ap->pRegExp)
+	    {
+	      free(ap->refCount);
+	      regfree(ap->pRegExp);
+	    }
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+	  if (ap->compiled_expression)
+	    {
+	      free(ap->refCount);
+	      free(ap->compiled_expression);
+	    }
+#endif
+	  free(ap);
+	}
+    }
+#endif
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  static bool Check_RegularExpression_Field(
+|                                      FIELD * field,
+|                                      const void  * argp)
+|
+|   Description   :  Validate buffer content to be a valid regular expression
+|
+|   Return Values :  TRUE  - field is valid
+|                    FALSE - field is invalid
++--------------------------------------------------------------------------*/
+static bool Check_RegularExpression_Field(FIELD * field, const void  * argp)
+{
+  bool match = FALSE;
+#if HAVE_REGEX_H_FUNCS
+  const RegExp_Arg *ap = (const RegExp_Arg*)argp;
+  if (ap && ap->pRegExp)
+    match = (regexec(ap->pRegExp,field_buffer(field,0),0,NULL,0) ? FALSE:TRUE);
+#elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS
+  RegExp_Arg *ap = (RegExp_Arg *)argp;
+  if (ap && ap->compiled_expression)
+    match = (step(field_buffer(field,0),ap->compiled_expression) ? TRUE:FALSE);
+#endif
+  return match;
+}
+
+static FIELDTYPE typeREGEXP = {
+  _HAS_ARGS | _RESIDENT,
+  1,                           /* this is mutable, so we can't be const */
+  (FIELDTYPE *)0,
+  (FIELDTYPE *)0,
+  Make_RegularExpression_Type,
+  Copy_RegularExpression_Type,
+  Free_RegularExpression_Type,
+  Check_RegularExpression_Field,
+  NULL,
+  NULL,
+  NULL
+};
+
+FIELDTYPE* TYPE_REGEXP = &typeREGEXP;
+
+/* fty_regex.c ends here */

+ 694 - 0
Source/CursesDialog/form/llib-lform

@@ -0,0 +1,694 @@
+/****************************************************************************
+ * Copyright (c) 1998 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: Thomas E. Dickey <[email protected]> 1996,1997                   *
+ ****************************************************************************/
+/* LINTLIBRARY */
+
+/* ./fld_arg.c */
+
+#include "form.priv.h"
+
+#undef set_fieldtype_arg
+int	set_fieldtype_arg(
+		FIELDTYPE *typ, 
+		void	*(*const make_arg)(
+		va_list	*p1), 
+		void	*(*const copy_arg)(
+		const void *p1), 
+		void	(*const free_arg)(
+		void	*p1))
+		{ return(*(int *)0); }
+
+#undef field_arg
+void	*field_arg(
+		const FIELD *field)
+		{ return(*(void **)0); }
+
+/* ./fld_attr.c */
+
+#undef set_field_fore
+int	set_field_fore(
+		FIELD	*field, 
+		chtype	attr)
+		{ return(*(int *)0); }
+
+#undef field_fore
+chtype	field_fore(
+		const FIELD *field)
+		{ return(*(chtype *)0); }
+
+#undef set_field_back
+int	set_field_back(
+		FIELD	*field, 
+		chtype	attr)
+		{ return(*(int *)0); }
+
+#undef field_back
+chtype	field_back(
+		const FIELD *field)
+		{ return(*(chtype *)0); }
+
+/* ./fld_current.c */
+
+#undef set_current_field
+int	set_current_field(
+		FORM	*form, 
+		FIELD	*field)
+		{ return(*(int *)0); }
+
+#undef current_field
+FIELD	*current_field(
+		const FORM *form)
+		{ return(*(FIELD **)0); }
+
+#undef field_index
+int	field_index(
+		const FIELD *field)
+		{ return(*(int *)0); }
+
+/* ./fld_def.c */
+
+#undef _nc_Default_Field
+FIELD	*_nc_Default_Field;
+
+#undef _nc_Make_Argument
+TypeArgument *_nc_Make_Argument(
+		const FIELDTYPE *typ, 
+		va_list	*ap, 
+		int	*err)
+		{ return(*(TypeArgument **)0); }
+
+#undef _nc_Copy_Argument
+TypeArgument *_nc_Copy_Argument(
+		const FIELDTYPE *typ, 
+		const TypeArgument *argp, 
+		int	*err)
+		{ return(*(TypeArgument **)0); }
+
+#undef _nc_Free_Argument
+void	_nc_Free_Argument(
+		const FIELDTYPE *typ, 
+		TypeArgument *argp)
+		{ /* void */ }
+
+#undef _nc_Copy_Type
+bool	_nc_Copy_Type(
+		FIELD	*dst, 
+		FIELD const *src)
+		{ return(*(bool *)0); }
+
+#undef _nc_Free_Type
+void	_nc_Free_Type(
+		FIELD	*field)
+		{ /* void */ }
+
+#undef new_field
+FIELD	*new_field(
+		int	rows, 
+		int	cols, 
+		int	frow, 
+		int	fcol, 
+		int	nrow, 
+		int	nbuf)
+		{ return(*(FIELD **)0); }
+
+#undef free_field
+int	free_field(
+		FIELD	*field)
+		{ return(*(int *)0); }
+
+/* ./fld_dup.c */
+
+#undef dup_field
+FIELD	*dup_field(
+		FIELD	*field, 
+		int	frow, 
+		int	fcol)
+		{ return(*(FIELD **)0); }
+
+/* ./fld_ftchoice.c */
+
+#undef set_fieldtype_choice
+int	set_fieldtype_choice(
+		FIELDTYPE *typ, 
+		bool	(*const next_choice)(
+		FIELD	*p1, 
+		const void *p2), 
+		bool	(*const prev_choice)(
+		FIELD	*p1, 
+		const void *p2))
+		{ return(*(int *)0); }
+
+/* ./fld_ftlink.c */
+
+#undef link_fieldtype
+FIELDTYPE *link_fieldtype(
+		FIELDTYPE *type1, 
+		FIELDTYPE *type2)
+		{ return(*(FIELDTYPE **)0); }
+
+/* ./fld_info.c */
+
+#undef field_info
+int	field_info(
+		const FIELD *field, 
+		int	*rows, 
+		int	*cols, 
+		int	*frow, 
+		int	*fcol, 
+		int	*nrow, 
+		int	*nbuf)
+		{ return(*(int *)0); }
+
+#undef dynamic_field_info
+int	dynamic_field_info(
+		const FIELD *field, 
+		int	*drows, 
+		int	*dcols, 
+		int	*maxgrow)
+		{ return(*(int *)0); }
+
+/* ./fld_just.c */
+
+#undef set_field_just
+int	set_field_just(
+		FIELD	*field, 
+		int	just)
+		{ return(*(int *)0); }
+
+#undef field_just
+int	field_just(
+		const FIELD *field)
+		{ return(*(int *)0); }
+
+/* ./fld_link.c */
+
+#undef link_field
+FIELD	*link_field(
+		FIELD	*field, 
+		int	frow, 
+		int	fcol)
+		{ return(*(FIELD **)0); }
+
+/* ./fld_max.c */
+
+#undef set_max_field
+int	set_max_field(
+		FIELD	*field, 
+		int	maxgrow)
+		{ return(*(int *)0); }
+
+/* ./fld_move.c */
+
+#undef move_field
+int	move_field(
+		FIELD	*field, 
+		int	frow, 
+		int	fcol)
+		{ return(*(int *)0); }
+
+/* ./fld_newftyp.c */
+
+#undef _nc_Default_FieldType
+const FIELDTYPE *_nc_Default_FieldType = {0};
+
+#undef new_fieldtype
+FIELDTYPE *new_fieldtype(
+		bool	(*const field_check)(
+		FIELD	*p1, 
+		const void *p2), 
+		bool	(*const char_check)(
+		int	p1, 
+		const void *p2))
+		{ return(*(FIELDTYPE **)0); }
+
+#undef free_fieldtype
+int	free_fieldtype(
+		FIELDTYPE *typ)
+		{ return(*(int *)0); }
+
+/* ./fld_opts.c */
+
+#undef set_field_opts
+int	set_field_opts(
+		FIELD	*field, 
+		Field_Options opts)
+		{ return(*(int *)0); }
+
+#undef field_opts
+Field_Options field_opts(
+		const FIELD *field)
+		{ return(*(Field_Options *)0); }
+
+#undef field_opts_on
+int	field_opts_on(
+		FIELD	*field, 
+		Field_Options opts)
+		{ return(*(int *)0); }
+
+#undef field_opts_off
+int	field_opts_off(
+		FIELD	*field, 
+		Field_Options opts)
+		{ return(*(int *)0); }
+
+/* ./fld_pad.c */
+
+#undef set_field_pad
+int	set_field_pad(
+		FIELD	*field, 
+		int	ch)
+		{ return(*(int *)0); }
+
+#undef field_pad
+int	field_pad(
+		const FIELD *field)
+		{ return(*(int *)0); }
+
+/* ./fld_page.c */
+
+#undef set_new_page
+int	set_new_page(
+		FIELD	*field, 
+		bool	new_page_flag)
+		{ return(*(int *)0); }
+
+#undef new_page
+bool	new_page(
+		const FIELD *field)
+		{ return(*(bool *)0); }
+
+/* ./fld_stat.c */
+
+#undef set_field_status
+int	set_field_status(
+		FIELD	*field, 
+		bool	status)
+		{ return(*(int *)0); }
+
+#undef field_status
+bool	field_status(
+		const FIELD *field)
+		{ return(*(bool *)0); }
+
+/* ./fld_type.c */
+
+#undef set_field_type
+int	set_field_type(
+		FIELD	*field, 
+		FIELDTYPE *type, 
+		...)
+		{ return(*(int *)0); }
+
+#undef field_type
+FIELDTYPE *field_type(
+		const FIELD *field)
+		{ return(*(FIELDTYPE **)0); }
+
+/* ./fld_user.c */
+
+#undef set_field_userptr
+int	set_field_userptr(
+		FIELD	*field, 
+		void	*usrptr)
+		{ return(*(int *)0); }
+
+#undef field_userptr
+void	*field_userptr(
+		const FIELD *field)
+		{ return(*(void **)0); }
+
+/* ./frm_cursor.c */
+
+#undef pos_form_cursor
+int	pos_form_cursor(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+/* ./frm_data.c */
+
+#undef data_behind
+bool	data_behind(
+		const FORM *form)
+		{ return(*(bool *)0); }
+
+#undef data_ahead
+bool	data_ahead(
+		const FORM *form)
+		{ return(*(bool *)0); }
+
+/* ./frm_def.c */
+
+#undef _nc_Default_Form
+FORM	*_nc_Default_Form;
+
+#undef new_form
+FORM	*new_form(
+		FIELD	**fields)
+		{ return(*(FORM **)0); }
+
+#undef free_form
+int	free_form(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+#undef set_form_fields
+int	set_form_fields(
+		FORM	*form, 
+		FIELD	**fields)
+		{ return(*(int *)0); }
+
+#undef form_fields
+FIELD	**form_fields(
+		const FORM *form)
+		{ return(*(FIELD ***)0); }
+
+#undef field_count
+int	field_count(
+		const FORM *form)
+		{ return(*(int *)0); }
+
+/* ./frm_driver.c */
+
+#undef _nc_Position_Form_Cursor
+int	_nc_Position_Form_Cursor(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+#undef _nc_Refresh_Current_Field
+int	_nc_Refresh_Current_Field(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+#undef _nc_Synchronize_Attributes
+int	_nc_Synchronize_Attributes(
+		FIELD	*field)
+		{ return(*(int *)0); }
+
+#undef _nc_Synchronize_Options
+int	_nc_Synchronize_Options(
+		FIELD	*field, 
+		Field_Options newopts)
+		{ return(*(int *)0); }
+
+#undef _nc_Set_Current_Field
+int	_nc_Set_Current_Field(
+		FORM	*form, 
+		FIELD	*newfield)
+		{ return(*(int *)0); }
+
+#undef _nc_Internal_Validation
+bool	_nc_Internal_Validation(
+		FORM	*form)
+		{ return(*(bool *)0); }
+
+#undef _nc_First_Active_Field
+FIELD	*_nc_First_Active_Field(
+		FORM	*form)
+		{ return(*(FIELD **)0); }
+
+#undef _nc_Set_Form_Page
+int	_nc_Set_Form_Page(
+		FORM	*form, 
+		int	page, 
+		FIELD	*field)
+		{ return(*(int *)0); }
+
+typedef struct {
+  int keycode;           
+  int (*cmd)(FORM *);    
+} Binding_Info;
+
+#undef form_driver
+int	form_driver(
+		FORM	*form, 
+		int	c)
+		{ return(*(int *)0); }
+
+#undef set_field_buffer
+int	set_field_buffer(
+		FIELD	*field, 
+		int	buffer, 
+		const char *value)
+		{ return(*(int *)0); }
+
+#undef field_buffer
+char	*field_buffer(
+		const FIELD *field, 
+		int	buffer)
+		{ return(*(char **)0); }
+
+/* ./frm_hook.c */
+
+#undef set_field_init
+int	set_field_init(
+		FORM	*form, 
+		Form_Hook func)
+		{ return(*(int *)0); }
+
+#undef field_init
+Form_Hook field_init(
+		const FORM *form)
+		{ return(*(Form_Hook *)0); }
+
+#undef set_field_term
+int	set_field_term(
+		FORM	*form, 
+		Form_Hook func)
+		{ return(*(int *)0); }
+
+#undef field_term
+Form_Hook field_term(
+		const FORM *form)
+		{ return(*(Form_Hook *)0); }
+
+#undef set_form_init
+int	set_form_init(
+		FORM	*form, 
+		Form_Hook func)
+		{ return(*(int *)0); }
+
+#undef form_init
+Form_Hook form_init(
+		const FORM *form)
+		{ return(*(Form_Hook *)0); }
+
+#undef set_form_term
+int	set_form_term(
+		FORM	*form, 
+		Form_Hook func)
+		{ return(*(int *)0); }
+
+#undef form_term
+Form_Hook form_term(
+		const FORM *form)
+		{ return(*(Form_Hook *)0); }
+
+/* ./frm_opts.c */
+
+#undef set_form_opts
+int	set_form_opts(
+		FORM	*form, 
+		Form_Options opts)
+		{ return(*(int *)0); }
+
+#undef form_opts
+Form_Options form_opts(
+		const FORM *form)
+		{ return(*(Form_Options *)0); }
+
+#undef form_opts_on
+int	form_opts_on(
+		FORM	*form, 
+		Form_Options opts)
+		{ return(*(int *)0); }
+
+#undef form_opts_off
+int	form_opts_off(
+		FORM	*form, 
+		Form_Options opts)
+		{ return(*(int *)0); }
+
+/* ./frm_page.c */
+
+#undef set_form_page
+int	set_form_page(
+		FORM	*form, 
+		int	page)
+		{ return(*(int *)0); }
+
+#undef form_page
+int	form_page(
+		const FORM *form)
+		{ return(*(int *)0); }
+
+/* ./frm_post.c */
+
+#undef post_form
+int	post_form(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+#undef unpost_form
+int	unpost_form(
+		FORM	*form)
+		{ return(*(int *)0); }
+
+/* ./frm_req_name.c */
+
+#undef form_request_name
+const char *form_request_name(
+		int	request)
+		{ return(*(const char **)0); }
+
+#undef form_request_by_name
+int	form_request_by_name(
+		const char *str)
+		{ return(*(int *)0); }
+
+/* ./frm_scale.c */
+
+#undef scale_form
+int	scale_form(
+		const FORM *form, 
+		int	*rows, 
+		int	*cols)
+		{ return(*(int *)0); }
+
+/* ./frm_sub.c */
+
+#undef set_form_sub
+int	set_form_sub(
+		FORM	*form, 
+		WINDOW	*win)
+		{ return(*(int *)0); }
+
+#undef form_sub
+WINDOW	*form_sub(
+		const FORM *form)
+		{ return(*(WINDOW **)0); }
+
+/* ./frm_user.c */
+
+#undef set_form_userptr
+int	set_form_userptr(
+		FORM	*form, 
+		void	*usrptr)
+		{ return(*(int *)0); }
+
+#undef form_userptr
+void	*form_userptr(
+		const FORM *form)
+		{ return(*(void **)0); }
+
+/* ./frm_win.c */
+
+#undef set_form_win
+int	set_form_win(
+		FORM	*form, 
+		WINDOW	*win)
+		{ return(*(int *)0); }
+
+#undef form_win
+WINDOW	*form_win(
+		const FORM *form)
+		{ return(*(WINDOW **)0); }
+
+/* ./fty_alnum.c */
+
+typedef struct {
+  int width;
+} alnumARG;
+
+#undef TYPE_ALNUM
+FIELDTYPE *TYPE_ALNUM;
+
+/* ./fty_alpha.c */
+
+typedef struct {
+  int width;
+} alphaARG;
+
+#undef TYPE_ALPHA
+FIELDTYPE *TYPE_ALPHA;
+
+/* ./fty_enum.c */
+
+typedef struct {
+  char **kwds;
+  int  count;
+  bool checkcase;
+  bool checkunique;
+} enumARG;
+
+#undef TYPE_ENUM
+FIELDTYPE *TYPE_ENUM;
+
+/* ./fty_int.c */
+
+typedef struct {
+  int precision;
+  long low;
+  long high;
+} integerARG;
+
+#undef TYPE_INTEGER
+FIELDTYPE *TYPE_INTEGER;
+
+/* ./fty_ipv4.c */
+#undef TYPE_IPV4
+FIELDTYPE *TYPE_IPV4;
+
+/* ./fty_num.c */
+
+#include <locale.h>
+
+typedef struct {
+  int    precision;
+  double low;
+  double high;
+  struct lconv* L;
+} numericARG;
+
+#undef TYPE_NUMERIC
+FIELDTYPE *TYPE_NUMERIC;
+
+/* ./fty_regex.c */
+
+#include <regex.h>
+
+typedef struct
+{
+  regex_t *pRegExp;
+  unsigned long *refCount;
+} RegExp_Arg;
+
+#undef TYPE_REGEXP
+FIELDTYPE *TYPE_REGEXP;

+ 93 - 0
Source/CursesDialog/form/mf_common.h

@@ -0,0 +1,93 @@
+/****************************************************************************
+ * Copyright (c) 1998,2000 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 <[email protected]> 1995,1997            *
+ ****************************************************************************/
+
+/* Common internal header for menu and form library */
+
+#if HAVE_CONFIG_H
+#  include <ncurses_cfg.h>
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#if DECL_ERRNO
+extern int errno;
+#endif
+
+/* in case of debug version we ignore the suppression of assertions */
+#ifdef TRACE
+#  ifdef NDEBUG
+#    undef NDEBUG
+#  endif
+#endif
+
+#include <nc_alloc.h>
+
+#if USE_RCS_IDS
+#define MODULE_ID(id) static const char Ident[] = id;
+#else
+#define MODULE_ID(id) /*nothing*/
+#endif
+
+
+/* Maximum regular 8-bit character code */
+#define MAX_REGULAR_CHARACTER (0xff)
+
+#define SET_ERROR(code) (errno=(code))
+#define GET_ERROR() (errno)
+#define RETURN(code) return( SET_ERROR(code) )
+
+/* The few common values in the status fields for menus and forms */
+#define _POSTED         (0x01)  /* menu or form is posted                  */
+#define _IN_DRIVER      (0x02)  /* menu or form is processing hook routine */
+
+/* Call object hook */
+#define Call_Hook( object, handler ) \
+   if ( (object) && ((object)->handler) )\
+   {\
+	(object)->status |= _IN_DRIVER;\
+	(object)->handler(object);\
+	(object)->status &= ~_IN_DRIVER;\
+   }
+
+#define INLINE
+
+#ifndef TRACE
+#  if CC_HAS_INLINE_FUNCS
+#    undef INLINE
+#    define INLINE inline
+#  endif
+#endif

+ 83 - 0
Source/CursesDialog/form/nc_alloc.h

@@ -0,0 +1,83 @@
+/****************************************************************************
+ * Copyright (c) 1998 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: Thomas E. Dickey <[email protected]> 1996,1997                   *
+ ****************************************************************************/
+/* $Id$ */
+
+#ifndef NC_ALLOC_included
+#define NC_ALLOC_included 1
+
+#if HAVE_LIBDMALLOC
+#include <dmalloc.h>    /* Gray Watson's library */
+#else
+#undef  HAVE_LIBDMALLOC
+#define HAVE_LIBDMALLOC 0
+#endif
+
+#if HAVE_LIBDBMALLOC
+#include <dbmalloc.h>   /* Conor Cahill's library */
+#else
+#undef  HAVE_LIBDBMALLOC
+#define HAVE_LIBDBMALLOC 0
+#endif
+
+#ifndef NO_LEAKS
+#define NO_LEAKS 0
+#endif
+
+#if HAVE_LIBDBMALLOC || HAVE_LIBDMALLOC || NO_LEAKS
+#define HAVE_NC_FREEALL 1
+struct termtype;
+extern void _nc_free_and_exit(int) GCC_NORETURN;
+extern void _nc_free_tparm(void);
+extern void _nc_leaks_dump_entry(void);
+#define ExitProgram(code) _nc_free_and_exit(code)
+#endif
+
+#ifndef HAVE_NC_FREEALL
+#define HAVE_NC_FREEALL 0
+#endif
+
+#ifndef ExitProgram
+#define ExitProgram(code) return code
+#endif
+
+/* doalloc.c */
+extern void *_nc_doalloc(void *, size_t);
+#if !HAVE_STRDUP
+#define strdup _nc_strdup
+extern char *_nc_strdup(const char *);
+#endif
+
+#define typeMalloc(type,elts) (type *)malloc((elts)*sizeof(type))
+#define typeCalloc(type,elts) (type *)calloc((elts),sizeof(type))
+#define typeRealloc(type,elts,ptr) (type *)_nc_doalloc(ptr, (elts)*sizeof(type))
+
+#endif /* NC_ALLOC_included */