Functions for moving an xref in a list.
[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 unref_xref_value(struct xref_value *xref)
83 {
84   if (xref)
85     gedcom_unlink_xref(xref->type, xref->string);
86 }
87
88 void UNREFALLFUNC(xref_list)(struct xref_list* obj)
89 {
90   if (obj) {
91     struct xref_list* runner;
92     for (runner = obj; runner; runner = runner->next) {
93       unref_xref_value(runner->xref);
94       UNREFALLFUNC(user_data)(runner->extra);
95     }
96   }
97 }
98
99 void CLEANFUNC(xref_list)(struct xref_list *obj)
100 {
101   if (obj) {
102     DESTROY_CHAIN_ELTS(user_data, obj->extra);
103   }
104 }
105
106 struct xref_value* gom_set_xref(struct xref_value** data, const char* xref)
107 {
108   struct xref_value* result = NULL;
109   struct xref_value* newval = NULL;
110   
111   if (data) {
112     if (xref) {
113       newval = gedcom_get_by_xref(xref);
114       if (!newval)
115         gedcom_error(_("No record found for xref '%s'"), xref);
116     }
117     
118     /* Unreference the old value if not NULL */
119     if (*data)
120       result = gedcom_unlink_xref((*data)->type, (*data)->string);
121     else
122       result = newval;
123     
124     /* Reference the new value if not NULL */
125     if (result != NULL && newval) {
126       result = gedcom_link_xref(newval->type, newval->string);
127       /* On error, perform rollback to old value (guaranteed to work) */
128       if (result == NULL)
129         gedcom_link_xref((*data)->type, (*data)->string);
130     }
131     
132     if (result != NULL) {
133       *data = newval;
134       result = newval;
135     }
136   }
137   return result;
138 }
139
140 struct xref_list* gom_add_xref(struct xref_list** data, const char* xref)
141 {
142   struct xref_value* result = NULL;
143   struct xref_value* newval = NULL;
144   struct xref_list* xrl = NULL;
145
146   if (data && xref) {
147     newval = gedcom_get_by_xref(xref);
148     if (!newval)
149       gedcom_error(_("No record found for xref '%s'"), xref);
150     else {
151       result = gedcom_link_xref(newval->type, newval->string);
152       if (result != NULL) {
153         MAKE_CHAIN_ELT(xref_list, *data, xrl);
154         if (xrl) xrl->xref = newval;
155       }
156     }
157   }
158
159   return xrl;
160 }
161
162 struct xref_list* find_xref(struct xref_list** data, const char* xref)
163 {
164   struct xref_list* result = NULL;
165   struct xref_value* xr = gedcom_get_by_xref(xref);
166   if (!xr)
167     gedcom_error(_("No record found for xref '%s'"), xref);
168   else {
169     struct xref_list* xrl;
170     for (xrl = *data ; xrl ; xrl = xrl->next) {
171       if (xrl->xref == xr) {
172         result = xrl;
173         break;
174       }
175     }
176     if (! result)
177       gedcom_error(_("Xref '%s' not part of chain"), xref);
178   }
179   return result;
180 }
181
182 int gom_remove_xref(struct xref_list** data, const char* xref)
183 {
184   int result = 1;
185
186   if (data && xref) {
187     struct xref_list* xrl = find_xref(data, xref);
188     if (xrl) {
189       UNLINK_CHAIN_ELT(xref_list, *data, xrl);
190       gedcom_unlink_xref(xrl->xref->type, xrl->xref->string);
191       CLEANFUNC(xref_list)(xrl);
192       SAFE_FREE(xrl);
193       result = 0;
194     }
195   }
196
197   return result;
198 }
199
200 int gom_move_xref(Gom_direction dir, struct xref_list** data, const char* xref)
201 {
202   int result = 1;
203
204   if (data && xref) {
205     struct xref_list* xrl = find_xref(data, xref);
206     if (xrl) {
207       MOVE_CHAIN_ELT(xref_list, dir, *data, xrl);
208       result = 0;
209     }
210   }
211
212   return result;
213 }