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