]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - form/fty_generic.c
ncurses 5.7 - patch 20090627
[ncurses.git] / form / fty_generic.c
diff --git a/form/fty_generic.c b/form/fty_generic.c
new file mode 100644 (file)
index 0000000..83b5822
--- /dev/null
@@ -0,0 +1,287 @@
+/****************************************************************************
+ * Copyright (c) 2008 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                                                *
+*                                                                          *
+***************************************************************************/
+
+#include "form.priv.h"
+
+MODULE_ID("$Id: fty_generic.c,v 1.1 2008/11/18 08:50:04 juergen Exp $")
+
+/*
+ * This is not a full implementation of a field type, but adds some
+ * support for higher level languages with some restrictions to interop
+ * with C language. Especially the collection of arguments for the
+ * various fieldtypes is not based on the vararg C mechanism, but on a
+ * iterator based callback mechanism that allowes the high level language
+ * to provide the arguments as a structure. Most languages have mechanisms
+ * to layout structures so that they can be passed to C.
+ * The languages can register a new generic fieldtype dynamically and store
+ * a handle (key) to the calling object as an argument. Together with that
+ * it can register a freearg callback, so that the high level language
+ * remains in control of the memory management of the arguments they pass.
+ * The design idea is, that the high-level language - typically a OO
+ * language like C# or Java, uses it's own dispatching mechanisms
+ * (polymorphism) to call the proper check routines responsible for the
+ * argument type. So these language implement typically only one generic
+ * fieldtype they register with the forms library using this call.
+ *
+ * For that purpose we have extended the fieldtype struc by a new element
+ * that gets the arguments from a single struct passed by the caller. 
+ * 
+ */
+
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static void *Generic_This_Type( void * arg )
+|   
+|   Description   :  We interpret the passed arg just as a handle the
+|                    calling language uses to keep track of its allocated
+|                    argument structures. We can simply copy it back.
+|
+|   Return Values :  Pointer to argument structure
++--------------------------------------------------------------------------*/
+static void *
+Generic_This_Type(void *arg)
+{
+  return (arg);
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform
+|   Function      :  FIELDTYPE *_nc_generic_fieldtype(
+|                       bool (* const field_check)(FIELD *,const void *),
+|                       bool (* const char_check) (int, const void *),
+|                      bool (*const next)(FORM*,FIELD*,const void*),
+|                      bool (*const prev)(FORM*,FIELD*,const void*),
+|                       void (*freecallback)(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. A callback to allow the
+|                    release of the allocated memory must also be provided.
+|                    For generic field types, we provide some more 
+|                    information about the field as parameters.
+|
+|                    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 occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(FIELDTYPE *)
+_nc_generic_fieldtype(bool (*const field_check) (FORM*, FIELD *, const void *),
+                     bool (*const char_check)  (int, FORM*, FIELD*, const void *),
+                     bool (*const next)(FORM*, FIELD*,const void*),
+                     bool (*const prev)(FORM*, FIELD*,const void*),
+                     void (*freecallback)(void*))
+{
+    int code = E_SYSTEM_ERROR;
+    FIELDTYPE* res = (FIELDTYPE*)0;
+
+    T((T_CALLED("_nc_generic_fieldtype(%p,%p,%p,%p,%p)"), 
+       field_check, char_check, next, prev, freecallback));
+
+    if (field_check || char_check)
+    {
+      res = typeMalloc(FIELDTYPE,1);
+      if (res)
+      {
+       *res = *_nc_Default_FieldType; 
+       res->status |= (_HAS_ARGS | _GENERIC);
+       res->fieldcheck.gfcheck = field_check;
+       res->charcheck.gccheck  = char_check;
+       res->genericarg = Generic_This_Type;
+       res->freearg = freecallback;
+       res->enum_next.gnext = next;
+       res->enum_prev.gprev = prev;
+       code = E_OK;
+      }
+    }
+    else
+      code = E_BAD_ARGUMENT;
+
+    if (E_OK != code)
+      SET_ERROR(code);
+
+    returnFieldType(res);
+}
+
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  static TypeArgument *GenericArgument(
+|                      const FIELDTYPE* typ,
+|                      int (*argiterator)(void**),
+|                      int* err)
+|   
+|   Description   :  The iterator callback must browse through all fieldtype
+|                    parameters that have an argument associated with the
+|                    type. The iterator returns 1 if the operation to get
+|                    the next element was successfull, 0 otherwise. If the
+|                    iterator could move to the next argument, it fills
+|                    the void* pointer representing the argument into the
+|                    location provided as argument to the iterator.
+|                    The err reference is used to keep track of errors.
+|
+|   Return Values :  Pointer to argument structure
++--------------------------------------------------------------------------*/
+static TypeArgument*
+GenericArgument(const FIELDTYPE *typ, 
+               int (*argiterator)(void**), int *err)
+{
+  TypeArgument *res = (TypeArgument *)0;
+
+  if (typ!=0 && (typ->status & _HAS_ARGS) != 0 && err!=0 && argiterator != 0)
+  {
+    if (typ->status & _LINKED_TYPE)
+    {
+      /* Composite fieldtypes keep track internally of their own memory */
+      TypeArgument* p = typeMalloc(TypeArgument,1);
+      if (p)
+      {
+       p->left  = GenericArgument(typ->left,  argiterator, err);
+       p->right = GenericArgument(typ->right, argiterator, err);
+       return p;
+      }
+      else
+       *err += 1;
+    }
+    else
+    {
+      assert(typ->genericarg != (void*)0);
+      if (typ->genericarg == 0)
+       *err += 1;
+      else
+       {
+         void* argp;
+         int valid = argiterator(&argp);
+         if (valid==0 || argp==0 || 
+             !(res = (TypeArgument*)typ->genericarg(argp)))
+           {
+             *err += 1;
+           }
+       }
+    }
+  }
+  return res;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  int _nc_set_generic_fieldtype(
+|                      FIELD* field,
+|                      FIELDTYPE* ftyp,
+|                      int (*argiterator)(void**))
+|   
+|   Description   :  Assign the fieldtype to the field and use the iterator
+|                    mechanism to get the arguments when a check is 
+|                    performed.
+|
+|   Return Values :  E_OK if all went well
+|                    E_SYSTEM_ERROR if an error occurred
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(int)
+_nc_set_generic_fieldtype(FIELD *field,
+                         FIELDTYPE* ftyp,
+                         int (*argiterator)(void**))
+{
+  int code = E_SYSTEM_ERROR;
+  int err = 0;
+
+  if (field)
+  {
+      if (field && field->type)
+       _nc_Free_Type(field);
+
+      field->type = ftyp;
+      if (ftyp)
+      {
+       if (argiterator)
+       {
+         /* The precondition is that the iterator is reset */
+         field->arg  = (void*)GenericArgument(field->type,argiterator,&err);
+         
+         if (err)
+           {
+             _nc_Free_Argument(field->type, (TypeArgument*)(field->arg));
+             field->type = (FIELDTYPE*)0;
+             field->arg  = (void*)0;
+           }
+         else
+           {
+             code = E_OK;
+             if (field->type)
+               field->type->ref++;
+           }
+       }
+      }
+      else
+      {
+       field->arg = (void*)0;
+       code = E_OK;
+      }
+    }
+    return code;
+}
+
+/*---------------------------------------------------------------------------
+|   Facility      :  libnform  
+|   Function      :  WINDOW* _nc_form_cursor(
+|                      FORM* form,
+|                      int *pRow, int *pCol)
+|   
+|   Description   :  Get the current position of the form cursor position
+|                    We also return the field window
+|
+|   Return Values :  The fields Window or NULL on error
++--------------------------------------------------------------------------*/
+NCURSES_EXPORT(WINDOW*) 
+_nc_form_cursor(const FORM* form, int* pRow, int* pCol)
+{
+  int code = E_SYSTEM_ERROR;
+  WINDOW* res = (WINDOW*)0;
+
+  if (!(form==0 || pRow==0 || pCol==0))
+  {
+      *pRow = form->currow;
+      *pCol = form->curcol;
+      res   = form->w;
+      code  = E_OK;
+  }
+  if (code != E_OK)
+    SET_ERROR(code);
+  return res;
+}
+
+
+/* fty_generic.c ends here */