Only try to delete address if present.
[gedcom-parse.git] / gom / family_link.c
1 /* Family link sub-structure 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 "family_link.h"
27 #include "individual.h"
28 #include "note_sub.h"
29 #include "user_rec.h"
30 #include "gom.h"
31 #include "gedcom.h"
32 #include "gom_internal.h"
33
34 Gedcom_ctxt sub_fam_link_start(_ELT_PARAMS_)
35 {
36   Gom_ctxt ctxt = (Gom_ctxt)parent;
37   Gom_ctxt result = NULL;
38
39   if (! ctxt)
40     NO_CONTEXT;
41   else {
42     struct family_link *link = SUB_MAKEFUNC(family_link)();
43     if (link) {
44       link->family = GEDCOM_XREF_PTR(parsed_value);
45       
46       switch (ctxt->ctxt_type) {
47         case REC_INDI:
48           ADDFUNC2(individual,family_link)(ctxt, elt, link); break;
49         default:
50           UNEXPECTED_CONTEXT(ctxt->ctxt_type);
51       }
52       result = MAKE_GOM_CTXT(elt, family_link, link);
53     }
54   }
55
56   return (Gedcom_ctxt)result;
57 }
58
59 Gedcom_ctxt sub_fam_link_pedi_start(_ELT_PARAMS_)
60 {
61   Gom_ctxt ctxt = (Gom_ctxt)parent;
62   Gom_ctxt result = NULL;
63
64   if (! ctxt)
65     NO_CONTEXT;
66   else {
67     struct family_link *link = SAFE_CTXT_CAST(family_link, ctxt);
68     if (link) {
69       int err = 0;
70       struct pedigree *ped = NULL;
71       MAKE_CHAIN_ELT(pedigree, link->pedigree, ped);
72       if (ped) {
73         ped->pedigree = strdup(GEDCOM_STRING(parsed_value));
74         if (! ped->pedigree) {
75           MEMORY_ERROR;
76           err = 1;
77         }
78       }
79       if (! err)
80         result = MAKE_GOM_CTXT(elt, pedigree, ped);
81     }
82   }
83   return (Gedcom_ctxt)result;
84 }
85
86 DEFINE_SUB_MAKEFUNC(family_link)
87 DEFINE_SUB_ADDFUNC(family_link)
88 DEFINE_SUB_FINDFUNC(family_link)
89 DEFINE_SUB_REMOVEFUNC(family_link)
90 DEFINE_SUB_MOVEFUNC(family_link)
91      
92 DEFINE_ADDFUNC2(family_link, note_sub, note)
93 DEFINE_ADDFUNC2(family_link, user_data, extra)
94
95 void family_link_subscribe()
96 {
97   gedcom_subscribe_to_element(ELT_SUB_FAMC, sub_fam_link_start,
98                               def_elt_end);
99   gedcom_subscribe_to_element(ELT_SUB_FAMS, sub_fam_link_start,
100                               def_elt_end);
101   gedcom_subscribe_to_element(ELT_SUB_FAMC_PEDI, sub_fam_link_pedi_start,
102                               def_elt_end);
103 }
104
105 void UNREFALLFUNC(pedigree)(struct pedigree* obj)
106 {
107   if (obj) {
108     struct pedigree* runner;
109     for (runner = obj; runner; runner = runner->next) {
110       UNREFALLFUNC(user_data)(runner->extra);
111     }
112   }
113 }
114
115 void CLEANFUNC(pedigree)(struct pedigree* ped)
116 {
117   if (ped) {
118     SAFE_FREE(ped->pedigree);
119   }
120 }
121
122 DEFINE_SUB_MAKEFUNC(pedigree)
123 DEFINE_SUB_ADDFUNC(pedigree)
124 DEFINE_SUB_FINDFUNC(pedigree)
125 DEFINE_SUB_REMOVEFUNC(pedigree)
126 DEFINE_SUB_MOVEFUNC(pedigree)
127      
128 void UNREFALLFUNC(family_link)(struct family_link* obj)
129 {
130   if (obj) {
131     struct family_link* runner;
132     for (runner = obj; runner; runner = runner->next) {
133       unref_xref_value(runner->family);
134       UNREFALLFUNC(pedigree)(runner->pedigree);
135       UNREFALLFUNC(note_sub)(runner->note);
136       UNREFALLFUNC(user_data)(runner->extra);
137     }
138   }
139 }
140
141 void CLEANFUNC(family_link)(struct family_link *link)
142 {
143   if (link) {
144     DESTROY_CHAIN_ELTS(pedigree, link->pedigree);
145     DESTROY_CHAIN_ELTS(note_sub, link->note);
146     DESTROY_CHAIN_ELTS(user_data, link->extra);
147   }
148 }
149
150 int write_pedigrees(Gedcom_write_hndl hndl, int parent, struct pedigree* ped)
151 {
152   int result = 0;
153   struct pedigree* obj;
154
155   if (!ped) return 1;
156
157   for (obj = ped; obj; obj = obj->next) {
158     result |= gedcom_write_element_str(hndl, ELT_SUB_FAMC_PEDI, 0, parent,
159                                        obj->pedigree);
160     if (obj->extra)
161       result |= write_user_data(hndl, obj->extra);  
162   }
163   
164   return result;
165 }
166
167 int write_family_links(Gedcom_write_hndl hndl, int parent, LinkType type,
168                        struct family_link *link)
169 {
170   int result = 0;
171   struct family_link* obj;
172   int elt = (type == LINK_TYPE_CHILD ? ELT_SUB_FAMC : ELT_SUB_FAMS);
173
174   if (!link) return 1;
175
176   for (obj = link; obj; obj = obj->next) {
177     result |= gedcom_write_element_xref(hndl, elt, 0, parent,
178                                         obj->family);
179     if (obj->pedigree)
180       result |= write_pedigrees(hndl, elt, obj->pedigree);
181     if (obj->note)
182       result |= write_note_subs(hndl, elt, obj->note);
183     if (obj->extra)
184       result |= write_user_data(hndl, obj->extra);      
185   }
186
187   return result;
188 }