xref: /netbsd/lib/libform/field_types.c (revision bf9ec67e)
1 /*	$NetBSD: field_types.c,v 1.3 2001/06/13 10:45:58 wiz Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998-1999 Brett Lymn
5  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6  * All rights reserved.
7  *
8  * This code has been donated to The NetBSD Foundation by the Author.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *
30  */
31 
32 #include <stdlib.h>
33 #include <stdarg.h>
34 #include "form.h"
35 #include "internals.h"
36 
37 extern FIELD _formi_default_field;
38 
39 /* function prototypes.... */
40 static void
41 _formi_create_field_args(FIELDTYPE *type, char **type_args,
42 			 formi_type_link **link, va_list *args, int *error);
43 static FIELDTYPE *
44 _formi_create_fieldtype(void);
45 
46 /*
47  * Process the arguments, if any, for the field type.
48  */
49 static void
50 _formi_create_field_args(FIELDTYPE *type, char **type_args,
51 			 formi_type_link **link, va_list *args, int *error)
52 {
53 	formi_type_link *l;
54 
55 	l = NULL;
56 	if ((type != NULL)
57 	    && ((type->flags & _TYPE_HAS_ARGS) == _TYPE_HAS_ARGS)) {
58 		if ((type->flags & _TYPE_IS_LINKED) == _TYPE_IS_LINKED) {
59 			l = (formi_type_link *)
60 				malloc(sizeof(formi_type_link));
61 			if (l != NULL) {
62 				_formi_create_field_args(type->link->next,
63 							 type_args,
64 							 &type->link->next->link,
65 							 args,
66 							 error);
67 				_formi_create_field_args(type->link->prev,
68 							 type_args,
69 							 &type->link->prev->link,
70 							 args,
71 							 error);
72 				(*link) = l;
73 			}
74 
75 			(*error)++;
76 		} else {
77 			if ((*type_args = (char *) type->make_args(args))
78 			    == NULL)
79 				(*error)++;
80 		}
81 	}
82 }
83 
84 /*
85  * Allocate a new fieldtype structure, initialise it and return the
86  * struct to the caller.
87  */
88 static FIELDTYPE *
89 _formi_create_fieldtype(void)
90 {
91 	FIELDTYPE *new;
92 
93 	if ((new = (FIELDTYPE *) malloc(sizeof(FIELDTYPE))) == NULL)
94 		return NULL;
95 
96 	new->flags = _TYPE_NO_FLAGS;
97 	new->refcount = 0;
98 	new->link = NULL;
99 	new->make_args = NULL;
100 	new->copy_args = NULL;
101 	new->free_args = NULL;
102 	new->field_check = NULL;
103 	new->char_check = NULL;
104 	new->next_choice = NULL;
105 	new->prev_choice = NULL;
106 
107 	return new;
108 }
109 
110 /*
111  * Set the field type of the field to be the one given.
112  */
113 int
114 set_field_type(FIELD *fptr, FIELDTYPE *type, ...)
115 {
116 	va_list args;
117 	FIELD *field;
118 	int error = 0;
119 
120 	va_start(args, type);
121 
122 	field = (fptr == NULL)? &_formi_default_field : fptr;
123 
124 	field->type = type;
125 	_formi_create_field_args(type, &fptr->args, &type->link, &args,
126 				 &error);
127 	va_end(args);
128 
129 	if (error)
130 		return E_BAD_ARGUMENT;
131 
132 	return E_OK;
133 }
134 
135 /*
136  * Return the field type associated with the given field
137  */
138 FIELDTYPE *
139 field_type(FIELD *fptr)
140 {
141 	FIELD *field;
142 
143 	field = (fptr == NULL)? &_formi_default_field : fptr;
144 
145 	return field->type;
146 }
147 
148 
149 /*
150  * Return the field arguments for the given field.
151  */
152 char *
153 field_arg(FIELD *fptr)
154 {
155 	FIELD *field;
156 
157 	field = (fptr == NULL)? &_formi_default_field : fptr;
158 
159 	return field->args;
160 }
161 
162 /*
163  * Create a new field type.  Caller must specify a field_check routine
164  * and char_check routine.
165  */
166 FIELDTYPE *
167 new_fieldtype(int (*field_check)(FIELD *, char *),
168 	      int (*char_check)(int, char *))
169 {
170 	FIELDTYPE *new;
171 
172 	if ((field_check == NULL) || (char_check == NULL))
173 		return NULL;
174 
175 	if ((new = _formi_create_fieldtype()) != NULL) {
176 		new->field_check = field_check;
177 		new->char_check = char_check;
178 	}
179 
180 	return new;
181 }
182 
183 /*
184  * Free the storage used by the fieldtype.
185  */
186 int
187 free_fieldtype(FIELDTYPE *fieldtype)
188 {
189 	if (fieldtype == NULL)
190 		return E_BAD_ARGUMENT;
191 
192 	if (fieldtype->refcount > 0)
193 		return E_CONNECTED;
194 
195 	if ((fieldtype->flags & _TYPE_IS_BUILTIN) == _TYPE_IS_BUILTIN)
196 		return E_BAD_ARGUMENT; /* don't delete builtin types! */
197 
198 	if ((fieldtype->flags & _TYPE_IS_LINKED) == _TYPE_IS_LINKED)
199 	{
200 		fieldtype->link->next->refcount--;
201 		fieldtype->link->prev->refcount--;
202 	}
203 
204 	free(fieldtype);
205 
206 	return E_OK;
207 }
208 
209 /*
210  * Set the field type arguments for the given field type.
211  */
212 int
213 set_fieldtype_arg(FIELDTYPE *fieldtype, char * (*make_args)(va_list *),
214 		  char * (*copy_args)(char*), void (*free_args)(char *))
215 {
216 	if ((fieldtype == NULL) || (make_args == NULL)
217 	    || (copy_args == NULL) || (free_args == NULL))
218 		return E_BAD_ARGUMENT;
219 
220 	fieldtype->make_args = make_args;
221 	fieldtype->copy_args = copy_args;
222 	fieldtype->free_args = free_args;
223 
224 	return E_OK;
225 }
226 
227 /*
228  * Set up the choice list functions for the given fieldtype.
229  */
230 int
231 set_fieldtype_choice(FIELDTYPE *fieldtype, int (*next_choice)(FIELD *, char *),
232 		     int (*prev_choice)(FIELD *, char *))
233 {
234 	if ((fieldtype == NULL) || (next_choice == NULL)
235 	    || (prev_choice == NULL))
236 		return E_BAD_ARGUMENT;
237 
238 	fieldtype->next_choice = next_choice;
239 	fieldtype->prev_choice = prev_choice;
240 
241 	return E_OK;
242 }
243 
244 /*
245  * Link the two given types to produce a new type, return this new type.
246  */
247 FIELDTYPE *
248 link_fieldtype(FIELDTYPE *type1, FIELDTYPE *type2)
249 {
250 	FIELDTYPE *new;
251 
252 	if ((type1 == NULL) || (type2 == NULL))
253 		return NULL;
254 
255 	if ((new = _formi_create_fieldtype()) == NULL)
256 		return NULL;
257 
258 	new->flags = _TYPE_IS_LINKED;
259 	new->flags |= ((type1->flags & _TYPE_HAS_ARGS)
260 		       | (type2->flags & _TYPE_HAS_ARGS));
261 	if ((new->link = (_FORMI_TYPE_LINK*) malloc(sizeof(_FORMI_TYPE_LINK))) == NULL)
262 		return NULL;
263 
264 	new->link->prev = type1;
265 	new->link->next = type2;
266 	type1->refcount++;
267 	type2->refcount++;
268 
269 	return new;
270 }
271