diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index adeac9735dde19f67ec8009535f16f16e5642f97..b1320a4a399d9eb54fc06671da6cb5b779d6e431 100644 (file)
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
#include <string>
#include <stdexcept>
+#include <libxml/parser.h>
+
#include "xml/repr.h"
#include "xml/attribute-record.h"
+#include "xml/rebase-hrefs.h"
#include "xml/simple-document.h"
#include "io/sys.h"
using Inkscape::XML::SimpleDocument;
using Inkscape::XML::Node;
using Inkscape::XML::AttributeRecord;
+using Inkscape::XML::calc_abs_doc_base;
+using Inkscape::XML::rebase_href_attrs;
Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns);
static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, GHashTable *prefix_map);
static gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar *default_ns, GHashTable *prefix_map);
-static void sp_repr_write_stream_root_element (Node *repr, Writer &out, bool add_whitespace, gchar const *default_ns, int inlineattrs, int indent);
-static void sp_repr_write_stream_element (Node *repr, Writer &out, gint indent_level, bool add_whitespace, Glib::QueryQuark elide_prefix, List<AttributeRecord const> attributes, int inlineattrs, int indent);
+static void sp_repr_write_stream_root_element(Node *repr, Writer &out,
+ bool add_whitespace, gchar const *default_ns,
+ int inlineattrs, int indent,
+ gchar const *old_href_abs_base,
+ gchar const *new_href_abs_base);
+static void sp_repr_write_stream_element(Node *repr, Writer &out,
+ gint indent_level, bool add_whitespace,
+ Glib::QueryQuark elide_prefix,
+ List<AttributeRecord const> attributes,
+ int inlineattrs, int indent,
+ gchar const *old_href_abs_base,
+ gchar const *new_href_abs_base);
#ifdef HAVE_LIBWMF
static xmlDocPtr sp_wmf_convert (const char * file_name);
&src,
localFilename,
src.getEncoding(),
- XML_PARSE_NOENT );
+ XML_PARSE_NOENT | XML_PARSE_HUGE);
}
}
@@ -528,9 +543,11 @@ sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_
}
-void
+static void
sp_repr_save_writer(Document *doc, Inkscape::IO::Writer *out,
- gchar const *default_ns)
+ gchar const *default_ns,
+ gchar const *old_href_abs_base,
+ gchar const *new_href_abs_base)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool inlineattrs = prefs->getBool("/options/svgoutput/inlineattrs");
out->writeString( str );
}
- Node *repr = sp_repr_document_first_child(doc);
- for ( repr = sp_repr_document_first_child(doc) ;
- repr ; repr = sp_repr_next(repr) )
+ for (Node *repr = sp_repr_document_first_child(doc);
+ repr; repr = sp_repr_next(repr))
{
- if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) {
- sp_repr_write_stream_root_element(repr, *out, TRUE, default_ns, inlineattrs, indent);
- } else if ( repr->type() == Inkscape::XML::COMMENT_NODE ) {
- sp_repr_write_stream(repr, *out, 0, TRUE, GQuark(0), inlineattrs, indent);
- out->writeChar( '\n' );
+ Inkscape::XML::NodeType const node_type = repr->type();
+ if ( node_type == Inkscape::XML::ELEMENT_NODE ) {
+ sp_repr_write_stream_root_element(repr, *out, TRUE, default_ns, inlineattrs, indent,
+ old_href_abs_base, new_href_abs_base);
} else {
- sp_repr_write_stream(repr, *out, 0, TRUE, GQuark(0), inlineattrs, indent);
+ sp_repr_write_stream(repr, *out, 0, TRUE, GQuark(0), inlineattrs, indent,
+ old_href_abs_base, new_href_abs_base);
+ if ( node_type == Inkscape::XML::COMMENT_NODE ) {
+ out->writeChar('\n');
+ }
}
}
}
Inkscape::IO::StringOutputStream souts;
Inkscape::IO::OutputStreamWriter outs(souts);
- sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI);
+ sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI, 0, 0);
outs.close();
Glib::ustring buf = souts.getString();
void
-sp_repr_save_stream (Document *doc, FILE *fp, gchar const *default_ns, bool compress)
+sp_repr_save_stream(Document *doc, FILE *fp, gchar const *default_ns, bool compress,
+ gchar const *const old_href_abs_base,
+ gchar const *const new_href_abs_base)
{
Inkscape::URI dummy("x");
Inkscape::IO::UriOutputStream bout(fp, dummy);
Inkscape::IO::GzipOutputStream *gout = compress ? new Inkscape::IO::GzipOutputStream(bout) : NULL;
Inkscape::IO::OutputStreamWriter *out = compress ? new Inkscape::IO::OutputStreamWriter( *gout ) : new Inkscape::IO::OutputStreamWriter( bout );
- sp_repr_save_writer(doc, out, default_ns);
-
+ sp_repr_save_writer(doc, out, default_ns, old_href_abs_base, new_href_abs_base);
+
delete out;
delete gout;
}
-/* Returns TRUE if file successfully saved; FALSE if not
+/**
+ * Returns true iff file successfully saved.
+ *
+ * \param filename The actual file to do I/O to, which might be a temp file.
+ *
+ * \param for_filename The base URI [actually filename] to assume for purposes of rewriting
+ * xlink:href attributes.
*/
bool
-sp_repr_save_file (Document *doc, gchar const *filename,
- gchar const *default_ns)
+sp_repr_save_rebased_file(Document *doc, gchar const *const filename, gchar const *default_ns,
+ gchar const *old_base, gchar const *for_filename)
{
- if (filename == NULL) {
- return FALSE;
+ if (!filename) {
+ return false;
}
bool compress;
Inkscape::IO::dump_fopen_call( filename, "B" );
FILE *file = Inkscape::IO::fopen_utf8name(filename, "w");
if (file == NULL) {
- return FALSE;
+ return false;
+ }
+
+ gchar *old_href_abs_base = NULL;
+ gchar *new_href_abs_base = NULL;
+ if (for_filename) {
+ old_href_abs_base = calc_abs_doc_base(old_base);
+ if (g_path_is_absolute(for_filename)) {
+ new_href_abs_base = g_path_get_dirname(for_filename);
+ } else {
+ gchar *const cwd = g_get_current_dir();
+ gchar *const for_abs_filename = g_build_filename(cwd, for_filename, NULL);
+ g_free(cwd);
+ new_href_abs_base = g_path_get_dirname(for_abs_filename);
+ g_free(for_abs_filename);
+ }
+
+ /* effic: Once we're confident that we never need (or never want) to resort
+ * to using sodipodi:absref instead of the xlink:href value,
+ * then we should do `if streq() { free them and set both to NULL; }'. */
}
+ sp_repr_save_stream(doc, file, default_ns, compress, old_href_abs_base, new_href_abs_base);
- sp_repr_save_stream (doc, file, default_ns, compress);
+ g_free(old_href_abs_base);
+ g_free(new_href_abs_base);
if (fclose (file) != 0) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
+/**
+ * Returns true iff file successfully saved.
+ */
+bool
+sp_repr_save_file(Document *doc, gchar const *const filename, gchar const *default_ns)
+{
+ return sp_repr_save_rebased_file(doc, filename, default_ns, NULL, NULL);
+}
+
+
/* (No doubt this function already exists elsewhere.) */
static void
repr_quote_write (Writer &out, const gchar * val)
}
-void
-sp_repr_write_stream_root_element (Node *repr, Writer &out, bool add_whitespace, gchar const *default_ns,
- int inlineattrs, int indent)
+static void
+sp_repr_write_stream_root_element(Node *repr, Writer &out,
+ bool add_whitespace, gchar const *default_ns,
+ int inlineattrs, int indent,
+ gchar const *const old_href_base,
+ gchar const *const new_href_base)
{
using Inkscape::Util::ptr_shared;
+
g_assert(repr != NULL);
Glib::QueryQuark xml_prefix=g_quark_from_static_string("xml");
@@ -777,11 +839,15 @@ sp_repr_write_stream_root_element (Node *repr, Writer &out, bool add_whitespace,
}
}
- return sp_repr_write_stream_element(repr, out, 0, add_whitespace, elide_prefix, attributes, inlineattrs, indent);
+ return sp_repr_write_stream_element(repr, out, 0, add_whitespace, elide_prefix, attributes,
+ inlineattrs, indent, old_href_base, new_href_base);
}
void sp_repr_write_stream( Node *repr, Writer &out, gint indent_level,
- bool add_whitespace, Glib::QueryQuark elide_prefix, int inlineattrs, int indent)
+ bool add_whitespace, Glib::QueryQuark elide_prefix,
+ int inlineattrs, int indent,
+ gchar const *const old_href_base,
+ gchar const *const new_href_base)
{
switch (repr->type()) {
case Inkscape::XML::TEXT_NODE: {
case Inkscape::XML::ELEMENT_NODE: {
sp_repr_write_stream_element( repr, out, indent_level,
add_whitespace, elide_prefix,
- repr->attributeList(), inlineattrs, indent);
+ repr->attributeList(),
+ inlineattrs, indent,
+ old_href_base, new_href_base);
break;
}
case Inkscape::XML::DOCUMENT_NODE: {
}
-void
+static void
sp_repr_write_stream_element (Node * repr, Writer & out, gint indent_level,
bool add_whitespace,
Glib::QueryQuark elide_prefix,
List<AttributeRecord const> attributes,
- int inlineattrs, int indent)
+ int inlineattrs, int indent,
+ gchar const *const old_href_base,
+ gchar const *const new_href_base)
{
Node *child;
bool loose;
// for its content and children:
gchar const *xml_space_attr = repr->attribute("xml:space");
if (xml_space_attr != NULL && !strcmp(xml_space_attr, "preserve")) {
- add_whitespace = FALSE;
+ add_whitespace = false;
}
- for ( List<AttributeRecord const> iter = attributes ;
+ for ( List<AttributeRecord const> iter = rebase_href_attrs(old_href_base, new_href_base,
+ attributes);
iter ; ++iter )
{
if (!inlineattrs) {
out.writeString( "\n" );
}
for (child = repr->firstChild(); child != NULL; child = child->next()) {
- sp_repr_write_stream (child, out, (loose) ? (indent_level + 1) : 0, add_whitespace, elide_prefix, inlineattrs, indent);
+ sp_repr_write_stream(child, out, ( loose ? indent_level + 1 : 0 ),
+ add_whitespace, elide_prefix, inlineattrs, indent,
+ old_href_base, new_href_base);
}
if (loose && add_whitespace && indent) {
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :