Allow elements out of context in GOM.
[gedcom-parse.git] / gom / change_date.c
index 0e568691afe2401b5e45630a3c4533a5b7a53e49..605039d8d2b28ea7f0f460c0beef51c660ce123a 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include "change_date.h"
 #include "family.h"
 #include "individual.h"
@@ -45,14 +46,10 @@ Gedcom_ctxt sub_chan_start(_ELT_PARAMS_)
   if (! ctxt)
     NO_CONTEXT;
   else {
-    struct change_date *chan
-      = (struct change_date *)malloc(sizeof(struct change_date));
-    if (! chan)
-      MEMORY_ERROR;
-    else {
-      memset (chan, 0, sizeof(struct change_date));
-      
-      switch (ctxt->ctxt_type) {
+    struct change_date *chan = SUB_MAKEFUNC(change_date)();
+    if (chan) {
+      int type = ctxt_type(ctxt);
+      switch (type) {
        case REC_FAM:
          ADDFUNC2_NOLIST(family,change_date)(ctxt, chan); break;
        case REC_INDI:
@@ -68,7 +65,7 @@ Gedcom_ctxt sub_chan_start(_ELT_PARAMS_)
        case REC_SUBM:
          ADDFUNC2_NOLIST(submitter,change_date)(ctxt, chan); break;
        default:
-         UNEXPECTED_CONTEXT(ctxt->ctxt_type);
+         UNEXPECTED_CONTEXT(type);
       }
       result = MAKE_GOM_CTXT(elt, change_date, chan);
     }
@@ -77,6 +74,10 @@ Gedcom_ctxt sub_chan_start(_ELT_PARAMS_)
   return (Gedcom_ctxt)result;
 }
 
+DEFINE_SUB_MAKEFUNC(change_date)
+DEFINE_SUB_SETFUNC(change_date)
+DEFINE_SUB_DELETEFUNC(change_date)
+
 DEFINE_DATE_CB(change_date, sub_chan_date_start, date)
 DEFINE_STRING_CB(change_date, sub_chan_time_start, time)
 
@@ -92,6 +93,14 @@ void change_date_subscribe()
                              def_elt_end);
 }
 
+void UNREFALLFUNC(change_date)(struct change_date* obj)
+{
+  if (obj) {
+    UNREFALLFUNC(note_sub)(obj->note);
+    UNREFALLFUNC(user_data)(obj->extra);
+  }
+}
+
 void CLEANFUNC(change_date)(struct change_date *chan)
 {
   if (chan) {
@@ -103,6 +112,51 @@ void CLEANFUNC(change_date)(struct change_date *chan)
   SAFE_FREE(chan);
 }
 
+int update_date(struct date_value** dv, struct tm* tm_ptr)
+{
+  int result;
+  struct date_value* dval = gedcom_new_date_value(NULL);
+  dval->type        = DV_NO_MODIFIER;
+  dval->date1.cal   = CAL_GREGORIAN;
+  dval->date1.day   = tm_ptr->tm_mday;
+  dval->date1.month = tm_ptr->tm_mon + 1;
+  dval->date1.year  = tm_ptr->tm_year + 1900;
+  result = gedcom_normalize_date(DI_FROM_NUMBERS, dval);
+
+  if (result == 0) {
+    if (*dv) free(*dv);
+    *dv = dval;
+  }
+  return result;
+}
+
+int update_time(char** tv, struct tm* tm_ptr)
+{
+  char tval[16];
+  sprintf(tval, "%02d:%02d:%02d",
+         tm_ptr->tm_hour, tm_ptr->tm_min, tm_ptr->tm_sec);
+
+  if (gom_set_string(tv, tval))
+    return 0;
+  else
+    return 1;
+}
+
+int gom_update_timestamp(struct change_date** chan, time_t t)
+{
+  int result = 1;
+  if (chan) {
+    if (! *chan) gom_set_new_change_date(chan);
+    if (*chan) {
+      struct tm *tm_ptr = localtime(&t);
+      result = 0;
+      result |= update_date(&((*chan)->date), tm_ptr);
+      result |= update_time(&((*chan)->time), tm_ptr);
+    }
+  }
+  return result;
+}
+
 int write_change_date(Gedcom_write_hndl hndl, int parent,
                      struct change_date *chan)
 {