xref: /minix3/lib/libform/form.c (revision a0e6850f820f09a03a1da1b4d78f9fafb3b9782f)
1*a0e6850fSThomas Cort /*	$NetBSD: form.c,v 1.15 2004/11/24 11:57:09 blymn Exp $	*/
2*a0e6850fSThomas Cort 
3*a0e6850fSThomas Cort /*-
4*a0e6850fSThomas Cort  * Copyright (c) 1998-1999 Brett Lymn
5*a0e6850fSThomas Cort  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6*a0e6850fSThomas Cort  * All rights reserved.
7*a0e6850fSThomas Cort  *
8*a0e6850fSThomas Cort  * This code has been donated to The NetBSD Foundation by the Author.
9*a0e6850fSThomas Cort  *
10*a0e6850fSThomas Cort  * Redistribution and use in source and binary forms, with or without
11*a0e6850fSThomas Cort  * modification, are permitted provided that the following conditions
12*a0e6850fSThomas Cort  * are met:
13*a0e6850fSThomas Cort  * 1. Redistributions of source code must retain the above copyright
14*a0e6850fSThomas Cort  *    notice, this list of conditions and the following disclaimer.
15*a0e6850fSThomas Cort  * 2. The name of the author may not be used to endorse or promote products
16*a0e6850fSThomas Cort  *    derived from this software without specific prior written permission
17*a0e6850fSThomas Cort  *
18*a0e6850fSThomas Cort  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*a0e6850fSThomas Cort  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*a0e6850fSThomas Cort  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*a0e6850fSThomas Cort  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*a0e6850fSThomas Cort  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*a0e6850fSThomas Cort  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*a0e6850fSThomas Cort  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*a0e6850fSThomas Cort  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*a0e6850fSThomas Cort  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*a0e6850fSThomas Cort  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*a0e6850fSThomas Cort  *
29*a0e6850fSThomas Cort  *
30*a0e6850fSThomas Cort  */
31*a0e6850fSThomas Cort 
32*a0e6850fSThomas Cort #include <sys/cdefs.h>
33*a0e6850fSThomas Cort __RCSID("$NetBSD: form.c,v 1.15 2004/11/24 11:57:09 blymn Exp $");
34*a0e6850fSThomas Cort 
35*a0e6850fSThomas Cort #include <stdlib.h>
36*a0e6850fSThomas Cort #include <strings.h>
37*a0e6850fSThomas Cort #include <form.h>
38*a0e6850fSThomas Cort #include "internals.h"
39*a0e6850fSThomas Cort 
40*a0e6850fSThomas Cort extern FIELD _formi_default_field;
41*a0e6850fSThomas Cort 
42*a0e6850fSThomas Cort FORM _formi_default_form = {
43*a0e6850fSThomas Cort 	FALSE, /* true if performing a init or term function */
44*a0e6850fSThomas Cort 	FALSE, /* the form is posted */
45*a0e6850fSThomas Cort 	FALSE, /* make field list circular if true */
46*a0e6850fSThomas Cort 	NULL, /* window for the form */
47*a0e6850fSThomas Cort 	NULL, /* subwindow for the form */
48*a0e6850fSThomas Cort 	NULL, /* use this window for output */
49*a0e6850fSThomas Cort 	NULL, /* user defined pointer */
50*a0e6850fSThomas Cort 	0, /* options for the form */
51*a0e6850fSThomas Cort 	NULL, /* function called when form posted and
52*a0e6850fSThomas Cort 				after page change */
53*a0e6850fSThomas Cort 	NULL, /* function called when form is unposted and
54*a0e6850fSThomas Cort 				before page change */
55*a0e6850fSThomas Cort 	NULL, /* function called when form posted and after
56*a0e6850fSThomas Cort 				 current field changes */
57*a0e6850fSThomas Cort 	NULL, /* function called when form unposted and
58*a0e6850fSThomas Cort 				 before current field changes */
59*a0e6850fSThomas Cort 	0, /* number of fields attached */
60*a0e6850fSThomas Cort 	0, /* current field */
61*a0e6850fSThomas Cort 	0, /* current page of form */
62*a0e6850fSThomas Cort 	0, /* number of pages in the form */
63*a0e6850fSThomas Cort 	NULL, /* dynamic array of fields that start
64*a0e6850fSThomas Cort 					   the pages */
65*a0e6850fSThomas Cort 	{NULL, NULL}, /* sorted field list */
66*a0e6850fSThomas Cort 	NULL /* array of fields attached to this form. */
67*a0e6850fSThomas Cort };
68*a0e6850fSThomas Cort 
69*a0e6850fSThomas Cort /*
70*a0e6850fSThomas Cort  * Set the window associated with the form
71*a0e6850fSThomas Cort  */
72*a0e6850fSThomas Cort int
set_form_win(FORM * form,WINDOW * win)73*a0e6850fSThomas Cort set_form_win(FORM *form, WINDOW *win)
74*a0e6850fSThomas Cort {
75*a0e6850fSThomas Cort 	if (form == NULL) {
76*a0e6850fSThomas Cort 		_formi_default_form.win = win;
77*a0e6850fSThomas Cort 		_formi_default_form.scrwin = win;
78*a0e6850fSThomas Cort 	} else {
79*a0e6850fSThomas Cort 		if (form->posted == TRUE)
80*a0e6850fSThomas Cort 			return E_POSTED;
81*a0e6850fSThomas Cort 		else {
82*a0e6850fSThomas Cort 			form->win = win;
83*a0e6850fSThomas Cort 			form->scrwin = win;
84*a0e6850fSThomas Cort 		}
85*a0e6850fSThomas Cort 	}
86*a0e6850fSThomas Cort 
87*a0e6850fSThomas Cort 	return E_OK;
88*a0e6850fSThomas Cort }
89*a0e6850fSThomas Cort 
90*a0e6850fSThomas Cort /*
91*a0e6850fSThomas Cort  * Return the window used by the given form
92*a0e6850fSThomas Cort  */
93*a0e6850fSThomas Cort WINDOW *
form_win(FORM * form)94*a0e6850fSThomas Cort form_win(FORM *form)
95*a0e6850fSThomas Cort {
96*a0e6850fSThomas Cort 	if (form == NULL)
97*a0e6850fSThomas Cort 		return _formi_default_form.win;
98*a0e6850fSThomas Cort 	else
99*a0e6850fSThomas Cort 		return form->win;
100*a0e6850fSThomas Cort }
101*a0e6850fSThomas Cort 
102*a0e6850fSThomas Cort /*
103*a0e6850fSThomas Cort  * Set the subwindow for the form.
104*a0e6850fSThomas Cort  */
105*a0e6850fSThomas Cort int
set_form_sub(FORM * form,WINDOW * window)106*a0e6850fSThomas Cort set_form_sub(FORM *form, WINDOW *window)
107*a0e6850fSThomas Cort {
108*a0e6850fSThomas Cort 	if (form == NULL) {
109*a0e6850fSThomas Cort 		_formi_default_form.subwin = window;
110*a0e6850fSThomas Cort 		_formi_default_form.scrwin = window;
111*a0e6850fSThomas Cort 	} else {
112*a0e6850fSThomas Cort 		if (form->posted == TRUE)
113*a0e6850fSThomas Cort 			return E_POSTED;
114*a0e6850fSThomas Cort 		else {
115*a0e6850fSThomas Cort 			form->subwin = window;
116*a0e6850fSThomas Cort 			form->scrwin = window;
117*a0e6850fSThomas Cort 		}
118*a0e6850fSThomas Cort 	}
119*a0e6850fSThomas Cort 
120*a0e6850fSThomas Cort 	return E_OK;
121*a0e6850fSThomas Cort }
122*a0e6850fSThomas Cort 
123*a0e6850fSThomas Cort /*
124*a0e6850fSThomas Cort  * Return the subwindow for the given form.
125*a0e6850fSThomas Cort  */
126*a0e6850fSThomas Cort WINDOW *
form_sub(FORM * form)127*a0e6850fSThomas Cort form_sub(FORM *form)
128*a0e6850fSThomas Cort {
129*a0e6850fSThomas Cort 	if (form == NULL)
130*a0e6850fSThomas Cort 		return _formi_default_form.subwin;
131*a0e6850fSThomas Cort 	else
132*a0e6850fSThomas Cort 		return form->subwin;
133*a0e6850fSThomas Cort }
134*a0e6850fSThomas Cort 
135*a0e6850fSThomas Cort /*
136*a0e6850fSThomas Cort  * Return the minimum size required to contain the form.
137*a0e6850fSThomas Cort  */
138*a0e6850fSThomas Cort int
scale_form(FORM * form,int * rows,int * cols)139*a0e6850fSThomas Cort scale_form(FORM *form, int *rows, int *cols)
140*a0e6850fSThomas Cort {
141*a0e6850fSThomas Cort 	int i, max_row, max_col, temp;
142*a0e6850fSThomas Cort 
143*a0e6850fSThomas Cort 	if ((form->fields == NULL) || (form->fields[0] == NULL))
144*a0e6850fSThomas Cort 		return E_NOT_CONNECTED;
145*a0e6850fSThomas Cort 
146*a0e6850fSThomas Cort 	max_row = 0;
147*a0e6850fSThomas Cort 	max_col = 0;
148*a0e6850fSThomas Cort 
149*a0e6850fSThomas Cort 	for (i = 0; i < form->field_count; i++) {
150*a0e6850fSThomas Cort 		temp = form->fields[i]->form_row + form->fields[i]->rows;
151*a0e6850fSThomas Cort 		max_row = (temp > max_row)? temp : max_row;
152*a0e6850fSThomas Cort 		temp = form->fields[i]->form_col + form->fields[i]->cols;
153*a0e6850fSThomas Cort 		max_col = (temp > max_col)? temp : max_col;
154*a0e6850fSThomas Cort 	}
155*a0e6850fSThomas Cort 
156*a0e6850fSThomas Cort 	(*rows) = max_row;
157*a0e6850fSThomas Cort 	(*cols) = max_col;
158*a0e6850fSThomas Cort 
159*a0e6850fSThomas Cort 	return E_OK;
160*a0e6850fSThomas Cort }
161*a0e6850fSThomas Cort 
162*a0e6850fSThomas Cort /*
163*a0e6850fSThomas Cort  * Set the user defined pointer for the form given.
164*a0e6850fSThomas Cort  */
165*a0e6850fSThomas Cort int
set_form_userptr(FORM * form,void * ptr)166*a0e6850fSThomas Cort set_form_userptr(FORM *form, void *ptr)
167*a0e6850fSThomas Cort {
168*a0e6850fSThomas Cort 	if (form == NULL)
169*a0e6850fSThomas Cort 		_formi_default_form.userptr = ptr;
170*a0e6850fSThomas Cort 	else
171*a0e6850fSThomas Cort 		form->userptr = ptr;
172*a0e6850fSThomas Cort 
173*a0e6850fSThomas Cort 	return E_OK;
174*a0e6850fSThomas Cort }
175*a0e6850fSThomas Cort 
176*a0e6850fSThomas Cort /*
177*a0e6850fSThomas Cort  * Return the user defined pointer associated with the given form.
178*a0e6850fSThomas Cort  */
179*a0e6850fSThomas Cort void *
form_userptr(FORM * form)180*a0e6850fSThomas Cort form_userptr(FORM *form)
181*a0e6850fSThomas Cort {
182*a0e6850fSThomas Cort 
183*a0e6850fSThomas Cort 	if (form == NULL)
184*a0e6850fSThomas Cort 		return _formi_default_form.userptr;
185*a0e6850fSThomas Cort 	else
186*a0e6850fSThomas Cort 		return form->userptr;
187*a0e6850fSThomas Cort }
188*a0e6850fSThomas Cort 
189*a0e6850fSThomas Cort /*
190*a0e6850fSThomas Cort  * Set the form options to the given ones.
191*a0e6850fSThomas Cort  */
192*a0e6850fSThomas Cort int
set_form_opts(FORM * form,Form_Options options)193*a0e6850fSThomas Cort set_form_opts(FORM *form, Form_Options options)
194*a0e6850fSThomas Cort {
195*a0e6850fSThomas Cort 	if (form == NULL)
196*a0e6850fSThomas Cort 		_formi_default_form.opts = options;
197*a0e6850fSThomas Cort 	else
198*a0e6850fSThomas Cort 		form->opts = options;
199*a0e6850fSThomas Cort 
200*a0e6850fSThomas Cort 	return E_OK;
201*a0e6850fSThomas Cort }
202*a0e6850fSThomas Cort 
203*a0e6850fSThomas Cort /*
204*a0e6850fSThomas Cort  * Turn the given options on for the form.
205*a0e6850fSThomas Cort  */
206*a0e6850fSThomas Cort int
form_opts_on(FORM * form,Form_Options options)207*a0e6850fSThomas Cort form_opts_on(FORM *form, Form_Options options)
208*a0e6850fSThomas Cort {
209*a0e6850fSThomas Cort 	if (form == NULL)
210*a0e6850fSThomas Cort 		_formi_default_form.opts |= options;
211*a0e6850fSThomas Cort 	else
212*a0e6850fSThomas Cort 		form->opts |= options;
213*a0e6850fSThomas Cort 
214*a0e6850fSThomas Cort 	return E_OK;
215*a0e6850fSThomas Cort }
216*a0e6850fSThomas Cort 
217*a0e6850fSThomas Cort /*
218*a0e6850fSThomas Cort  * Turn the given options off for the form.
219*a0e6850fSThomas Cort  */
220*a0e6850fSThomas Cort int
form_opts_off(FORM * form,Form_Options options)221*a0e6850fSThomas Cort form_opts_off(FORM *form, Form_Options options)
222*a0e6850fSThomas Cort {
223*a0e6850fSThomas Cort 	if (form == NULL)
224*a0e6850fSThomas Cort 		_formi_default_form.opts &= ~options;
225*a0e6850fSThomas Cort 	else
226*a0e6850fSThomas Cort 		form->opts &= ~options;
227*a0e6850fSThomas Cort 
228*a0e6850fSThomas Cort 
229*a0e6850fSThomas Cort 	return E_OK;
230*a0e6850fSThomas Cort }
231*a0e6850fSThomas Cort 
232*a0e6850fSThomas Cort /*
233*a0e6850fSThomas Cort  * Return the options set for the given form.
234*a0e6850fSThomas Cort  */
235*a0e6850fSThomas Cort Form_Options
form_opts(FORM * form)236*a0e6850fSThomas Cort form_opts(FORM *form)
237*a0e6850fSThomas Cort {
238*a0e6850fSThomas Cort 	if (form == NULL)
239*a0e6850fSThomas Cort 		return _formi_default_form.opts;
240*a0e6850fSThomas Cort 	else
241*a0e6850fSThomas Cort 		return form->opts;
242*a0e6850fSThomas Cort }
243*a0e6850fSThomas Cort 
244*a0e6850fSThomas Cort /*
245*a0e6850fSThomas Cort  * Set the form init function for the given form
246*a0e6850fSThomas Cort  */
247*a0e6850fSThomas Cort int
set_form_init(FORM * form,Form_Hook func)248*a0e6850fSThomas Cort set_form_init(FORM *form, Form_Hook func)
249*a0e6850fSThomas Cort {
250*a0e6850fSThomas Cort 	if (form == NULL)
251*a0e6850fSThomas Cort 		_formi_default_form.form_init = func;
252*a0e6850fSThomas Cort 	else
253*a0e6850fSThomas Cort 		form->form_init = func;
254*a0e6850fSThomas Cort 
255*a0e6850fSThomas Cort 	return E_OK;
256*a0e6850fSThomas Cort }
257*a0e6850fSThomas Cort 
258*a0e6850fSThomas Cort /*
259*a0e6850fSThomas Cort  * Return the init function associated with the given form.
260*a0e6850fSThomas Cort  */
261*a0e6850fSThomas Cort Form_Hook
form_init(FORM * form)262*a0e6850fSThomas Cort form_init(FORM *form)
263*a0e6850fSThomas Cort {
264*a0e6850fSThomas Cort 	if (form == NULL)
265*a0e6850fSThomas Cort 		return _formi_default_form.form_init;
266*a0e6850fSThomas Cort 	else
267*a0e6850fSThomas Cort 		return form->form_init;
268*a0e6850fSThomas Cort }
269*a0e6850fSThomas Cort 
270*a0e6850fSThomas Cort /*
271*a0e6850fSThomas Cort  * Set the function to be called on form termination.
272*a0e6850fSThomas Cort  */
273*a0e6850fSThomas Cort int
set_form_term(FORM * form,Form_Hook function)274*a0e6850fSThomas Cort set_form_term(FORM *form, Form_Hook function)
275*a0e6850fSThomas Cort {
276*a0e6850fSThomas Cort 	if (form == NULL)
277*a0e6850fSThomas Cort 		_formi_default_form.form_term = function;
278*a0e6850fSThomas Cort 	else
279*a0e6850fSThomas Cort 		form->form_term = function;
280*a0e6850fSThomas Cort 
281*a0e6850fSThomas Cort 	return E_OK;
282*a0e6850fSThomas Cort }
283*a0e6850fSThomas Cort 
284*a0e6850fSThomas Cort /*
285*a0e6850fSThomas Cort  * Return the function defined for the termination function.
286*a0e6850fSThomas Cort  */
287*a0e6850fSThomas Cort Form_Hook
form_term(FORM * form)288*a0e6850fSThomas Cort form_term(FORM *form)
289*a0e6850fSThomas Cort {
290*a0e6850fSThomas Cort 
291*a0e6850fSThomas Cort 	if (form == NULL)
292*a0e6850fSThomas Cort 		return _formi_default_form.form_term;
293*a0e6850fSThomas Cort 	else
294*a0e6850fSThomas Cort 		return form->form_term;
295*a0e6850fSThomas Cort }
296*a0e6850fSThomas Cort 
297*a0e6850fSThomas Cort 
298*a0e6850fSThomas Cort /*
299*a0e6850fSThomas Cort  * Attach the given fields to the form.
300*a0e6850fSThomas Cort  */
301*a0e6850fSThomas Cort int
set_form_fields(FORM * form,FIELD ** fields)302*a0e6850fSThomas Cort set_form_fields(FORM *form, FIELD **fields)
303*a0e6850fSThomas Cort {
304*a0e6850fSThomas Cort 	int num_fields = 0, i, maxpg = 1, status;
305*a0e6850fSThomas Cort 
306*a0e6850fSThomas Cort 	if (form == NULL)
307*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
308*a0e6850fSThomas Cort 
309*a0e6850fSThomas Cort 	if (form->posted == TRUE)
310*a0e6850fSThomas Cort 		return E_POSTED;
311*a0e6850fSThomas Cort 
312*a0e6850fSThomas Cort 	if (fields == NULL)
313*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
314*a0e6850fSThomas Cort 
315*a0e6850fSThomas Cort 	while (fields[num_fields] != NULL) {
316*a0e6850fSThomas Cort 		if ((fields[num_fields]->parent != NULL) &&
317*a0e6850fSThomas Cort 		    (fields[num_fields]->parent != form))
318*a0e6850fSThomas Cort 			return E_CONNECTED;
319*a0e6850fSThomas Cort 		num_fields++;
320*a0e6850fSThomas Cort 	}
321*a0e6850fSThomas Cort 
322*a0e6850fSThomas Cort 	  /* disconnect old fields, if any */
323*a0e6850fSThomas Cort 	if (form->fields != NULL) {
324*a0e6850fSThomas Cort 		for (i = 0; i < form->field_count; i++) {
325*a0e6850fSThomas Cort 			form->fields[i]->parent = NULL;
326*a0e6850fSThomas Cort 			form->fields[i]->index = -1;
327*a0e6850fSThomas Cort 		}
328*a0e6850fSThomas Cort 	}
329*a0e6850fSThomas Cort 
330*a0e6850fSThomas Cort 	  /* kill old page pointers if any */
331*a0e6850fSThomas Cort 	if (form->page_starts != NULL)
332*a0e6850fSThomas Cort 		free(form->page_starts);
333*a0e6850fSThomas Cort 
334*a0e6850fSThomas Cort 	form->field_count = num_fields;
335*a0e6850fSThomas Cort 
336*a0e6850fSThomas Cort 	  /* now connect the new fields to the form */
337*a0e6850fSThomas Cort 	for (i = 0; i < num_fields; i++) {
338*a0e6850fSThomas Cort 		fields[i]->parent = form;
339*a0e6850fSThomas Cort 		fields[i]->index = i;
340*a0e6850fSThomas Cort 		  /* set the page number of the field */
341*a0e6850fSThomas Cort 		if (fields[i]->page_break == 1)
342*a0e6850fSThomas Cort 			maxpg++;
343*a0e6850fSThomas Cort 		fields[i]->page = maxpg;
344*a0e6850fSThomas Cort 	}
345*a0e6850fSThomas Cort 
346*a0e6850fSThomas Cort 	form->fields = fields;
347*a0e6850fSThomas Cort 	form->cur_field = 0;
348*a0e6850fSThomas Cort 	form->max_page = maxpg;
349*a0e6850fSThomas Cort 	if ((status = _formi_find_pages(form)) != E_OK)
350*a0e6850fSThomas Cort 		return status;
351*a0e6850fSThomas Cort 
352*a0e6850fSThomas Cort 	  /* sort the fields and set the navigation pointers */
353*a0e6850fSThomas Cort 	_formi_sort_fields(form);
354*a0e6850fSThomas Cort 	_formi_stitch_fields(form);
355*a0e6850fSThomas Cort 
356*a0e6850fSThomas Cort 	return E_OK;
357*a0e6850fSThomas Cort }
358*a0e6850fSThomas Cort 
359*a0e6850fSThomas Cort /*
360*a0e6850fSThomas Cort  * Return the fields attached to the form given.
361*a0e6850fSThomas Cort  */
362*a0e6850fSThomas Cort FIELD **
form_fields(FORM * form)363*a0e6850fSThomas Cort form_fields(FORM *form)
364*a0e6850fSThomas Cort {
365*a0e6850fSThomas Cort 	if (form == NULL)
366*a0e6850fSThomas Cort 		return NULL;
367*a0e6850fSThomas Cort 
368*a0e6850fSThomas Cort 	return form->fields;
369*a0e6850fSThomas Cort }
370*a0e6850fSThomas Cort 
371*a0e6850fSThomas Cort /*
372*a0e6850fSThomas Cort  * Return the number of fields attached to the given form.
373*a0e6850fSThomas Cort  */
374*a0e6850fSThomas Cort int
field_count(FORM * form)375*a0e6850fSThomas Cort field_count(FORM *form)
376*a0e6850fSThomas Cort {
377*a0e6850fSThomas Cort 	if (form == NULL)
378*a0e6850fSThomas Cort 		return -1;
379*a0e6850fSThomas Cort 
380*a0e6850fSThomas Cort 	return form->field_count;
381*a0e6850fSThomas Cort }
382*a0e6850fSThomas Cort 
383*a0e6850fSThomas Cort /*
384*a0e6850fSThomas Cort  * Move the given field to the row and column given.
385*a0e6850fSThomas Cort  */
386*a0e6850fSThomas Cort int
move_field(FIELD * fptr,int frow,int fcol)387*a0e6850fSThomas Cort move_field(FIELD *fptr, int frow, int fcol)
388*a0e6850fSThomas Cort {
389*a0e6850fSThomas Cort 	FIELD *field = (fptr == NULL) ? &_formi_default_field : fptr;
390*a0e6850fSThomas Cort 
391*a0e6850fSThomas Cort 	if (field->parent != NULL)
392*a0e6850fSThomas Cort 		return E_CONNECTED;
393*a0e6850fSThomas Cort 
394*a0e6850fSThomas Cort 	field->form_row = frow;
395*a0e6850fSThomas Cort 	field->form_col = fcol;
396*a0e6850fSThomas Cort 
397*a0e6850fSThomas Cort 	return E_OK;
398*a0e6850fSThomas Cort }
399*a0e6850fSThomas Cort 
400*a0e6850fSThomas Cort /*
401*a0e6850fSThomas Cort  * Set the page of the form to the given page.
402*a0e6850fSThomas Cort  */
403*a0e6850fSThomas Cort int
set_form_page(FORM * form,int page)404*a0e6850fSThomas Cort set_form_page(FORM *form, int page)
405*a0e6850fSThomas Cort {
406*a0e6850fSThomas Cort 	if (form == NULL)
407*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
408*a0e6850fSThomas Cort 
409*a0e6850fSThomas Cort 	if (form->in_init == TRUE)
410*a0e6850fSThomas Cort 		return E_BAD_STATE;
411*a0e6850fSThomas Cort 
412*a0e6850fSThomas Cort 	if (page > form->max_page)
413*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
414*a0e6850fSThomas Cort 
415*a0e6850fSThomas Cort 	form->page = page;
416*a0e6850fSThomas Cort 	return E_OK;
417*a0e6850fSThomas Cort }
418*a0e6850fSThomas Cort 
419*a0e6850fSThomas Cort /*
420*a0e6850fSThomas Cort  * Return the maximum page of the form.
421*a0e6850fSThomas Cort  */
422*a0e6850fSThomas Cort int
form_max_page(FORM * form)423*a0e6850fSThomas Cort form_max_page(FORM *form)
424*a0e6850fSThomas Cort {
425*a0e6850fSThomas Cort 	if (form == NULL)
426*a0e6850fSThomas Cort 		return _formi_default_form.max_page;
427*a0e6850fSThomas Cort 	else
428*a0e6850fSThomas Cort 		return form->max_page;
429*a0e6850fSThomas Cort }
430*a0e6850fSThomas Cort 
431*a0e6850fSThomas Cort /*
432*a0e6850fSThomas Cort  * Return the current page of the form.
433*a0e6850fSThomas Cort  */
434*a0e6850fSThomas Cort int
form_page(FORM * form)435*a0e6850fSThomas Cort form_page(FORM *form)
436*a0e6850fSThomas Cort {
437*a0e6850fSThomas Cort 	if (form == NULL)
438*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
439*a0e6850fSThomas Cort 
440*a0e6850fSThomas Cort 	return form->page;
441*a0e6850fSThomas Cort }
442*a0e6850fSThomas Cort 
443*a0e6850fSThomas Cort /*
444*a0e6850fSThomas Cort  * Set the current field to the field given.
445*a0e6850fSThomas Cort  */
446*a0e6850fSThomas Cort int
set_current_field(FORM * form,FIELD * field)447*a0e6850fSThomas Cort set_current_field(FORM *form, FIELD *field)
448*a0e6850fSThomas Cort {
449*a0e6850fSThomas Cort 	if (form == NULL)
450*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
451*a0e6850fSThomas Cort 
452*a0e6850fSThomas Cort 	if (form->in_init == TRUE)
453*a0e6850fSThomas Cort 		return E_BAD_STATE;
454*a0e6850fSThomas Cort 
455*a0e6850fSThomas Cort 	if (field == NULL)
456*a0e6850fSThomas Cort 		return E_INVALID_FIELD;
457*a0e6850fSThomas Cort 
458*a0e6850fSThomas Cort 	if ((field->parent == NULL) || (field->parent != form))
459*a0e6850fSThomas Cort 		return E_INVALID_FIELD; /* field is not of this form */
460*a0e6850fSThomas Cort 
461*a0e6850fSThomas Cort 	form->cur_field = field->index;
462*a0e6850fSThomas Cort 
463*a0e6850fSThomas Cort 	  /* XXX update page if posted??? */
464*a0e6850fSThomas Cort 	return E_OK;
465*a0e6850fSThomas Cort }
466*a0e6850fSThomas Cort 
467*a0e6850fSThomas Cort /*
468*a0e6850fSThomas Cort  * Return the current field of the given form.
469*a0e6850fSThomas Cort  */
470*a0e6850fSThomas Cort FIELD *
current_field(FORM * form)471*a0e6850fSThomas Cort current_field(FORM *form)
472*a0e6850fSThomas Cort {
473*a0e6850fSThomas Cort 	if (form == NULL)
474*a0e6850fSThomas Cort 		return NULL;
475*a0e6850fSThomas Cort 
476*a0e6850fSThomas Cort 	if (form->fields == NULL)
477*a0e6850fSThomas Cort 		return NULL;
478*a0e6850fSThomas Cort 
479*a0e6850fSThomas Cort 	return form->fields[form->cur_field];
480*a0e6850fSThomas Cort }
481*a0e6850fSThomas Cort 
482*a0e6850fSThomas Cort /*
483*a0e6850fSThomas Cort  * Allocate a new form with the given fields.
484*a0e6850fSThomas Cort  */
485*a0e6850fSThomas Cort FORM *
new_form(FIELD ** fields)486*a0e6850fSThomas Cort new_form(FIELD **fields)
487*a0e6850fSThomas Cort {
488*a0e6850fSThomas Cort 	FORM *new;
489*a0e6850fSThomas Cort 
490*a0e6850fSThomas Cort 	if ((new = (FORM *) malloc(sizeof(FORM))) == NULL)
491*a0e6850fSThomas Cort 		return NULL;
492*a0e6850fSThomas Cort 
493*a0e6850fSThomas Cort 
494*a0e6850fSThomas Cort 	  /* copy in the defaults... */
495*a0e6850fSThomas Cort 	bcopy(&_formi_default_form, new, sizeof(FORM));
496*a0e6850fSThomas Cort 
497*a0e6850fSThomas Cort 	if (new->win == NULL)
498*a0e6850fSThomas Cort 		new->scrwin = stdscr; /* something for curses to write to */
499*a0e6850fSThomas Cort 
500*a0e6850fSThomas Cort 	if (fields != NULL) { /* attach the fields, if any */
501*a0e6850fSThomas Cort 		if (set_form_fields(new, fields) < 0) {
502*a0e6850fSThomas Cort 			free(new); /* field attach failed, back out */
503*a0e6850fSThomas Cort 			return NULL;
504*a0e6850fSThomas Cort 		}
505*a0e6850fSThomas Cort 	}
506*a0e6850fSThomas Cort 
507*a0e6850fSThomas Cort 	return new;
508*a0e6850fSThomas Cort }
509*a0e6850fSThomas Cort 
510*a0e6850fSThomas Cort /*
511*a0e6850fSThomas Cort  * Free the given form.
512*a0e6850fSThomas Cort  */
513*a0e6850fSThomas Cort int
free_form(FORM * form)514*a0e6850fSThomas Cort free_form(FORM *form)
515*a0e6850fSThomas Cort {
516*a0e6850fSThomas Cort 	int i;
517*a0e6850fSThomas Cort 
518*a0e6850fSThomas Cort 	if (form == NULL)
519*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
520*a0e6850fSThomas Cort 
521*a0e6850fSThomas Cort 	if (form->posted == TRUE)
522*a0e6850fSThomas Cort 		return E_POSTED;
523*a0e6850fSThomas Cort 
524*a0e6850fSThomas Cort 	for (i = 0; i < form->field_count; i++) {
525*a0e6850fSThomas Cort 		  /* detach all the fields from the form */
526*a0e6850fSThomas Cort 		form->fields[i]->parent = NULL;
527*a0e6850fSThomas Cort 		form->fields[i]->index = -1;
528*a0e6850fSThomas Cort 	}
529*a0e6850fSThomas Cort 
530*a0e6850fSThomas Cort 	free(form);
531*a0e6850fSThomas Cort 
532*a0e6850fSThomas Cort 	return E_OK;
533*a0e6850fSThomas Cort }
534*a0e6850fSThomas Cort 
535*a0e6850fSThomas Cort /*
536*a0e6850fSThomas Cort  * Tell if the current field of the form has offscreen data ahead
537*a0e6850fSThomas Cort  */
538*a0e6850fSThomas Cort int
data_ahead(FORM * form)539*a0e6850fSThomas Cort data_ahead(FORM *form)
540*a0e6850fSThomas Cort {
541*a0e6850fSThomas Cort 	FIELD *cur;
542*a0e6850fSThomas Cort 
543*a0e6850fSThomas Cort 	if ((form == NULL) || (form->fields == NULL)
544*a0e6850fSThomas Cort 	    || (form->fields[0] == NULL))
545*a0e6850fSThomas Cort 		return FALSE;
546*a0e6850fSThomas Cort 
547*a0e6850fSThomas Cort 	cur = form->fields[form->cur_field];
548*a0e6850fSThomas Cort 
549*a0e6850fSThomas Cort 	  /*XXXX wrong */
550*a0e6850fSThomas Cort 	if (cur->cur_line->expanded > cur->cols)
551*a0e6850fSThomas Cort 		return TRUE;
552*a0e6850fSThomas Cort 
553*a0e6850fSThomas Cort 	return FALSE;
554*a0e6850fSThomas Cort }
555*a0e6850fSThomas Cort 
556*a0e6850fSThomas Cort /*
557*a0e6850fSThomas Cort  * Tell if current field of the form has offscreen data behind
558*a0e6850fSThomas Cort  */
559*a0e6850fSThomas Cort int
data_behind(FORM * form)560*a0e6850fSThomas Cort data_behind(FORM *form)
561*a0e6850fSThomas Cort {
562*a0e6850fSThomas Cort 	FIELD *cur;
563*a0e6850fSThomas Cort 
564*a0e6850fSThomas Cort 	if ((form == NULL) || (form->fields == NULL)
565*a0e6850fSThomas Cort 	    || (form->fields[0] == NULL))
566*a0e6850fSThomas Cort 		return FALSE;
567*a0e6850fSThomas Cort 
568*a0e6850fSThomas Cort 	cur = form->fields[form->cur_field];
569*a0e6850fSThomas Cort 
570*a0e6850fSThomas Cort 	if (cur->start_char > 0)
571*a0e6850fSThomas Cort 		return TRUE;
572*a0e6850fSThomas Cort 
573*a0e6850fSThomas Cort 	return FALSE;
574*a0e6850fSThomas Cort }
575*a0e6850fSThomas Cort 
576*a0e6850fSThomas Cort /*
577*a0e6850fSThomas Cort  * Position the form cursor.
578*a0e6850fSThomas Cort  */
579*a0e6850fSThomas Cort int
pos_form_cursor(FORM * form)580*a0e6850fSThomas Cort pos_form_cursor(FORM *form)
581*a0e6850fSThomas Cort {
582*a0e6850fSThomas Cort 	FIELD *cur;
583*a0e6850fSThomas Cort 	int row, col;
584*a0e6850fSThomas Cort 
585*a0e6850fSThomas Cort 	if ((form == NULL) || (form->fields == NULL) ||
586*a0e6850fSThomas Cort 	    (form->fields[0] == NULL))
587*a0e6850fSThomas Cort 		return E_BAD_ARGUMENT;
588*a0e6850fSThomas Cort 
589*a0e6850fSThomas Cort 	if (form->posted != 1)
590*a0e6850fSThomas Cort 		return E_NOT_POSTED;
591*a0e6850fSThomas Cort 
592*a0e6850fSThomas Cort 	cur = form->fields[form->cur_field];
593*a0e6850fSThomas Cort 	row = cur->form_row;
594*a0e6850fSThomas Cort 	col = cur->form_col;
595*a0e6850fSThomas Cort 
596*a0e6850fSThomas Cort 	  /* if the field is public then show the cursor pos */
597*a0e6850fSThomas Cort 	if ((cur->opts & O_PUBLIC) == O_PUBLIC) {
598*a0e6850fSThomas Cort 		row += cur->cursor_ypos;
599*a0e6850fSThomas Cort 		col += cur->cursor_xpos;
600*a0e6850fSThomas Cort 		if (cur->cursor_xpos >= cur->cols) {
601*a0e6850fSThomas Cort 			col = cur->form_col;
602*a0e6850fSThomas Cort 			row++;
603*a0e6850fSThomas Cort 		}
604*a0e6850fSThomas Cort 	}
605*a0e6850fSThomas Cort 
606*a0e6850fSThomas Cort #ifdef DEBUG
607*a0e6850fSThomas Cort 	fprintf(dbg, "pos_cursor: row=%d, col=%d\n", row, col);
608*a0e6850fSThomas Cort #endif
609*a0e6850fSThomas Cort 
610*a0e6850fSThomas Cort 	wmove(form->scrwin, row, col);
611*a0e6850fSThomas Cort 
612*a0e6850fSThomas Cort 	return E_OK;
613*a0e6850fSThomas Cort }
614