[gnumeric] xlsx: import external links with anchors right.



commit c443ca290cc11786405de9c7f3d1d2286d153b10
Author: Morten Welinder <terra gnome org>
Date:   Wed Mar 8 13:43:27 2017 -0500

    xlsx: import external links with anchors right.

 plugins/excel/ChangeLog    |    5 +++++
 plugins/excel/xlsx-read.c  |   31 +++++++++++++++++++------------
 plugins/excel/xlsx-write.c |   20 +++++++++++++-------
 3 files changed, 37 insertions(+), 19 deletions(-)
---
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index ba9f319..5727c7f 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-08  Morten Welinder  <terra gnome org>
+
+       * xlsx-read.c (xlsx_CT_HyperLinks): Handle external links with
+       anchors.
+
 2017-02-28  Jean Brefort  <jean brefort normalesup org>
 
        * xlsx-write-drawing.c (xlsx_write_go_style_full): do not export
diff --git a/plugins/excel/xlsx-read.c b/plugins/excel/xlsx-read.c
index c148503..a33eae4 100644
--- a/plugins/excel/xlsx-read.c
+++ b/plugins/excel/xlsx-read.c
@@ -3134,20 +3134,21 @@ xlsx_CT_HyperLinks (GsfXMLIn *xin, xmlChar const **attrs)
        GnmRange r;
        GType link_type = 0;
        GnmHLink *lnk = NULL;
-       xmlChar const *target = NULL;
-       xmlChar const *tooltip = NULL;
-       xmlChar const *extern_id = NULL;
+       char const *location = NULL;
+       char const *tooltip = NULL;
+       char const *extern_id = NULL;
+       char *target = NULL;
 
        /* <hyperlink ref="A42" r:id="rId1"/> */
        for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
                if (attr_range (xin, attrs, "ref", &r))
                        has_ref = TRUE;
                else if (0 == strcmp (attrs[0], "location"))
-                       target = attrs[1];
+                       location = CXML2C (attrs[1]);
                else if (0 == strcmp (attrs[0], "tooltip"))
-                       tooltip = attrs[1];
+                       tooltip = CXML2C (attrs[1]);
                else if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
-                       extern_id = attrs[1];
+                       extern_id = CXML2C (attrs[1]);
 #if 0 /* ignore "display" on import, it always seems to be the cell content */
                else if (0 == strcmp (attrs[0], "display"))
                        ;
@@ -3157,27 +3158,32 @@ xlsx_CT_HyperLinks (GsfXMLIn *xin, xmlChar const **attrs)
        if (!has_ref)
                return;
 
-       if (NULL != target)
-               link_type = gnm_hlink_cur_wb_get_type ();
-       else if (NULL != extern_id) {
+       if (NULL != extern_id) {
                GsfOpenPkgRel const *rel = gsf_open_pkg_lookup_rel_by_id (
                        gsf_xml_in_get_input (xin), extern_id);
                if (NULL != rel &&
                    gsf_open_pkg_rel_is_extern (rel) &&
                    0 == strcmp (gsf_open_pkg_rel_get_type (rel),
                                 
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";)) {
-                       target = gsf_open_pkg_rel_get_target (rel);
-                       if (NULL != target) {
-                               if (0 == strncmp (target, "mailto:";, 7))
+                       const char *url = gsf_open_pkg_rel_get_target (rel);
+                       if (url) {
+                               if (0 == strncmp (url, "mailto:";, 7))
                                        link_type = gnm_hlink_email_get_type ();
                                else
                                        link_type = gnm_hlink_url_get_type ();
+                               target = location
+                                       ? g_strconcat (url, "#", location, NULL)
+                                       : g_strdup (url);
                        }
                }
+       } else if (NULL != target) {
+               target = g_strdup (location);
+               link_type = gnm_hlink_cur_wb_get_type ();
        }
 
        if (0 == link_type) {
                xlsx_warning (xin, _("Unknown type of hyperlink"));
+               g_free (target);
                return;
        }
 
@@ -3187,6 +3193,7 @@ xlsx_CT_HyperLinks (GsfXMLIn *xin, xmlChar const **attrs)
        style = gnm_style_new ();
        gnm_style_set_hlink (style, lnk);
        sheet_style_apply_range (state->sheet, &r, style);
+       g_free (target);
 }
 
 static void
diff --git a/plugins/excel/xlsx-write.c b/plugins/excel/xlsx-write.c
index 8d47206..902c07c 100644
--- a/plugins/excel/xlsx-write.c
+++ b/plugins/excel/xlsx-write.c
@@ -2069,15 +2069,22 @@ xlsx_write_hlink (GnmHLink const *lnk, GSList *ranges, XLSXClosure *info)
 {
        gchar const *target = gnm_hlink_get_target (lnk);
        gchar const *rid = NULL;
+       gchar const *location = NULL;
        gchar const *tip = gnm_hlink_get_tip (lnk);
        GType const t = G_OBJECT_TYPE (lnk);
 
-       if (t == gnm_hlink_url_get_type () ||
-           t == gnm_hlink_email_get_type ()) {
+       if (g_type_is_a (t, gnm_hlink_url_get_type ())) {
+               // URLs, including email.
+
+               // FIXME: An anchor within the url should be extracted into
+               // location
+
                rid = gsf_outfile_open_pkg_add_extern_rel (
                        GSF_OUTFILE_OPEN_PKG (gsf_xml_out_get_output (info->xml)),
                        target, ns_rel_hlink);
-       } else if (t != gnm_hlink_cur_wb_get_type ())
+       } else if (t == gnm_hlink_cur_wb_get_type ()) {
+               location = target;
+       } else
                return;
 
        for (; ranges  != NULL ; ranges = ranges->next) {
@@ -2086,11 +2093,10 @@ xlsx_write_hlink (GnmHLink const *lnk, GSList *ranges, XLSXClosure *info)
                gsf_xml_out_start_element (info->xml, "hyperlink");
                xlsx_add_range (info->xml, "ref", range);
 
-               if (t == gnm_hlink_cur_wb_get_type ())
-                       gsf_xml_out_add_cstr (info->xml, "location", target);
-               else if (NULL != rid)
+               if (rid)
                        gsf_xml_out_add_cstr (info->xml, "r:id", rid);
-
+               if (location)
+                       gsf_xml_out_add_cstr (info->xml, "location", target);
                if (tip)
                        gsf_xml_out_add_cstr (info->xml, "tooltip", tip);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]