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.
8 /***************************************************************************
10 * Author : Juergen Pfeifer *
12 ***************************************************************************/
14 #include "form.priv.h"
16 MODULE_ID("$Id: fty_enum.c,v 1.18 2003/11/08 20:25:29 tom Exp $")
25 /*---------------------------------------------------------------------------
27 | Function : static void *Make_Enum_Type( va_list * ap )
29 | Description : Allocate structure for enumeration type argument.
31 | Return Values : Pointer to argument structure or NULL on error
32 +--------------------------------------------------------------------------*/
33 static void *Make_Enum_Type(va_list * ap)
35 enumARG *argp = (enumARG *)malloc(sizeof(enumARG));
40 char **kp = (char **)0;
43 argp->kwds = va_arg(*ap,char **);
44 ccase = va_arg(*ap,int);
45 cunique = va_arg(*ap,int);
46 argp->checkcase = ccase ? TRUE : FALSE;
47 argp->checkunique = cunique ? TRUE : FALSE;
50 while( kp && (*kp++) ) cnt++;
56 /*---------------------------------------------------------------------------
58 | Function : static void *Copy_Enum_Type( const void * argp )
60 | Description : Copy structure for enumeration type argument.
62 | Return Values : Pointer to argument structure or NULL on error.
63 +--------------------------------------------------------------------------*/
64 static void *Copy_Enum_Type(const void * argp)
66 enumARG *result = (enumARG *)0;
70 const enumARG *ap = (const enumARG *)argp;
72 result = (enumARG *)malloc(sizeof(enumARG));
76 return (void *)result;
79 /*---------------------------------------------------------------------------
81 | Function : static void Free_Enum_Type( void * argp )
83 | Description : Free structure for enumeration type argument.
86 +--------------------------------------------------------------------------*/
87 static void Free_Enum_Type(void * argp)
93 #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
98 /*---------------------------------------------------------------------------
100 | Function : static int Compare(const unsigned char * s,
101 | const unsigned char * buf,
104 | Description : Check whether or not the text in 'buf' matches the
105 | text in 's', at least partial.
107 | Return Values : NOMATCH - buffer doesn't match
108 | PARTIAL - buffer matches partially
109 | EXACT - buffer matches exactly
110 +--------------------------------------------------------------------------*/
111 static int Compare(const unsigned char *s, const unsigned char *buf,
114 SKIP_SPACE(buf); /* Skip leading spaces in both texts */
119 return (((*s)!='\0') ? NOMATCH : EXACT);
127 if (*buf++=='\0') return EXACT;
132 while(toupper(*s++)==toupper(*buf))
134 if (*buf++=='\0') return EXACT;
138 /* At this location buf points to the first character where it no longer
139 matches with s. So if only blanks are following, we have a partial
140 match otherwise there is no match */
145 /* If it happens that the reference buffer is at its end, the partial
146 match is actually an exact match. */
147 return ((s[-1]!='\0') ? PARTIAL : EXACT);
150 /*---------------------------------------------------------------------------
151 | Facility : libnform
152 | Function : static bool Check_Enum_Field(
156 | Description : Validate buffer content to be a valid enumeration value
158 | Return Values : TRUE - field is valid
159 | FALSE - field is invalid
160 +--------------------------------------------------------------------------*/
161 static bool Check_Enum_Field(FIELD * field, const void * argp)
163 char **kwds = ((const enumARG *)argp)->kwds;
164 bool ccase = ((const enumARG *)argp)->checkcase;
165 bool unique = ((const enumARG *)argp)->checkunique;
166 unsigned char *bp = (unsigned char *)field_buffer(field,0);
170 while( kwds && (s=(*kwds++)) )
172 if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)
174 p=t=s; /* t is at least a partial match */
175 if ((unique && res!=EXACT))
177 while( kwds && (p = *kwds++) )
179 if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)
193 set_field_buffer(field,0,t);
203 static const char *dummy[] = { (char *)0 };
205 /*---------------------------------------------------------------------------
206 | Facility : libnform
207 | Function : static bool Next_Enum(FIELD * field,
210 | Description : Check for the next enumeration value
212 | Return Values : TRUE - next value found and loaded
213 | FALSE - no next value loaded
214 +--------------------------------------------------------------------------*/
215 static bool Next_Enum(FIELD * field, const void * argp)
217 const enumARG *args = (const enumARG *)argp;
218 char **kwds = args->kwds;
219 bool ccase = args->checkcase;
220 int cnt = args->count;
221 unsigned char *bp = (unsigned char *)field_buffer(field,0);
226 if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT)
231 if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
233 set_field_buffer(field,0,*kwds);
240 /*---------------------------------------------------------------------------
241 | Facility : libnform
242 | Function : static bool Previous_Enum(
246 | Description : Check for the previous enumeration value
248 | Return Values : TRUE - previous value found and loaded
249 | FALSE - no previous value loaded
250 +--------------------------------------------------------------------------*/
251 static bool Previous_Enum(FIELD * field, const void * argp)
253 const enumARG *args = (const enumARG *)argp;
254 int cnt = args->count;
255 char **kwds = &args->kwds[cnt-1];
256 bool ccase = args->checkcase;
257 unsigned char *bp = (unsigned char *)field_buffer(field,0);
262 if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT)
267 kwds = &args->kwds[args->count-1];
269 if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
271 set_field_buffer(field,0,*kwds);
279 static FIELDTYPE typeENUM = {
280 _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
281 1, /* this is mutable, so we can't be const */
293 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ENUM = &typeENUM;
295 /* fty_enum.c ends here */