Declare SUB_MAKEFUNC.
[gedcom-parse.git] / gom / user_rec.c
1 /* User record object in the gedcom object model.
2    Copyright (C) 2002 The Genes Development Team
3    This file is part of the Gedcom parser library.
4    Contributed by Peter Verthez <Peter.Verthez@advalvas.be>, 2002.
5
6    The Gedcom parser library is free software; you can redistribute it
7    and/or modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The Gedcom parser library is distributed in the hope that it will be
12    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the Gedcom parser library; if not, write to the
18    Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* $Id$ */
22 /* $Name$ */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include "header.h"
27 #include "submission.h"
28 #include "submitter.h"
29 #include "family.h"
30 #include "individual.h"
31 #include "multimedia.h"
32 #include "note.h"
33 #include "repository.h"
34 #include "source.h"
35 #include "address.h"
36 #include "event.h"
37 #include "place.h"
38 #include "source_citation.h"
39 #include "note_sub.h"
40 #include "multimedia_link.h"
41 #include "lds_event.h"
42 #include "user_ref.h"
43 #include "change_date.h"
44 #include "personal_name.h"
45 #include "family_link.h"
46 #include "association.h"
47 #include "source_event.h"
48 #include "source_description.h"
49 #include "user_rec.h"
50 #include "gom.h"
51 #include "gedcom.h"
52 #include "gom_internal.h"
53
54 struct user_rec* gom_first_user_rec = NULL;
55
56 Gedcom_ctxt user_rec_start(_REC_PARAMS_)
57 {
58   struct user_rec* user = NULL;
59   struct xref_value* xr = NULL;
60   Gom_ctxt result  = NULL;
61   Gedcom_ctxt ctxt = NULL;
62   int err = 0;
63   
64   if (GEDCOM_IS_XREF_PTR(xref))
65     xr = GEDCOM_XREF_PTR(xref);
66   if (xr) {
67     if (! xr->object) {
68       user = MAKEFUNC(user_rec)(xr->string);
69       xr->object = (Gedcom_ctxt) user;
70     }
71     ctxt = xr->object;
72     if (ctxt) {
73       user = (struct user_rec*) ctxt;
74     }
75   }
76   else {
77     user = MAKEFUNC(user_rec)(NULL);
78     ctxt = (Gedcom_ctxt) user;
79   }
80
81   if (user) {
82     user->tag = strdup(tag);
83     if (! user->tag) {
84       MEMORY_ERROR;
85       err = 1;
86     }
87     else if (GEDCOM_IS_STRING(parsed_value)) {
88       user->str_value = strdup(GEDCOM_STRING(parsed_value));
89       if (!user->str_value) {
90         MEMORY_ERROR;
91         err = 1;
92       }
93     }
94     else if (GEDCOM_IS_XREF_PTR(parsed_value))
95       user->xref_value = GEDCOM_XREF_PTR(parsed_value);
96     
97     if (! err)
98       result = MAKE_GOM_CTXT(rec, user_rec, ctxt);
99   }
100   
101   return (Gedcom_ctxt)result;
102 }
103
104 DEFINE_DESTROYFUNC(user_rec, gom_first_user_rec)
105 DEFINE_DELETEFUNC(user_rec)
106 DEFINE_GETXREFFUNC(user_rec, XREF_USER)
107
108 DEFINE_ADDFUNC2(user_rec, user_data, extra)
109
110 /* Specific function, because xrefstr not mandatory here */
111 struct user_rec* MAKEFUNC(user_rec)(const char* xrefstr)
112 {
113   struct user_rec* rec = NULL;
114   MAKE_CHAIN_ELT(user_rec, gom_first_user_rec, rec);
115   if (rec && xrefstr) {
116     rec->xrefstr = strdup(xrefstr);
117     if (! rec->xrefstr) MEMORY_ERROR;
118   }
119   return rec;
120 }
121
122 struct user_rec* ADDFUNC(user_rec)(const char* xrefstr, const char* tag)
123 {
124   struct user_rec *obj = NULL;
125   struct xref_value* xrv = gedcom_get_by_xref(xrefstr);
126   if (tag && tag[0] == '_') {
127     if (xrv)
128       gom_xref_already_in_use(xrefstr);
129     else {
130       obj = MAKEFUNC(user_rec)(xrefstr);
131       if (obj) {
132         obj->tag = strdup(tag);
133         if (! obj->tag)
134           MEMORY_ERROR;
135         else
136           xrv = gedcom_add_xref(XREF_USER, xrefstr, (Gedcom_ctxt)obj);
137         if (!xrv) {
138           DESTROYFUNC(user_rec)(obj);
139           obj = NULL;
140         }
141       }
142     }
143   }
144   return obj;
145 }
146
147 Gedcom_ctxt user_elt_start(_ELT_PARAMS_)
148 {
149   Gom_ctxt ctxt = (Gom_ctxt)parent;
150   Gom_ctxt result = NULL;
151   int err = 0;
152
153   if (! ctxt)
154     NO_CONTEXT;
155   else {
156     struct user_data *data
157       = (struct user_data *)malloc(sizeof(struct user_data));
158
159     if (! data)
160       MEMORY_ERROR;
161     else {
162       memset (data, 0, sizeof(struct user_data));
163       
164       data->level = level;
165       data->tag = strdup(tag);
166       if (! data->tag) {
167         MEMORY_ERROR;
168         free(data);
169         err = 1;
170       }
171       else if (GEDCOM_IS_STRING(parsed_value)) {
172         data->str_value = strdup(GEDCOM_STRING(parsed_value));
173         if (! data->str_value) {
174           MEMORY_ERROR;
175           free(data->tag);
176           free(data->str_value);
177           err = 1;
178         }
179       }
180       else if (GEDCOM_IS_XREF_PTR(parsed_value))
181         data->xref_value = GEDCOM_XREF_PTR(parsed_value);
182
183       if (! err) {
184         switch (ctxt->obj_type) {
185           case T_header:
186             ADDFUNC2(header,user_data)(ctxt, data); break;
187           case T_submission:
188             ADDFUNC2(submission,user_data)(ctxt, data); break;
189           case T_submitter:
190             ADDFUNC2(submitter,user_data)(ctxt, data); break;
191           case T_family:
192             ADDFUNC2(family,user_data)(ctxt, data); break;
193           case T_individual:
194             ADDFUNC2(individual,user_data)(ctxt, data); break;
195           case T_multimedia:
196             ADDFUNC2(multimedia,user_data)(ctxt, data); break;
197           case T_note:
198             ADDFUNC2(note,user_data)(ctxt, data); break;
199           case T_repository:
200             ADDFUNC2(repository,user_data)(ctxt, data); break;
201           case T_source:
202             ADDFUNC2(source,user_data)(ctxt, data); break;
203           case T_user_rec:
204             ADDFUNC2(user_rec,user_data)(ctxt, data); break;
205           case T_address:
206             ADDFUNC2(address,user_data)(ctxt, data); break;
207           case T_event:
208             ADDFUNC2(event,user_data)(ctxt, data); break;
209           case T_place:
210             ADDFUNC2(place,user_data)(ctxt, data); break;
211           case T_source_citation:
212             ADDFUNC2(source_citation,user_data)(ctxt, data); break;
213           case T_note_sub:
214             ADDFUNC2(note_sub,user_data)(ctxt, data); break;
215           case T_multimedia_link:
216             ADDFUNC2(multimedia_link,user_data)(ctxt, data); break;
217           case T_lds_event:
218             ADDFUNC2(lds_event,user_data)(ctxt, data); break;
219           case T_user_ref_number:
220             ADDFUNC2(user_ref_number,user_data)(ctxt, data); break;
221           case T_change_date:
222             ADDFUNC2(change_date,user_data)(ctxt, data); break;
223           case T_personal_name:
224             ADDFUNC2(personal_name,user_data)(ctxt, data); break;
225           case T_family_link:
226             ADDFUNC2(family_link,user_data)(ctxt, data); break;
227           case T_association:
228             ADDFUNC2(association,user_data)(ctxt, data); break;
229           case T_source_event:
230             ADDFUNC2(source_event,user_data)(ctxt, data); break;
231           case T_source_description:
232             ADDFUNC2(source_description,user_data)(ctxt, data); break;
233           default:
234             UNEXPECTED_CONTEXT(ctxt->ctxt_type);
235         }
236         result = make_gom_ctxt(elt, ctxt->obj_type, ctxt->ctxt_ptr);
237       }
238     }
239   }
240   
241   return (Gedcom_ctxt)result;
242 }
243
244 void user_rec_subscribe()
245 {
246   gedcom_subscribe_to_record(REC_USER, user_rec_start, def_rec_end);
247   gedcom_subscribe_to_element(ELT_USER, user_elt_start, def_elt_end);
248 }
249
250 void CLEANFUNC(user_data)(struct user_data* data)
251 {
252   if (data) {
253     SAFE_FREE(data->tag);
254     SAFE_FREE(data->str_value);
255   }
256 }
257
258 void CLEANFUNC(user_rec)(struct user_rec* rec)
259 {
260   if (rec) {
261     SAFE_FREE(rec->xrefstr);
262     SAFE_FREE(rec->tag);
263     SAFE_FREE(rec->str_value);
264     DESTROY_CHAIN_ELTS(user_data, rec->extra);
265   }
266 }
267
268 void user_recs_cleanup()
269 {
270   DESTROY_CHAIN_ELTS(user_rec, gom_first_user_rec);
271 }
272
273 struct user_rec* gom_get_first_user_rec()
274 {
275   return gom_first_user_rec;
276 }
277
278 int write_user_recs(Gedcom_write_hndl hndl)
279 {
280   int result = 0;
281   struct user_rec* obj;
282
283   for (obj = gom_first_user_rec; obj; obj = obj->next) {
284     if (obj->xref_value)
285       result |= gedcom_write_user_xref(hndl, 0, obj->tag, obj->xrefstr,
286                                        obj->xref_value);
287     else
288       result |= gedcom_write_user_str(hndl, 0, obj->tag, obj->xrefstr,
289                                       obj->str_value);
290     if (obj->extra)
291       result |= write_user_data(hndl, obj->extra);
292   }
293   return result;  
294 }
295
296 int write_user_data(Gedcom_write_hndl hndl, struct user_data* data)
297 {
298   int result = 0;
299   struct user_data* obj;
300
301   if (!data) return 1;
302
303   for (obj = data; data; data = data->next) {
304     if (obj->xref_value)
305       result |= gedcom_write_user_xref(hndl, obj->level, obj->tag, NULL,
306                                        obj->xref_value);
307     else
308       result |= gedcom_write_user_str(hndl, obj->level, obj->tag, NULL,
309                                       obj->str_value);
310   }
311   return result;
312 }