frm_def.c revision 184989
1235537Sgber/****************************************************************************
2235537Sgber * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
3235537Sgber *                                                                          *
4235537Sgber * Permission is hereby granted, free of charge, to any person obtaining a  *
5235537Sgber * copy of this software and associated documentation files (the            *
6235537Sgber * "Software"), to deal in the Software without restriction, including      *
7235537Sgber * without limitation the rights to use, copy, modify, merge, publish,      *
8235537Sgber * distribute, distribute with modifications, sublicense, and/or sell       *
9235537Sgber * copies of the Software, and to permit persons to whom the Software is    *
10235537Sgber * furnished to do so, subject to the following conditions:                 *
11235537Sgber *                                                                          *
12235537Sgber * The above copyright notice and this permission notice shall be included  *
13235537Sgber * in all copies or substantial portions of the Software.                   *
14235537Sgber *                                                                          *
15235537Sgber * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16235537Sgber * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17235537Sgber * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18235537Sgber * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19235537Sgber * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20235537Sgber * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21235537Sgber * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22235537Sgber *                                                                          *
23235537Sgber * Except as contained in this notice, the name(s) of the above copyright   *
24235537Sgber * holders shall not be used in advertising or otherwise to promote the     *
25235537Sgber * sale, use or other dealings in this Software without prior written       *
26235537Sgber * authorization.                                                           *
27235537Sgber ****************************************************************************/
28235537Sgber
29235537Sgber/****************************************************************************
30235537Sgber *   Author:  Juergen Pfeifer, 1995,1997                                    *
31235537Sgber ****************************************************************************/
32235537Sgber
33235537Sgber#include "form.priv.h"
34235537Sgber
35235537SgberMODULE_ID("$Id: frm_def.c,v 1.23 2008/08/04 00:07:55 tom Exp $")
36235537Sgber
37235537Sgber/* this can't be readonly */
38235537Sgberstatic FORM default_form =
39235537Sgber{
40235537Sgber  0,				/* status     */
41235537Sgber  0,				/* rows       */
42235537Sgber  0,				/* cols       */
43235537Sgber  0,				/* currow     */
44235537Sgber  0,				/* curcol     */
45235537Sgber  0,				/* toprow     */
46235537Sgber  0,				/* begincol   */
47235537Sgber  -1,				/* maxfield   */
48235537Sgber  -1,				/* maxpage    */
49235537Sgber  -1,				/* curpage    */
50235537Sgber  ALL_FORM_OPTS,		/* opts       */
51235537Sgber  (WINDOW *)0,			/* win        */
52235537Sgber  (WINDOW *)0,			/* sub        */
53235537Sgber  (WINDOW *)0,			/* w          */
54235537Sgber  (FIELD **)0,			/* field      */
55235537Sgber  (FIELD *)0,			/* current    */
56235537Sgber  (_PAGE *) 0,			/* page       */
57235537Sgber  (char *)0,			/* usrptr     */
58235537Sgber  NULL,				/* forminit   */
59235537Sgber  NULL,				/* formterm   */
60235537Sgber  NULL,				/* fieldinit  */
61235537Sgber  NULL				/* fieldterm  */
62235537Sgber};
63235537Sgber
64235537SgberNCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form;
65235537Sgber
66235537Sgber/*---------------------------------------------------------------------------
67235537Sgber|   Facility      :  libnform
68235537Sgber|   Function      :  static FIELD *Insert_Field_By_Position(
69235537Sgber|                                     FIELD *new_field,
70235537Sgber|                                     FIELD *head )
71235537Sgber|
72235537Sgber|   Description   :  Insert new_field into sorted fieldlist with head "head"
73235537Sgber|                    and return new head of sorted fieldlist. Sorting
74235537Sgber|                    criteria is (row,column). This is a circular list.
75235537Sgber|
76235537Sgber|   Return Values :  New head of sorted fieldlist
77235537Sgber+--------------------------------------------------------------------------*/
78235537Sgberstatic FIELD *
79235537SgberInsert_Field_By_Position(FIELD *newfield, FIELD *head)
80235537Sgber{
81235537Sgber  FIELD *current, *newhead;
82235537Sgber
83235537Sgber  assert(newfield);
84235537Sgber
85235537Sgber  if (!head)
86235537Sgber    {				/* empty list is trivial */
87235537Sgber      newhead = newfield->snext = newfield->sprev = newfield;
88235537Sgber    }
89235537Sgber  else
90235537Sgber    {
91235537Sgber      newhead = current = head;
92235537Sgber      while ((current->frow < newfield->frow) ||
93235537Sgber	     ((current->frow == newfield->frow) &&
94235537Sgber	      (current->fcol < newfield->fcol)))
95235537Sgber	{
96235537Sgber	  current = current->snext;
97235537Sgber	  if (current == head)
98235537Sgber	    {			/* We cycled through. Reset head to indicate that */
99235537Sgber	      head = (FIELD *)0;
100235537Sgber	      break;
101235537Sgber	    }
102235537Sgber	}
103235537Sgber      /* we leave the loop with current pointing to the field after newfield */
104235537Sgber      newfield->snext = current;
105235537Sgber      newfield->sprev = current->sprev;
106235537Sgber      newfield->snext->sprev = newfield;
107235537Sgber      newfield->sprev->snext = newfield;
108235537Sgber      if (current == head)
109235537Sgber	newhead = newfield;
110235537Sgber    }
111235537Sgber  return (newhead);
112235537Sgber}
113235537Sgber
114235537Sgber/*---------------------------------------------------------------------------
115235537Sgber|   Facility      :  libnform
116235537Sgber|   Function      :  static void Disconnect_Fields(FORM *form)
117235537Sgber|
118235537Sgber|   Description   :  Break association between form and array of fields.
119235537Sgber|
120235537Sgber|   Return Values :  -
121235537Sgber+--------------------------------------------------------------------------*/
122235537Sgberstatic void
123235537SgberDisconnect_Fields(FORM *form)
124235537Sgber{
125235537Sgber  if (form->field)
126235537Sgber    {
127235537Sgber      FIELD **fields;
128235537Sgber
129235537Sgber      for (fields = form->field; *fields; fields++)
130235537Sgber	{
131235537Sgber	  if (form == (*fields)->form)
132235537Sgber	    (*fields)->form = (FORM *)0;
133235537Sgber	}
134235537Sgber
135235537Sgber      form->rows = form->cols = 0;
136235537Sgber      form->maxfield = form->maxpage = -1;
137235537Sgber      form->field = (FIELD **)0;
138235537Sgber      if (form->page)
139235537Sgber	free(form->page);
140235537Sgber      form->page = (_PAGE *) 0;
141235537Sgber    }
142235537Sgber}
143235537Sgber
144235537Sgber/*---------------------------------------------------------------------------
145235537Sgber|   Facility      :  libnform
146235537Sgber|   Function      :  static int Connect_Fields(FORM *form, FIELD **fields)
147235537Sgber|
148235537Sgber|   Description   :  Set association between form and array of fields.
149235537Sgber|
150235537Sgber|   Return Values :  E_OK            - no error
151235537Sgber|                    E_CONNECTED     - a field is already connected
152235537Sgber|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
153235537Sgber|                    E_SYSTEM_ERROR  - not enough memory
154235537Sgber+--------------------------------------------------------------------------*/
155235537Sgberstatic int
156235537SgberConnect_Fields(FORM *form, FIELD **fields)
157235537Sgber{
158235537Sgber  int field_cnt, j;
159235537Sgber  int page_nr;
160235537Sgber  int maximum_row_in_field, maximum_col_in_field;
161235537Sgber  _PAGE *pg;
162235537Sgber
163235537Sgber  T((T_CALLED("Connect_Fields(%p,%p)"), form, fields));
164235537Sgber
165235537Sgber  assert(form);
166235537Sgber
167235537Sgber  form->field = fields;
168235537Sgber  form->maxfield = 0;
169235537Sgber  form->maxpage = 0;
170235537Sgber
171235537Sgber  if (!fields)
172235537Sgber    RETURN(E_OK);
173235537Sgber
174235537Sgber  page_nr = 0;
175235537Sgber  /* store formpointer in fields and count pages */
176235537Sgber  for (field_cnt = 0; fields[field_cnt]; field_cnt++)
177235537Sgber    {
178235537Sgber      if (fields[field_cnt]->form)
179235537Sgber	RETURN(E_CONNECTED);
180235537Sgber      if (field_cnt == 0 ||
181235537Sgber	  (fields[field_cnt]->status & _NEWPAGE))
182235537Sgber	page_nr++;
183235537Sgber      fields[field_cnt]->form = form;
184235537Sgber    }
185235537Sgber  if (field_cnt == 0 || (short)field_cnt < 0)
186235537Sgber    RETURN(E_BAD_ARGUMENT);
187235537Sgber
188235537Sgber  /* allocate page structures */
189235537Sgber  if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0)
190235537Sgber    {
191235537Sgber      T((T_CREATE("_PAGE %p"), pg));
192235537Sgber      form->page = pg;
193235537Sgber    }
194235537Sgber  else
195235537Sgber    RETURN(E_SYSTEM_ERROR);
196235537Sgber
197235537Sgber  /* Cycle through fields and calculate page boundaries as well as
198235537Sgber     size of the form */
199235537Sgber  for (j = 0; j < field_cnt; j++)
200235537Sgber    {
201235537Sgber      if (j == 0)
202235537Sgber	pg->pmin = j;
203235537Sgber      else
204235537Sgber	{
205235537Sgber	  if (fields[j]->status & _NEWPAGE)
206235537Sgber	    {
207235537Sgber	      pg->pmax = j - 1;
208235537Sgber	      pg++;
209235537Sgber	      pg->pmin = j;
210235537Sgber	    }
211235537Sgber	}
212235537Sgber
213235537Sgber      maximum_row_in_field = fields[j]->frow + fields[j]->rows;
214235537Sgber      maximum_col_in_field = fields[j]->fcol + fields[j]->cols;
215235537Sgber
216235537Sgber      if (form->rows < maximum_row_in_field)
217235537Sgber	form->rows = maximum_row_in_field;
218235537Sgber      if (form->cols < maximum_col_in_field)
219235537Sgber	form->cols = maximum_col_in_field;
220235537Sgber    }
221235537Sgber
222235537Sgber  pg->pmax = field_cnt - 1;
223235537Sgber  form->maxfield = field_cnt;
224235537Sgber  form->maxpage = page_nr;
225235537Sgber
226235537Sgber  /* Sort fields on form pages */
227235537Sgber  for (page_nr = 0; page_nr < form->maxpage; page_nr++)
228235537Sgber    {
229235537Sgber      FIELD *fld = (FIELD *)0;
230235537Sgber
231235537Sgber      for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++)
232235537Sgber	{
233235537Sgber	  fields[j]->index = j;
234235537Sgber	  fields[j]->page = page_nr;
235235537Sgber	  fld = Insert_Field_By_Position(fields[j], fld);
236235537Sgber	}
237235537Sgber      if (fld)
238235537Sgber	{
239235537Sgber	  form->page[page_nr].smin = fld->index;
240235537Sgber	  form->page[page_nr].smax = fld->sprev->index;
241235537Sgber	}
242235537Sgber      else
243235537Sgber	{
244235537Sgber	  form->page[page_nr].smin = 0;
245235537Sgber	  form->page[page_nr].smax = 0;
246235537Sgber	}
247235537Sgber    }
248235537Sgber  RETURN(E_OK);
249235537Sgber}
250235537Sgber
251235537Sgber/*---------------------------------------------------------------------------
252235537Sgber|   Facility      :  libnform
253235537Sgber|   Function      :  static int Associate_Fields(FORM *form, FIELD **fields)
254235537Sgber|
255235537Sgber|   Description   :  Set association between form and array of fields.
256235537Sgber|                    If there are fields, position to first active field.
257235537Sgber|
258235537Sgber|   Return Values :  E_OK            - success
259235537Sgber|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
260235537Sgber|                    E_CONNECTED     - a field is already connected
261235537Sgber|                    E_SYSTEM_ERROR  - not enough memory
262235537Sgber+--------------------------------------------------------------------------*/
263235537SgberNCURSES_INLINE static int
264235537SgberAssociate_Fields(FORM *form, FIELD **fields)
265235537Sgber{
266235537Sgber  int res = Connect_Fields(form, fields);
267235537Sgber
268235537Sgber  if (res == E_OK)
269235537Sgber    {
270235537Sgber      if (form->maxpage > 0)
271235537Sgber	{
272235537Sgber	  form->curpage = 0;
273235537Sgber	  form_driver(form, FIRST_ACTIVE_MAGIC);
274235537Sgber	}
275235537Sgber      else
276235537Sgber	{
277235537Sgber	  form->curpage = -1;
278235537Sgber	  form->current = (FIELD *)0;
279235537Sgber	}
280235537Sgber    }
281235537Sgber  return (res);
282235537Sgber}
283235537Sgber
284235537Sgber/*---------------------------------------------------------------------------
285235537Sgber|   Facility      :  libnform
286235537Sgber|   Function      :  FORM *new_form( FIELD **fields )
287235537Sgber|
288235537Sgber|   Description   :  Create new form with given array of fields.
289235537Sgber|
290235537Sgber|   Return Values :  Pointer to form. NULL if error occurred.
291235537Sgber!                    Set errno:
292235537Sgber|                    E_OK            - success
293235537Sgber|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
294235537Sgber|                    E_CONNECTED     - a field is already connected
295235537Sgber|                    E_SYSTEM_ERROR  - not enough memory
296235537Sgber+--------------------------------------------------------------------------*/
297235537SgberNCURSES_EXPORT(FORM *)
298235537Sgbernew_form(FIELD **fields)
299235537Sgber{
300235537Sgber  int err = E_SYSTEM_ERROR;
301235537Sgber
302235537Sgber  FORM *form = typeMalloc(FORM, 1);
303235537Sgber
304235537Sgber  T((T_CALLED("new_form(%p)"), fields));
305235537Sgber  if (form)
306235537Sgber    {
307235537Sgber      T((T_CREATE("form %p"), form));
308235537Sgber      *form = *_nc_Default_Form;
309235537Sgber      if ((err = Associate_Fields(form, fields)) != E_OK)
310235537Sgber	{
311235537Sgber	  free_form(form);
312235537Sgber	  form = (FORM *)0;
313235537Sgber	}
314235537Sgber    }
315235537Sgber
316235537Sgber  if (!form)
317236188Smarcel    SET_ERROR(err);
318236188Smarcel
319235537Sgber  returnForm(form);
320236188Smarcel}
321236188Smarcel
322236188Smarcel/*---------------------------------------------------------------------------
323236188Smarcel|   Facility      :  libnform
324236188Smarcel|   Function      :  int free_form( FORM *form )
325235537Sgber|
326235537Sgber|   Description   :  Release internal memory associated with form.
327235537Sgber|
328235537Sgber|   Return Values :  E_OK           - no error
329235537Sgber|                    E_BAD_ARGUMENT - invalid form pointer
330235537Sgber|                    E_POSTED       - form is posted
331235537Sgber+--------------------------------------------------------------------------*/
332235537SgberNCURSES_EXPORT(int)
333235537Sgberfree_form(FORM *form)
334235537Sgber{
335235537Sgber  T((T_CALLED("free_form(%p)"), form));
336235537Sgber
337235537Sgber  if (!form)
338235537Sgber    RETURN(E_BAD_ARGUMENT);
339235537Sgber
340235537Sgber  if (form->status & _POSTED)
341235537Sgber    RETURN(E_POSTED);
342235537Sgber
343235537Sgber  Disconnect_Fields(form);
344235537Sgber  if (form->page)
345235537Sgber    free(form->page);
346235537Sgber  free(form);
347235537Sgber
348235537Sgber  RETURN(E_OK);
349235537Sgber}
350235537Sgber
351235537Sgber/*---------------------------------------------------------------------------
352235537Sgber|   Facility      :  libnform
353235537Sgber|   Function      :  int set_form_fields( FORM *form, FIELD **fields )
354235537Sgber|
355235537Sgber|   Description   :  Set a new association of an array of fields to a form
356235537Sgber|
357235537Sgber|   Return Values :  E_OK            - no error
358235537Sgber|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
359235537Sgber|                    E_CONNECTED     - a field is already connected
360235537Sgber|                    E_POSTED        - form is posted
361235537Sgber|                    E_SYSTEM_ERROR  - not enough memory
362235537Sgber+--------------------------------------------------------------------------*/
363235537SgberNCURSES_EXPORT(int)
364235537Sgberset_form_fields(FORM *form, FIELD **fields)
365235537Sgber{
366235537Sgber  FIELD **old;
367235537Sgber  int res;
368235537Sgber
369235537Sgber  T((T_CALLED("set_form_fields(%p,%p)"), form, fields));
370235537Sgber
371235537Sgber  if (!form)
372235537Sgber    RETURN(E_BAD_ARGUMENT);
373235537Sgber
374235537Sgber  if (form->status & _POSTED)
375235537Sgber    RETURN(E_POSTED);
376235537Sgber
377235537Sgber  old = form->field;
378235537Sgber  Disconnect_Fields(form);
379235537Sgber
380235537Sgber  if ((res = Associate_Fields(form, fields)) != E_OK)
381235537Sgber    Connect_Fields(form, old);
382235537Sgber
383235537Sgber  RETURN(res);
384235537Sgber}
385235537Sgber
386235537Sgber/*---------------------------------------------------------------------------
387235537Sgber|   Facility      :  libnform
388235537Sgber|   Function      :  FIELD **form_fields( const FORM *form )
389235537Sgber|
390235537Sgber|   Description   :  Retrieve array of fields
391235537Sgber|
392235537Sgber|   Return Values :  Pointer to field array
393235537Sgber+--------------------------------------------------------------------------*/
394235537SgberNCURSES_EXPORT(FIELD **)
395235537Sgberform_fields(const FORM *form)
396235537Sgber{
397235537Sgber  T((T_CALLED("form_field(%p)"), form));
398235537Sgber  returnFieldPtr(Normalize_Form(form)->field);
399235537Sgber}
400235537Sgber
401235537Sgber/*---------------------------------------------------------------------------
402235537Sgber|   Facility      :  libnform
403235537Sgber|   Function      :  int field_count( const FORM *form )
404235537Sgber|
405235537Sgber|   Description   :  Retrieve number of fields
406235537Sgber|
407235537Sgber|   Return Values :  Number of fields, -1 if none are defined
408235537Sgber+--------------------------------------------------------------------------*/
409235537SgberNCURSES_EXPORT(int)
410235537Sgberfield_count(const FORM *form)
411235537Sgber{
412235537Sgber  T((T_CALLED("field_count(%p)"), form));
413235537Sgber
414235537Sgber  returnCode(Normalize_Form(form)->maxfield);
415235537Sgber}
416235537Sgber
417235537Sgber/* frm_def.c ends here */
418235537Sgber