1166124Srafan/**************************************************************************** 2174993Srafan * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * 3166124Srafan * * 4166124Srafan * Permission is hereby granted, free of charge, to any person obtaining a * 5166124Srafan * copy of this software and associated documentation files (the * 6166124Srafan * "Software"), to deal in the Software without restriction, including * 7166124Srafan * without limitation the rights to use, copy, modify, merge, publish, * 8166124Srafan * distribute, distribute with modifications, sublicense, and/or sell * 9166124Srafan * copies of the Software, and to permit persons to whom the Software is * 10166124Srafan * furnished to do so, subject to the following conditions: * 11166124Srafan * * 12166124Srafan * The above copyright notice and this permission notice shall be included * 13166124Srafan * in all copies or substantial portions of the Software. * 14166124Srafan * * 15166124Srafan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16166124Srafan * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17166124Srafan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18166124Srafan * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19166124Srafan * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20166124Srafan * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21166124Srafan * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22166124Srafan * * 23166124Srafan * Except as contained in this notice, the name(s) of the above copyright * 24166124Srafan * holders shall not be used in advertising or otherwise to promote the * 25166124Srafan * sale, use or other dealings in this Software without prior written * 26166124Srafan * authorization. * 27166124Srafan ****************************************************************************/ 2850276Speter 2950276Speter/*************************************************************************** 3050276Speter* * 31166124Srafan* Author : Juergen Pfeifer * 3250276Speter* * 3350276Speter***************************************************************************/ 3450276Speter 3550276Speter#include "form.priv.h" 3650276Speter 37174993SrafanMODULE_ID("$Id: fty_enum.c,v 1.22 2007/10/13 19:32:26 tom Exp $") 3850276Speter 39166124Srafantypedef struct 40166124Srafan { 41166124Srafan char **kwds; 42166124Srafan int count; 43166124Srafan bool checkcase; 44166124Srafan bool checkunique; 45166124Srafan } 46166124SrafanenumARG; 4750276Speter 4850276Speter/*--------------------------------------------------------------------------- 4950276Speter| Facility : libnform 5050276Speter| Function : static void *Make_Enum_Type( va_list * ap ) 5150276Speter| 5250276Speter| Description : Allocate structure for enumeration type argument. 5350276Speter| 5450276Speter| Return Values : Pointer to argument structure or NULL on error 5550276Speter+--------------------------------------------------------------------------*/ 56166124Srafanstatic void * 57166124SrafanMake_Enum_Type(va_list *ap) 5850276Speter{ 59174993Srafan enumARG *argp = typeMalloc(enumARG, 1); 6050276Speter 6150276Speter if (argp) 6250276Speter { 6366963Speter int cnt = 0; 6466963Speter char **kp = (char **)0; 6550276Speter int ccase, cunique; 6666963Speter 67174993Srafan T((T_CREATE("enumARG %p"), argp)); 68166124Srafan argp->kwds = va_arg(*ap, char **); 69166124Srafan ccase = va_arg(*ap, int); 70166124Srafan cunique = va_arg(*ap, int); 71166124Srafan 72166124Srafan argp->checkcase = ccase ? TRUE : FALSE; 7350276Speter argp->checkunique = cunique ? TRUE : FALSE; 7466963Speter 7550276Speter kp = argp->kwds; 76166124Srafan while (kp && (*kp++)) 77166124Srafan cnt++; 7850276Speter argp->count = cnt; 7950276Speter } 8050276Speter return (void *)argp; 8150276Speter} 8250276Speter 8350276Speter/*--------------------------------------------------------------------------- 8450276Speter| Facility : libnform 8550276Speter| Function : static void *Copy_Enum_Type( const void * argp ) 8650276Speter| 8750276Speter| Description : Copy structure for enumeration type argument. 8850276Speter| 8950276Speter| Return Values : Pointer to argument structure or NULL on error. 9050276Speter+--------------------------------------------------------------------------*/ 91166124Srafanstatic void * 92166124SrafanCopy_Enum_Type(const void *argp) 9350276Speter{ 9450276Speter enumARG *result = (enumARG *)0; 9550276Speter 9650276Speter if (argp) 9750276Speter { 9866963Speter const enumARG *ap = (const enumARG *)argp; 9966963Speter 100174993Srafan result = typeMalloc(enumARG, 1); 101166124Srafan 10250276Speter if (result) 103174993Srafan { 104174993Srafan T((T_CREATE("enumARG %p"), result)); 105174993Srafan *result = *ap; 106174993Srafan } 10750276Speter } 10850276Speter return (void *)result; 10950276Speter} 11050276Speter 11150276Speter/*--------------------------------------------------------------------------- 11250276Speter| Facility : libnform 11350276Speter| Function : static void Free_Enum_Type( void * argp ) 11450276Speter| 11550276Speter| Description : Free structure for enumeration type argument. 11650276Speter| 11750276Speter| Return Values : - 11850276Speter+--------------------------------------------------------------------------*/ 119166124Srafanstatic void 120166124SrafanFree_Enum_Type(void *argp) 12150276Speter{ 122166124Srafan if (argp) 12350276Speter free(argp); 12450276Speter} 12550276Speter 12650276Speter#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++ 12750276Speter#define NOMATCH 0 12850276Speter#define PARTIAL 1 12950276Speter#define EXACT 2 13050276Speter 13150276Speter/*--------------------------------------------------------------------------- 13250276Speter| Facility : libnform 13350276Speter| Function : static int Compare(const unsigned char * s, 13450276Speter| const unsigned char * buf, 13550276Speter| bool ccase ) 13650276Speter| 137166124Srafan| Description : Check whether or not the text in 'buf' matches the 13850276Speter| text in 's', at least partial. 13950276Speter| 14050276Speter| Return Values : NOMATCH - buffer doesn't match 14150276Speter| PARTIAL - buffer matches partially 14250276Speter| EXACT - buffer matches exactly 14350276Speter+--------------------------------------------------------------------------*/ 144166124Srafanstatic int 145166124SrafanCompare(const unsigned char *s, const unsigned char *buf, 146166124Srafan bool ccase) 14750276Speter{ 148166124Srafan SKIP_SPACE(buf); /* Skip leading spaces in both texts */ 14950276Speter SKIP_SPACE(s); 15050276Speter 151166124Srafan if (*buf == '\0') 15250276Speter { 153166124Srafan return (((*s) != '\0') ? NOMATCH : EXACT); 154166124Srafan } 155166124Srafan else 15650276Speter { 15750276Speter if (ccase) 15850276Speter { 159166124Srafan while (*s++ == *buf) 16050276Speter { 161166124Srafan if (*buf++ == '\0') 162166124Srafan return EXACT; 163166124Srafan } 164166124Srafan } 165166124Srafan else 16650276Speter { 167166124Srafan while (toupper(*s++) == toupper(*buf)) 16850276Speter { 169166124Srafan if (*buf++ == '\0') 170166124Srafan return EXACT; 17150276Speter } 17250276Speter } 17350276Speter } 17450276Speter /* At this location buf points to the first character where it no longer 17550276Speter matches with s. So if only blanks are following, we have a partial 17650276Speter match otherwise there is no match */ 17750276Speter SKIP_SPACE(buf); 178166124Srafan if (*buf) 17950276Speter return NOMATCH; 18050276Speter 18150276Speter /* If it happens that the reference buffer is at its end, the partial 18250276Speter match is actually an exact match. */ 183166124Srafan return ((s[-1] != '\0') ? PARTIAL : EXACT); 18450276Speter} 18550276Speter 18650276Speter/*--------------------------------------------------------------------------- 18750276Speter| Facility : libnform 18850276Speter| Function : static bool Check_Enum_Field( 18950276Speter| FIELD * field, 19050276Speter| const void * argp) 19150276Speter| 19250276Speter| Description : Validate buffer content to be a valid enumeration value 19350276Speter| 19450276Speter| Return Values : TRUE - field is valid 19550276Speter| FALSE - field is invalid 19650276Speter+--------------------------------------------------------------------------*/ 197166124Srafanstatic bool 198166124SrafanCheck_Enum_Field(FIELD *field, const void *argp) 19950276Speter{ 200166124Srafan char **kwds = ((const enumARG *)argp)->kwds; 201166124Srafan bool ccase = ((const enumARG *)argp)->checkcase; 202166124Srafan bool unique = ((const enumARG *)argp)->checkunique; 203166124Srafan unsigned char *bp = (unsigned char *)field_buffer(field, 0); 20450276Speter char *s, *t, *p; 20550276Speter int res; 206166124Srafan 207166124Srafan while (kwds && (s = (*kwds++))) 20850276Speter { 209166124Srafan if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH) 21050276Speter { 211166124Srafan p = t = s; /* t is at least a partial match */ 212166124Srafan if ((unique && res != EXACT)) 21350276Speter { 214166124Srafan while (kwds && (p = *kwds++)) 21550276Speter { 216166124Srafan if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH) 21750276Speter { 218166124Srafan if (res == EXACT) 21950276Speter { 22050276Speter t = p; 22150276Speter break; 22250276Speter } 22350276Speter else 22450276Speter t = (char *)0; 22550276Speter } 22650276Speter } 227166124Srafan } 22850276Speter if (t) 22950276Speter { 230166124Srafan set_field_buffer(field, 0, t); 23150276Speter return TRUE; 23250276Speter } 23350276Speter if (!p) 23450276Speter break; 23550276Speter } 23650276Speter } 23750276Speter return FALSE; 23850276Speter} 23950276Speter 240166124Srafanstatic const char *dummy[] = 241166124Srafan{(char *)0}; 24250276Speter 24350276Speter/*--------------------------------------------------------------------------- 24450276Speter| Facility : libnform 24550276Speter| Function : static bool Next_Enum(FIELD * field, 24650276Speter| const void * argp) 24750276Speter| 24850276Speter| Description : Check for the next enumeration value 24950276Speter| 25050276Speter| Return Values : TRUE - next value found and loaded 25150276Speter| FALSE - no next value loaded 25250276Speter+--------------------------------------------------------------------------*/ 253166124Srafanstatic bool 254166124SrafanNext_Enum(FIELD *field, const void *argp) 25550276Speter{ 25650276Speter const enumARG *args = (const enumARG *)argp; 257166124Srafan char **kwds = args->kwds; 258166124Srafan bool ccase = args->checkcase; 259166124Srafan int cnt = args->count; 260166124Srafan unsigned char *bp = (unsigned char *)field_buffer(field, 0); 26150276Speter 262166124Srafan if (kwds) 263166124Srafan { 264166124Srafan while (cnt--) 265166124Srafan { 266166124Srafan if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT) 267166124Srafan break; 268166124Srafan } 269166124Srafan if (cnt <= 0) 270166124Srafan kwds = args->kwds; 271166124Srafan if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT)) 272166124Srafan { 273166124Srafan set_field_buffer(field, 0, *kwds); 274166124Srafan return TRUE; 275166124Srafan } 276166124Srafan } 27750276Speter return FALSE; 27850276Speter} 27950276Speter 28050276Speter/*--------------------------------------------------------------------------- 28150276Speter| Facility : libnform 28250276Speter| Function : static bool Previous_Enum( 28350276Speter| FIELD * field, 28450276Speter| const void * argp) 28550276Speter| 28650276Speter| Description : Check for the previous enumeration value 28750276Speter| 28850276Speter| Return Values : TRUE - previous value found and loaded 28950276Speter| FALSE - no previous value loaded 29050276Speter+--------------------------------------------------------------------------*/ 291166124Srafanstatic bool 292166124SrafanPrevious_Enum(FIELD *field, const void *argp) 29350276Speter{ 29450276Speter const enumARG *args = (const enumARG *)argp; 295166124Srafan int cnt = args->count; 296166124Srafan char **kwds = &args->kwds[cnt - 1]; 297166124Srafan bool ccase = args->checkcase; 298166124Srafan unsigned char *bp = (unsigned char *)field_buffer(field, 0); 29950276Speter 300166124Srafan if (kwds) 301166124Srafan { 302166124Srafan while (cnt--) 303166124Srafan { 304166124Srafan if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT) 305166124Srafan break; 306166124Srafan } 307166124Srafan 308166124Srafan if (cnt <= 0) 309166124Srafan kwds = &args->kwds[args->count - 1]; 310166124Srafan 311166124Srafan if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT)) 312166124Srafan { 313166124Srafan set_field_buffer(field, 0, *kwds); 314166124Srafan return TRUE; 315166124Srafan } 316166124Srafan } 31750276Speter return FALSE; 31850276Speter} 31950276Speter 320166124Srafanstatic FIELDTYPE typeENUM = 321166124Srafan{ 32250276Speter _HAS_ARGS | _HAS_CHOICE | _RESIDENT, 323166124Srafan 1, /* this is mutable, so we can't be const */ 32450276Speter (FIELDTYPE *)0, 32550276Speter (FIELDTYPE *)0, 32650276Speter Make_Enum_Type, 32750276Speter Copy_Enum_Type, 32850276Speter Free_Enum_Type, 32950276Speter Check_Enum_Field, 33050276Speter NULL, 33150276Speter Next_Enum, 33250276Speter Previous_Enum 33350276Speter}; 33450276Speter 335166124SrafanNCURSES_EXPORT_VAR(FIELDTYPE *) 336166124SrafanTYPE_ENUM = &typeENUM; 33750276Speter 33850276Speter/* fty_enum.c ends here */ 339