1 |
|
|
/* $OpenBSD: frm_def.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ |
2 |
|
|
/**************************************************************************** |
3 |
|
|
* Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * |
4 |
|
|
* * |
5 |
|
|
* Permission is hereby granted, free of charge, to any person obtaining a * |
6 |
|
|
* copy of this software and associated documentation files (the * |
7 |
|
|
* "Software"), to deal in the Software without restriction, including * |
8 |
|
|
* without limitation the rights to use, copy, modify, merge, publish, * |
9 |
|
|
* distribute, distribute with modifications, sublicense, and/or sell * |
10 |
|
|
* copies of the Software, and to permit persons to whom the Software is * |
11 |
|
|
* furnished to do so, subject to the following conditions: * |
12 |
|
|
* * |
13 |
|
|
* The above copyright notice and this permission notice shall be included * |
14 |
|
|
* in all copies or substantial portions of the Software. * |
15 |
|
|
* * |
16 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
17 |
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
18 |
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
19 |
|
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
20 |
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
21 |
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
22 |
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
23 |
|
|
* * |
24 |
|
|
* Except as contained in this notice, the name(s) of the above copyright * |
25 |
|
|
* holders shall not be used in advertising or otherwise to promote the * |
26 |
|
|
* sale, use or other dealings in this Software without prior written * |
27 |
|
|
* authorization. * |
28 |
|
|
****************************************************************************/ |
29 |
|
|
|
30 |
|
|
/**************************************************************************** |
31 |
|
|
* Author: Juergen Pfeifer, 1995,1997 * |
32 |
|
|
****************************************************************************/ |
33 |
|
|
|
34 |
|
|
#include "form.priv.h" |
35 |
|
|
|
36 |
|
|
MODULE_ID("$Id: frm_def.c,v 1.8 2015/01/23 22:48:51 krw Exp $") |
37 |
|
|
|
38 |
|
|
/* this can't be readonly */ |
39 |
|
|
static FORM default_form = |
40 |
|
|
{ |
41 |
|
|
0, /* status */ |
42 |
|
|
0, /* rows */ |
43 |
|
|
0, /* cols */ |
44 |
|
|
0, /* currow */ |
45 |
|
|
0, /* curcol */ |
46 |
|
|
0, /* toprow */ |
47 |
|
|
0, /* begincol */ |
48 |
|
|
-1, /* maxfield */ |
49 |
|
|
-1, /* maxpage */ |
50 |
|
|
-1, /* curpage */ |
51 |
|
|
ALL_FORM_OPTS, /* opts */ |
52 |
|
|
(WINDOW *)0, /* win */ |
53 |
|
|
(WINDOW *)0, /* sub */ |
54 |
|
|
(WINDOW *)0, /* w */ |
55 |
|
|
(FIELD **)0, /* field */ |
56 |
|
|
(FIELD *)0, /* current */ |
57 |
|
|
(_PAGE *) 0, /* page */ |
58 |
|
|
(char *)0, /* usrptr */ |
59 |
|
|
NULL, /* forminit */ |
60 |
|
|
NULL, /* formterm */ |
61 |
|
|
NULL, /* fieldinit */ |
62 |
|
|
NULL /* fieldterm */ |
63 |
|
|
}; |
64 |
|
|
|
65 |
|
|
NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form; |
66 |
|
|
|
67 |
|
|
/*--------------------------------------------------------------------------- |
68 |
|
|
| Facility : libnform |
69 |
|
|
| Function : static FIELD *Insert_Field_By_Position( |
70 |
|
|
| FIELD *new_field, |
71 |
|
|
| FIELD *head ) |
72 |
|
|
| |
73 |
|
|
| Description : Insert new_field into sorted fieldlist with head "head" |
74 |
|
|
| and return new head of sorted fieldlist. Sorting |
75 |
|
|
| criteria is (row,column). This is a circular list. |
76 |
|
|
| |
77 |
|
|
| Return Values : New head of sorted fieldlist |
78 |
|
|
+--------------------------------------------------------------------------*/ |
79 |
|
|
static FIELD * |
80 |
|
|
Insert_Field_By_Position(FIELD *newfield, FIELD *head) |
81 |
|
|
{ |
82 |
|
|
FIELD *current, *newhead; |
83 |
|
|
|
84 |
|
|
assert(newfield); |
85 |
|
|
|
86 |
|
|
if (!head) |
87 |
|
|
{ /* empty list is trivial */ |
88 |
|
|
newhead = newfield->snext = newfield->sprev = newfield; |
89 |
|
|
} |
90 |
|
|
else |
91 |
|
|
{ |
92 |
|
|
newhead = current = head; |
93 |
|
|
while ((current->frow < newfield->frow) || |
94 |
|
|
((current->frow == newfield->frow) && |
95 |
|
|
(current->fcol < newfield->fcol))) |
96 |
|
|
{ |
97 |
|
|
current = current->snext; |
98 |
|
|
if (current == head) |
99 |
|
|
{ /* We cycled through. Reset head to indicate that */ |
100 |
|
|
head = (FIELD *)0; |
101 |
|
|
break; |
102 |
|
|
} |
103 |
|
|
} |
104 |
|
|
/* we leave the loop with current pointing to the field after newfield */ |
105 |
|
|
newfield->snext = current; |
106 |
|
|
newfield->sprev = current->sprev; |
107 |
|
|
newfield->snext->sprev = newfield; |
108 |
|
|
newfield->sprev->snext = newfield; |
109 |
|
|
if (current == head) |
110 |
|
|
newhead = newfield; |
111 |
|
|
} |
112 |
|
|
return (newhead); |
113 |
|
|
} |
114 |
|
|
|
115 |
|
|
/*--------------------------------------------------------------------------- |
116 |
|
|
| Facility : libnform |
117 |
|
|
| Function : static void Disconnect_Fields(FORM *form) |
118 |
|
|
| |
119 |
|
|
| Description : Break association between form and array of fields. |
120 |
|
|
| |
121 |
|
|
| Return Values : - |
122 |
|
|
+--------------------------------------------------------------------------*/ |
123 |
|
|
static void |
124 |
|
|
Disconnect_Fields(FORM *form) |
125 |
|
|
{ |
126 |
|
|
if (form->field) |
127 |
|
|
{ |
128 |
|
|
FIELD **fields; |
129 |
|
|
|
130 |
|
|
for (fields = form->field; *fields; fields++) |
131 |
|
|
{ |
132 |
|
|
if (form == (*fields)->form) |
133 |
|
|
(*fields)->form = (FORM *)0; |
134 |
|
|
} |
135 |
|
|
|
136 |
|
|
form->rows = form->cols = 0; |
137 |
|
|
form->maxfield = form->maxpage = -1; |
138 |
|
|
form->field = (FIELD **)0; |
139 |
|
|
if (form->page) |
140 |
|
|
free(form->page); |
141 |
|
|
form->page = (_PAGE *) 0; |
142 |
|
|
} |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
/*--------------------------------------------------------------------------- |
146 |
|
|
| Facility : libnform |
147 |
|
|
| Function : static int Connect_Fields(FORM *form, FIELD **fields) |
148 |
|
|
| |
149 |
|
|
| Description : Set association between form and array of fields. |
150 |
|
|
| |
151 |
|
|
| Return Values : E_OK - no error |
152 |
|
|
| E_CONNECTED - a field is already connected |
153 |
|
|
| E_BAD_ARGUMENT - Invalid form pointer or field array |
154 |
|
|
| E_SYSTEM_ERROR - not enough memory |
155 |
|
|
+--------------------------------------------------------------------------*/ |
156 |
|
|
static int |
157 |
|
|
Connect_Fields(FORM *form, FIELD **fields) |
158 |
|
|
{ |
159 |
|
|
int field_cnt, j; |
160 |
|
|
int page_nr; |
161 |
|
|
int maximum_row_in_field, maximum_col_in_field; |
162 |
|
|
_PAGE *pg; |
163 |
|
|
|
164 |
|
|
T((T_CALLED("Connect_Fields(%p,%p)"), form, fields)); |
165 |
|
|
|
166 |
|
|
assert(form); |
167 |
|
|
|
168 |
|
|
form->field = fields; |
169 |
|
|
form->maxfield = 0; |
170 |
|
|
form->maxpage = 0; |
171 |
|
|
|
172 |
|
|
if (!fields) |
173 |
|
|
RETURN(E_OK); |
174 |
|
|
|
175 |
|
|
page_nr = 0; |
176 |
|
|
/* store formpointer in fields and count pages */ |
177 |
|
|
for (field_cnt = 0; fields[field_cnt]; field_cnt++) |
178 |
|
|
{ |
179 |
|
|
if (fields[field_cnt]->form) |
180 |
|
|
RETURN(E_CONNECTED); |
181 |
|
|
if (field_cnt == 0 || |
182 |
|
|
(fields[field_cnt]->status & _NEWPAGE)) |
183 |
|
|
page_nr++; |
184 |
|
|
fields[field_cnt]->form = form; |
185 |
|
|
} |
186 |
|
|
if (field_cnt == 0 || (short)field_cnt < 0) |
187 |
|
|
RETURN(E_BAD_ARGUMENT); |
188 |
|
|
|
189 |
|
|
/* allocate page structures */ |
190 |
|
|
if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0) |
191 |
|
|
{ |
192 |
|
|
T((T_CREATE("_PAGE %p"), pg)); |
193 |
|
|
form->page = pg; |
194 |
|
|
} |
195 |
|
|
else |
196 |
|
|
RETURN(E_SYSTEM_ERROR); |
197 |
|
|
|
198 |
|
|
/* Cycle through fields and calculate page boundaries as well as |
199 |
|
|
size of the form */ |
200 |
|
|
for (j = 0; j < field_cnt; j++) |
201 |
|
|
{ |
202 |
|
|
if (j == 0) |
203 |
|
|
pg->pmin = j; |
204 |
|
|
else |
205 |
|
|
{ |
206 |
|
|
if (fields[j]->status & _NEWPAGE) |
207 |
|
|
{ |
208 |
|
|
pg->pmax = j - 1; |
209 |
|
|
pg++; |
210 |
|
|
pg->pmin = j; |
211 |
|
|
} |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
maximum_row_in_field = fields[j]->frow + fields[j]->rows; |
215 |
|
|
maximum_col_in_field = fields[j]->fcol + fields[j]->cols; |
216 |
|
|
|
217 |
|
|
if (form->rows < maximum_row_in_field) |
218 |
|
|
form->rows = maximum_row_in_field; |
219 |
|
|
if (form->cols < maximum_col_in_field) |
220 |
|
|
form->cols = maximum_col_in_field; |
221 |
|
|
} |
222 |
|
|
|
223 |
|
|
pg->pmax = field_cnt - 1; |
224 |
|
|
form->maxfield = field_cnt; |
225 |
|
|
form->maxpage = page_nr; |
226 |
|
|
|
227 |
|
|
/* Sort fields on form pages */ |
228 |
|
|
for (page_nr = 0; page_nr < form->maxpage; page_nr++) |
229 |
|
|
{ |
230 |
|
|
FIELD *fld = (FIELD *)0; |
231 |
|
|
|
232 |
|
|
for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++) |
233 |
|
|
{ |
234 |
|
|
fields[j]->index = j; |
235 |
|
|
fields[j]->page = page_nr; |
236 |
|
|
fld = Insert_Field_By_Position(fields[j], fld); |
237 |
|
|
} |
238 |
|
|
if (fld) |
239 |
|
|
{ |
240 |
|
|
form->page[page_nr].smin = fld->index; |
241 |
|
|
form->page[page_nr].smax = fld->sprev->index; |
242 |
|
|
} |
243 |
|
|
else |
244 |
|
|
{ |
245 |
|
|
form->page[page_nr].smin = 0; |
246 |
|
|
form->page[page_nr].smax = 0; |
247 |
|
|
} |
248 |
|
|
} |
249 |
|
|
RETURN(E_OK); |
250 |
|
|
} |
251 |
|
|
|
252 |
|
|
/*--------------------------------------------------------------------------- |
253 |
|
|
| Facility : libnform |
254 |
|
|
| Function : static int Associate_Fields(FORM *form, FIELD **fields) |
255 |
|
|
| |
256 |
|
|
| Description : Set association between form and array of fields. |
257 |
|
|
| If there are fields, position to first active field. |
258 |
|
|
| |
259 |
|
|
| Return Values : E_OK - success |
260 |
|
|
| E_BAD_ARGUMENT - Invalid form pointer or field array |
261 |
|
|
| E_CONNECTED - a field is already connected |
262 |
|
|
| E_SYSTEM_ERROR - not enough memory |
263 |
|
|
+--------------------------------------------------------------------------*/ |
264 |
|
|
NCURSES_INLINE static int |
265 |
|
|
Associate_Fields(FORM *form, FIELD **fields) |
266 |
|
|
{ |
267 |
|
|
int res = Connect_Fields(form, fields); |
268 |
|
|
|
269 |
|
|
if (res == E_OK) |
270 |
|
|
{ |
271 |
|
|
if (form->maxpage > 0) |
272 |
|
|
{ |
273 |
|
|
form->curpage = 0; |
274 |
|
|
form_driver(form, FIRST_ACTIVE_MAGIC); |
275 |
|
|
} |
276 |
|
|
else |
277 |
|
|
{ |
278 |
|
|
form->curpage = -1; |
279 |
|
|
form->current = (FIELD *)0; |
280 |
|
|
} |
281 |
|
|
} |
282 |
|
|
return (res); |
283 |
|
|
} |
284 |
|
|
|
285 |
|
|
/*--------------------------------------------------------------------------- |
286 |
|
|
| Facility : libnform |
287 |
|
|
| Function : FORM *new_form( FIELD **fields ) |
288 |
|
|
| |
289 |
|
|
| Description : Create new form with given array of fields. |
290 |
|
|
| |
291 |
|
|
| Return Values : Pointer to form. NULL if error occurred. |
292 |
|
|
! Set errno: |
293 |
|
|
| E_OK - success |
294 |
|
|
| E_BAD_ARGUMENT - Invalid form pointer or field array |
295 |
|
|
| E_CONNECTED - a field is already connected |
296 |
|
|
| E_SYSTEM_ERROR - not enough memory |
297 |
|
|
+--------------------------------------------------------------------------*/ |
298 |
|
|
NCURSES_EXPORT(FORM *) |
299 |
|
|
new_form(FIELD **fields) |
300 |
|
|
{ |
301 |
|
|
int err = E_SYSTEM_ERROR; |
302 |
|
|
|
303 |
|
|
FORM *form = typeMalloc(FORM, 1); |
304 |
|
|
|
305 |
|
|
T((T_CALLED("new_form(%p)"), fields)); |
306 |
|
|
if (form) |
307 |
|
|
{ |
308 |
|
|
T((T_CREATE("form %p"), form)); |
309 |
|
|
*form = *_nc_Default_Form; |
310 |
|
|
if ((err = Associate_Fields(form, fields)) != E_OK) |
311 |
|
|
{ |
312 |
|
|
free_form(form); |
313 |
|
|
form = (FORM *)0; |
314 |
|
|
} |
315 |
|
|
} |
316 |
|
|
|
317 |
|
|
if (!form) |
318 |
|
|
SET_ERROR(err); |
319 |
|
|
|
320 |
|
|
returnForm(form); |
321 |
|
|
} |
322 |
|
|
|
323 |
|
|
/*--------------------------------------------------------------------------- |
324 |
|
|
| Facility : libnform |
325 |
|
|
| Function : int free_form( FORM *form ) |
326 |
|
|
| |
327 |
|
|
| Description : Release internal memory associated with form. |
328 |
|
|
| |
329 |
|
|
| Return Values : E_OK - no error |
330 |
|
|
| E_BAD_ARGUMENT - invalid form pointer |
331 |
|
|
| E_POSTED - form is posted |
332 |
|
|
+--------------------------------------------------------------------------*/ |
333 |
|
|
NCURSES_EXPORT(int) |
334 |
|
|
free_form(FORM *form) |
335 |
|
|
{ |
336 |
|
|
T((T_CALLED("free_form(%p)"), form)); |
337 |
|
|
|
338 |
|
|
if (!form) |
339 |
|
|
RETURN(E_BAD_ARGUMENT); |
340 |
|
|
|
341 |
|
|
if (form->status & _POSTED) |
342 |
|
|
RETURN(E_POSTED); |
343 |
|
|
|
344 |
|
|
Disconnect_Fields(form); |
345 |
|
|
if (form->page) |
346 |
|
|
free(form->page); |
347 |
|
|
free(form); |
348 |
|
|
|
349 |
|
|
RETURN(E_OK); |
350 |
|
|
} |
351 |
|
|
|
352 |
|
|
/*--------------------------------------------------------------------------- |
353 |
|
|
| Facility : libnform |
354 |
|
|
| Function : int set_form_fields( FORM *form, FIELD **fields ) |
355 |
|
|
| |
356 |
|
|
| Description : Set a new association of an array of fields to a form |
357 |
|
|
| |
358 |
|
|
| Return Values : E_OK - no error |
359 |
|
|
| E_BAD_ARGUMENT - Invalid form pointer or field array |
360 |
|
|
| E_CONNECTED - a field is already connected |
361 |
|
|
| E_POSTED - form is posted |
362 |
|
|
| E_SYSTEM_ERROR - not enough memory |
363 |
|
|
+--------------------------------------------------------------------------*/ |
364 |
|
|
NCURSES_EXPORT(int) |
365 |
|
|
set_form_fields(FORM *form, FIELD **fields) |
366 |
|
|
{ |
367 |
|
|
FIELD **old; |
368 |
|
|
int res; |
369 |
|
|
|
370 |
|
|
T((T_CALLED("set_form_fields(%p,%p)"), form, fields)); |
371 |
|
|
|
372 |
|
|
if (!form) |
373 |
|
|
RETURN(E_BAD_ARGUMENT); |
374 |
|
|
|
375 |
|
|
if (form->status & _POSTED) |
376 |
|
|
RETURN(E_POSTED); |
377 |
|
|
|
378 |
|
|
old = form->field; |
379 |
|
|
Disconnect_Fields(form); |
380 |
|
|
|
381 |
|
|
if ((res = Associate_Fields(form, fields)) != E_OK) |
382 |
|
|
Connect_Fields(form, old); |
383 |
|
|
|
384 |
|
|
RETURN(res); |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
/*--------------------------------------------------------------------------- |
388 |
|
|
| Facility : libnform |
389 |
|
|
| Function : FIELD **form_fields( const FORM *form ) |
390 |
|
|
| |
391 |
|
|
| Description : Retrieve array of fields |
392 |
|
|
| |
393 |
|
|
| Return Values : Pointer to field array |
394 |
|
|
+--------------------------------------------------------------------------*/ |
395 |
|
|
NCURSES_EXPORT(FIELD **) |
396 |
|
|
form_fields(const FORM *form) |
397 |
|
|
{ |
398 |
|
|
T((T_CALLED("form_field(%p)"), form)); |
399 |
|
|
returnFieldPtr(Normalize_Form(form)->field); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
/*--------------------------------------------------------------------------- |
403 |
|
|
| Facility : libnform |
404 |
|
|
| Function : int field_count( const FORM *form ) |
405 |
|
|
| |
406 |
|
|
| Description : Retrieve number of fields |
407 |
|
|
| |
408 |
|
|
| Return Values : Number of fields, -1 if none are defined |
409 |
|
|
+--------------------------------------------------------------------------*/ |
410 |
|
|
NCURSES_EXPORT(int) |
411 |
|
|
field_count(const FORM *form) |
412 |
|
|
{ |
413 |
|
|
T((T_CALLED("field_count(%p)"), form)); |
414 |
|
|
|
415 |
|
|
returnCode(Normalize_Form(form)->maxfield); |
416 |
|
|
} |
417 |
|
|
|
418 |
|
|
/* frm_def.c ends here */ |