1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /***************************************************************************
31 * Author : Juergen Pfeifer *
33 ***************************************************************************/
35 #include "form.priv.h"
37 MODULE_ID("$Id: fty_enum.c,v 1.25 2010/01/23 21:14:36 tom Exp $")
56 /*---------------------------------------------------------------------------
58 | Function : static void *Generic_Enum_Type(void * arg)
60 | Description : Allocate structure for enumeration type argument.
62 | Return Values : Pointer to argument structure or NULL on error
63 +--------------------------------------------------------------------------*/
65 Generic_Enum_Type(void *arg)
67 enumARG *argp = (enumARG *)0;
68 enumParams *params = (enumParams *) arg;
72 argp = typeMalloc(enumARG, 1);
77 char **kp = (char **)0;
78 char **kwds = (char **)0;
82 T((T_CREATE("enumARG %p"), (void *)argp));
84 ccase = params->ccase;
85 cunique = params->cunique;
87 argp->checkcase = ccase ? TRUE : FALSE;
88 argp->checkunique = cunique ? TRUE : FALSE;
89 argp->kwds = (char **)0;
98 /* We copy the keywords, because we can't rely on the fact
99 that the caller doesn't relocate or free the memory used
100 for the keywords (maybe he has GC)
102 argp->kwds = typeMalloc(char *, cnt + 1);
105 kptarget = argp->kwds;
106 while (kptarget && kp && (*kp))
108 (*kptarget++) = strdup(*kp++);
110 *kptarget = (char *)0;
117 /*---------------------------------------------------------------------------
118 | Facility : libnform
119 | Function : static void *Make_Enum_Type( va_list * ap )
121 | Description : Allocate structure for enumeration type argument.
123 | Return Values : Pointer to argument structure or NULL on error
124 +--------------------------------------------------------------------------*/
126 Make_Enum_Type(va_list *ap)
130 params.kwds = va_arg(*ap, char **);
131 params.ccase = va_arg(*ap, int);
132 params.cunique = va_arg(*ap, int);
134 return Generic_Enum_Type((void *)¶ms);
137 /*---------------------------------------------------------------------------
138 | Facility : libnform
139 | Function : static void *Copy_Enum_Type( const void * argp )
141 | Description : Copy structure for enumeration type argument.
143 | Return Values : Pointer to argument structure or NULL on error.
144 +--------------------------------------------------------------------------*/
146 Copy_Enum_Type(const void *argp)
148 enumARG *result = (enumARG *)0;
152 const enumARG *ap = (const enumARG *)argp;
154 result = typeMalloc(enumARG, 1);
158 T((T_CREATE("enumARG %p"), (void *)result));
164 char **kp = ap->kwds;
165 result->kwds = typeMalloc(char *, 1 + ap->count);
167 kptarget = result->kwds;
168 while (kptarget && kp && (*kp))
170 (*kptarget++) = strdup(*kp++);
172 *kptarget = (char *)0;
176 return (void *)result;
179 /*---------------------------------------------------------------------------
180 | Facility : libnform
181 | Function : static void Free_Enum_Type( void * argp )
183 | Description : Free structure for enumeration type argument.
186 +--------------------------------------------------------------------------*/
188 Free_Enum_Type(void *argp)
192 const enumARG *ap = (const enumARG *)argp;
194 if (ap->kwds && ap->count > 0)
196 char **kp = ap->kwds;
204 assert(cnt == ap->count);
211 #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
216 /*---------------------------------------------------------------------------
217 | Facility : libnform
218 | Function : static int Compare(const unsigned char * s,
219 | const unsigned char * buf,
222 | Description : Check whether or not the text in 'buf' matches the
223 | text in 's', at least partial.
225 | Return Values : NOMATCH - buffer doesn't match
226 | PARTIAL - buffer matches partially
227 | EXACT - buffer matches exactly
228 +--------------------------------------------------------------------------*/
230 Compare(const unsigned char *s, const unsigned char *buf,
233 SKIP_SPACE(buf); /* Skip leading spaces in both texts */
238 return (((*s) != '\0') ? NOMATCH : EXACT);
252 while (toupper(*s++) == toupper(*buf))
259 /* At this location buf points to the first character where it no longer
260 matches with s. So if only blanks are following, we have a partial
261 match otherwise there is no match */
266 /* If it happens that the reference buffer is at its end, the partial
267 match is actually an exact match. */
268 return ((s[-1] != '\0') ? PARTIAL : EXACT);
271 /*---------------------------------------------------------------------------
272 | Facility : libnform
273 | Function : static bool Check_Enum_Field(
277 | Description : Validate buffer content to be a valid enumeration value
279 | Return Values : TRUE - field is valid
280 | FALSE - field is invalid
281 +--------------------------------------------------------------------------*/
283 Check_Enum_Field(FIELD *field, const void *argp)
285 char **kwds = ((const enumARG *)argp)->kwds;
286 bool ccase = ((const enumARG *)argp)->checkcase;
287 bool unique = ((const enumARG *)argp)->checkunique;
288 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
292 while (kwds && (s = (*kwds++)))
294 if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH)
296 p = t = s; /* t is at least a partial match */
297 if ((unique && res != EXACT))
299 while (kwds && (p = *kwds++))
301 if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH)
315 set_field_buffer(field, 0, t);
325 static const char *dummy[] =
328 /*---------------------------------------------------------------------------
329 | Facility : libnform
330 | Function : static bool Next_Enum(FIELD * field,
333 | Description : Check for the next enumeration value
335 | Return Values : TRUE - next value found and loaded
336 | FALSE - no next value loaded
337 +--------------------------------------------------------------------------*/
339 Next_Enum(FIELD *field, const void *argp)
341 const enumARG *args = (const enumARG *)argp;
342 char **kwds = args->kwds;
343 bool ccase = args->checkcase;
344 int cnt = args->count;
345 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
351 if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT)
356 if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
358 set_field_buffer(field, 0, *kwds);
365 /*---------------------------------------------------------------------------
366 | Facility : libnform
367 | Function : static bool Previous_Enum(
371 | Description : Check for the previous enumeration value
373 | Return Values : TRUE - previous value found and loaded
374 | FALSE - no previous value loaded
375 +--------------------------------------------------------------------------*/
377 Previous_Enum(FIELD *field, const void *argp)
379 const enumARG *args = (const enumARG *)argp;
380 int cnt = args->count;
381 char **kwds = &args->kwds[cnt - 1];
382 bool ccase = args->checkcase;
383 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
389 if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT)
394 kwds = &args->kwds[args->count - 1];
396 if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
398 set_field_buffer(field, 0, *kwds);
405 static FIELDTYPE typeENUM =
407 _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
408 1, /* this is mutable, so we can't be const */
414 INIT_FT_FUNC(Check_Enum_Field),
416 INIT_FT_FUNC(Next_Enum),
417 INIT_FT_FUNC(Previous_Enum),
418 #if NCURSES_INTEROP_FUNCS
423 NCURSES_EXPORT_VAR(FIELDTYPE *)
424 TYPE_ENUM = &typeENUM;
426 #if NCURSES_INTEROP_FUNCS
427 /* The next routines are to simplify the use of ncurses from
428 programming languages with restictions on interop with C level
429 constructs (e.g. variable access or va_list + ellipsis constructs)
431 NCURSES_EXPORT(FIELDTYPE *)
438 /* fty_enum.c ends here */