1 /****************************************************************************
2 * Copyright 2018,2020 Thomas E. Dickey *
3 * Copyright 2008-2012,2016 Free Software Foundation, Inc. *
5 * Permission is hereby granted, free of charge, to any person obtaining a *
6 * copy of this software and associated documentation files (the *
7 * "Software"), to deal in the Software without restriction, including *
8 * without limitation the rights to use, copy, modify, merge, publish, *
9 * distribute, distribute with modifications, sublicense, and/or sell *
10 * copies of the Software, and to permit persons to whom the Software is *
11 * furnished to do so, subject to the following conditions: *
13 * The above copyright notice and this permission notice shall be included *
14 * in all copies or substantial portions of the Software. *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
24 * Except as contained in this notice, the name(s) of the above copyright *
25 * holders shall not be used in advertising or otherwise to promote the *
26 * sale, use or other dealings in this Software without prior written *
28 ****************************************************************************/
30 /***************************************************************************
32 * Author : Juergen Pfeifer *
34 ***************************************************************************/
36 #include "form.priv.h"
38 MODULE_ID("$Id: fty_generic.c,v 1.10 2020/02/02 23:34:34 tom Exp $")
41 * This is not a full implementation of a field type, but adds some
42 * support for higher level languages with some restrictions to interop
43 * with C language. Especially the collection of arguments for the
44 * various fieldtypes is not based on the vararg C mechanism, but on a
45 * iterator based callback mechanism that allowes the high level language
46 * to provide the arguments as a structure. Most languages have mechanisms
47 * to layout structures so that they can be passed to C.
48 * The languages can register a new generic fieldtype dynamically and store
49 * a handle (key) to the calling object as an argument. Together with that
50 * it can register a freearg callback, so that the high level language
51 * remains in control of the memory management of the arguments they pass.
52 * The design idea is, that the high-level language - typically a OO
53 * language like C# or Java, uses it's own dispatching mechanisms
54 * (polymorphism) to call the proper check routines responsible for the
55 * argument type. So these language implement typically only one generic
56 * fieldtype they register with the forms library using this call.
58 * For that purpose we have extended the fieldtype struc by a new element
59 * that gets the arguments from a single struct passed by the caller.
62 #if NCURSES_INTEROP_FUNCS
64 /*---------------------------------------------------------------------------
66 | Function : static void *Generic_This_Type( void * arg )
68 | Description : We interpret the passed arg just as a handle the
69 | calling language uses to keep track of its allocated
70 | argument structures. We can simply copy it back.
72 | Return Values : Pointer to argument structure
73 +--------------------------------------------------------------------------*/
75 Generic_This_Type(void *arg)
80 /*---------------------------------------------------------------------------
82 | Function : FIELDTYPE *_nc_generic_fieldtype(
83 | bool (* const field_check)(FIELD *,const void *),
84 | bool (* const char_check) (int, const void *),
85 | bool (*const next)(FORM*,FIELD*,const void*),
86 | bool (*const prev)(FORM*,FIELD*,const void*),
87 | void (*freecallback)(void*))
89 | Description : Create a new fieldtype. The application programmer must
90 | write a field_check and a char_check function and give
91 | them as input to this call. A callback to allow the
92 | release of the allocated memory must also be provided.
93 | For generic field types, we provide some more
94 | information about the field as parameters.
96 | If an error occurs, errno is set to
97 | E_BAD_ARGUMENT - invalid arguments
98 | E_SYSTEM_ERROR - system error (no memory)
100 | Return Values : Fieldtype pointer or NULL if error occurred
101 +--------------------------------------------------------------------------*/
102 NCURSES_EXPORT(FIELDTYPE *)
103 _nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *),
104 bool (*const char_check) (int, FORM *, FIELD *, const
106 bool (*const next) (FORM *, FIELD *, const void *),
107 bool (*const prev) (FORM *, FIELD *, const void *),
108 void (*freecallback) (void *))
110 int code = E_SYSTEM_ERROR;
111 FIELDTYPE *res = (FIELDTYPE *)0;
115 T((T_CALLED("_nc_generic_fieldtype(%s,%s,%s,%s,%s)"),
116 TR_FUNC_ARG(0, field_check),
117 TR_FUNC_ARG(1, char_check),
118 TR_FUNC_ARG(2, next),
119 TR_FUNC_ARG(3, prev),
120 TR_FUNC_ARG(4, freecallback)));
122 if (field_check || char_check)
124 res = typeMalloc(FIELDTYPE, 1);
128 *res = *_nc_Default_FieldType;
129 SetStatus(res, (_HAS_ARGS | _GENERIC));
130 res->fieldcheck.gfcheck = field_check;
131 res->charcheck.gccheck = char_check;
132 res->genericarg = Generic_This_Type;
133 res->freearg = freecallback;
134 res->enum_next.gnext = next;
135 res->enum_prev.gprev = prev;
140 code = E_BAD_ARGUMENT;
145 returnFieldType(res);
148 /*---------------------------------------------------------------------------
149 | Facility : libnform
150 | Function : static TypeArgument *GenericArgument(
151 | const FIELDTYPE* typ,
152 | int (*argiterator)(void**),
155 | Description : The iterator callback must browse through all fieldtype
156 | parameters that have an argument associated with the
157 | type. The iterator returns 1 if the operation to get
158 | the next element was successful, 0 otherwise. If the
159 | iterator could move to the next argument, it fills
160 | the void* pointer representing the argument into the
161 | location provided as argument to the iterator.
162 | The err reference is used to keep track of errors.
164 | Return Values : Pointer to argument structure
165 +--------------------------------------------------------------------------*/
166 static TypeArgument *
167 GenericArgument(const FIELDTYPE *typ,
168 int (*argiterator) (void **), int *err)
170 TypeArgument *res = (TypeArgument *)0;
172 if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0)
174 if (typ->status & _LINKED_TYPE)
176 /* Composite fieldtypes keep track internally of their own memory */
177 TypeArgument *p = typeMalloc(TypeArgument, 1);
181 p->left = GenericArgument(typ->left, argiterator, err);
182 p->right = GenericArgument(typ->right, argiterator, err);
190 assert(typ->genericarg != (void *)0);
191 if (typ->genericarg == 0)
196 int valid = argiterator(&argp);
198 if (valid == 0 || argp == 0 ||
199 !(res = (TypeArgument *)typ->genericarg(argp)))
209 /*---------------------------------------------------------------------------
210 | Facility : libnform
211 | Function : int _nc_set_generic_fieldtype(
214 | int (*argiterator)(void**))
216 | Description : Assign the fieldtype to the field and use the iterator
217 | mechanism to get the arguments when a check is
220 | Return Values : E_OK if all went well
221 | E_SYSTEM_ERROR if an error occurred
222 +--------------------------------------------------------------------------*/
224 _nc_set_generic_fieldtype(FIELD *field,
226 int (*argiterator) (void **))
228 int code = E_SYSTEM_ERROR;
233 if (field && field->type)
234 _nc_Free_Type(field);
241 /* The precondition is that the iterator is reset */
242 field->arg = (void *)GenericArgument(field->type, argiterator, &err);
246 _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
247 field->type = (FIELDTYPE *)0;
248 field->arg = (void *)0;
260 field->arg = (void *)0;
267 /*---------------------------------------------------------------------------
268 | Facility : libnform
269 | Function : WINDOW* _nc_form_cursor(
271 | int *pRow, int *pCol)
273 | Description : Get the current position of the form cursor position
274 | We also return the field window
276 | Return Values : The fields Window or NULL on error
277 +--------------------------------------------------------------------------*/
278 NCURSES_EXPORT(WINDOW *)
279 _nc_form_cursor(const FORM *form, int *pRow, int *pCol)
281 int code = E_SYSTEM_ERROR;
282 WINDOW *res = (WINDOW *)0;
284 if (!(form == 0 || pRow == 0 || pCol == 0))
286 *pRow = form->currow;
287 *pCol = form->curcol;
297 extern void _nc_fty_generic(void);
299 _nc_fty_generic(void)
304 /* fty_generic.c ends here */