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