X-Git-Url: https://git.dlugolecki.net.pl/?a=blobdiff_plain;ds=sidebyside;f=gedcom%2Fwrite.c;h=f04697e6fb03ed4e56fcdaf2b6010937483daa45;hb=70346270bff0a6eab3fc61edb4c5cf06a956dd23;hp=7554b560ea7832163748df254fd4926ffec76a9f;hpb=58c7f618a6964a7fa5fc95c67f13f0a52689a29a;p=gedcom-parse.git
diff --git a/gedcom/write.c b/gedcom/write.c
index 7554b56..f04697e 100644
--- a/gedcom/write.c
+++ b/gedcom/write.c
@@ -24,6 +24,7 @@
#include "gedcom_internal.h"
#include "gedcom.h"
#include "encoding.h"
+#include "encoding_state.h"
#include "tag_data.h"
#include "buffer.h"
#include "utf8tools.h"
@@ -34,12 +35,6 @@
#define MAXWRITELEN MAXGEDCLINELEN
-/* SYS_NEWLINE is defined in config.h */
-struct encoding_state write_encoding =
-{ "ASCII", "ASCII", ONE_BYTE, WITHOUT_BOM, SYS_NEWLINE };
-Enc_from write_encoding_from = ENC_FROM_FILE;
-Enc_from write_terminator_from = ENC_FROM_SYS;
-
struct Gedcom_write_struct {
int filedesc;
convert_t conv;
@@ -49,19 +44,6 @@ struct Gedcom_write_struct {
int ctxt_level;
};
-const char* default_encoding[] = {
- /* ONE_BYTE */ "ASCII",
- /* TWO_BYTE_HILO */ "UCS-2BE",
- /* TWO_BYTE_LOHI */ "UCS-2LE"
-};
-
-const char* terminator[] = {
- /* END_CR */ "\x0D",
- /* END_LF */ "\x0A",
- /* END_CR_LF */ "\x0D\x0A",
- /* END_LF_CR */ "\x0A\x0D"
-};
-
void cleanup_write_buffer();
struct safe_buffer write_buffer = { NULL, 0, NULL, 0, cleanup_write_buffer };
@@ -122,7 +104,8 @@ int write_simple(Gedcom_write_hndl hndl,
}
int write_encoding_value(Gedcom_write_hndl hndl,
- int level, char* xref, char* tag, char* value)
+ int level, const char* xref, const char* tag,
+ const char* value)
{
if (strcmp(value, write_encoding.charset))
gedcom_warning(_("Forcing HEAD.CHAR value to '%s'"),
@@ -171,8 +154,13 @@ int write_long(Gedcom_write_hndl hndl, int elt_or_rec,
if (prefix_len + line_len + term_len > MAXWRITELEN) {
line_len = MAXWRITELEN - prefix_len - term_len;
- if (!cont_as_conc)
+ if (!cont_as_conc) {
cont_tag = "CONC";
+ while (value_ptr[line_len] == ' '
+ || value_ptr[line_len-1] == ' ') {
+ line_len--;
+ }
+ }
}
memset(value_part, 0, sizeof(value_part));
@@ -182,7 +170,7 @@ int write_long(Gedcom_write_hndl hndl, int elt_or_rec,
if (line_len < value_len) {
value_ptr = value_ptr + line_len;
value_len = value_len - line_len;
- while (*value_ptr == '\n') {
+ if (*value_ptr == '\n') {
value_ptr++;
value_len--;
}
@@ -201,80 +189,13 @@ int write_long(Gedcom_write_hndl hndl, int elt_or_rec,
return 0;
}
-int gedcom_write_set_encoding(Enc_from from, const char* new_charset,
- Encoding width, Enc_bom bom)
-{
- char* new_encoding = NULL;
- if (from == ENC_FROM_SYS) {
- return 1;
- }
- write_encoding_from = from;
- if (from == ENC_MANUAL) {
- if (!strcmp(new_charset, "UNICODE")) {
- if (width == ONE_BYTE) {
- gedcom_error(_("Unicode cannot be encoded into one byte"));
- return 1;
- }
- else {
- new_encoding = get_encoding(new_charset, width);
- if (new_encoding) {
- write_encoding.encoding = new_encoding;
- write_encoding.width = width;
- write_encoding.bom = bom;
- strncpy(write_encoding.charset, new_charset, MAX_CHARSET_LEN);
- }
- else
- return 1;
- }
- }
- else {
- new_encoding = get_encoding(new_charset, ONE_BYTE);
- if (new_encoding) {
- write_encoding.encoding = new_encoding;
- write_encoding.width = ONE_BYTE;
- write_encoding.bom = bom;
- strncpy(write_encoding.charset, new_charset, MAX_CHARSET_LEN);
- }
- else
- return 1;
- }
- }
- return 0;
-}
-
-void copy_write_encoding_from_file()
-{
- if (read_encoding.charset[0] != '\0') {
- strncpy(write_encoding.charset, read_encoding.charset, MAX_CHARSET_LEN);
- write_encoding.encoding = read_encoding.encoding;
- write_encoding.width = read_encoding.width;
- write_encoding.bom = read_encoding.bom;
- }
-}
-
-int gedcom_write_set_line_terminator(Enc_from from, Enc_line_end end)
-{
- const char* new_term = NULL;
- write_terminator_from = from;
- if (from == ENC_FROM_SYS) {
- new_term = SYS_NEWLINE;
- }
- else if (from == ENC_MANUAL) {
- new_term = terminator[end];
- }
- if (new_term)
- strncpy(write_encoding.terminator, new_term, MAX_TERMINATOR_LEN);
- return 0;
-}
+/** The basic function for opening a GEDCOM file for writing.
-void copy_write_terminator_from_file()
-{
- if (read_encoding.terminator[0] != '\0') {
- strncpy(write_encoding.terminator, read_encoding.terminator,
- MAX_TERMINATOR_LEN);
- }
-}
+ \param filename The name of the file to write
+ \return A write handle, which needs to be used in the writing functions,
+ or \c NULL in case of errors.
+ */
Gedcom_write_hndl gedcom_write_open(const char *filename)
{
Gedcom_write_hndl hndl;
@@ -284,10 +205,8 @@ Gedcom_write_hndl gedcom_write_open(const char *filename)
if (!hndl)
MEMORY_ERROR;
else {
- if (write_encoding_from == ENC_FROM_FILE)
- copy_write_encoding_from_file();
- if (write_terminator_from == ENC_FROM_FILE)
- copy_write_terminator_from_file();
+ init_write_encoding();
+ init_write_terminator();
hndl->total_conv_fails = 0;
hndl->conv = initialize_utf8_conversion(write_encoding.encoding, 0);
if (!hndl->conv) {
@@ -325,6 +244,16 @@ Gedcom_write_hndl gedcom_write_open(const char *filename)
return hndl;
}
+/** The basic function for closing a GEDCOM file for writing.
+
+ \param hndl The write handle as returned by gedcom_write_open().
+ \param total_conv_fails If you pass an actual integer pointer for this,
+ the function will write in it the total number of conversion failures;
+ you can pass \c NULL if you're not interested
+
+ \retval 0 in case of success
+ \retval >0 in case of failure.
+ */
int gedcom_write_close(Gedcom_write_hndl hndl, int* total_conv_fails)
{
int result = 0;
@@ -415,7 +344,7 @@ char* convert_at(const char* input)
int _gedcom_write_val(Gedcom_write_hndl hndl,
int rec_or_elt, int tag, int parent_rec_or_elt,
- char* xrefstr, char* val)
+ const char* xrefstr, const char* val)
{
int result = 1;
int level = 0;
@@ -435,8 +364,24 @@ int _gedcom_write_val(Gedcom_write_hndl hndl,
return result;
}
+/** Function for writing lines corresponding to standard records (i.e. on
+ level 0).
+
+ \param hndl The write handle that was returned by gedcom_write_open().
+ \param rec One of the identifiers given in the first column in
+ this table (except REC_USER).
+ \param xrefstr The cross-reference key of the record (something like
+ \c "@FAM01@".
+ \param val The value of the record line, which should be \c NULL for some
+ record types, according to
+ this table.
+
+ \retval 0 on success
+ \retval >0 on failure
+*/
int gedcom_write_record_str(Gedcom_write_hndl hndl,
- Gedcom_rec rec, char* xrefstr, char* val)
+ Gedcom_rec rec, const char* xrefstr,
+ const char* val)
{
int result = 1;
if (check_type(rec, (val ? GV_CHAR_PTR : GV_NULL)))
@@ -444,9 +389,34 @@ int gedcom_write_record_str(Gedcom_write_hndl hndl,
return result;
}
+/** Function for writing lines corresponding to standard elements (i.e. on
+ level bigger than 0), with a string as value.
+
+ \param hndl The write handle that was returned by gedcom_write_open().
+ \param elt One of the identifiers given in the first column in
+ this table
+ (except ELT_USER).
+ \param tag Some of the \c elt identifiers can actually stand for different
+ tags. For this reason, the \c tag has to be passed for some of them. This
+ parsed tag is the same as was returned by the callback functions, and is
+ an identifier of the form TAG_name
. This parameter
+ is needed whenever the second column in
+ this table shows several
+ possible tags (this is e.g. the case for \c ELT_SUB_FAM_EVT). Otherwise,
+ you can pass 0.
+ \param parent_rec_or_elt The corresponding \c rec or \c elt identifier of
+ the logically enclosing statement: this will determine the level number
+ written on the line, as the level number of the parent + 1.
+ \param val The value of the element line, which should be \c NULL for some
+ element types, according to
+ this table.
+
+ \retval 0 on success
+ \retval >0 on failure
+*/
int gedcom_write_element_str(Gedcom_write_hndl hndl,
Gedcom_elt elt, int tag, int parent_rec_or_elt,
- char* val)
+ const char* val)
{
int result = 1;
if (check_type(elt, (val ? GV_CHAR_PTR : GV_NULL)))
@@ -455,9 +425,14 @@ int gedcom_write_element_str(Gedcom_write_hndl hndl,
return result;
}
+/** Function for writing lines corresponding to standard elements (i.e. on
+ level bigger than 0), with a cross-reference as value.
+
+ See gedcom_write_element_str() for details.
+*/
int gedcom_write_element_xref(Gedcom_write_hndl hndl,
Gedcom_elt elt, int tag, int parent_rec_or_elt,
- struct xref_value* val)
+ const struct xref_value* val)
{
int result = 1;
if (check_type(elt, (val ? GV_XREF_PTR : GV_NULL)))
@@ -466,9 +441,14 @@ int gedcom_write_element_xref(Gedcom_write_hndl hndl,
return result;
}
+/** Function for writing lines corresponding to standard elements (i.e. on
+ level bigger than 0), with a date as value.
+
+ See gedcom_write_element_str() for details.
+*/
int gedcom_write_element_date(Gedcom_write_hndl hndl,
Gedcom_elt elt, int tag, int parent_rec_or_elt,
- struct date_value* val)
+ const struct date_value* val)
{
int result = 1;
if (check_type(elt, (val ? GV_DATE_VALUE : GV_NULL)))
@@ -477,9 +457,14 @@ int gedcom_write_element_date(Gedcom_write_hndl hndl,
return result;
}
+/** Function for writing lines corresponding to standard elements (i.e. on
+ level bigger than 0), with an age as value.
+
+ See gedcom_write_element_str() for details.
+*/
int gedcom_write_element_age(Gedcom_write_hndl hndl,
Gedcom_elt elt, int tag, int parent_rec_or_elt,
- struct age_value* val)
+ const struct age_value* val)
{
int result = 1;
if (check_type(elt, (val ? GV_AGE_VALUE : GV_NULL)))
@@ -488,8 +473,25 @@ int gedcom_write_element_age(Gedcom_write_hndl hndl,
return result;
}
-int gedcom_write_user_str(Gedcom_write_hndl hndl, int level, char* tag,
- char* xrefstr, char* value)
+/** Function for writing lines corresponding to user-defined records and
+ elements, with a string as value.
+
+ In the case of user-defined tags, the
+ level and tag string are passed verbatim (not controlled by the library).
+ This allows to write any extra data that doesn't use a standard tag, but
+ is only allowed for tags starting with an underscore.
+
+ \param hndl The write handle that was returned by gedcom_write_open().
+ \param level The integer level of the GEDCOM line
+ \param tag The tag, as a literal string
+ \param xrefstr An optional cross-reference of the record or element.
+ \param value The value of the record or element line.
+
+ \retval 0 on success
+ \retval >0 on failure
+*/
+int gedcom_write_user_str(Gedcom_write_hndl hndl, int level, const char* tag,
+ const char* xrefstr, const char* value)
{
int result = 1;
if (tag && tag[0] == '_')
@@ -497,8 +499,13 @@ int gedcom_write_user_str(Gedcom_write_hndl hndl, int level, char* tag,
return result;
}
-int gedcom_write_user_xref(Gedcom_write_hndl hndl, int level, char* tag,
- char* xrefstr, struct xref_value* val)
+/** Function for writing lines corresponding to user-defined records and
+ elements, with a cross-reference as value.
+
+ See gedcom_write_user_str() for details.
+*/
+int gedcom_write_user_xref(Gedcom_write_hndl hndl, int level, const char* tag,
+ const char* xrefstr, const struct xref_value* val)
{
int result = 1;
if (tag && tag[0] == '_')