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