diff --git a/plugins/fn-lookup/functions.c b/plugins/fn-lookup/functions.c
index c7ce7f9..91a96d5 100644
--- a/plugins/fn-lookup/functions.c
+++ b/plugins/fn-lookup/functions.c
@@ -43,6 +43,7 @@
 #include <workbook.h>
 #include <sheet.h>
 #include <parse-util.h>
+#include <hlink.h>
 #include <gnm-i18n.h>
 
 #include <goffice/goffice.h>
@@ -1686,10 +1687,10 @@ static GnmFuncHelp const help_hyperlink[] = {
 static GnmValue *
 gnumeric_hyperlink (GnmFuncEvalInfo *ei, GnmValue const * const *args)
 {
-	GnmValue const * v = args[1];
-	if (v == NULL)
-		v = args[0];
-	return value_dup (v);
+	GnmValue const *uri = args[0];
+	GnmValue const *v = args[1] ? args[1] : uri;
+	return gnm_hlink_new_value (value_peek_string (v),
+				    value_peek_string (uri));
 }
 
 /***************************************************************************/
diff --git a/src/hlink.c b/src/hlink.c
index 393f2da..b26bdd8 100644
--- a/src/hlink.c
+++ b/src/hlink.c
@@ -38,6 +38,7 @@
 #include "expr.h"
 #include "value.h"
 #include "mstyle.h"
+#include "cell.h"
 
 #include <goffice/goffice.h>
 #include <gsf/gsf-impl-utils.h>
@@ -74,8 +75,18 @@ gnm_hlink_activate (GnmHLink *lnk, WBCGtk *wbcg)
 GnmHLink *
 sheet_hlink_find (Sheet const *sheet, GnmCellPos const *pos)
 {
-	GnmStyle const *style = sheet_style_get (sheet, pos->col, pos->row);
-	return gnm_style_get_hlink (style);
+	GnmCell const *cell = sheet_cell_get (sheet, pos->col, pos->row);
+	GnmHLink *hlink = cell
+		? gnm_hlink_from_value (cell->value)
+		: NULL;
+
+	if (hlink) {
+		return hlink;
+	} else {
+		GnmStyle const *style =
+			sheet_style_get (sheet, pos->col, pos->row);
+		return gnm_style_get_hlink (style);
+	}
 }
 
 static void
@@ -313,9 +324,142 @@ GSF_CLASS (GnmHLinkExternal, gnm_hlink_external,
 	   gnm_hlink_external_class_init, NULL,
 	   GNM_HLINK_TYPE)
 
+
+static PangoAttribute *gnm_pango_attr_hlink_new (GnmHLink *hlink);
+
+typedef struct {
+	PangoAttribute attr;
+	GnmHLink *hlink;
+} GnmPangoAttrHLink;
+
+static PangoAttribute *
+gnm_pango_attr_hlink_copy (PangoAttribute const *attr)
+{
+	GnmPangoAttrHLink *a = (GnmPangoAttrHLink *)attr;
+	GnmHLink *hlink;
+
+	hlink = (GnmHLink *)g_object_new (GNM_HLINK_URL_TYPE, NULL);
+	gnm_hlink_set_target (hlink, gnm_hlink_get_target (a->hlink));
+	return gnm_pango_attr_hlink_new (hlink);
+}
+
+static void
+gnm_pango_attr_hlink_destroy (PangoAttribute *attr)
+{
+	GnmPangoAttrHLink *a = (GnmPangoAttrHLink *)attr;
+	g_object_unref (a->hlink);
+	g_free (attr);
+}
+
+static gboolean
+gnm_pango_attr_hlink_compare (PangoAttribute const *attr1,
+			      PangoAttribute const *attr2)
+{
+	GnmPangoAttrHLink *a1 = (GnmPangoAttrHLink *)attr1;
+	GnmPangoAttrHLink *a2 = (GnmPangoAttrHLink *)attr2;
+	/* Can this ever happen and do we care?  */
+	return (a1->hlink == a2->hlink);
+}
+
+static PangoAttrType
+gnm_pango_attr_hlink_get_attr_type (void)
+{
+	static PangoAttrType t = PANGO_ATTR_INVALID;
+
+	if (t == PANGO_ATTR_INVALID)
+		t = pango_attr_type_register ("GnmHLink");
+
+	return t;
+}
+
+static PangoAttribute *
+gnm_pango_attr_hlink_new (GnmHLink *hlink)
+{
+	GnmPangoAttrHLink *result;
+
+	static PangoAttrClass klass = {
+		0,
+		gnm_pango_attr_hlink_copy,
+		gnm_pango_attr_hlink_destroy,
+		gnm_pango_attr_hlink_compare
+	};
+
+	if (!klass.type)
+		klass.type = gnm_pango_attr_hlink_get_attr_type ();
+
+	result = g_new (GnmPangoAttrHLink, 1);
+	result->attr.klass = &klass;
+	result->hlink = g_object_ref (hlink);
+
+	return (PangoAttribute *) result;
+}
+
+GnmValue *
+gnm_hlink_new_value (const char *str, const char *uri)
+{
+	GnmValue *v;
+	GOFormat *fmt;
+	GnmHLink *hlink;
+	PangoAttrList *attrs;
+	PangoAttribute *attr;
+
+	v = value_new_string (str);
+
+	hlink = (GnmHLink *)g_object_new (GNM_HLINK_URL_TYPE, NULL);
+	gnm_hlink_set_target (hlink, uri);
+
+	attrs = pango_attr_list_new ();
+	attr = gnm_pango_attr_hlink_new (hlink);
+	attr->start_index = 0;
+	attr->end_index = G_MAXINT;
+	pango_attr_list_insert (attrs, attr);
+
+	fmt = go_format_new_markup (attrs, FALSE);
+	value_set_fmt (v, fmt);
+
+	g_object_unref (hlink);
+	go_format_unref (fmt);
+
+	return v;
+}
+
+GnmHLink *
+gnm_hlink_from_value (const GnmValue *v)
+{
+	GOFormat const *fmt;
+	const PangoAttrList *attrs;
+	PangoAttrIterator *aiter;
+	PangoAttribute *a;
+	GnmHLink *hlink;
+
+	if (!v)
+		return NULL;
+	fmt = VALUE_FMT (v);
+	if (!fmt)
+		return NULL;
+	if (!go_format_is_markup (fmt))
+		return NULL;
+
+	attrs = go_format_get_markup (fmt);
+	if (!attrs)
+		return NULL;
+
+	aiter = pango_attr_list_get_iterator ((PangoAttrList *)attrs);
+	a = pango_attr_iterator_get (aiter,
+				     gnm_pango_attr_hlink_get_attr_type ());
+	hlink = a ? ((GnmPangoAttrHLink *)a)->hlink : NULL;
+	pango_attr_iterator_destroy (aiter);
+
+	return hlink;
+}
+
+
+
 void
 _gnm_hlink_init (void)
 {
+	gnm_pango_attr_hlink_get_attr_type ();
+
 	/* make sure that all hlink types are registered */
 	gnm_hlink_cur_wb_get_type ();
 	gnm_hlink_url_get_type ();
diff --git a/src/hlink.h b/src/hlink.h
index dd703b8..34c76c9 100644
--- a/src/hlink.h
+++ b/src/hlink.h
@@ -30,6 +30,9 @@ GType gnm_hlink_url_get_type (void);
 GType gnm_hlink_email_get_type (void);
 GType gnm_hlink_external_get_type (void);
 
+GnmValue *gnm_hlink_new_value (const char *str, const char *uri);
+GnmHLink *gnm_hlink_from_value (const GnmValue *v);
+
 /* Protected. */
 void _gnm_hlink_init (void);
 
