150276Speter/****************************************************************************
2262685Sdelphij * Copyright (c) 1998-2010,2012 Free Software Foundation, Inc.              *
350276Speter *                                                                          *
450276Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
550276Speter * copy of this software and associated documentation files (the            *
650276Speter * "Software"), to deal in the Software without restriction, including      *
750276Speter * without limitation the rights to use, copy, modify, merge, publish,      *
850276Speter * distribute, distribute with modifications, sublicense, and/or sell       *
950276Speter * copies of the Software, and to permit persons to whom the Software is    *
1050276Speter * furnished to do so, subject to the following conditions:                 *
1150276Speter *                                                                          *
1250276Speter * The above copyright notice and this permission notice shall be included  *
1350276Speter * in all copies or substantial portions of the Software.                   *
1450276Speter *                                                                          *
1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2250276Speter *                                                                          *
2350276Speter * Except as contained in this notice, the name(s) of the above copyright   *
2450276Speter * holders shall not be used in advertising or otherwise to promote the     *
2550276Speter * sale, use or other dealings in this Software without prior written       *
2650276Speter * authorization.                                                           *
2750276Speter ****************************************************************************/
2850276Speter
2950276Speter/****************************************************************************
30166124Srafan *   Author:  Juergen Pfeifer, 1995,1997                                    *
3150276Speter ****************************************************************************/
3250276Speter
3350276Speter#include "form.priv.h"
3450276Speter
35262685SdelphijMODULE_ID("$Id: frm_def.c,v 1.26 2012/03/11 00:37:16 tom Exp $")
3650276Speter
3750276Speter/* this can't be readonly */
38166124Srafanstatic FORM default_form =
39166124Srafan{
40166124Srafan  0,				/* status     */
41166124Srafan  0,				/* rows       */
42166124Srafan  0,				/* cols       */
43166124Srafan  0,				/* currow     */
44166124Srafan  0,				/* curcol     */
45166124Srafan  0,				/* toprow     */
46166124Srafan  0,				/* begincol   */
47166124Srafan  -1,				/* maxfield   */
48166124Srafan  -1,				/* maxpage    */
49166124Srafan  -1,				/* curpage    */
50166124Srafan  ALL_FORM_OPTS,		/* opts       */
51166124Srafan  (WINDOW *)0,			/* win        */
52166124Srafan  (WINDOW *)0,			/* sub        */
53166124Srafan  (WINDOW *)0,			/* w          */
54166124Srafan  (FIELD **)0,			/* field      */
55166124Srafan  (FIELD *)0,			/* current    */
56166124Srafan  (_PAGE *) 0,			/* page       */
57166124Srafan  (char *)0,			/* usrptr     */
58166124Srafan  NULL,				/* forminit   */
59166124Srafan  NULL,				/* formterm   */
60166124Srafan  NULL,				/* fieldinit  */
61166124Srafan  NULL				/* fieldterm  */
6250276Speter};
6350276Speter
6476726SpeterNCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form;
6550276Speter
6650276Speter/*---------------------------------------------------------------------------
6750276Speter|   Facility      :  libnform
6850276Speter|   Function      :  static FIELD *Insert_Field_By_Position(
6950276Speter|                                     FIELD *new_field,
7050276Speter|                                     FIELD *head )
7150276Speter|
7250276Speter|   Description   :  Insert new_field into sorted fieldlist with head "head"
7350276Speter|                    and return new head of sorted fieldlist. Sorting
7450276Speter|                    criteria is (row,column). This is a circular list.
7550276Speter|
7650276Speter|   Return Values :  New head of sorted fieldlist
7750276Speter+--------------------------------------------------------------------------*/
78166124Srafanstatic FIELD *
79166124SrafanInsert_Field_By_Position(FIELD *newfield, FIELD *head)
8050276Speter{
8150276Speter  FIELD *current, *newhead;
82166124Srafan
8350276Speter  assert(newfield);
8450276Speter
8550276Speter  if (!head)
86166124Srafan    {				/* empty list is trivial */
8750276Speter      newhead = newfield->snext = newfield->sprev = newfield;
8850276Speter    }
8950276Speter  else
9050276Speter    {
9150276Speter      newhead = current = head;
92166124Srafan      while ((current->frow < newfield->frow) ||
93166124Srafan	     ((current->frow == newfield->frow) &&
94166124Srafan	      (current->fcol < newfield->fcol)))
9550276Speter	{
9650276Speter	  current = current->snext;
97166124Srafan	  if (current == head)
98166124Srafan	    {			/* We cycled through. Reset head to indicate that */
9950276Speter	      head = (FIELD *)0;
10050276Speter	      break;
10150276Speter	    }
10250276Speter	}
103166124Srafan      /* we leave the loop with current pointing to the field after newfield */
104166124Srafan      newfield->snext = current;
105166124Srafan      newfield->sprev = current->sprev;
10650276Speter      newfield->snext->sprev = newfield;
10750276Speter      newfield->sprev->snext = newfield;
108166124Srafan      if (current == head)
10950276Speter	newhead = newfield;
11050276Speter    }
111166124Srafan  return (newhead);
11250276Speter}
11350276Speter
11450276Speter/*---------------------------------------------------------------------------
11550276Speter|   Facility      :  libnform
11650276Speter|   Function      :  static void Disconnect_Fields(FORM *form)
11750276Speter|
11850276Speter|   Description   :  Break association between form and array of fields.
11950276Speter|
12050276Speter|   Return Values :  -
12150276Speter+--------------------------------------------------------------------------*/
122166124Srafanstatic void
123166124SrafanDisconnect_Fields(FORM *form)
12450276Speter{
12550276Speter  if (form->field)
12650276Speter    {
12750276Speter      FIELD **fields;
12850276Speter
129166124Srafan      for (fields = form->field; *fields; fields++)
13050276Speter	{
131166124Srafan	  if (form == (*fields)->form)
13250276Speter	    (*fields)->form = (FORM *)0;
13350276Speter	}
134166124Srafan
13550276Speter      form->rows = form->cols = 0;
13650276Speter      form->maxfield = form->maxpage = -1;
13750276Speter      form->field = (FIELD **)0;
138166124Srafan      if (form->page)
13950276Speter	free(form->page);
140166124Srafan      form->page = (_PAGE *) 0;
141166124Srafan    }
14250276Speter}
14350276Speter
14450276Speter/*---------------------------------------------------------------------------
14550276Speter|   Facility      :  libnform
14650276Speter|   Function      :  static int Connect_Fields(FORM *form, FIELD **fields)
14750276Speter|
14850276Speter|   Description   :  Set association between form and array of fields.
14950276Speter|
15050276Speter|   Return Values :  E_OK            - no error
15150276Speter|                    E_CONNECTED     - a field is already connected
15250276Speter|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
15350276Speter|                    E_SYSTEM_ERROR  - not enough memory
15450276Speter+--------------------------------------------------------------------------*/
155166124Srafanstatic int
156166124SrafanConnect_Fields(FORM *form, FIELD **fields)
15750276Speter{
15850276Speter  int field_cnt, j;
15950276Speter  int page_nr;
16050276Speter  int maximum_row_in_field, maximum_col_in_field;
16150276Speter  _PAGE *pg;
162166124Srafan
163262629Sdelphij  T((T_CALLED("Connect_Fields(%p,%p)"), (void *)form, (void *)fields));
164166124Srafan
16550276Speter  assert(form);
16650276Speter
167166124Srafan  form->field = fields;
16850276Speter  form->maxfield = 0;
169166124Srafan  form->maxpage = 0;
17050276Speter
17150276Speter  if (!fields)
17250276Speter    RETURN(E_OK);
173166124Srafan
17450276Speter  page_nr = 0;
17550276Speter  /* store formpointer in fields and count pages */
176166124Srafan  for (field_cnt = 0; fields[field_cnt]; field_cnt++)
17750276Speter    {
178166124Srafan      if (fields[field_cnt]->form)
17950276Speter	RETURN(E_CONNECTED);
180166124Srafan      if (field_cnt == 0 ||
181166124Srafan	  (fields[field_cnt]->status & _NEWPAGE))
18250276Speter	page_nr++;
18350276Speter      fields[field_cnt]->form = form;
184166124Srafan    }
185166124Srafan  if (field_cnt == 0 || (short)field_cnt < 0)
18650276Speter    RETURN(E_BAD_ARGUMENT);
187166124Srafan
18850276Speter  /* allocate page structures */
189174993Srafan  if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0)
19050276Speter    {
191262629Sdelphij      T((T_CREATE("_PAGE %p"), (void *)pg));
19250276Speter      form->page = pg;
19350276Speter    }
19450276Speter  else
19550276Speter    RETURN(E_SYSTEM_ERROR);
196166124Srafan
19750276Speter  /* Cycle through fields and calculate page boundaries as well as
19850276Speter     size of the form */
199166124Srafan  for (j = 0; j < field_cnt; j++)
20050276Speter    {
201166124Srafan      if (j == 0)
202262685Sdelphij	pg->pmin = (short) j;
20350276Speter      else
20450276Speter	{
20550276Speter	  if (fields[j]->status & _NEWPAGE)
20650276Speter	    {
207262685Sdelphij	      pg->pmax = (short) (j - 1);
20850276Speter	      pg++;
209262685Sdelphij	      pg->pmin = (short) j;
21050276Speter	    }
21150276Speter	}
212166124Srafan
21350276Speter      maximum_row_in_field = fields[j]->frow + fields[j]->rows;
21450276Speter      maximum_col_in_field = fields[j]->fcol + fields[j]->cols;
215166124Srafan
216166124Srafan      if (form->rows < maximum_row_in_field)
217262685Sdelphij	form->rows = (short) maximum_row_in_field;
218166124Srafan      if (form->cols < maximum_col_in_field)
219262685Sdelphij	form->cols = (short) maximum_col_in_field;
22050276Speter    }
221166124Srafan
222262685Sdelphij  pg->pmax = (short) (field_cnt - 1);
223262685Sdelphij  form->maxfield = (short) field_cnt;
224262685Sdelphij  form->maxpage = (short) page_nr;
225166124Srafan
22650276Speter  /* Sort fields on form pages */
227166124Srafan  for (page_nr = 0; page_nr < form->maxpage; page_nr++)
22850276Speter    {
22950276Speter      FIELD *fld = (FIELD *)0;
230166124Srafan
231166124Srafan      for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++)
23250276Speter	{
233262685Sdelphij	  fields[j]->index = (short) j;
234262685Sdelphij	  fields[j]->page = (short) page_nr;
235166124Srafan	  fld = Insert_Field_By_Position(fields[j], fld);
23650276Speter	}
237184989Srafan      if (fld)
238184989Srafan	{
239184989Srafan	  form->page[page_nr].smin = fld->index;
240184989Srafan	  form->page[page_nr].smax = fld->sprev->index;
241184989Srafan	}
242184989Srafan      else
243184989Srafan	{
244184989Srafan	  form->page[page_nr].smin = 0;
245184989Srafan	  form->page[page_nr].smax = 0;
246184989Srafan	}
24750276Speter    }
24850276Speter  RETURN(E_OK);
24950276Speter}
25050276Speter
25150276Speter/*---------------------------------------------------------------------------
25250276Speter|   Facility      :  libnform
25350276Speter|   Function      :  static int Associate_Fields(FORM *form, FIELD **fields)
25450276Speter|
25550276Speter|   Description   :  Set association between form and array of fields.
25650276Speter|                    If there are fields, position to first active field.
25750276Speter|
25850276Speter|   Return Values :  E_OK            - success
259166124Srafan|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
260166124Srafan|                    E_CONNECTED     - a field is already connected
261166124Srafan|                    E_SYSTEM_ERROR  - not enough memory
26250276Speter+--------------------------------------------------------------------------*/
263166124SrafanNCURSES_INLINE static int
264166124SrafanAssociate_Fields(FORM *form, FIELD **fields)
26550276Speter{
266166124Srafan  int res = Connect_Fields(form, fields);
267166124Srafan
26850276Speter  if (res == E_OK)
26950276Speter    {
270166124Srafan      if (form->maxpage > 0)
27150276Speter	{
27250276Speter	  form->curpage = 0;
273166124Srafan	  form_driver(form, FIRST_ACTIVE_MAGIC);
27450276Speter	}
27550276Speter      else
27650276Speter	{
27750276Speter	  form->curpage = -1;
27850276Speter	  form->current = (FIELD *)0;
279166124Srafan	}
28050276Speter    }
281166124Srafan  return (res);
28250276Speter}
283166124Srafan
28450276Speter/*---------------------------------------------------------------------------
28550276Speter|   Facility      :  libnform
286262629Sdelphij|   Function      :  FORM *new_form_sp(SCREEN* sp, FIELD** fields )
28750276Speter|
28850276Speter|   Description   :  Create new form with given array of fields.
28950276Speter|
290166124Srafan|   Return Values :  Pointer to form. NULL if error occurred.
291166124Srafan!                    Set errno:
292166124Srafan|                    E_OK            - success
293166124Srafan|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
294166124Srafan|                    E_CONNECTED     - a field is already connected
295166124Srafan|                    E_SYSTEM_ERROR  - not enough memory
29650276Speter+--------------------------------------------------------------------------*/
29776726SpeterNCURSES_EXPORT(FORM *)
298262629SdelphijNCURSES_SP_NAME(new_form) (NCURSES_SP_DCLx FIELD **fields)
299166124Srafan{
30050276Speter  int err = E_SYSTEM_ERROR;
301262629Sdelphij  FORM *form = (FORM *)0;
30250276Speter
303262629Sdelphij  T((T_CALLED("new_form(%p,%p)"), (void *)SP_PARM, (void *)fields));
304166124Srafan
305262629Sdelphij  if (IsValidScreen(SP_PARM))
30650276Speter    {
307262629Sdelphij      form = typeMalloc(FORM, 1);
308262629Sdelphij
309262629Sdelphij      if (form)
31050276Speter	{
311262629Sdelphij	  T((T_CREATE("form %p"), (void *)form));
312262629Sdelphij	  *form = *_nc_Default_Form;
313262629Sdelphij	  /* This ensures win and sub are always non-null,
314262629Sdelphij	     so we can derive always the SCREEN that this form is
315262629Sdelphij	     running on. */
316262629Sdelphij	  form->win = StdScreen(SP_PARM);
317262629Sdelphij	  form->sub = StdScreen(SP_PARM);
318262629Sdelphij	  if ((err = Associate_Fields(form, fields)) != E_OK)
319262629Sdelphij	    {
320262629Sdelphij	      free_form(form);
321262629Sdelphij	      form = (FORM *)0;
322262629Sdelphij	    }
32350276Speter	}
32450276Speter    }
32550276Speter
32650276Speter  if (!form)
32750276Speter    SET_ERROR(err);
328166124Srafan
329166124Srafan  returnForm(form);
33050276Speter}
33150276Speter
33250276Speter/*---------------------------------------------------------------------------
33350276Speter|   Facility      :  libnform
334262629Sdelphij|   Function      :  FORM* new_form(FIELD** fields )
335262629Sdelphij|
336262629Sdelphij|   Description   :  Create new form with given array of fields.
337262629Sdelphij|
338262629Sdelphij|   Return Values :  Pointer to form. NULL if error occurred.
339262629Sdelphij!                    Set errno:
340262629Sdelphij|                    E_OK            - success
341262629Sdelphij|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
342262629Sdelphij|                    E_CONNECTED     - a field is already connected
343262629Sdelphij|                    E_SYSTEM_ERROR  - not enough memory
344262629Sdelphij+--------------------------------------------------------------------------*/
345262629Sdelphij#if NCURSES_SP_FUNCS
346262629SdelphijNCURSES_EXPORT(FORM *)
347262629Sdelphijnew_form(FIELD **fields)
348262629Sdelphij{
349262629Sdelphij  return NCURSES_SP_NAME(new_form) (CURRENT_SCREEN, fields);
350262629Sdelphij}
351262629Sdelphij#endif
352262629Sdelphij
353262629Sdelphij/*---------------------------------------------------------------------------
354262629Sdelphij|   Facility      :  libnform
35550276Speter|   Function      :  int free_form( FORM *form )
35650276Speter|
35750276Speter|   Description   :  Release internal memory associated with form.
35850276Speter|
35950276Speter|   Return Values :  E_OK           - no error
36050276Speter|                    E_BAD_ARGUMENT - invalid form pointer
36150276Speter|                    E_POSTED       - form is posted
36250276Speter+--------------------------------------------------------------------------*/
36376726SpeterNCURSES_EXPORT(int)
364166124Srafanfree_form(FORM *form)
36550276Speter{
366262629Sdelphij  T((T_CALLED("free_form(%p)"), (void *)form));
367166124Srafan
368166124Srafan  if (!form)
36950276Speter    RETURN(E_BAD_ARGUMENT);
37050276Speter
371166124Srafan  if (form->status & _POSTED)
37250276Speter    RETURN(E_POSTED);
373166124Srafan
374166124Srafan  Disconnect_Fields(form);
375166124Srafan  if (form->page)
37650276Speter    free(form->page);
37750276Speter  free(form);
378166124Srafan
37950276Speter  RETURN(E_OK);
38050276Speter}
38150276Speter
38250276Speter/*---------------------------------------------------------------------------
38350276Speter|   Facility      :  libnform
38450276Speter|   Function      :  int set_form_fields( FORM *form, FIELD **fields )
38550276Speter|
38650276Speter|   Description   :  Set a new association of an array of fields to a form
38750276Speter|
388166124Srafan|   Return Values :  E_OK            - no error
389166124Srafan|                    E_BAD_ARGUMENT  - Invalid form pointer or field array
390166124Srafan|                    E_CONNECTED     - a field is already connected
391166124Srafan|                    E_POSTED        - form is posted
392166124Srafan|                    E_SYSTEM_ERROR  - not enough memory
39350276Speter+--------------------------------------------------------------------------*/
39476726SpeterNCURSES_EXPORT(int)
395166124Srafanset_form_fields(FORM *form, FIELD **fields)
39650276Speter{
39750276Speter  FIELD **old;
39850276Speter  int res;
399166124Srafan
400262629Sdelphij  T((T_CALLED("set_form_fields(%p,%p)"), (void *)form, (void *)fields));
401166124Srafan
402166124Srafan  if (!form)
40350276Speter    RETURN(E_BAD_ARGUMENT);
40450276Speter
405166124Srafan  if (form->status & _POSTED)
40650276Speter    RETURN(E_POSTED);
407166124Srafan
40850276Speter  old = form->field;
409166124Srafan  Disconnect_Fields(form);
410166124Srafan
411166124Srafan  if ((res = Associate_Fields(form, fields)) != E_OK)
412166124Srafan    Connect_Fields(form, old);
413166124Srafan
41450276Speter  RETURN(res);
41550276Speter}
416166124Srafan
41750276Speter/*---------------------------------------------------------------------------
41850276Speter|   Facility      :  libnform
41950276Speter|   Function      :  FIELD **form_fields( const FORM *form )
42050276Speter|
42150276Speter|   Description   :  Retrieve array of fields
42250276Speter|
42350276Speter|   Return Values :  Pointer to field array
42450276Speter+--------------------------------------------------------------------------*/
42576726SpeterNCURSES_EXPORT(FIELD **)
426166124Srafanform_fields(const FORM *form)
42750276Speter{
428262629Sdelphij  T((T_CALLED("form_field(%p)"), (const void *)form));
429166124Srafan  returnFieldPtr(Normalize_Form(form)->field);
43050276Speter}
43150276Speter
43250276Speter/*---------------------------------------------------------------------------
43350276Speter|   Facility      :  libnform
43450276Speter|   Function      :  int field_count( const FORM *form )
43550276Speter|
43650276Speter|   Description   :  Retrieve number of fields
43750276Speter|
43850276Speter|   Return Values :  Number of fields, -1 if none are defined
43950276Speter+--------------------------------------------------------------------------*/
44076726SpeterNCURSES_EXPORT(int)
441166124Srafanfield_count(const FORM *form)
44250276Speter{
443262629Sdelphij  T((T_CALLED("field_count(%p)"), (const void *)form));
444166124Srafan
445166124Srafan  returnCode(Normalize_Form(form)->maxfield);
44650276Speter}
44750276Speter
44850276Speter/* frm_def.c ends here */
449