106bfebdeSXin LI /**************************************************************************** 2e1865124SBaptiste Daroussin * Copyright 2018,2020 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*7a656419SBaptiste Daroussin MODULE_ID("$Id: fty_generic.c,v 1.14 2020/12/12 17:27:44 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 43*7a656419SBaptiste 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 45*7a656419SBaptiste 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. 48*7a656419SBaptiste 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 54*7a656419SBaptiste 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 * 59*7a656419SBaptiste 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 * 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 +--------------------------------------------------------------------------*/ 103*7a656419SBaptiste Daroussin FORM_EXPORT(FIELDTYPE *) 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 * 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 +--------------------------------------------------------------------------*/ 224*7a656419SBaptiste Daroussin FORM_EXPORT(int) 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 | 277*7a656419SBaptiste Daroussin | Return Values : The field's Window or NULL on error 27806bfebdeSXin LI +--------------------------------------------------------------------------*/ 279*7a656419SBaptiste Daroussin FORM_EXPORT(WINDOW *) 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 28506bfebdeSXin LI 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