106bfebdeSXin LI /**************************************************************************** 2*e1865124SBaptiste Daroussin * Copyright 2018,2020 Thomas E. Dickey * 3*e1865124SBaptiste 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*e1865124SBaptiste Daroussin MODULE_ID("$Id: fty_generic.c,v 1.10 2020/02/02 23:34:34 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 4306bfebdeSXin LI * with C language. Especially the collection of arguments for the 4406bfebdeSXin LI * various fieldtypes is not based on the vararg C mechanism, but on a 4506bfebdeSXin LI * iterator based callback mechanism that allowes 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. 4806bfebdeSXin LI * The languages can register a new generic fieldtype dynamically and store 4906bfebdeSXin LI * a handle (key) to the calling object as an argument. Together with that 5006bfebdeSXin LI * it can register a freearg callback, so that the high level language 5106bfebdeSXin LI * remains in control of the memory management of the arguments they pass. 5206bfebdeSXin LI * The design idea is, that the high-level language - typically a OO 5306bfebdeSXin LI * language like C# or Java, uses it's own dispatching mechanisms 5406bfebdeSXin LI * (polymorphism) to call the proper check routines responsible for the 5506bfebdeSXin LI * argument type. So these language implement typically only one generic 5606bfebdeSXin LI * fieldtype they register with the forms library using this call. 5706bfebdeSXin LI * 5806bfebdeSXin LI * For that purpose we have extended the fieldtype struc by a new element 5906bfebdeSXin LI * that gets the arguments from a single struct passed by the caller. 6006bfebdeSXin LI * 6106bfebdeSXin LI */ 6206bfebdeSXin LI #if NCURSES_INTEROP_FUNCS 6306bfebdeSXin LI 6406bfebdeSXin LI /*--------------------------------------------------------------------------- 6506bfebdeSXin LI | Facility : libnform 6606bfebdeSXin LI | Function : static void *Generic_This_Type( void * arg ) 6706bfebdeSXin LI | 6806bfebdeSXin LI | Description : We interpret the passed arg just as a handle the 6906bfebdeSXin LI | calling language uses to keep track of its allocated 7006bfebdeSXin LI | argument structures. We can simply copy it back. 7106bfebdeSXin LI | 7206bfebdeSXin LI | Return Values : Pointer to argument structure 7306bfebdeSXin LI +--------------------------------------------------------------------------*/ 7406bfebdeSXin LI static void * 7506bfebdeSXin LI Generic_This_Type(void *arg) 7606bfebdeSXin LI { 7706bfebdeSXin LI return (arg); 7806bfebdeSXin LI } 7906bfebdeSXin LI 8006bfebdeSXin LI /*--------------------------------------------------------------------------- 8106bfebdeSXin LI | Facility : libnform 8206bfebdeSXin LI | Function : FIELDTYPE *_nc_generic_fieldtype( 8306bfebdeSXin LI | bool (* const field_check)(FIELD *,const void *), 8406bfebdeSXin LI | bool (* const char_check) (int, const void *), 8506bfebdeSXin LI | bool (*const next)(FORM*,FIELD*,const void*), 8606bfebdeSXin LI | bool (*const prev)(FORM*,FIELD*,const void*), 8706bfebdeSXin LI | void (*freecallback)(void*)) 8806bfebdeSXin LI | 8906bfebdeSXin LI | Description : Create a new fieldtype. The application programmer must 9006bfebdeSXin LI | write a field_check and a char_check function and give 9106bfebdeSXin LI | them as input to this call. A callback to allow the 9206bfebdeSXin LI | release of the allocated memory must also be provided. 9306bfebdeSXin LI | For generic field types, we provide some more 9406bfebdeSXin LI | information about the field as parameters. 9506bfebdeSXin LI | 9606bfebdeSXin LI | If an error occurs, errno is set to 9706bfebdeSXin LI | E_BAD_ARGUMENT - invalid arguments 9806bfebdeSXin LI | E_SYSTEM_ERROR - system error (no memory) 9906bfebdeSXin LI | 10006bfebdeSXin LI | Return Values : Fieldtype pointer or NULL if error occurred 10106bfebdeSXin LI +--------------------------------------------------------------------------*/ 10206bfebdeSXin LI NCURSES_EXPORT(FIELDTYPE *) 10306bfebdeSXin LI _nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *), 10406bfebdeSXin LI bool (*const char_check) (int, FORM *, FIELD *, const 10506bfebdeSXin LI void *), 10606bfebdeSXin LI bool (*const next) (FORM *, FIELD *, const void *), 10706bfebdeSXin LI bool (*const prev) (FORM *, FIELD *, const void *), 10806bfebdeSXin LI void (*freecallback) (void *)) 10906bfebdeSXin LI { 11006bfebdeSXin LI int code = E_SYSTEM_ERROR; 11106bfebdeSXin LI FIELDTYPE *res = (FIELDTYPE *)0; 11206bfebdeSXin LI 113aae38d10SBaptiste Daroussin TR_FUNC_BFR(5); 114aae38d10SBaptiste Daroussin 115aae38d10SBaptiste Daroussin T((T_CALLED("_nc_generic_fieldtype(%s,%s,%s,%s,%s)"), 116aae38d10SBaptiste Daroussin TR_FUNC_ARG(0, field_check), 117aae38d10SBaptiste Daroussin TR_FUNC_ARG(1, char_check), 118aae38d10SBaptiste Daroussin TR_FUNC_ARG(2, next), 119aae38d10SBaptiste Daroussin TR_FUNC_ARG(3, prev), 120aae38d10SBaptiste Daroussin TR_FUNC_ARG(4, freecallback))); 12106bfebdeSXin LI 12206bfebdeSXin LI if (field_check || char_check) 12306bfebdeSXin LI { 12406bfebdeSXin LI res = typeMalloc(FIELDTYPE, 1); 12506bfebdeSXin LI 12606bfebdeSXin LI if (res) 12706bfebdeSXin LI { 12806bfebdeSXin LI *res = *_nc_Default_FieldType; 12973f0a83dSXin LI SetStatus(res, (_HAS_ARGS | _GENERIC)); 13006bfebdeSXin LI res->fieldcheck.gfcheck = field_check; 13106bfebdeSXin LI res->charcheck.gccheck = char_check; 13206bfebdeSXin LI res->genericarg = Generic_This_Type; 13306bfebdeSXin LI res->freearg = freecallback; 13406bfebdeSXin LI res->enum_next.gnext = next; 13506bfebdeSXin LI res->enum_prev.gprev = prev; 13606bfebdeSXin LI code = E_OK; 13706bfebdeSXin LI } 13806bfebdeSXin LI } 13906bfebdeSXin LI else 14006bfebdeSXin LI code = E_BAD_ARGUMENT; 14106bfebdeSXin LI 14206bfebdeSXin LI if (E_OK != code) 14306bfebdeSXin LI SET_ERROR(code); 14406bfebdeSXin LI 14506bfebdeSXin LI returnFieldType(res); 14606bfebdeSXin LI } 14706bfebdeSXin LI 14806bfebdeSXin LI /*--------------------------------------------------------------------------- 14906bfebdeSXin LI | Facility : libnform 15006bfebdeSXin LI | Function : static TypeArgument *GenericArgument( 15106bfebdeSXin LI | const FIELDTYPE* typ, 15206bfebdeSXin LI | int (*argiterator)(void**), 15306bfebdeSXin LI | int* err) 15406bfebdeSXin LI | 15506bfebdeSXin LI | Description : The iterator callback must browse through all fieldtype 15606bfebdeSXin LI | parameters that have an argument associated with the 15706bfebdeSXin LI | type. The iterator returns 1 if the operation to get 158aae38d10SBaptiste Daroussin | the next element was successful, 0 otherwise. If the 15906bfebdeSXin LI | iterator could move to the next argument, it fills 16006bfebdeSXin LI | the void* pointer representing the argument into the 16106bfebdeSXin LI | location provided as argument to the iterator. 16206bfebdeSXin LI | The err reference is used to keep track of errors. 16306bfebdeSXin LI | 16406bfebdeSXin LI | Return Values : Pointer to argument structure 16506bfebdeSXin LI +--------------------------------------------------------------------------*/ 16606bfebdeSXin LI static TypeArgument * 16706bfebdeSXin LI GenericArgument(const FIELDTYPE *typ, 16806bfebdeSXin LI int (*argiterator) (void **), int *err) 16906bfebdeSXin LI { 17006bfebdeSXin LI TypeArgument *res = (TypeArgument *)0; 17106bfebdeSXin LI 17206bfebdeSXin LI if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0) 17306bfebdeSXin LI { 17406bfebdeSXin LI if (typ->status & _LINKED_TYPE) 17506bfebdeSXin LI { 17606bfebdeSXin LI /* Composite fieldtypes keep track internally of their own memory */ 17706bfebdeSXin LI TypeArgument *p = typeMalloc(TypeArgument, 1); 17806bfebdeSXin LI 17906bfebdeSXin LI if (p) 18006bfebdeSXin LI { 18106bfebdeSXin LI p->left = GenericArgument(typ->left, argiterator, err); 18206bfebdeSXin LI p->right = GenericArgument(typ->right, argiterator, err); 18306bfebdeSXin LI return p; 18406bfebdeSXin LI } 18506bfebdeSXin LI else 18606bfebdeSXin LI *err += 1; 18706bfebdeSXin LI } 18806bfebdeSXin LI else 18906bfebdeSXin LI { 19006bfebdeSXin LI assert(typ->genericarg != (void *)0); 19106bfebdeSXin LI if (typ->genericarg == 0) 19206bfebdeSXin LI *err += 1; 19306bfebdeSXin LI else 19406bfebdeSXin LI { 19506bfebdeSXin LI void *argp; 19606bfebdeSXin LI int valid = argiterator(&argp); 19706bfebdeSXin LI 19806bfebdeSXin LI if (valid == 0 || argp == 0 || 19906bfebdeSXin LI !(res = (TypeArgument *)typ->genericarg(argp))) 20006bfebdeSXin LI { 20106bfebdeSXin LI *err += 1; 20206bfebdeSXin LI } 20306bfebdeSXin LI } 20406bfebdeSXin LI } 20506bfebdeSXin LI } 20606bfebdeSXin LI return res; 20706bfebdeSXin LI } 20806bfebdeSXin LI 20906bfebdeSXin LI /*--------------------------------------------------------------------------- 21006bfebdeSXin LI | Facility : libnform 21106bfebdeSXin LI | Function : int _nc_set_generic_fieldtype( 21206bfebdeSXin LI | FIELD* field, 21306bfebdeSXin LI | FIELDTYPE* ftyp, 21406bfebdeSXin LI | int (*argiterator)(void**)) 21506bfebdeSXin LI | 21606bfebdeSXin LI | Description : Assign the fieldtype to the field and use the iterator 21706bfebdeSXin LI | mechanism to get the arguments when a check is 21806bfebdeSXin LI | performed. 21906bfebdeSXin LI | 22006bfebdeSXin LI | Return Values : E_OK if all went well 22106bfebdeSXin LI | E_SYSTEM_ERROR if an error occurred 22206bfebdeSXin LI +--------------------------------------------------------------------------*/ 22306bfebdeSXin LI NCURSES_EXPORT(int) 22406bfebdeSXin LI _nc_set_generic_fieldtype(FIELD *field, 22506bfebdeSXin LI FIELDTYPE *ftyp, 22606bfebdeSXin LI int (*argiterator) (void **)) 22706bfebdeSXin LI { 22806bfebdeSXin LI int code = E_SYSTEM_ERROR; 22906bfebdeSXin LI int err = 0; 23006bfebdeSXin LI 23106bfebdeSXin LI if (field) 23206bfebdeSXin LI { 23306bfebdeSXin LI if (field && field->type) 23406bfebdeSXin LI _nc_Free_Type(field); 23506bfebdeSXin LI 23606bfebdeSXin LI field->type = ftyp; 23706bfebdeSXin LI if (ftyp) 23806bfebdeSXin LI { 23906bfebdeSXin LI if (argiterator) 24006bfebdeSXin LI { 24106bfebdeSXin LI /* The precondition is that the iterator is reset */ 24206bfebdeSXin LI field->arg = (void *)GenericArgument(field->type, argiterator, &err); 24306bfebdeSXin LI 24406bfebdeSXin LI if (err) 24506bfebdeSXin LI { 24606bfebdeSXin LI _nc_Free_Argument(field->type, (TypeArgument *)(field->arg)); 24706bfebdeSXin LI field->type = (FIELDTYPE *)0; 24806bfebdeSXin LI field->arg = (void *)0; 24906bfebdeSXin LI } 25006bfebdeSXin LI else 25106bfebdeSXin LI { 25206bfebdeSXin LI code = E_OK; 25306bfebdeSXin LI if (field->type) 25406bfebdeSXin LI field->type->ref++; 25506bfebdeSXin LI } 25606bfebdeSXin LI } 25706bfebdeSXin LI } 25806bfebdeSXin LI else 25906bfebdeSXin LI { 26006bfebdeSXin LI field->arg = (void *)0; 26106bfebdeSXin LI code = E_OK; 26206bfebdeSXin LI } 26306bfebdeSXin LI } 26406bfebdeSXin LI return code; 26506bfebdeSXin LI } 26606bfebdeSXin LI 26706bfebdeSXin LI /*--------------------------------------------------------------------------- 26806bfebdeSXin LI | Facility : libnform 26906bfebdeSXin LI | Function : WINDOW* _nc_form_cursor( 27006bfebdeSXin LI | FORM* form, 27106bfebdeSXin LI | int *pRow, int *pCol) 27206bfebdeSXin LI | 27306bfebdeSXin LI | Description : Get the current position of the form cursor position 27406bfebdeSXin LI | We also return the field window 27506bfebdeSXin LI | 27606bfebdeSXin LI | Return Values : The fields Window or NULL on error 27706bfebdeSXin LI +--------------------------------------------------------------------------*/ 27806bfebdeSXin LI NCURSES_EXPORT(WINDOW *) 27906bfebdeSXin LI _nc_form_cursor(const FORM *form, int *pRow, int *pCol) 28006bfebdeSXin LI { 28106bfebdeSXin LI int code = E_SYSTEM_ERROR; 28206bfebdeSXin LI WINDOW *res = (WINDOW *)0; 28306bfebdeSXin LI 28406bfebdeSXin LI if (!(form == 0 || pRow == 0 || pCol == 0)) 28506bfebdeSXin LI { 28606bfebdeSXin LI *pRow = form->currow; 28706bfebdeSXin LI *pCol = form->curcol; 28806bfebdeSXin LI res = form->w; 28906bfebdeSXin LI code = E_OK; 29006bfebdeSXin LI } 29106bfebdeSXin LI if (code != E_OK) 29206bfebdeSXin LI SET_ERROR(code); 29306bfebdeSXin LI return res; 29406bfebdeSXin LI } 29506bfebdeSXin LI 29606bfebdeSXin LI #else 29706bfebdeSXin LI extern void _nc_fty_generic(void); 29806bfebdeSXin LI void 29906bfebdeSXin LI _nc_fty_generic(void) 30006bfebdeSXin LI { 30106bfebdeSXin LI } 30206bfebdeSXin LI #endif 30306bfebdeSXin LI 30406bfebdeSXin LI /* fty_generic.c ends here */ 305