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