Added reading date from the GEDCOM file and storing it in individual.
[familia.git] / src / gedcom / familia_gedcom.c
index dcb80328a5cfc883de9192ce3818e4da4720f234..e92de3a43ca69903b87fa585ed228fa281869cf4 100644 (file)
@@ -6,6 +6,8 @@
 #include "../storage/individual.h"
 #include "../memory_stack.h"
 
+#include "../debug.h"
+
 Gedcom_ctxt familia_gedcom_header_start (Gedcom_rec rec,
                                        int level,
                                        Gedcom_val xref,
@@ -14,18 +16,20 @@ Gedcom_ctxt familia_gedcom_header_start (Gedcom_rec rec,
                                        int parsed_tag,
                                        Gedcom_val parsed_value)
 {
+       assert(rec == REC_HEAD);
+
        fprintf(stderr, "The header starts (l: %d, tag: %s, raw:%s) \n", level, tag, raw_value);
        return (Gedcom_ctxt)1;
 }
 
-void familia_gedcom_header_end (Gedcom_rec rec, Gedcom_ctxt self)
+void familia_gedcom_header_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
 {
        /* context will print as "1" */
        fprintf(stderr, "The header ends, context is %d\n", (int)self);
 }
 
 Gedcom_ctxt familia_gedcom_header_source_start(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
@@ -34,12 +38,12 @@ Gedcom_ctxt familia_gedcom_header_source_start(Gedcom_elt  elt,
 {
        char *source = GEDCOM_STRING(parsed_value);
        printf("This file was created by %s\n", source);
-       return parent;
+       return ctxt;
 }
 
 /*
 void familia_gedcom_header_source_end(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        Gedcom_ctxt self,
                                        Gedcom_val  parsed_value)
 {
@@ -48,7 +52,7 @@ void familia_gedcom_header_source_end(Gedcom_elt  elt,
 */
 
 Gedcom_ctxt familia_gedcom_header_version_start(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
@@ -57,11 +61,11 @@ Gedcom_ctxt familia_gedcom_header_version_start(Gedcom_elt  elt,
 {
        char *source = GEDCOM_STRING(parsed_value);
        printf("Program version: %s (l: %d, tag: %s, raw:%s) \n", source, level, tag, raw_value);
-       return parent;
+       return ctxt;
 }
 /*
 void familia_gedcom_header_version_end(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        Gedcom_ctxt self,
                                        Gedcom_val  parsed_value)
 {
@@ -79,16 +83,19 @@ Gedcom_ctxt familia_gedcom_family_start (Gedcom_rec rec,
        struct familia_family * family = NULL;
        struct xref_value *xr = GEDCOM_XREF_PTR(xref);
 
+       assert(rec == REC_FAM);
+       assert(parsed_tag == TAG_FAM);
+
        family = familia_memory_stack_find(xr->string, FS_FAMILY);
 
        return (Gedcom_ctxt)family;
 }
-/*
-void familia_gedcom_family_end (Gedcom_rec rec, Gedcom_ctxt self)
+
+void familia_gedcom_family_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
 {
-       familia_storage_add_family(familia_storage_get_current(), self);
+/*     familia_storage_add_family(familia_storage_get_current(), self);*/
 }
-*/
+
 Gedcom_ctxt familia_gedcom_individual_start (Gedcom_rec rec,
                                        int level,
                                        Gedcom_val xref,
@@ -100,51 +107,59 @@ Gedcom_ctxt familia_gedcom_individual_start (Gedcom_rec rec,
        struct familia_individual * individual = NULL;
        struct xref_value *xr = GEDCOM_XREF_PTR(xref);
 
+       assert(rec == REC_INDI);
+       assert(parsed_tag == TAG_INDI);
+
        individual = familia_memory_stack_find(xr->string, FS_INDIVIDUAL);
 
        return (Gedcom_ctxt)individual;
 }
-/*
-void familia_gedcom_individual_end (Gedcom_rec rec, Gedcom_ctxt self)
+
+void familia_gedcom_individual_end (Gedcom_rec rec, Gedcom_ctxt self, Gedcom_val parsed_value)
 {
-       familia_storage_add_individual(familia_storage_get_current(), self);
+/*     familia_storage_add_individual(familia_storage_get_current(), self);*/
 }
-*/
+
 Gedcom_ctxt familia_gedcom_individual_set_first_name(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
                                        int         parsed_tag,
                                        Gedcom_val  parsed_value)
 {
-       familia_individual_set_first_name(parent, GEDCOM_STRING(parsed_value));
-       return parent;
+       assert(elt == ELT_SUB_PERS_NAME);
+       assert(parsed_tag == TAG_NAME);
+
+       familia_individual_set_first_name(ctxt, GEDCOM_STRING(parsed_value));
+       return ctxt;
 }
 /*
 void familia_gedcom_individual_first_name_end(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        Gedcom_ctxt self,
                                        Gedcom_val  parsed_value)
 {
 }
 */
 Gedcom_ctxt familia_gedcom_individual_last_name_start(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
                                        int         parsed_tag,
                                        Gedcom_val  parsed_value)
 {
+       assert(elt == ELT_SUB_PERS_NAME_SURN);
+
        if (GEDCOM_IS_STRING(parsed_value)) {
-               familia_individual_set_last_name(parent, GEDCOM_STRING(parsed_value));
+               familia_individual_set_last_name(ctxt, GEDCOM_STRING(parsed_value));
        }
-       return parent;
+       return ctxt;
 }
 /*
 void familia_gedcom_individual_last_name_end(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        Gedcom_ctxt self,
                                        Gedcom_val  parsed_value)
 {
@@ -152,51 +167,199 @@ void familia_gedcom_individual_last_name_end(Gedcom_elt  elt,
 */
 
 Gedcom_ctxt familia_gedcom_individual_add_family(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
+                                       int         level,
+                                       char*       tag,
+                                       char*       raw_value,
+                                       int         parsed_tag,
+                                       Gedcom_val  parsed_value)
+{
+       void * family = NULL;
+       struct xref_value *xr = NULL;
+
+       assert(elt == ELT_SUB_FAMS);
+       assert(parsed_tag == TAG_FAMS);
+
+       xr = GEDCOM_XREF_PTR(parsed_value);
+
+       family = familia_memory_stack_find(xr->string, FS_FAMILY);
+       familia_individual_add_family(ctxt, family);
+
+       return ctxt;
+}
+
+/**
+ * Set parents for child
+ */
+Gedcom_ctxt familia_gedcom_individual_set_parents(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
                                        int         parsed_tag,
                                        Gedcom_val  parsed_value)
 {
-       void * object = NULL;
-       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);
+       void * child = NULL;
+       /* XREF_PTR(FAM) */
+       struct xref_value *xr = NULL;
+
+       assert(elt == ELT_FAM_CHIL);
+       assert(parsed_tag == TAG_CHIL);
+
+       xr = GEDCOM_XREF_PTR(parsed_value);
 
-       object = familia_memory_stack_find(xr->string, FS_FAMILY);
-       familia_individual_add_family(parent, object);
+       child = familia_memory_stack_find(xr->string, FS_INDIVIDUAL);
+       familia_individual_set_parents(child, ctxt);
 
-       return parent;
+       return ctxt;
 }
 
 /**
  * Adds child to the family
  */
 Gedcom_ctxt familia_gedcom_family_add_child(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+                                       Gedcom_ctxt ctxt,
                                        int         level,
                                        char*       tag,
                                        char*       raw_value,
                                        int         parsed_tag,
                                        Gedcom_val  parsed_value)
 {
-       void * object = NULL;
+       void * family = NULL;
        /* XREF_PTR(FAM) */
-       struct xref_value *xr = GEDCOM_XREF_PTR(parsed_value);
+       struct xref_value *xr = NULL;
 
-       object = familia_memory_stack_find(xr->string, FS_FAMILY);
-       /* parent: REC_INDI */
-       familia_family_add_child(object, parent);
+       assert(elt == ELT_SUB_FAMC);
+       assert(parsed_tag == TAG_FAMC);
+
+       xr = GEDCOM_XREF_PTR(parsed_value);
+
+       family = familia_memory_stack_find(xr->string, FS_FAMILY);
+       familia_family_add_child(family, ctxt);
 
-       return parent;
+       return ctxt;
 }
 
-/*
-void familia_gedcom_individual_family_end(Gedcom_elt  elt,
-                                       Gedcom_ctxt parent,
+/**
+ * Adds first parent to the family
+ * Parent is the first individual in family. It can be e.g. Husband
+ */
+Gedcom_ctxt familia_gedcom_family_set_parent1(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
+                                       int         level,
+                                       char*       tag,
+                                       char*       raw_value,
+                                       int         parsed_tag,
+                                       Gedcom_val  parsed_value)
+{
+       void * parent = NULL;
+       /* XREF_PTR(INDI) */
+       struct xref_value *xr = NULL;
+
+       assert(elt == ELT_FAM_HUSB);
+       assert(parsed_tag == TAG_HUSB);
+
+       xr = GEDCOM_XREF_PTR(parsed_value);
+
+       parent = familia_memory_stack_find(xr->string, FS_FAMILY);
+       /* ctxt: REC_FAM */
+       familia_family_set_parent(ctxt, parent, Individual1);
+
+       return ctxt;
+}
+
+/**
+ * Adds second parent to the family
+ * Parent is the first individual in family. It can be e.g. Wife
+ */
+Gedcom_ctxt familia_gedcom_family_set_parent2(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
+                                       int         level,
+                                       char*       tag,
+                                       char*       raw_value,
+                                       int         parsed_tag,
+                                       Gedcom_val  parsed_value)
+{
+       void * parent = NULL;
+       /* XREF_PTR(INDI) */
+       struct xref_value *xr = NULL;
+
+       assert(elt == ELT_FAM_WIFE);
+       assert(parsed_tag == TAG_WIFE);
+
+       xr = GEDCOM_XREF_PTR(parsed_value);
+
+       parent = familia_memory_stack_find(xr->string, FS_FAMILY);
+       /* ctxt: REC_FAM */
+       familia_family_set_parent(ctxt, parent, Individual2);
+
+       return ctxt;
+}
+
+/**
+ * Sets date for the current event. Currently supports only individual birth.
+ * TODO: Implement all events.
+ */
+Gedcom_ctxt familia_gedcom_event_set_date(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
+                                       int         level,
+                                       char*       tag,
+                                       char*       raw_value,
+                                       int         parsed_tag,
+                                       Gedcom_val  parsed_value)
+{
+       struct fged_timestampable_ctxt * tctxt = ctxt;
+
+       switch(tctxt->type) {
+       case BIRTH: {
+               struct date_value dv;
+               struct familia_individual * ind = NULL;
+
+               assert(GEDCOM_IS_DATE(parsed_value));
+
+               ind = ((struct fged_ctxt *)ctxt)->object;
+               dv = GEDCOM_DATE(parsed_value);
+
+               familia_individual_set_birth_date(ind, dv);
+               break;
+       }
+       };
+
+       return ctxt;
+}
+Gedcom_ctxt familia_gedcom_timestampable_ctxt_wrap(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
+                                       int         level,
+                                       char*       tag,
+                                       char*       raw_value,
+                                       int         parsed_tag,
+                                       Gedcom_val  parsed_value)
+{
+       struct fged_timestampable_ctxt * tctxt = NULL;
+       tctxt = (struct fged_timestampable_ctxt *)malloc(sizeof(struct fged_timestampable_ctxt));
+       tctxt->ctxt = ctxt;
+       tctxt->type = UNSET;
+       
+       switch(elt) {
+       case ELT_SUB_INDIV_BIRT:
+               tctxt->type = BIRTH;
+               break;
+       }
+       return tctxt;
+}
+
+void familia_gedcom_timestampable_ctxt_unwrap(Gedcom_elt  elt,
+                                       Gedcom_ctxt ctxt,
                                        Gedcom_ctxt self,
                                        Gedcom_val  parsed_value)
 {
-}*/
+       struct fged_timestampable_ctxt * tctxt = NULL;
+
+       tctxt = self;
+
+       self = tctxt->ctxt;
+       free(tctxt);
+}
 
 void familia_gedcom_error (Gedcom_msg_type type, char *msg)
 {
@@ -209,33 +372,30 @@ void familia_gedcom_init()
 {
        gedcom_set_message_handler(familia_gedcom_error);
 
-       gedcom_subscribe_to_record(REC_HEAD,
-                               familia_gedcom_header_start,
-                               familia_gedcom_header_end);
-       gedcom_subscribe_to_element(ELT_HEAD_SOUR,
-                               familia_gedcom_header_source_start,
-                               NULL);
-       gedcom_subscribe_to_element(ELT_HEAD_SOUR_VERS,
-                               familia_gedcom_header_version_start,
-                               NULL);
-       gedcom_subscribe_to_record(REC_FAM,
-                               familia_gedcom_family_start,
-                               NULL);
-       gedcom_subscribe_to_record(REC_INDI,
-                               familia_gedcom_individual_start,
-                               NULL);
-       gedcom_subscribe_to_element(ELT_SUB_PERS_NAME,
-                               familia_gedcom_individual_set_first_name,
-                               NULL);
-       gedcom_subscribe_to_element(ELT_SUB_PERS_NAME_SURN,
-                               familia_gedcom_individual_last_name_start,
-                               NULL);
-       gedcom_subscribe_to_element(ELT_SUB_FAMS,
-                               familia_gedcom_family_add_child,
-                               NULL);
-       gedcom_subscribe_to_element(ELT_SUB_FAMC,
-                               familia_gedcom_family_add_child,
-                               NULL);
+       gedcom_subscribe_to_record(REC_HEAD, familia_gedcom_header_start, familia_gedcom_header_end);
+       /* Create and set family as current (set to ctxt) */
+       gedcom_subscribe_to_record(REC_FAM, familia_gedcom_family_start, familia_gedcom_family_end);
+       /* Create and set individual as current (set to ctxt) */
+       gedcom_subscribe_to_record(REC_INDI, familia_gedcom_individual_start, familia_gedcom_individual_end);
+       gedcom_subscribe_to_element(ELT_HEAD_SOUR, familia_gedcom_header_source_start, NULL);
+       gedcom_subscribe_to_element(ELT_HEAD_SOUR_VERS, familia_gedcom_header_version_start, NULL);
+       /* Set in current individual first name */
+       gedcom_subscribe_to_element(ELT_SUB_PERS_NAME, familia_gedcom_individual_set_first_name, NULL);
+       /* Set in current individual last name */
+       gedcom_subscribe_to_element(ELT_SUB_PERS_NAME_SURN, familia_gedcom_individual_last_name_start, NULL);
+       /* Add to current individual new family */
+       gedcom_subscribe_to_element(ELT_SUB_FAMS, familia_gedcom_individual_add_family, NULL);
+       /* Set current family as parents to child */
+       gedcom_subscribe_to_element(ELT_FAM_CHIL, familia_gedcom_individual_set_parents, NULL);
+       /* Set current individual new parents */
+       gedcom_subscribe_to_element(ELT_SUB_FAMC, familia_gedcom_family_add_child, NULL);
+       /* Set in current family first parent (e.g. husband) */
+       gedcom_subscribe_to_element(ELT_FAM_HUSB, familia_gedcom_family_set_parent1, NULL);
+       /* Set in current family second parent (e.g. wife) */
+       gedcom_subscribe_to_element(ELT_FAM_WIFE, familia_gedcom_family_set_parent2, NULL);
+       
+       gedcom_subscribe_to_element(ELT_SUB_EVT_DATE, familia_gedcom_event_set_date, NULL);
+       gedcom_subscribe_to_element(ELT_SUB_INDIV_BIRT, familia_gedcom_timestampable_ctxt_wrap, familia_gedcom_timestampable_ctxt_unwrap);
 
        familia_memory_stack_init();
 }