Reworked the xref functions.
[gedcom-parse.git] / gom / gom_modify.c
1 /* Source code for modifying 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 "utf8tools.h"
27 #include "user_rec.h"
28 #include "gom.h"
29 #include "gom_internal.h"
30
31 void gom_set_unknown(const char* unknown)
32 {
33   convert_set_unknown(unknown);
34 }
35
36 char* gom_get_string(char* data)
37 {
38   return data;
39 }
40
41 char* gom_get_string_for_locale(char* data, int* conversion_failures)
42 {
43   return convert_utf8_to_locale(gom_get_string(data), conversion_failures);
44 }
45
46 char* gom_set_string(char** data, const char* utf8_str)
47 {
48   char* result = NULL;
49   char* newptr;
50
51   if (!is_utf8_string(utf8_str)) {
52     gedcom_error(_("The input '%s' is not a valid UTF-8 string"), utf8_str);
53   }
54   else {
55     newptr = strdup(utf8_str);
56     if (!newptr)
57       MEMORY_ERROR;
58     else {
59       if (*data) free(*data);
60       *data = newptr;
61       result = *data;
62     }
63   }
64   
65   return result;
66 }
67
68 char* gom_set_string_for_locale(char** data, const char* locale_str)
69 {
70   char* result = NULL;
71   char* utf8_str = convert_locale_to_utf8(locale_str);
72   
73   if (!utf8_str)
74     gedcom_error(_("The input '%s' is not a valid string for the locale"),
75                  locale_str);
76   else
77     result = gom_set_string(data, utf8_str);
78
79   return result;
80 }
81
82 void CLEANFUNC(xref_list)(struct xref_list *obj)
83 {
84   if (obj) {
85     DESTROY_CHAIN_ELTS(user_data, obj->extra);
86   }
87 }
88
89 struct xref_value* gom_set_xref(struct xref_value** data, const char* xref)
90 {
91   struct xref_value* result = NULL;
92   struct xref_value* newval = NULL;
93   
94   if (data) {
95     if (xref) {
96       newval = gedcom_get_by_xref(xref);
97       if (!newval)
98         gedcom_error(_("No record found for xref '%s'"), xref);
99     }
100     
101     /* Unreference the old value if not NULL */
102     if (*data)
103       result = gedcom_unlink_xref((*data)->type, (*data)->string);
104     else
105       result = newval;
106     
107     /* Reference the new value if not NULL */
108     if (result != NULL && newval) {
109       result = gedcom_link_xref(newval->type, newval->string);
110       /* On error, perform rollback to old value (guaranteed to work) */
111       if (result == NULL)
112         gedcom_link_xref((*data)->type, (*data)->string);
113     }
114     
115     if (result != NULL) {
116       *data = newval;
117       result = newval;
118     }
119   }
120   return result;
121 }
122
123 struct xref_list* gom_add_xref(struct xref_list** data, const char* xref)
124 {
125   struct xref_value* result = NULL;
126   struct xref_value* newval = NULL;
127   struct xref_list* xrl = NULL;
128
129   if (data && xref) {
130     newval = gedcom_get_by_xref(xref);
131     if (!newval)
132       gedcom_error(_("No record found for xref '%s'"), xref);
133     else {
134       result = gedcom_link_xref(newval->type, newval->string);
135       if (result != NULL) {
136         MAKE_CHAIN_ELT(xref_list, *data, xrl);
137         if (xrl) xrl->xref = newval;
138       }
139     }
140   }
141
142   return xrl;
143 }
144
145 int gom_remove_xref(struct xref_list** data, const char* xref)
146 {
147   struct xref_value* xr = NULL;
148   int result = 1;
149   
150   if (data && xref) {
151     xr = gedcom_get_by_xref(xref);
152     if (!xr)
153       gedcom_error(_("No record found for xref '%s'"), xref);
154     else {
155       struct xref_list* xrl = NULL;
156       for (xrl = *data ; xrl ; xrl = xrl->next) {
157         if (xrl->xref == xr) {
158           UNLINK_CHAIN_ELT(xref_list, *data, xrl);
159           gedcom_unlink_xref(xr->type, xr->string);
160           CLEANFUNC(xref_list)(xrl);
161           SAFE_FREE(xrl);
162           result = 0;
163           break;
164         }
165       }
166       if (result == 1)
167         gedcom_error(_("Xref '%s' to remove not part of chain"), xref);
168     }
169   }
170
171   return result;
172 }