blob: c96a080db09d4a317622eaf0add1a91aeefef9e6 [file] [log] [blame]
Amit Daniel Kachhape6a01f52011-07-20 11:45:59 +05301/****************************************************************************
2 * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. *
3 * *
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: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
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. *
22 * *
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 *
26 * authorization. *
27 ****************************************************************************/
28
29/***************************************************************************
30* *
31* Author : Juergen Pfeifer *
32* *
33***************************************************************************/
34
35#include "form.priv.h"
36
37MODULE_ID("$Id: fty_enum.c,v 1.22 2007/10/13 19:32:26 tom Exp $")
38
39typedef struct
40 {
41 char **kwds;
42 int count;
43 bool checkcase;
44 bool checkunique;
45 }
46enumARG;
47
48/*---------------------------------------------------------------------------
49| Facility : libnform
50| Function : static void *Make_Enum_Type( va_list * ap )
51|
52| Description : Allocate structure for enumeration type argument.
53|
54| Return Values : Pointer to argument structure or NULL on error
55+--------------------------------------------------------------------------*/
56static void *
57Make_Enum_Type(va_list *ap)
58{
59 enumARG *argp = typeMalloc(enumARG, 1);
60
61 if (argp)
62 {
63 int cnt = 0;
64 char **kp = (char **)0;
65 int ccase, cunique;
66
67 T((T_CREATE("enumARG %p"), argp));
68 argp->kwds = va_arg(*ap, char **);
69 ccase = va_arg(*ap, int);
70 cunique = va_arg(*ap, int);
71
72 argp->checkcase = ccase ? TRUE : FALSE;
73 argp->checkunique = cunique ? TRUE : FALSE;
74
75 kp = argp->kwds;
76 while (kp && (*kp++))
77 cnt++;
78 argp->count = cnt;
79 }
80 return (void *)argp;
81}
82
83/*---------------------------------------------------------------------------
84| Facility : libnform
85| Function : static void *Copy_Enum_Type( const void * argp )
86|
87| Description : Copy structure for enumeration type argument.
88|
89| Return Values : Pointer to argument structure or NULL on error.
90+--------------------------------------------------------------------------*/
91static void *
92Copy_Enum_Type(const void *argp)
93{
94 enumARG *result = (enumARG *)0;
95
96 if (argp)
97 {
98 const enumARG *ap = (const enumARG *)argp;
99
100 result = typeMalloc(enumARG, 1);
101
102 if (result)
103 {
104 T((T_CREATE("enumARG %p"), result));
105 *result = *ap;
106 }
107 }
108 return (void *)result;
109}
110
111/*---------------------------------------------------------------------------
112| Facility : libnform
113| Function : static void Free_Enum_Type( void * argp )
114|
115| Description : Free structure for enumeration type argument.
116|
117| Return Values : -
118+--------------------------------------------------------------------------*/
119static void
120Free_Enum_Type(void *argp)
121{
122 if (argp)
123 free(argp);
124}
125
126#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
127#define NOMATCH 0
128#define PARTIAL 1
129#define EXACT 2
130
131/*---------------------------------------------------------------------------
132| Facility : libnform
133| Function : static int Compare(const unsigned char * s,
134| const unsigned char * buf,
135| bool ccase )
136|
137| Description : Check whether or not the text in 'buf' matches the
138| text in 's', at least partial.
139|
140| Return Values : NOMATCH - buffer doesn't match
141| PARTIAL - buffer matches partially
142| EXACT - buffer matches exactly
143+--------------------------------------------------------------------------*/
144static int
145Compare(const unsigned char *s, const unsigned char *buf,
146 bool ccase)
147{
148 SKIP_SPACE(buf); /* Skip leading spaces in both texts */
149 SKIP_SPACE(s);
150
151 if (*buf == '\0')
152 {
153 return (((*s) != '\0') ? NOMATCH : EXACT);
154 }
155 else
156 {
157 if (ccase)
158 {
159 while (*s++ == *buf)
160 {
161 if (*buf++ == '\0')
162 return EXACT;
163 }
164 }
165 else
166 {
167 while (toupper(*s++) == toupper(*buf))
168 {
169 if (*buf++ == '\0')
170 return EXACT;
171 }
172 }
173 }
174 /* At this location buf points to the first character where it no longer
175 matches with s. So if only blanks are following, we have a partial
176 match otherwise there is no match */
177 SKIP_SPACE(buf);
178 if (*buf)
179 return NOMATCH;
180
181 /* If it happens that the reference buffer is at its end, the partial
182 match is actually an exact match. */
183 return ((s[-1] != '\0') ? PARTIAL : EXACT);
184}
185
186/*---------------------------------------------------------------------------
187| Facility : libnform
188| Function : static bool Check_Enum_Field(
189| FIELD * field,
190| const void * argp)
191|
192| Description : Validate buffer content to be a valid enumeration value
193|
194| Return Values : TRUE - field is valid
195| FALSE - field is invalid
196+--------------------------------------------------------------------------*/
197static bool
198Check_Enum_Field(FIELD *field, const void *argp)
199{
200 char **kwds = ((const enumARG *)argp)->kwds;
201 bool ccase = ((const enumARG *)argp)->checkcase;
202 bool unique = ((const enumARG *)argp)->checkunique;
203 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
204 char *s, *t, *p;
205 int res;
206
207 while (kwds && (s = (*kwds++)))
208 {
209 if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH)
210 {
211 p = t = s; /* t is at least a partial match */
212 if ((unique && res != EXACT))
213 {
214 while (kwds && (p = *kwds++))
215 {
216 if ((res = Compare((unsigned char *)p, bp, ccase)) != NOMATCH)
217 {
218 if (res == EXACT)
219 {
220 t = p;
221 break;
222 }
223 else
224 t = (char *)0;
225 }
226 }
227 }
228 if (t)
229 {
230 set_field_buffer(field, 0, t);
231 return TRUE;
232 }
233 if (!p)
234 break;
235 }
236 }
237 return FALSE;
238}
239
240static const char *dummy[] =
241{(char *)0};
242
243/*---------------------------------------------------------------------------
244| Facility : libnform
245| Function : static bool Next_Enum(FIELD * field,
246| const void * argp)
247|
248| Description : Check for the next enumeration value
249|
250| Return Values : TRUE - next value found and loaded
251| FALSE - no next value loaded
252+--------------------------------------------------------------------------*/
253static bool
254Next_Enum(FIELD *field, const void *argp)
255{
256 const enumARG *args = (const enumARG *)argp;
257 char **kwds = args->kwds;
258 bool ccase = args->checkcase;
259 int cnt = args->count;
260 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
261
262 if (kwds)
263 {
264 while (cnt--)
265 {
266 if (Compare((unsigned char *)(*kwds++), bp, ccase) == EXACT)
267 break;
268 }
269 if (cnt <= 0)
270 kwds = args->kwds;
271 if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
272 {
273 set_field_buffer(field, 0, *kwds);
274 return TRUE;
275 }
276 }
277 return FALSE;
278}
279
280/*---------------------------------------------------------------------------
281| Facility : libnform
282| Function : static bool Previous_Enum(
283| FIELD * field,
284| const void * argp)
285|
286| Description : Check for the previous enumeration value
287|
288| Return Values : TRUE - previous value found and loaded
289| FALSE - no previous value loaded
290+--------------------------------------------------------------------------*/
291static bool
292Previous_Enum(FIELD *field, const void *argp)
293{
294 const enumARG *args = (const enumARG *)argp;
295 int cnt = args->count;
296 char **kwds = &args->kwds[cnt - 1];
297 bool ccase = args->checkcase;
298 unsigned char *bp = (unsigned char *)field_buffer(field, 0);
299
300 if (kwds)
301 {
302 while (cnt--)
303 {
304 if (Compare((unsigned char *)(*kwds--), bp, ccase) == EXACT)
305 break;
306 }
307
308 if (cnt <= 0)
309 kwds = &args->kwds[args->count - 1];
310
311 if ((cnt >= 0) || (Compare((const unsigned char *)dummy, bp, ccase) == EXACT))
312 {
313 set_field_buffer(field, 0, *kwds);
314 return TRUE;
315 }
316 }
317 return FALSE;
318}
319
320static FIELDTYPE typeENUM =
321{
322 _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
323 1, /* this is mutable, so we can't be const */
324 (FIELDTYPE *)0,
325 (FIELDTYPE *)0,
326 Make_Enum_Type,
327 Copy_Enum_Type,
328 Free_Enum_Type,
329 Check_Enum_Field,
330 NULL,
331 Next_Enum,
332 Previous_Enum
333};
334
335NCURSES_EXPORT_VAR(FIELDTYPE *)
336TYPE_ENUM = &typeENUM;
337
338/* fty_enum.c ends here */