106bfebdeSXin LI /****************************************************************************
2*21817992SBaptiste Daroussin * Copyright 2018-2020,2021 Thomas E. Dickey *
3e1865124SBaptiste Daroussin * Copyright 2008-2012,2016 Free Software Foundation, Inc. *
406bfebdeSXin LI * *
506bfebdeSXin LI * Permission is hereby granted, free of charge, to any person obtaining a *
606bfebdeSXin LI * copy of this software and associated documentation files (the *
706bfebdeSXin LI * "Software"), to deal in the Software without restriction, including *
806bfebdeSXin LI * without limitation the rights to use, copy, modify, merge, publish, *
906bfebdeSXin LI * distribute, distribute with modifications, sublicense, and/or sell *
1006bfebdeSXin LI * copies of the Software, and to permit persons to whom the Software is *
1106bfebdeSXin LI * furnished to do so, subject to the following conditions: *
1206bfebdeSXin LI * *
1306bfebdeSXin LI * The above copyright notice and this permission notice shall be included *
1406bfebdeSXin LI * in all copies or substantial portions of the Software. *
1506bfebdeSXin LI * *
1606bfebdeSXin LI * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
1706bfebdeSXin LI * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
1806bfebdeSXin LI * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
1906bfebdeSXin LI * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
2006bfebdeSXin LI * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
2106bfebdeSXin LI * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
2206bfebdeSXin LI * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
2306bfebdeSXin LI * *
2406bfebdeSXin LI * Except as contained in this notice, the name(s) of the above copyright *
2506bfebdeSXin LI * holders shall not be used in advertising or otherwise to promote the *
2606bfebdeSXin LI * sale, use or other dealings in this Software without prior written *
2706bfebdeSXin LI * authorization. *
2806bfebdeSXin LI ****************************************************************************/
2906bfebdeSXin LI
3006bfebdeSXin LI /***************************************************************************
3106bfebdeSXin LI * *
3206bfebdeSXin LI * Author : Juergen Pfeifer *
3306bfebdeSXin LI * *
3406bfebdeSXin LI ***************************************************************************/
3506bfebdeSXin LI
3606bfebdeSXin LI #include "form.priv.h"
3706bfebdeSXin LI
38*21817992SBaptiste Daroussin MODULE_ID("$Id: fty_generic.c,v 1.15 2021/03/27 23:49:53 tom Exp $")
3906bfebdeSXin LI
4006bfebdeSXin LI /*
4106bfebdeSXin LI * This is not a full implementation of a field type, but adds some
4206bfebdeSXin LI * support for higher level languages with some restrictions to interop
437a656419SBaptiste Daroussin * with C language. In particular, the collection of arguments for the
4406bfebdeSXin LI * various fieldtypes is not based on the vararg C mechanism, but on a
457a656419SBaptiste Daroussin * iterator based callback mechanism that allows the high level language
4606bfebdeSXin LI * to provide the arguments as a structure. Most languages have mechanisms
4706bfebdeSXin LI * to layout structures so that they can be passed to C.
487a656419SBaptiste Daroussin *
4906bfebdeSXin LI * The languages can register a new generic fieldtype dynamically and store
5006bfebdeSXin LI * a handle (key) to the calling object as an argument. Together with that
5106bfebdeSXin LI * it can register a freearg callback, so that the high level language
5206bfebdeSXin LI * remains in control of the memory management of the arguments they pass.
5306bfebdeSXin LI * The design idea is, that the high-level language - typically a OO
547a656419SBaptiste Daroussin * language like C# or Java, uses its own dispatching mechanisms
5506bfebdeSXin LI * (polymorphism) to call the proper check routines responsible for the
5606bfebdeSXin LI * argument type. So these language implement typically only one generic
5706bfebdeSXin LI * fieldtype they register with the forms library using this call.
5806bfebdeSXin LI *
597a656419SBaptiste Daroussin * For that purpose we have extended the fieldtype structure by a new element
6006bfebdeSXin LI * that gets the arguments from a single struct passed by the caller.
6106bfebdeSXin LI *
6206bfebdeSXin LI */
6306bfebdeSXin LI #if NCURSES_INTEROP_FUNCS
6406bfebdeSXin LI
6506bfebdeSXin LI /*---------------------------------------------------------------------------
6606bfebdeSXin LI | Facility : libnform
6706bfebdeSXin LI | Function : static void *Generic_This_Type( void * arg )
6806bfebdeSXin LI |
6906bfebdeSXin LI | Description : We interpret the passed arg just as a handle the
7006bfebdeSXin LI | calling language uses to keep track of its allocated
7106bfebdeSXin LI | argument structures. We can simply copy it back.
7206bfebdeSXin LI |
7306bfebdeSXin LI | Return Values : Pointer to argument structure
7406bfebdeSXin LI +--------------------------------------------------------------------------*/
7506bfebdeSXin LI static void *
Generic_This_Type(void * arg)7606bfebdeSXin LI Generic_This_Type(void *arg)
7706bfebdeSXin LI {
7806bfebdeSXin LI return (arg);
7906bfebdeSXin LI }
8006bfebdeSXin LI
8106bfebdeSXin LI /*---------------------------------------------------------------------------
8206bfebdeSXin LI | Facility : libnform
8306bfebdeSXin LI | Function : FIELDTYPE *_nc_generic_fieldtype(
8406bfebdeSXin LI | bool (* const field_check)(FIELD *,const void *),
8506bfebdeSXin LI | bool (* const char_check) (int, const void *),
8606bfebdeSXin LI | bool (*const next)(FORM*,FIELD*,const void*),
8706bfebdeSXin LI | bool (*const prev)(FORM*,FIELD*,const void*),
8806bfebdeSXin LI | void (*freecallback)(void*))
8906bfebdeSXin LI |
9006bfebdeSXin LI | Description : Create a new fieldtype. The application programmer must
9106bfebdeSXin LI | write a field_check and a char_check function and give
9206bfebdeSXin LI | them as input to this call. A callback to allow the
9306bfebdeSXin LI | release of the allocated memory must also be provided.
9406bfebdeSXin LI | For generic field types, we provide some more
9506bfebdeSXin LI | information about the field as parameters.
9606bfebdeSXin LI |
9706bfebdeSXin LI | If an error occurs, errno is set to
9806bfebdeSXin LI | E_BAD_ARGUMENT - invalid arguments
9906bfebdeSXin LI | E_SYSTEM_ERROR - system error (no memory)
10006bfebdeSXin LI |
10106bfebdeSXin LI | Return Values : Fieldtype pointer or NULL if error occurred
10206bfebdeSXin LI +--------------------------------------------------------------------------*/
1037a656419SBaptiste Daroussin FORM_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 *))10406bfebdeSXin LI _nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *),
10506bfebdeSXin LI bool (*const char_check) (int, FORM *, FIELD *, const
10606bfebdeSXin LI void *),
10706bfebdeSXin LI bool (*const next) (FORM *, FIELD *, const void *),
10806bfebdeSXin LI bool (*const prev) (FORM *, FIELD *, const void *),
10906bfebdeSXin LI void (*freecallback) (void *))
11006bfebdeSXin LI {
11106bfebdeSXin LI int code = E_SYSTEM_ERROR;
11206bfebdeSXin LI FIELDTYPE *res = (FIELDTYPE *)0;
11306bfebdeSXin LI
114aae38d10SBaptiste Daroussin TR_FUNC_BFR(5);
115aae38d10SBaptiste Daroussin
116aae38d10SBaptiste Daroussin T((T_CALLED("_nc_generic_fieldtype(%s,%s,%s,%s,%s)"),
117aae38d10SBaptiste Daroussin TR_FUNC_ARG(0, field_check),
118aae38d10SBaptiste Daroussin TR_FUNC_ARG(1, char_check),
119aae38d10SBaptiste Daroussin TR_FUNC_ARG(2, next),
120aae38d10SBaptiste Daroussin TR_FUNC_ARG(3, prev),
121aae38d10SBaptiste Daroussin TR_FUNC_ARG(4, freecallback)));
12206bfebdeSXin LI
12306bfebdeSXin LI if (field_check || char_check)
12406bfebdeSXin LI {
12506bfebdeSXin LI res = typeMalloc(FIELDTYPE, 1);
12606bfebdeSXin LI
12706bfebdeSXin LI if (res)
12806bfebdeSXin LI {
12906bfebdeSXin LI *res = *_nc_Default_FieldType;
13073f0a83dSXin LI SetStatus(res, (_HAS_ARGS | _GENERIC));
13106bfebdeSXin LI res->fieldcheck.gfcheck = field_check;
13206bfebdeSXin LI res->charcheck.gccheck = char_check;
13306bfebdeSXin LI res->genericarg = Generic_This_Type;
13406bfebdeSXin LI res->freearg = freecallback;
13506bfebdeSXin LI res->enum_next.gnext = next;
13606bfebdeSXin LI res->enum_prev.gprev = prev;
13706bfebdeSXin LI code = E_OK;
13806bfebdeSXin LI }
13906bfebdeSXin LI }
14006bfebdeSXin LI else
14106bfebdeSXin LI code = E_BAD_ARGUMENT;
14206bfebdeSXin LI
14306bfebdeSXin LI if (E_OK != code)
14406bfebdeSXin LI SET_ERROR(code);
14506bfebdeSXin LI
14606bfebdeSXin LI returnFieldType(res);
14706bfebdeSXin LI }
14806bfebdeSXin LI
14906bfebdeSXin LI /*---------------------------------------------------------------------------
15006bfebdeSXin LI | Facility : libnform
15106bfebdeSXin LI | Function : static TypeArgument *GenericArgument(
15206bfebdeSXin LI | const FIELDTYPE* typ,
15306bfebdeSXin LI | int (*argiterator)(void**),
15406bfebdeSXin LI | int* err)
15506bfebdeSXin LI |
15606bfebdeSXin LI | Description : The iterator callback must browse through all fieldtype
15706bfebdeSXin LI | parameters that have an argument associated with the
15806bfebdeSXin LI | type. The iterator returns 1 if the operation to get
159aae38d10SBaptiste Daroussin | the next element was successful, 0 otherwise. If the
16006bfebdeSXin LI | iterator could move to the next argument, it fills
16106bfebdeSXin LI | the void* pointer representing the argument into the
16206bfebdeSXin LI | location provided as argument to the iterator.
16306bfebdeSXin LI | The err reference is used to keep track of errors.
16406bfebdeSXin LI |
16506bfebdeSXin LI | Return Values : Pointer to argument structure
16606bfebdeSXin LI +--------------------------------------------------------------------------*/
16706bfebdeSXin LI static TypeArgument *
GenericArgument(const FIELDTYPE * typ,int (* argiterator)(void **),int * err)16806bfebdeSXin LI GenericArgument(const FIELDTYPE *typ,
16906bfebdeSXin LI int (*argiterator) (void **), int *err)
17006bfebdeSXin LI {
17106bfebdeSXin LI TypeArgument *res = (TypeArgument *)0;
17206bfebdeSXin LI
17306bfebdeSXin LI if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0)
17406bfebdeSXin LI {
17506bfebdeSXin LI if (typ->status & _LINKED_TYPE)
17606bfebdeSXin LI {
17706bfebdeSXin LI /* Composite fieldtypes keep track internally of their own memory */
17806bfebdeSXin LI TypeArgument *p = typeMalloc(TypeArgument, 1);
17906bfebdeSXin LI
18006bfebdeSXin LI if (p)
18106bfebdeSXin LI {
18206bfebdeSXin LI p->left = GenericArgument(typ->left, argiterator, err);
18306bfebdeSXin LI p->right = GenericArgument(typ->right, argiterator, err);
18406bfebdeSXin LI return p;
18506bfebdeSXin LI }
18606bfebdeSXin LI else
18706bfebdeSXin LI *err += 1;
18806bfebdeSXin LI }
18906bfebdeSXin LI else
19006bfebdeSXin LI {
19106bfebdeSXin LI assert(typ->genericarg != (void *)0);
19206bfebdeSXin LI if (typ->genericarg == 0)
19306bfebdeSXin LI *err += 1;
19406bfebdeSXin LI else
19506bfebdeSXin LI {
19606bfebdeSXin LI void *argp;
19706bfebdeSXin LI int valid = argiterator(&argp);
19806bfebdeSXin LI
19906bfebdeSXin LI if (valid == 0 || argp == 0 ||
20006bfebdeSXin LI !(res = (TypeArgument *)typ->genericarg(argp)))
20106bfebdeSXin LI {
20206bfebdeSXin LI *err += 1;
20306bfebdeSXin LI }
20406bfebdeSXin LI }
20506bfebdeSXin LI }
20606bfebdeSXin LI }
20706bfebdeSXin LI return res;
20806bfebdeSXin LI }
20906bfebdeSXin LI
21006bfebdeSXin LI /*---------------------------------------------------------------------------
21106bfebdeSXin LI | Facility : libnform
21206bfebdeSXin LI | Function : int _nc_set_generic_fieldtype(
21306bfebdeSXin LI | FIELD* field,
21406bfebdeSXin LI | FIELDTYPE* ftyp,
21506bfebdeSXin LI | int (*argiterator)(void**))
21606bfebdeSXin LI |
21706bfebdeSXin LI | Description : Assign the fieldtype to the field and use the iterator
21806bfebdeSXin LI | mechanism to get the arguments when a check is
21906bfebdeSXin LI | performed.
22006bfebdeSXin LI |
22106bfebdeSXin LI | Return Values : E_OK if all went well
22206bfebdeSXin LI | E_SYSTEM_ERROR if an error occurred
22306bfebdeSXin LI +--------------------------------------------------------------------------*/
2247a656419SBaptiste Daroussin FORM_EXPORT(int)
_nc_set_generic_fieldtype(FIELD * field,FIELDTYPE * ftyp,int (* argiterator)(void **))22506bfebdeSXin LI _nc_set_generic_fieldtype(FIELD *field,
22606bfebdeSXin LI FIELDTYPE *ftyp,
22706bfebdeSXin LI int (*argiterator) (void **))
22806bfebdeSXin LI {
22906bfebdeSXin LI int code = E_SYSTEM_ERROR;
23006bfebdeSXin LI int err = 0;
23106bfebdeSXin LI
23206bfebdeSXin LI if (field)
23306bfebdeSXin LI {
23406bfebdeSXin LI if (field && field->type)
23506bfebdeSXin LI _nc_Free_Type(field);
23606bfebdeSXin LI
23706bfebdeSXin LI field->type = ftyp;
23806bfebdeSXin LI if (ftyp)
23906bfebdeSXin LI {
24006bfebdeSXin LI if (argiterator)
24106bfebdeSXin LI {
24206bfebdeSXin LI /* The precondition is that the iterator is reset */
24306bfebdeSXin LI field->arg = (void *)GenericArgument(field->type, argiterator, &err);
24406bfebdeSXin LI
24506bfebdeSXin LI if (err)
24606bfebdeSXin LI {
24706bfebdeSXin LI _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
24806bfebdeSXin LI field->type = (FIELDTYPE *)0;
24906bfebdeSXin LI field->arg = (void *)0;
25006bfebdeSXin LI }
25106bfebdeSXin LI else
25206bfebdeSXin LI {
25306bfebdeSXin LI code = E_OK;
25406bfebdeSXin LI if (field->type)
25506bfebdeSXin LI field->type->ref++;
25606bfebdeSXin LI }
25706bfebdeSXin LI }
25806bfebdeSXin LI }
25906bfebdeSXin LI else
26006bfebdeSXin LI {
26106bfebdeSXin LI field->arg = (void *)0;
26206bfebdeSXin LI code = E_OK;
26306bfebdeSXin LI }
26406bfebdeSXin LI }
26506bfebdeSXin LI return code;
26606bfebdeSXin LI }
26706bfebdeSXin LI
26806bfebdeSXin LI /*---------------------------------------------------------------------------
26906bfebdeSXin LI | Facility : libnform
27006bfebdeSXin LI | Function : WINDOW* _nc_form_cursor(
27106bfebdeSXin LI | FORM* form,
27206bfebdeSXin LI | int *pRow, int *pCol)
27306bfebdeSXin LI |
27406bfebdeSXin LI | Description : Get the current position of the form cursor position
27506bfebdeSXin LI | We also return the field window
27606bfebdeSXin LI |
2777a656419SBaptiste Daroussin | Return Values : The field's Window or NULL on error
27806bfebdeSXin LI +--------------------------------------------------------------------------*/
2797a656419SBaptiste Daroussin FORM_EXPORT(WINDOW *)
_nc_form_cursor(const FORM * form,int * pRow,int * pCol)28006bfebdeSXin LI _nc_form_cursor(const FORM *form, int *pRow, int *pCol)
28106bfebdeSXin LI {
28206bfebdeSXin LI int code = E_SYSTEM_ERROR;
28306bfebdeSXin LI WINDOW *res = (WINDOW *)0;
28406bfebdeSXin LI
285*21817992SBaptiste Daroussin if (form != 0 && pRow != 0 && pCol != 0)
28606bfebdeSXin LI {
28706bfebdeSXin LI *pRow = form->currow;
28806bfebdeSXin LI *pCol = form->curcol;
28906bfebdeSXin LI res = form->w;
29006bfebdeSXin LI code = E_OK;
29106bfebdeSXin LI }
29206bfebdeSXin LI if (code != E_OK)
29306bfebdeSXin LI SET_ERROR(code);
29406bfebdeSXin LI return res;
29506bfebdeSXin LI }
29606bfebdeSXin LI
29706bfebdeSXin LI #else
29806bfebdeSXin LI extern void _nc_fty_generic(void);
29906bfebdeSXin LI void
30006bfebdeSXin LI _nc_fty_generic(void)
30106bfebdeSXin LI {
30206bfebdeSXin LI }
30306bfebdeSXin LI #endif
30406bfebdeSXin LI
30506bfebdeSXin LI /* fty_generic.c ends here */
306