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, Juergen.Pfeifer@T-Online.de *
12 ***************************************************************************/
14 #include "form.priv.h"
16 MODULE_ID("$Id: fty_enum.c,v 1.8 1997/10/18 19:33:20 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));
42 argp->kwds = va_arg(*ap,char **);
43 ccase = va_arg(*ap,int);
44 cunique = va_arg(*ap,int);
45 argp->checkcase = ccase ? TRUE : FALSE;
46 argp->checkunique = cunique ? TRUE : FALSE;
49 while( (*kp++) ) cnt++;
55 /*---------------------------------------------------------------------------
57 | Function : static void *Copy_Enum_Type( const void * argp )
59 | Description : Copy structure for enumeration type argument.
61 | Return Values : Pointer to argument structure or NULL on error.
62 +--------------------------------------------------------------------------*/
63 static void *Copy_Enum_Type(const void * argp)
65 const enumARG *ap = (const enumARG *)argp;
66 enumARG *result = (enumARG *)0;
70 result = (enumARG *)malloc(sizeof(enumARG));
74 return (void *)result;
77 /*---------------------------------------------------------------------------
79 | Function : static void Free_Enum_Type( void * argp )
81 | Description : Free structure for enumeration type argument.
84 +--------------------------------------------------------------------------*/
85 static void Free_Enum_Type(void * argp)
91 #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
96 /*---------------------------------------------------------------------------
98 | Function : static int Compare(const unsigned char * s,
99 | const unsigned char * buf,
102 | Description : Check wether or not the text in 'buf' matches the
103 | text in 's', at least partial.
105 | Return Values : NOMATCH - buffer doesn't match
106 | PARTIAL - buffer matches partially
107 | EXACT - buffer matches exactly
108 +--------------------------------------------------------------------------*/
109 static int Compare(const unsigned char *s, const unsigned char *buf,
112 SKIP_SPACE(buf); /* Skip leading spaces in both texts */
117 return (((*s)!='\0') ? NOMATCH : EXACT);
125 if (*buf++=='\0') return EXACT;
130 while(toupper(*s++)==toupper(*buf))
132 if (*buf++=='\0') return EXACT;
136 /* At this location buf points to the first character where it no longer
137 matches with s. So if only blanks are following, we have a partial
138 match otherwise there is no match */
143 /* If it happens that the reference buffer is at its end, the partial
144 match is actually an exact match. */
145 return ((s[-1]!='\0') ? PARTIAL : EXACT);
148 /*---------------------------------------------------------------------------
149 | Facility : libnform
150 | Function : static bool Check_Enum_Field(
154 | Description : Validate buffer content to be a valid enumeration value
156 | Return Values : TRUE - field is valid
157 | FALSE - field is invalid
158 +--------------------------------------------------------------------------*/
159 static bool Check_Enum_Field(FIELD * field, const void * argp)
161 char **kwds = ((const enumARG *)argp)->kwds;
162 bool ccase = ((const enumARG *)argp)->checkcase;
163 bool unique = ((const enumARG *)argp)->checkunique;
164 unsigned char *bp = (unsigned char *)field_buffer(field,0);
168 while( (s=(*kwds++)) )
170 if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)
172 p=t=s; /* t is at least a partial match */
173 if ((unique && res!=EXACT))
175 while( (p = *kwds++) )
177 if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)
191 set_field_buffer(field,0,t);
201 static const char *dummy[] = { (char *)0 };
203 /*---------------------------------------------------------------------------
204 | Facility : libnform
205 | Function : static bool Next_Enum(FIELD * field,
208 | Description : Check for the next enumeration value
210 | Return Values : TRUE - next value found and loaded
211 | FALSE - no next value loaded
212 +--------------------------------------------------------------------------*/
213 static bool Next_Enum(FIELD * field, const void * argp)
215 const enumARG *args = (const enumARG *)argp;
216 char **kwds = args->kwds;
217 bool ccase = args->checkcase;
218 int cnt = args->count;
219 unsigned char *bp = (unsigned char *)field_buffer(field,0);
223 if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT)
228 if ((cnt>=0) || (Compare((unsigned char *)dummy,bp,ccase)==EXACT))
230 set_field_buffer(field,0,*kwds);
236 /*---------------------------------------------------------------------------
237 | Facility : libnform
238 | Function : static bool Previous_Enum(
242 | Description : Check for the previous enumeration value
244 | Return Values : TRUE - previous value found and loaded
245 | FALSE - no previous value loaded
246 +--------------------------------------------------------------------------*/
247 static bool Previous_Enum(FIELD * field, const void * argp)
249 const enumARG *args = (const enumARG *)argp;
250 int cnt = args->count;
251 char **kwds = &args->kwds[cnt-1];
252 bool ccase = args->checkcase;
253 unsigned char *bp = (unsigned char *)field_buffer(field,0);
257 if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT)
262 kwds = &args->kwds[args->count-1];
264 if ((cnt>=0) || (Compare((unsigned char *)dummy,bp,ccase)==EXACT))
266 set_field_buffer(field,0,*kwds);
273 static FIELDTYPE typeENUM = {
274 _HAS_ARGS | _HAS_CHOICE | _RESIDENT,
275 1, /* this is mutable, so we can't be const */
287 FIELDTYPE* TYPE_ENUM = &typeENUM;
289 /* fty_enum.c ends here */