ncursesw-morphos/form/fty_generic.c
Thomas E. Dickey da1f84b7eb ncurses 5.7 - patch 20090627
+ update llib-lncurses[wt] to use sp-funcs.
+ various code-fixes to build/work with --disable-macros configure
  option.
+ add several new files from Juergen Pfeifer which will be used when
  integration of "sp-funcs" is complete.  This includes a port to
  MinGW.
2009-06-28 01:00:34 +00:00

288 lines
11 KiB
C

/****************************************************************************
* 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 */