source: trunk/essentials/sys-libs/ncurses/form/fty_enum.c@ 3951

Last change on this file since 3951 was 2621, checked in by bird, 20 years ago

GNU ncurses 5.5

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