Functions for moving an xref in a list.
[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 UNREFALLFUNC(user_data)(struct user_data *obj)
251 {
252   if (obj) {
253     struct user_data* runner;
254     for (runner = obj; runner; runner = runner->next)
255       unref_xref_value(runner->xref_value);
256   }
257 }
258
259 void CLEANFUNC(user_data)(struct user_data* data)
260 {
261   if (data) {
262     SAFE_FREE(data->tag);
263     SAFE_FREE(data->str_value);
264   }
265 }
266
267 void UNREFALLFUNC(user_rec)(struct user_rec *obj)
268 {
269   if (obj) {
270     unref_xref_value(obj->xref_value);
271     UNREFALLFUNC(user_data)(obj->extra);
272   }
273 }
274
275 void CLEANFUNC(user_rec)(struct user_rec* rec)
276 {
277   if (rec) {
278     SAFE_FREE(rec->xrefstr);
279     SAFE_FREE(rec->tag);
280     SAFE_FREE(rec->str_value);
281     DESTROY_CHAIN_ELTS(user_data, rec->extra);
282   }
283 }
284
285 void user_recs_cleanup()
286 {
287   DESTROY_CHAIN_ELTS(user_rec, gom_first_user_rec);
288 }
289
290 struct user_rec* gom_get_first_user_rec()
291 {
292   return gom_first_user_rec;
293 }
294
295 int write_user_recs(Gedcom_write_hndl hndl)
296 {
297   int result = 0;
298   struct user_rec* obj;
299
300   for (obj = gom_first_user_rec; obj; obj = obj->next) {
301     if (obj->xref_value)
302       result |= gedcom_write_user_xref(hndl, 0, obj->tag, obj->xrefstr,
303                                        obj->xref_value);
304     else
305       result |= gedcom_write_user_str(hndl, 0, obj->tag, obj->xrefstr,
306                                       obj->str_value);
307     if (obj->extra)
308       result |= write_user_data(hndl, obj->extra);
309   }
310   return result;  
311 }
312
313 int write_user_data(Gedcom_write_hndl hndl, struct user_data* data)
314 {
315   int result = 0;
316   struct user_data* obj;
317
318   if (!data) return 1;
319
320   for (obj = data; data; data = data->next) {
321     if (obj->xref_value)
322       result |= gedcom_write_user_xref(hndl, obj->level, obj->tag, NULL,
323                                        obj->xref_value);
324     else
325       result |= gedcom_write_user_str(hndl, obj->level, obj->tag, NULL,
326                                       obj->str_value);
327   }
328   return result;
329 }