blob: 429ceac44a054489cb33585153d66abdb47bf6e3 [file] [log] [blame]
Steve Kondikae271bc2015-11-15 02:50:53 +01001/****************************************************************************
2 * Copyright (c) 2008-2010,2012 Free Software Foundation, Inc. *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
22 * *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
26 * authorization. *
27 ****************************************************************************/
28
29/***************************************************************************
30* *
31* Author : Juergen Pfeifer *
32* *
33***************************************************************************/
34
35#include "form.priv.h"
36
37MODULE_ID("$Id: fty_generic.c,v 1.6 2012/06/10 00:27:49 tom Exp $")
38
39/*
40 * This is not a full implementation of a field type, but adds some
41 * support for higher level languages with some restrictions to interop
42 * with C language. Especially the collection of arguments for the
43 * various fieldtypes is not based on the vararg C mechanism, but on a
44 * iterator based callback mechanism that allowes the high level language
45 * to provide the arguments as a structure. Most languages have mechanisms
46 * to layout structures so that they can be passed to C.
47 * The languages can register a new generic fieldtype dynamically and store
48 * a handle (key) to the calling object as an argument. Together with that
49 * it can register a freearg callback, so that the high level language
50 * remains in control of the memory management of the arguments they pass.
51 * The design idea is, that the high-level language - typically a OO
52 * language like C# or Java, uses it's own dispatching mechanisms
53 * (polymorphism) to call the proper check routines responsible for the
54 * argument type. So these language implement typically only one generic
55 * fieldtype they register with the forms library using this call.
56 *
57 * For that purpose we have extended the fieldtype struc by a new element
58 * that gets the arguments from a single struct passed by the caller.
59 *
60 */
61#if NCURSES_INTEROP_FUNCS
62
63/*---------------------------------------------------------------------------
64| Facility : libnform
65| Function : static void *Generic_This_Type( void * arg )
66|
67| Description : We interpret the passed arg just as a handle the
68| calling language uses to keep track of its allocated
69| argument structures. We can simply copy it back.
70|
71| Return Values : Pointer to argument structure
72+--------------------------------------------------------------------------*/
73static void *
74Generic_This_Type(void *arg)
75{
76 return (arg);
77}
78
79/*---------------------------------------------------------------------------
80| Facility : libnform
81| Function : FIELDTYPE *_nc_generic_fieldtype(
82| bool (* const field_check)(FIELD *,const void *),
83| bool (* const char_check) (int, const void *),
84| bool (*const next)(FORM*,FIELD*,const void*),
85| bool (*const prev)(FORM*,FIELD*,const void*),
86| void (*freecallback)(void*))
87|
88| Description : Create a new fieldtype. The application programmer must
89| write a field_check and a char_check function and give
90| them as input to this call. A callback to allow the
91| release of the allocated memory must also be provided.
92| For generic field types, we provide some more
93| information about the field as parameters.
94|
95| If an error occurs, errno is set to
96| E_BAD_ARGUMENT - invalid arguments
97| E_SYSTEM_ERROR - system error (no memory)
98|
99| Return Values : Fieldtype pointer or NULL if error occurred
100+--------------------------------------------------------------------------*/
101NCURSES_EXPORT(FIELDTYPE *)
102_nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *),
103 bool (*const char_check) (int, FORM *, FIELD *, const
104 void *),
105 bool (*const next) (FORM *, FIELD *, const void *),
106 bool (*const prev) (FORM *, FIELD *, const void *),
107 void (*freecallback) (void *))
108{
109 int code = E_SYSTEM_ERROR;
110 FIELDTYPE *res = (FIELDTYPE *)0;
111
112 T((T_CALLED("_nc_generic_fieldtype(%p,%p,%p,%p,%p)"),
113 field_check, char_check, next, prev, freecallback));
114
115 if (field_check || char_check)
116 {
117 res = typeMalloc(FIELDTYPE, 1);
118
119 if (res)
120 {
121 *res = *_nc_Default_FieldType;
122 SetStatus(res, (_HAS_ARGS | _GENERIC));
123 res->fieldcheck.gfcheck = field_check;
124 res->charcheck.gccheck = char_check;
125 res->genericarg = Generic_This_Type;
126 res->freearg = freecallback;
127 res->enum_next.gnext = next;
128 res->enum_prev.gprev = prev;
129 code = E_OK;
130 }
131 }
132 else
133 code = E_BAD_ARGUMENT;
134
135 if (E_OK != code)
136 SET_ERROR(code);
137
138 returnFieldType(res);
139}
140
141/*---------------------------------------------------------------------------
142| Facility : libnform
143| Function : static TypeArgument *GenericArgument(
144| const FIELDTYPE* typ,
145| int (*argiterator)(void**),
146| int* err)
147|
148| Description : The iterator callback must browse through all fieldtype
149| parameters that have an argument associated with the
150| type. The iterator returns 1 if the operation to get
151| the next element was successfull, 0 otherwise. If the
152| iterator could move to the next argument, it fills
153| the void* pointer representing the argument into the
154| location provided as argument to the iterator.
155| The err reference is used to keep track of errors.
156|
157| Return Values : Pointer to argument structure
158+--------------------------------------------------------------------------*/
159static TypeArgument *
160GenericArgument(const FIELDTYPE *typ,
161 int (*argiterator) (void **), int *err)
162{
163 TypeArgument *res = (TypeArgument *)0;
164
165 if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0)
166 {
167 if (typ->status & _LINKED_TYPE)
168 {
169 /* Composite fieldtypes keep track internally of their own memory */
170 TypeArgument *p = typeMalloc(TypeArgument, 1);
171
172 if (p)
173 {
174 p->left = GenericArgument(typ->left, argiterator, err);
175 p->right = GenericArgument(typ->right, argiterator, err);
176 return p;
177 }
178 else
179 *err += 1;
180 }
181 else
182 {
183 assert(typ->genericarg != (void *)0);
184 if (typ->genericarg == 0)
185 *err += 1;
186 else
187 {
188 void *argp;
189 int valid = argiterator(&argp);
190
191 if (valid == 0 || argp == 0 ||
192 !(res = (TypeArgument *)typ->genericarg(argp)))
193 {
194 *err += 1;
195 }
196 }
197 }
198 }
199 return res;
200}
201
202/*---------------------------------------------------------------------------
203| Facility : libnform
204| Function : int _nc_set_generic_fieldtype(
205| FIELD* field,
206| FIELDTYPE* ftyp,
207| int (*argiterator)(void**))
208|
209| Description : Assign the fieldtype to the field and use the iterator
210| mechanism to get the arguments when a check is
211| performed.
212|
213| Return Values : E_OK if all went well
214| E_SYSTEM_ERROR if an error occurred
215+--------------------------------------------------------------------------*/
216NCURSES_EXPORT(int)
217_nc_set_generic_fieldtype(FIELD *field,
218 FIELDTYPE *ftyp,
219 int (*argiterator) (void **))
220{
221 int code = E_SYSTEM_ERROR;
222 int err = 0;
223
224 if (field)
225 {
226 if (field && field->type)
227 _nc_Free_Type(field);
228
229 field->type = ftyp;
230 if (ftyp)
231 {
232 if (argiterator)
233 {
234 /* The precondition is that the iterator is reset */
235 field->arg = (void *)GenericArgument(field->type, argiterator, &err);
236
237 if (err)
238 {
239 _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
240 field->type = (FIELDTYPE *)0;
241 field->arg = (void *)0;
242 }
243 else
244 {
245 code = E_OK;
246 if (field->type)
247 field->type->ref++;
248 }
249 }
250 }
251 else
252 {
253 field->arg = (void *)0;
254 code = E_OK;
255 }
256 }
257 return code;
258}
259
260/*---------------------------------------------------------------------------
261| Facility : libnform
262| Function : WINDOW* _nc_form_cursor(
263| FORM* form,
264| int *pRow, int *pCol)
265|
266| Description : Get the current position of the form cursor position
267| We also return the field window
268|
269| Return Values : The fields Window or NULL on error
270+--------------------------------------------------------------------------*/
271NCURSES_EXPORT(WINDOW *)
272_nc_form_cursor(const FORM *form, int *pRow, int *pCol)
273{
274 int code = E_SYSTEM_ERROR;
275 WINDOW *res = (WINDOW *)0;
276
277 if (!(form == 0 || pRow == 0 || pCol == 0))
278 {
279 *pRow = form->currow;
280 *pCol = form->curcol;
281 res = form->w;
282 code = E_OK;
283 }
284 if (code != E_OK)
285 SET_ERROR(code);
286 return res;
287}
288
289#else
290extern void _nc_fty_generic(void);
291void
292_nc_fty_generic(void)
293{
294}
295#endif
296
297/* fty_generic.c ends here */