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