1 /****************************************************************************
2 * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc. *
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: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
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. *
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 *
27 ****************************************************************************/
29 /***************************************************************************
31 * Author : Juergen Pfeifer *
33 ***************************************************************************/
35 #include "form.priv.h"
37 MODULE_ID("$Id: fty_generic.c,v 1.5 2010/01/23 21:14:36 tom Exp $")
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.
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.
61 #if NCURSES_INTEROP_FUNCS
63 /*---------------------------------------------------------------------------
65 | Function : static void *Generic_This_Type( void * arg )
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.
71 | Return Values : Pointer to argument structure
72 +--------------------------------------------------------------------------*/
74 Generic_This_Type(void *arg
)
79 /*---------------------------------------------------------------------------
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*))
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.
95 | If an error occurs, errno is set to
96 | E_BAD_ARGUMENT - invalid arguments
97 | E_SYSTEM_ERROR - system error (no memory)
99 | Return Values : Fieldtype pointer or NULL if error occurred
100 +--------------------------------------------------------------------------*/
101 NCURSES_EXPORT(FIELDTYPE
*)
102 _nc_generic_fieldtype(bool (*const field_check
) (FORM
*, FIELD
*, const void *),
103 bool (*const char_check
) (int, FORM
*, FIELD
*, const
105 bool (*const next
) (FORM
*, FIELD
*, const void *),
106 bool (*const prev
) (FORM
*, FIELD
*, const void *),
107 void (*freecallback
) (void *))
109 int code
= E_SYSTEM_ERROR
;
110 FIELDTYPE
*res
= (FIELDTYPE
*)0;
112 T((T_CALLED("_nc_generic_fieldtype(%p,%p,%p,%p,%p)"),
113 field_check
, char_check
, next
, prev
, freecallback
));
115 if (field_check
|| char_check
)
117 res
= typeMalloc(FIELDTYPE
, 1);
121 *res
= *_nc_Default_FieldType
;
122 res
->status
|= (_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
;
133 code
= E_BAD_ARGUMENT
;
138 returnFieldType(res
);
141 /*---------------------------------------------------------------------------
142 | Facility : libnform
143 | Function : static TypeArgument *GenericArgument(
144 | const FIELDTYPE* typ,
145 | int (*argiterator)(void**),
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.
157 | Return Values : Pointer to argument structure
158 +--------------------------------------------------------------------------*/
159 static TypeArgument
*
160 GenericArgument(const FIELDTYPE
*typ
,
161 int (*argiterator
) (void **), int *err
)
163 TypeArgument
*res
= (TypeArgument
*)0;
165 if (typ
!= 0 && (typ
->status
& _HAS_ARGS
) != 0 && err
!= 0 && argiterator
!= 0)
167 if (typ
->status
& _LINKED_TYPE
)
169 /* Composite fieldtypes keep track internally of their own memory */
170 TypeArgument
*p
= typeMalloc(TypeArgument
, 1);
174 p
->left
= GenericArgument(typ
->left
, argiterator
, err
);
175 p
->right
= GenericArgument(typ
->right
, argiterator
, err
);
183 assert(typ
->genericarg
!= (void *)0);
184 if (typ
->genericarg
== 0)
189 int valid
= argiterator(&argp
);
191 if (valid
== 0 || argp
== 0 ||
192 !(res
= (TypeArgument
*)typ
->genericarg(argp
)))
202 /*---------------------------------------------------------------------------
203 | Facility : libnform
204 | Function : int _nc_set_generic_fieldtype(
207 | int (*argiterator)(void**))
209 | Description : Assign the fieldtype to the field and use the iterator
210 | mechanism to get the arguments when a check is
213 | Return Values : E_OK if all went well
214 | E_SYSTEM_ERROR if an error occurred
215 +--------------------------------------------------------------------------*/
217 _nc_set_generic_fieldtype(FIELD
*field
,
219 int (*argiterator
) (void **))
221 int code
= E_SYSTEM_ERROR
;
226 if (field
&& field
->type
)
227 _nc_Free_Type(field
);
234 /* The precondition is that the iterator is reset */
235 field
->arg
= (void *)GenericArgument(field
->type
, argiterator
, &err
);
239 _nc_Free_Argument(field
->type
, (TypeArgument
*)(field
->arg
));
240 field
->type
= (FIELDTYPE
*)0;
241 field
->arg
= (void *)0;
253 field
->arg
= (void *)0;
260 /*---------------------------------------------------------------------------
261 | Facility : libnform
262 | Function : WINDOW* _nc_form_cursor(
264 | int *pRow, int *pCol)
266 | Description : Get the current position of the form cursor position
267 | We also return the field window
269 | Return Values : The fields Window or NULL on error
270 +--------------------------------------------------------------------------*/
271 NCURSES_EXPORT(WINDOW
*)
272 _nc_form_cursor(const FORM
*form
, int *pRow
, int *pCol
)
274 int code
= E_SYSTEM_ERROR
;
275 WINDOW
*res
= (WINDOW
*)0;
277 if (!(form
== 0 || pRow
== 0 || pCol
== 0))
279 *pRow
= form
->currow
;
280 *pCol
= form
->curcol
;
290 extern void _nc_fty_generic(void);
292 _nc_fty_generic(void)
297 /* fty_generic.c ends here */