Add mouse vertical scrolling.
[familia.git] / src / gedcom / familia_gedcom.c
1 #include <assert.h>
2
3 #include "familia_gedcom.h"
4
5 #include "../storage/storage.h"
6 #include "../storage/individual.h"
7 #include "../memory_stack.h"
8
9 #include "../debug.h"
10
11 Gedcom_ctxt familia_gedcom_header_start (Gedcom_rec rec,
12                                         int level,
13                                         Gedcom_val xref,
14                                         char *tag,
15                                         char *raw_value,
16                                         int parsed_tag,
17                                         Gedcom_val parsed_value)
18 {
19         assert(rec == REC_HEAD);
20
21         fprintf(stderr, "The header starts (l: %d, tag: %s, raw:%s) \n", level, tag, raw_value);
22         return (Gedcom_ctxt)1;
23 }
24
25 void familia_gedcom_header_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
26 {
27         /* context will print as "1" */
28         fprintf(stderr, "The header ends, context is %d\n", (int)self);
29 }
30
31 Gedcom_ctxt familia_gedcom_header_source_start(Gedcom_elt  elt,
32                                         Gedcom_ctxt ctxt,
33                                         int         level,
34                                         char*       tag,
35                                         char*       raw_value,
36                                         int         parsed_tag,
37                                         Gedcom_val  parsed_value)
38 {
39         char *source = GEDCOM_STRING(parsed_value);
40         printf("This file was created by %s\n", source);
41         return ctxt;
42 }
43
44 /*
45 void familia_gedcom_header_source_end(Gedcom_elt  elt,
46                                         Gedcom_ctxt ctxt,
47                                         Gedcom_ctxt self,
48                                         Gedcom_val  parsed_value)
49 {
50         printf("End of the source description\n");
51 }
52 */
53
54 Gedcom_ctxt familia_gedcom_header_version_start(Gedcom_elt  elt,
55                                         Gedcom_ctxt ctxt,
56                                         int         level,
57                                         char*       tag,
58                                         char*       raw_value,
59                                         int         parsed_tag,
60                                         Gedcom_val  parsed_value)
61 {
62         char *source = GEDCOM_STRING(parsed_value);
63         printf("Program version: %s (l: %d, tag: %s, raw:%s) \n", source, level, tag, raw_value);
64         return ctxt;
65 }
66 /*
67 void familia_gedcom_header_version_end(Gedcom_elt  elt,
68                                         Gedcom_ctxt ctxt,
69                                         Gedcom_ctxt self,
70                                         Gedcom_val  parsed_value)
71 {
72         printf("End of the version description\n");
73 }*/
74
75 Gedcom_ctxt familia_gedcom_family_start (Gedcom_rec rec,
76                                         int level,
77                                         Gedcom_val xref,
78                                         char *tag,
79                                         char *raw_value,
80                                         int parsed_tag,
81                                         Gedcom_val parsed_value)
82 {
83         struct familia_family * family = NULL;
84         struct xref_value *xr = GEDCOM_XREF_PTR(xref);
85
86         assert(rec == REC_FAM);
87         assert(parsed_tag == TAG_FAM);
88
89         family = familia_memory_stack_find(xr->string, FS_FAMILY);
90
91         return (Gedcom_ctxt)family;
92 }
93
94 void familia_gedcom_family_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
95 {
96 /*      familia_storage_add_family(familia_storage_get_current(), self);*/
97 }
98
99 Gedcom_ctxt familia_gedcom_individual_start (Gedcom_rec rec,
100                                         int level,
101                                         Gedcom_val xref,
102                                         char *tag,
103                                         char *raw_value,
104                                         int parsed_tag,
105                                         Gedcom_val parsed_value)
106 {
107         struct familia_individual * individual = NULL;
108         struct xref_value *xr = GEDCOM_XREF_PTR(xref);
109
110         assert(rec == REC_INDI);
111         assert(parsed_tag == TAG_INDI);
112
113         individual = familia_memory_stack_find(xr->string, FS_INDIVIDUAL);
114
115         return (Gedcom_ctxt)individual;
116 }
117
118 void familia_gedcom_individual_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
119 {
120 /*      familia_storage_add_individual(familia_storage_get_current(), self);*/
121 }
122
123 Gedcom_ctxt familia_gedcom_individual_set_first_name(Gedcom_elt  elt,
124                                         Gedcom_ctxt ctxt,
125                                         int         level,
126                                         char*       tag,
127                                         char*       raw_value,
128                                         int         parsed_tag,
129                                         Gedcom_val  parsed_value)
130 {
131         assert(elt == ELT_SUB_PERS_NAME);
132         assert(parsed_tag == TAG_NAME);
133
134         familia_individual_set_first_name(ctxt, GEDCOM_STRING(parsed_value));
135         return ctxt;
136 }
137 /*
138 void familia_gedcom_individual_first_name_end(Gedcom_elt  elt,
139                                         Gedcom_ctxt ctxt,
140                                         Gedcom_ctxt self,
141                                         Gedcom_val  parsed_value)
142 {
143 }
144 */
145 Gedcom_ctxt familia_gedcom_individual_last_name_start(Gedcom_elt  elt,
146                                         Gedcom_ctxt ctxt,
147                                         int         level,
148                                         char*       tag,
149                                         char*       raw_value,
150                                         int         parsed_tag,
151                                         Gedcom_val  parsed_value)
152 {
153         assert(elt == ELT_SUB_PERS_NAME_SURN);
154
155         if (GEDCOM_IS_STRING(parsed_value)) {
156                 familia_individual_set_last_name(ctxt, GEDCOM_STRING(parsed_value));
157         }
158         return ctxt;
159 }
160 /*
161 void familia_gedcom_individual_last_name_end(Gedcom_elt  elt,
162                                         Gedcom_ctxt ctxt,
163                                         Gedcom_ctxt self,
164                                         Gedcom_val  parsed_value)
165 {
166 }
167 */
168
169 Gedcom_ctxt familia_gedcom_individual_add_family(Gedcom_elt  elt,
170                                         Gedcom_ctxt ctxt,
171                                         int         level,
172                                         char*       tag,
173                                         char*       raw_value,
174                                         int         parsed_tag,
175                                         Gedcom_val  parsed_value)
176 {
177         void * family = NULL;
178         struct xref_value *xr = NULL;
179
180         assert(elt == ELT_SUB_FAMS);
181         assert(parsed_tag == TAG_FAMS);
182
183         xr = GEDCOM_XREF_PTR(parsed_value);
184
185         family = familia_memory_stack_find(xr->string, FS_FAMILY);
186         familia_individual_add_family(ctxt, family);
187
188         return ctxt;
189 }
190
191 /**
192  * Set parents for child
193  */
194 Gedcom_ctxt familia_gedcom_individual_set_parents(Gedcom_elt  elt,
195                                         Gedcom_ctxt ctxt,
196                                         int         level,
197                                         char*       tag,
198                                         char*       raw_value,
199                                         int         parsed_tag,
200                                         Gedcom_val  parsed_value)
201 {
202         void * child = NULL;
203         /* XREF_PTR(FAM) */
204         struct xref_value *xr = NULL;
205
206         assert(elt == ELT_FAM_CHIL);
207         assert(parsed_tag == TAG_CHIL);
208
209         xr = GEDCOM_XREF_PTR(parsed_value);
210
211         child = familia_memory_stack_find(xr->string, FS_INDIVIDUAL);
212         familia_individual_set_parents(child, ctxt);
213
214         return ctxt;
215 }
216
217 /**
218  * Adds child to the family
219  */
220 Gedcom_ctxt familia_gedcom_family_add_child(Gedcom_elt  elt,
221                                         Gedcom_ctxt ctxt,
222                                         int         level,
223                                         char*       tag,
224                                         char*       raw_value,
225                                         int         parsed_tag,
226                                         Gedcom_val  parsed_value)
227 {
228         void * family = NULL;
229         /* XREF_PTR(FAM) */
230         struct xref_value *xr = NULL;
231
232         assert(elt == ELT_SUB_FAMC);
233         assert(parsed_tag == TAG_FAMC);
234
235         xr = GEDCOM_XREF_PTR(parsed_value);
236
237         family = familia_memory_stack_find(xr->string, FS_FAMILY);
238         familia_family_add_child(family, ctxt);
239
240         return ctxt;
241 }
242
243 /**
244  * Adds first parent to the family
245  * Parent is the first individual in family. It can be e.g. Husband
246  */
247 Gedcom_ctxt familia_gedcom_family_set_parent1(Gedcom_elt  elt,
248                                         Gedcom_ctxt ctxt,
249                                         int         level,
250                                         char*       tag,
251                                         char*       raw_value,
252                                         int         parsed_tag,
253                                         Gedcom_val  parsed_value)
254 {
255         void * parent = NULL;
256         /* XREF_PTR(INDI) */
257         struct xref_value *xr = NULL;
258
259         assert(elt == ELT_FAM_HUSB);
260         assert(parsed_tag == TAG_HUSB);
261
262         xr = GEDCOM_XREF_PTR(parsed_value);
263
264         parent = familia_memory_stack_find(xr->string, FS_FAMILY);
265         /* ctxt: REC_FAM */
266         familia_family_set_parent(ctxt, parent, Individual1);
267
268         return ctxt;
269 }
270
271 /**
272  * Adds second parent to the family
273  * Parent is the first individual in family. It can be e.g. Wife
274  */
275 Gedcom_ctxt familia_gedcom_family_set_parent2(Gedcom_elt  elt,
276                                         Gedcom_ctxt ctxt,
277                                         int         level,
278                                         char*       tag,
279                                         char*       raw_value,
280                                         int         parsed_tag,
281                                         Gedcom_val  parsed_value)
282 {
283         void * parent = NULL;
284         /* XREF_PTR(INDI) */
285         struct xref_value *xr = NULL;
286
287         assert(elt == ELT_FAM_WIFE);
288         assert(parsed_tag == TAG_WIFE);
289
290         xr = GEDCOM_XREF_PTR(parsed_value);
291
292         parent = familia_memory_stack_find(xr->string, FS_FAMILY);
293         /* ctxt: REC_FAM */
294         familia_family_set_parent(ctxt, parent, Individual2);
295
296         return ctxt;
297 }
298
299 /**
300  * Sets date for the current event. Currently supports only individual birth.
301  * TODO: Implement all events.
302  */
303 Gedcom_ctxt familia_gedcom_event_set_date(Gedcom_elt  elt,
304                                         Gedcom_ctxt ctxt,
305                                         int         level,
306                                         char*       tag,
307                                         char*       raw_value,
308                                         int         parsed_tag,
309                                         Gedcom_val  parsed_value)
310 {
311         struct fged_timestampable_ctxt * tctxt = ctxt;
312
313         switch(tctxt->type) {
314         case BIRTH: {
315                 struct date_value dv;
316                 struct familia_individual * ind = NULL;
317
318                 assert(GEDCOM_IS_DATE(parsed_value));
319
320                 ind = ((struct fged_ctxt *)ctxt)->object;
321                 dv = GEDCOM_DATE(parsed_value);
322
323                 familia_individual_set_birth_date(ind, dv);
324                 break;
325         }
326         };
327
328         return ctxt;
329 }
330 Gedcom_ctxt familia_gedcom_timestampable_ctxt_wrap(Gedcom_elt  elt,
331                                         Gedcom_ctxt ctxt,
332                                         int         level,
333                                         char*       tag,
334                                         char*       raw_value,
335                                         int         parsed_tag,
336                                         Gedcom_val  parsed_value)
337 {
338         struct fged_timestampable_ctxt * tctxt = NULL;
339         tctxt = (struct fged_timestampable_ctxt *)malloc(sizeof(struct fged_timestampable_ctxt));
340         tctxt->ctxt = ctxt;
341         tctxt->type = UNSET;
342         
343         switch(elt) {
344         case ELT_SUB_INDIV_BIRT:
345                 tctxt->type = BIRTH;
346                 break;
347         }
348         return tctxt;
349 }
350
351 void familia_gedcom_timestampable_ctxt_unwrap(Gedcom_elt  elt,
352                                         Gedcom_ctxt ctxt,
353                                         Gedcom_ctxt self,
354                                         Gedcom_val  parsed_value)
355 {
356         struct fged_timestampable_ctxt * tctxt = NULL;
357
358         tctxt = self;
359
360         self = tctxt->ctxt;
361         free(tctxt);
362 }
363
364 void familia_gedcom_error (Gedcom_msg_type type, char *msg)
365 {
366         fprintf(stderr, "> %s\n", msg);
367 }
368
369
370
371 void familia_gedcom_init()
372 {
373         gedcom_set_message_handler(familia_gedcom_error);
374
375         gedcom_subscribe_to_record(REC_HEAD, familia_gedcom_header_start, familia_gedcom_header_end);
376         /* Create and set family as current (set to ctxt) */
377         gedcom_subscribe_to_record(REC_FAM, familia_gedcom_family_start, familia_gedcom_family_end);
378         /* Create and set individual as current (set to ctxt) */
379         gedcom_subscribe_to_record(REC_INDI, familia_gedcom_individual_start, familia_gedcom_individual_end);
380         gedcom_subscribe_to_element(ELT_HEAD_SOUR, familia_gedcom_header_source_start, NULL);
381         gedcom_subscribe_to_element(ELT_HEAD_SOUR_VERS, familia_gedcom_header_version_start, NULL);
382         /* Set in current individual first name */
383         gedcom_subscribe_to_element(ELT_SUB_PERS_NAME, familia_gedcom_individual_set_first_name, NULL);
384         /* Set in current individual last name */
385         gedcom_subscribe_to_element(ELT_SUB_PERS_NAME_SURN, familia_gedcom_individual_last_name_start, NULL);
386         /* Add to current individual new family */
387         gedcom_subscribe_to_element(ELT_SUB_FAMS, familia_gedcom_individual_add_family, NULL);
388         /* Set current family as parents to child */
389         gedcom_subscribe_to_element(ELT_FAM_CHIL, familia_gedcom_individual_set_parents, NULL);
390         /* Set current individual new parents */
391         gedcom_subscribe_to_element(ELT_SUB_FAMC, familia_gedcom_family_add_child, NULL);
392         /* Set in current family first parent (e.g. husband) */
393         gedcom_subscribe_to_element(ELT_FAM_HUSB, familia_gedcom_family_set_parent1, NULL);
394         /* Set in current family second parent (e.g. wife) */
395         gedcom_subscribe_to_element(ELT_FAM_WIFE, familia_gedcom_family_set_parent2, NULL);
396         
397         gedcom_subscribe_to_element(ELT_SUB_EVT_DATE, familia_gedcom_event_set_date, NULL);
398         gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT, familia_gedcom_timestampable_ctxt_wrap, familia_gedcom_timestampable_ctxt_unwrap);
399
400         familia_memory_stack_init();
401 }
402
403 void familia_gedcom_dump_val(Gedcom_val val)
404 {
405         if (GEDCOM_IS_NULL(val)) {
406                 fprintf(stderr, "| %25s |\n", "NULL");
407         }
408         else if (GEDCOM_IS_STRING(val)) {
409                 fprintf(stderr, "| %4s | %20s |\n", "STRING", GEDCOM_STRING(val));
410         }
411         else if (GEDCOM_IS_DATE(val)) {
412                 fprintf(stderr, "| %4s | %20s |\n", "DATE", "(@todo)");
413         }
414         else if (GEDCOM_IS_AGE(val)) {
415                 fprintf(stderr, "| %4s | %20s |\n", "AGE", "(@todo)");
416         }
417         else if (GEDCOM_IS_XREF_PTR(val)) {
418                 struct xref_value *xref = NULL;
419                 fprintf(stderr, "| %25s | %15s | %4s |\n", "STRING", "OBJECT", "TYPE");
420                 xref = GEDCOM_XREF_PTR(val);
421                 fprintf(stderr, "| %25s | %15s | %4s |\n",
422                         xref->string,
423                         xref->object ? "initialized" : "NULL",
424                         (xref->type == XREF_NONE) ? "NONE" :
425                                 (xref->type == XREF_FAM ) ? "FAM" :
426                                 (xref->type == XREF_INDI) ? "INDI" :
427                                 (xref->type == XREF_NOTE) ? "NOTE" :
428                                 (xref->type == XREF_OBJE) ? "OBJE" :
429                                 (xref->type == XREF_REPO) ? "REPO" :
430                                 (xref->type == XREF_SOUR) ? "SOUR" :
431                                 (xref->type == XREF_SUBM) ? "SUBM" :
432                                 (xref->type == XREF_SUBN) ? "SUBN" :
433                                 (xref->type == XREF_ANY ) ? "ANY" :
434                                 (xref->type == XREF_USER) ? "USER" : "???");
435         } 
436         else {
437                 fprintf(stderr, "| %20s |\n", "???");
438         }
439 }