1/****************************************************************************
2 * Copyright (c) 1998-2011,2012 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, 1995,1997                                    *
31 ****************************************************************************/
32
33#include "form.priv.h"
34
35MODULE_ID("$Id: fld_def.c,v 1.40 2012/03/11 00:37:16 tom Exp $")
36
37/* this can't be readonly */
38static FIELD default_field =
39{
40  0,				/* status  */
41  0,				/* rows    */
42  0,				/* cols    */
43  0,				/* frow    */
44  0,				/* fcol    */
45  0,				/* drows   */
46  0,				/* dcols   */
47  0,				/* maxgrow */
48  0,				/* nrow    */
49  0,				/* nbuf    */
50  NO_JUSTIFICATION,		/* just    */
51  0,				/* page    */
52  0,				/* index   */
53  (int)' ',			/* pad     */
54  A_NORMAL,			/* fore    */
55  A_NORMAL,			/* back    */
56  ALL_FIELD_OPTS,		/* opts    */
57  (FIELD *)0,			/* snext   */
58  (FIELD *)0,			/* sprev   */
59  (FIELD *)0,			/* link    */
60  (FORM *)0,			/* form    */
61  (FIELDTYPE *)0,		/* type    */
62  (char *)0,			/* arg     */
63  (FIELD_CELL *)0,		/* buf     */
64  (char *)0			/* usrptr  */
65  NCURSES_FIELD_EXTENSION
66};
67
68NCURSES_EXPORT_VAR(FIELD *) _nc_Default_Field = &default_field;
69
70/*---------------------------------------------------------------------------
71|   Facility      :  libnform
72|   Function      :  TypeArgument *_nc_Make_Argument(
73|                              const FIELDTYPE *typ,
74|                              va_list *ap,
75|                              int *err )
76|
77|   Description   :  Create an argument structure for the specified type.
78|                    Use the type-dependent argument list to construct
79|                    it.
80|
81|   Return Values :  Pointer to argument structure. Maybe NULL.
82|                    In case of an error in *err an error counter is increased.
83+--------------------------------------------------------------------------*/
84NCURSES_EXPORT(TypeArgument *)
85_nc_Make_Argument(const FIELDTYPE *typ, va_list *ap, int *err)
86{
87  TypeArgument *res = (TypeArgument *)0;
88  TypeArgument *p;
89
90  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
91    {
92      assert(err != 0 && ap != (va_list *)0);
93      if ((typ->status & _LINKED_TYPE) != 0)
94	{
95	  p = typeMalloc(TypeArgument, 1);
96
97	  if (p != 0)
98	    {
99	      p->left = _nc_Make_Argument(typ->left, ap, err);
100	      p->right = _nc_Make_Argument(typ->right, ap, err);
101	      return p;
102	    }
103	  else
104	    {
105	      *err += 1;
106	    }
107	}
108      else
109	{
110	  assert(typ->makearg != (void *)0);
111	  if (!(res = (TypeArgument *)typ->makearg(ap)))
112	    {
113	      *err += 1;
114	    }
115	}
116    }
117  return res;
118}
119
120/*---------------------------------------------------------------------------
121|   Facility      :  libnform
122|   Function      :  TypeArgument *_nc_Copy_Argument(const FIELDTYPE *typ,
123|                                                    const TypeArgument *argp,
124|                                                    int *err )
125|
126|   Description   :  Create a copy of an argument structure for the specified
127|                    type.
128|
129|   Return Values :  Pointer to argument structure. Maybe NULL.
130|                    In case of an error in *err an error counter is increased.
131+--------------------------------------------------------------------------*/
132NCURSES_EXPORT(TypeArgument *)
133_nc_Copy_Argument(const FIELDTYPE *typ, const TypeArgument *argp, int *err)
134{
135  TypeArgument *res = (TypeArgument *)0;
136  TypeArgument *p;
137
138  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
139    {
140      assert(err != 0 && argp != 0);
141      if ((typ->status & _LINKED_TYPE) != 0)
142	{
143	  p = typeMalloc(TypeArgument, 1);
144
145	  if (p != 0)
146	    {
147	      p->left = _nc_Copy_Argument(typ, argp->left, err);
148	      p->right = _nc_Copy_Argument(typ, argp->right, err);
149	      return p;
150	    }
151	  *err += 1;
152	}
153      else
154	{
155	  if (typ->copyarg != (void *)0)
156	    {
157	      if (!(res = (TypeArgument *)(typ->copyarg((const void *)argp))))
158		{
159		  *err += 1;
160		}
161	    }
162	  else
163	    {
164	      res = (TypeArgument *)argp;
165	    }
166	}
167    }
168  return res;
169}
170
171/*---------------------------------------------------------------------------
172|   Facility      :  libnform
173|   Function      :  void _nc_Free_Argument(const FIELDTYPE *typ,
174|                                           TypeArgument * argp )
175|
176|   Description   :  Release memory associated with the argument structure
177|                    for the given fieldtype.
178|
179|   Return Values :  -
180+--------------------------------------------------------------------------*/
181NCURSES_EXPORT(void)
182_nc_Free_Argument(const FIELDTYPE *typ, TypeArgument *argp)
183{
184  if (typ != 0 && (typ->status & _HAS_ARGS) != 0)
185    {
186      if ((typ->status & _LINKED_TYPE) != 0)
187	{
188	  if (argp != 0)
189	    {
190	      _nc_Free_Argument(typ->left, argp->left);
191	      _nc_Free_Argument(typ->right, argp->right);
192	      free(argp);
193	    }
194	}
195      else
196	{
197	  if (typ->freearg != (void *)0)
198	    {
199	      typ->freearg((void *)argp);
200	    }
201	}
202    }
203}
204
205/*---------------------------------------------------------------------------
206|   Facility      :  libnform
207|   Function      :  bool _nc_Copy_Type( FIELD *dst, FIELD const *src )
208|
209|   Description   :  Copy argument structure of field src to field dst
210|
211|   Return Values :  TRUE       - copy worked
212|                    FALSE      - error occurred
213+--------------------------------------------------------------------------*/
214NCURSES_EXPORT(bool)
215_nc_Copy_Type(FIELD *dst, FIELD const *src)
216{
217  int err = 0;
218
219  assert(dst != 0 && src != 0);
220
221  dst->type = src->type;
222  dst->arg = (void *)_nc_Copy_Argument(src->type, (TypeArgument *)(src->arg), &err);
223
224  if (err != 0)
225    {
226      _nc_Free_Argument(dst->type, (TypeArgument *)(dst->arg));
227      dst->type = (FIELDTYPE *)0;
228      dst->arg = (void *)0;
229      return FALSE;
230    }
231  else
232    {
233      if (dst->type != 0)
234	{
235	  dst->type->ref++;
236	}
237      return TRUE;
238    }
239}
240
241/*---------------------------------------------------------------------------
242|   Facility      :  libnform
243|   Function      :  void _nc_Free_Type( FIELD *field )
244|
245|   Description   :  Release Argument structure for this field
246|
247|   Return Values :  -
248+--------------------------------------------------------------------------*/
249NCURSES_EXPORT(void)
250_nc_Free_Type(FIELD *field)
251{
252  assert(field != 0);
253  if (field->type != 0)
254    {
255      field->type->ref--;
256      _nc_Free_Argument(field->type, (TypeArgument *)(field->arg));
257    }
258}
259
260/*---------------------------------------------------------------------------
261|   Facility      :  libnform
262|   Function      :  FIELD *new_field( int rows, int cols,
263|                                      int frow, int fcol,
264|                                      int nrow, int nbuf )
265|
266|   Description   :  Create a new field with this many 'rows' and 'cols',
267|                    starting at 'frow/fcol' in the subwindow of the form.
268|                    Allocate 'nrow' off-screen rows and 'nbuf' additional
269|                    buffers. If an error occurs, errno is set to
270|
271|                    E_BAD_ARGUMENT - invalid argument
272|                    E_SYSTEM_ERROR - system error
273|
274|   Return Values :  Pointer to the new field or NULL if failure.
275+--------------------------------------------------------------------------*/
276NCURSES_EXPORT(FIELD *)
277new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf)
278{
279  static const FIELD_CELL blank = BLANK;
280  static const FIELD_CELL zeros = ZEROS;
281
282  FIELD *New_Field = (FIELD *)0;
283  int err = E_BAD_ARGUMENT;
284
285  T((T_CALLED("new_field(%d,%d,%d,%d,%d,%d)"), rows, cols, frow, fcol, nrow, nbuf));
286  if (rows > 0 &&
287      cols > 0 &&
288      frow >= 0 &&
289      fcol >= 0 &&
290      nrow >= 0 &&
291      nbuf >= 0 &&
292      ((err = E_SYSTEM_ERROR) != 0) &&	/* trick: this resets the default error */
293      (New_Field = typeMalloc(FIELD, 1)) != 0)
294    {
295      T((T_CREATE("field %p"), (void *)New_Field));
296      *New_Field = default_field;
297      New_Field->rows = (short) rows;
298      New_Field->cols = (short) cols;
299      New_Field->drows = rows + nrow;
300      New_Field->dcols = cols;
301      New_Field->frow = (short) frow;
302      New_Field->fcol = (short) fcol;
303      New_Field->nrow = nrow;
304      New_Field->nbuf = (short) nbuf;
305      New_Field->link = New_Field;
306
307#if USE_WIDEC_SUPPORT
308      New_Field->working = newpad(1, Buffer_Length(New_Field) + 1);
309      New_Field->expanded = typeCalloc(char *, 1 + (unsigned)nbuf);
310#endif
311
312      if (_nc_Copy_Type(New_Field, &default_field))
313	{
314	  size_t len;
315
316	  len = Total_Buffer_Size(New_Field);
317	  if ((New_Field->buf = (FIELD_CELL *)malloc(len)))
318	    {
319	      /* Prefill buffers with blanks and insert terminating zeroes
320	         between buffers */
321	      int i, j;
322	      int cells = Buffer_Length(New_Field);
323
324	      for (i = 0; i <= New_Field->nbuf; i++)
325		{
326		  FIELD_CELL *buffer = &(New_Field->buf[(cells + 1) * i]);
327
328		  for (j = 0; j < cells; ++j)
329		    {
330		      buffer[j] = blank;
331		    }
332		  buffer[j] = zeros;
333		}
334	      returnField(New_Field);
335	    }
336	}
337    }
338
339  if (New_Field)
340    free_field(New_Field);
341
342  SET_ERROR(err);
343  returnField((FIELD *)0);
344}
345
346/*---------------------------------------------------------------------------
347|   Facility      :  libnform
348|   Function      :  int free_field( FIELD *field )
349|
350|   Description   :  Frees the storage allocated for the field.
351|
352|   Return Values :  E_OK           - success
353|                    E_BAD_ARGUMENT - invalid field pointer
354|                    E_CONNECTED    - field is connected
355+--------------------------------------------------------------------------*/
356NCURSES_EXPORT(int)
357free_field(FIELD *field)
358{
359  T((T_CALLED("free_field(%p)"), (void *)field));
360  if (!field)
361    {
362      RETURN(E_BAD_ARGUMENT);
363    }
364  else if (field->form != 0)
365    {
366      RETURN(E_CONNECTED);
367    }
368  else if (field == field->link)
369    {
370      if (field->buf != 0)
371	free(field->buf);
372    }
373  else
374    {
375      FIELD *f;
376
377      for (f = field; f->link != field; f = f->link)
378	{
379	}
380      f->link = field->link;
381    }
382  _nc_Free_Type(field);
383#if USE_WIDEC_SUPPORT
384  if (field->expanded != 0)
385    {
386      int n;
387
388      for (n = 0; n <= field->nbuf; ++n)
389	{
390	  FreeIfNeeded(field->expanded[n]);
391	}
392      free(field->expanded);
393      (void)delwin(field->working);
394    }
395#endif
396  free(field);
397  RETURN(E_OK);
398}
399
400/* fld_def.c ends here */
401