Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Source/CursesDialog/form/fty_enum.c
5017 views
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, [email protected] *
11
* *
12
***************************************************************************/
13
14
#include "form.priv.h"
15
16
MODULE_ID("$Id$")
17
18
typedef struct {
19
char **kwds;
20
int count;
21
bool checkcase;
22
bool checkunique;
23
} enumARG;
24
25
/*---------------------------------------------------------------------------
26
| Facility : libnform
27
| Function : static void *Make_Enum_Type( va_list * ap )
28
|
29
| Description : Allocate structure for enumeration type argument.
30
|
31
| Return Values : Pointer to argument structure or NULL on error
32
+--------------------------------------------------------------------------*/
33
static void *Make_Enum_Type(va_list * ap)
34
{
35
enumARG *argp = (enumARG *)malloc(sizeof(enumARG));
36
37
if (argp)
38
{
39
int cnt = 0;
40
char **kp = (char **)0;
41
int ccase, cunique;
42
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;
48
49
kp = argp->kwds;
50
while( kp && (*kp++) ) cnt++;
51
argp->count = cnt;
52
}
53
return (void *)argp;
54
}
55
56
/*---------------------------------------------------------------------------
57
| Facility : libnform
58
| Function : static void *Copy_Enum_Type( const void * argp )
59
|
60
| Description : Copy structure for enumeration type argument.
61
|
62
| Return Values : Pointer to argument structure or NULL on error.
63
+--------------------------------------------------------------------------*/
64
static void *Copy_Enum_Type(const void * argp)
65
{
66
enumARG *result = (enumARG *)0;
67
68
if (argp)
69
{
70
const enumARG *ap = (const enumARG *)argp;
71
72
result = (enumARG *)malloc(sizeof(enumARG));
73
if (result)
74
*result = *ap;
75
}
76
return (void *)result;
77
}
78
79
/*---------------------------------------------------------------------------
80
| Facility : libnform
81
| Function : static void Free_Enum_Type( void * argp )
82
|
83
| Description : Free structure for enumeration type argument.
84
|
85
| Return Values : -
86
+--------------------------------------------------------------------------*/
87
static void Free_Enum_Type(void * argp)
88
{
89
if (argp)
90
free(argp);
91
}
92
93
#define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++
94
#define NOMATCH 0
95
#define PARTIAL 1
96
#define EXACT 2
97
98
/*---------------------------------------------------------------------------
99
| Facility : libnform
100
| Function : static int Compare(const unsigned char * s,
101
| const unsigned char * buf,
102
| bool ccase )
103
|
104
| Description : Check whether or not the text in 'buf' matches the
105
| text in 's', at least partial.
106
|
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,
112
bool ccase)
113
{
114
SKIP_SPACE(buf); /* Skip leading spaces in both texts */
115
SKIP_SPACE(s);
116
117
if (*buf=='\0')
118
{
119
return (((*s)=='\0') ? EXACT : NOMATCH);
120
}
121
else
122
{
123
if (ccase)
124
{
125
while(*s++ == *buf)
126
{
127
if (*buf++=='\0') return EXACT;
128
}
129
}
130
else
131
{
132
while(toupper(*s++)==toupper(*buf))
133
{
134
if (*buf++=='\0') return EXACT;
135
}
136
}
137
}
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 */
141
SKIP_SPACE(buf);
142
if (*buf)
143
return NOMATCH;
144
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') ? EXACT : PARTIAL);
148
}
149
150
/*---------------------------------------------------------------------------
151
| Facility : libnform
152
| Function : static bool Check_Enum_Field(
153
| FIELD * field,
154
| const void * argp)
155
|
156
| Description : Validate buffer content to be a valid enumeration value
157
|
158
| Return Values : TRUE - field is valid
159
| FALSE - field is invalid
160
+--------------------------------------------------------------------------*/
161
static bool Check_Enum_Field(FIELD * field, const void * argp)
162
{
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);
167
char *s, *t, *p;
168
int res;
169
170
while( kwds && (s=(*kwds++)) )
171
{
172
if ((res=Compare((unsigned char *)s,bp,ccase))!=NOMATCH)
173
{
174
p=t=s; /* t is at least a partial match */
175
if ((unique && res!=EXACT))
176
{
177
while( kwds && (p = *kwds++) )
178
{
179
if ((res=Compare((unsigned char *)p,bp,ccase))!=NOMATCH)
180
{
181
if (res==EXACT)
182
{
183
t = p;
184
break;
185
}
186
else
187
t = (char *)0;
188
}
189
}
190
}
191
if (t)
192
{
193
set_field_buffer(field,0,t);
194
return TRUE;
195
}
196
if (!p)
197
break;
198
}
199
}
200
return FALSE;
201
}
202
203
static const char *dummy[] = { (char *)0 };
204
205
/*---------------------------------------------------------------------------
206
| Facility : libnform
207
| Function : static bool Next_Enum(FIELD * field,
208
| const void * argp)
209
|
210
| Description : Check for the next enumeration value
211
|
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)
216
{
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);
222
223
if (kwds) {
224
while(cnt--)
225
{
226
if (Compare((unsigned char *)(*kwds++),bp,ccase)==EXACT)
227
break;
228
}
229
if (cnt<=0)
230
kwds = args->kwds;
231
if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
232
{
233
set_field_buffer(field,0,*kwds);
234
return TRUE;
235
}
236
}
237
return FALSE;
238
}
239
240
/*---------------------------------------------------------------------------
241
| Facility : libnform
242
| Function : static bool Previous_Enum(
243
| FIELD * field,
244
| const void * argp)
245
|
246
| Description : Check for the previous enumeration value
247
|
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)
252
{
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);
258
259
if (kwds) {
260
while(cnt--)
261
{
262
if (Compare((unsigned char *)(*kwds--),bp,ccase)==EXACT)
263
break;
264
}
265
266
if (cnt<=0)
267
kwds = &args->kwds[args->count-1];
268
269
if ((cnt>=0) || (Compare((const unsigned char *)dummy,bp,ccase)==EXACT))
270
{
271
set_field_buffer(field,0,*kwds);
272
return TRUE;
273
}
274
}
275
return FALSE;
276
}
277
278
279
static FIELDTYPE typeENUM = {
280
_HAS_ARGS | _HAS_CHOICE | _RESIDENT,
281
1, /* this is mutable, so we can't be const */
282
(FIELDTYPE *)0,
283
(FIELDTYPE *)0,
284
Make_Enum_Type,
285
Copy_Enum_Type,
286
Free_Enum_Type,
287
Check_Enum_Field,
288
NULL,
289
Next_Enum,
290
Previous_Enum
291
};
292
293
FIELDTYPE* TYPE_ENUM = &typeENUM;
294
295
/* fty_enum.c ends here */
296
297