[gnumeric] Improve text import/export from and to ODF. [#663135]



commit 6f79c7e3752e5e69f6263bbac963059ee9d7e910
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date:   Tue Nov 1 00:17:05 2011 -0600

    Improve text import/export from and to ODF. [#663135]
    
    2011-11-01  Andreas J. Guelzow <aguelzow pyrshep ca>
    
    	* openoffice-read.c (OOParseState): add fields
    	(oo_add_text_to_cell): preserve markup
    	(oo_cell_content_span_start): new
    	(oo_cell_content_span_end): new
    	(oo_pango_set_end): new
    	(oo_apply_character_style): new
    	(oo_style): handle text style
    	(od_style_prop_text): new
    	(oo_style_prop): connect od_style_prop_text
    	(opendoc_content_dtd): connect oo_cell_content_span_*
    	(openoffice_file_open): handle new fields

 NEWS                                 |    2 +-
 plugins/openoffice/ChangeLog         |   14 +++
 plugins/openoffice/openoffice-read.c |  179 +++++++++++++++++++++++++++++++++-
 3 files changed, 191 insertions(+), 4 deletions(-)
---
diff --git a/NEWS b/NEWS
index d04f61d..2bfd4fd 100644
--- a/NEWS
+++ b/NEWS
@@ -44,7 +44,7 @@ Andreas:
 	* Fix autofitting of row height in presence of superscripted
 	scientific notation. [#662472]
 	* Improve shape import from ODF. [#663078]
-	* Improve text import/export from and to ODF. [#627509]
+	* Improve text import/export from and to ODF. [#627509, #663135]
 	* Import hyperlinks from ODF. [#603533]
 
 Jean:
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index bda6012..3c77e73 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,17 @@
+2011-11-01  Andreas J. Guelzow <aguelzow pyrshep ca>
+
+	* openoffice-read.c (OOParseState): add fields
+	(oo_add_text_to_cell): preserve markup
+	(oo_cell_content_span_start): new
+	(oo_cell_content_span_end): new
+	(oo_pango_set_end): new
+	(oo_apply_character_style): new
+	(oo_style): handle text style
+	(od_style_prop_text): new
+	(oo_style_prop): connect od_style_prop_text
+	(opendoc_content_dtd): connect oo_cell_content_span_*
+	(openoffice_file_open): handle new fields
+
 2011-10-31  Andreas J. Guelzow <aguelzow pyrshep ca>
 
 	* openoffice-read.c (oo_cell_content_link): new
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index 438fd1d..a8c80de 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -311,6 +311,7 @@ typedef struct {
 	GnmCellPos	 extent_style;
 	GnmComment      *cell_comment;
 	GnmCell         *curr_cell;
+	GSList          *span_style_stack;
 
 	int		 col_inc, row_inc;
 	gboolean	 content_is_simple;
@@ -332,9 +333,11 @@ typedef struct {
 		GHashTable	*sheet;
 		GHashTable	*master_pages;
 		GHashTable	*page_layouts;
+		GHashTable	*text;
 	} styles;
 	struct {
 		GnmStyle	*cells;
+		PangoAttrList   *text;
 		OOColRowStyle	*col_rows;
 		OOSheetStyle	*sheets;
 		gboolean         requires_disposal;
@@ -393,6 +396,11 @@ typedef struct {
 } OOParseState;
 
 typedef struct {
+	int start;
+	char *style_name;
+} span_style_info_t;
+
+typedef struct {
 	GnmConventions base;
 	OOParseState *state;
 	GsfXMLIn *xin;
@@ -3147,11 +3155,15 @@ oo_add_text_to_cell (OOParseState *state, char const *str)
 		return;
 
 	if (VALUE_IS_STRING (state->curr_cell->value)) {
-		if (*str != 0)
+		if (*str != 0) {
+			GOFormat *fmt = go_format_ref (state->curr_cell->value->v_str.fmt);
 			v = value_new_string_str 
 				(go_string_new_nocopy 
 				 (g_strconcat (state->curr_cell->value->v_str.val->str,
 					       str, NULL)));
+			value_set_fmt (v, fmt);
+			go_format_unref (fmt);
+		}
 	} else
 		v = value_new_string (str);
 	if (v != NULL)
@@ -3186,6 +3198,101 @@ oo_cell_content_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
 	oo_update_data_extent (state, 1, 1);
 }
 
+
+static void
+oo_cell_content_span_start (GsfXMLIn *xin, xmlChar const **attrs)
+{
+       OOParseState *state = (OOParseState *)xin->user_state;
+
+	if (state->content_is_simple) {
+		span_style_info_t *ssi = g_new0 (span_style_info_t, 1);
+
+		if (xin->content->str != NULL && *xin->content->str != 0) {
+			oo_add_text_to_cell (state, xin->content->str + state->p_content_offset);
+			state->p_content_offset = strlen (xin->content->str);
+		}
+
+		ssi->start = VALUE_IS_STRING (state->curr_cell->value) ? 
+			strlen (state->curr_cell->value->v_str.val->str) : 0;
+
+		for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+			if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_TEXT, "style-name"))
+				ssi->style_name = g_strdup (attrs[1]);
+
+		state->span_style_stack = g_slist_prepend (state->span_style_stack, ssi);
+	}
+}
+
+static gboolean            
+oo_pango_set_end (PangoAttribute *attribute, gpointer data)
+{
+	attribute->end_index = GPOINTER_TO_INT (data);
+	return FALSE;
+}
+
+static void
+oo_apply_character_style (GsfXMLIn *xin, OOParseState *state, char *name, int start, int end)
+{
+	PangoAttrList *attrs = g_hash_table_lookup (state->styles.text, name);
+	PangoAttrList *old = NULL;
+
+	if (attrs == NULL) {
+		oo_warning (xin, _("Unknown text style with name \"%s\" encountered!"), name);
+		return;
+	}
+	if (end == start)
+		return;
+
+	if (VALUE_IS_STRING (state->curr_cell->value)) {
+		GOFormat *fmt;
+
+		attrs = pango_attr_list_copy (attrs);
+		pango_attr_list_filter (attrs, (PangoAttrFilterFunc) oo_pango_set_end, GINT_TO_POINTER (end - start));
+
+		if (state->curr_cell->value->v_str.fmt != NULL) {
+			old = pango_attr_list_copy 
+				((PangoAttrList *)go_format_get_markup (state->curr_cell->value->v_str.fmt));
+		} else
+			old = pango_attr_list_new ();
+		pango_attr_list_splice  (old, attrs, start, end - start);
+		pango_attr_list_unref (attrs);
+		fmt = go_format_new_markup (old, FALSE);
+		value_set_fmt (state->curr_cell->value, fmt);
+		go_format_unref (fmt);
+	}
+}
+
+static void
+oo_cell_content_span_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
+{
+	OOParseState *state = (OOParseState *)xin->user_state;
+
+	if (state->content_is_simple) {
+		int end;
+		span_style_info_t *ssi = NULL;
+
+		g_return_if_fail (state->span_style_stack != NULL);
+
+		if (xin->content->str != NULL && *xin->content->str != 0) {
+			oo_add_text_to_cell (state, xin->content->str + state->p_content_offset);
+			state->p_content_offset = strlen (xin->content->str);
+		}
+
+		end = VALUE_IS_STRING (state->curr_cell->value) ? 
+			strlen (state->curr_cell->value->v_str.val->str) : 0;
+
+		ssi = state->span_style_stack->data;
+		state->span_style_stack = state->span_style_stack->next;
+
+		if (ssi != NULL) {
+			if (ssi->style_name != NULL && end > 0)
+				oo_apply_character_style (xin, state, ssi->style_name, ssi->start, end);
+			g_free (ssi->style_name);
+			g_free (ssi);
+		}
+	}
+}
+
 static void
 oo_cell_content_special (GsfXMLIn *xin, int count, char const *sym)
 {
@@ -3590,6 +3697,13 @@ oo_style (GsfXMLIn *xin, xmlChar const **attrs)
 		}
 
 	switch (state->cur_style.type) {
+	case OO_STYLE_TEXT:
+		state->cur_style.text = pango_attr_list_new ();
+		if (name != NULL)
+			g_hash_table_replace (state->styles.text,
+					      g_strdup (name), pango_attr_list_ref (state->cur_style.text));
+		
+		break;
 	case OO_STYLE_CELL:
 		style = (parent_name != NULL)
 			? g_hash_table_lookup (state->styles.cell, parent_name)
@@ -3715,7 +3829,10 @@ oo_style_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
 	case OO_STYLE_GRAPHICS :
 		state->chart.cur_graph_style = NULL;
 		break;
-
+	case OO_STYLE_TEXT:
+		pango_attr_list_unref (state->cur_style.text);
+		state->cur_style.text = NULL;
+		break;
 	default :
 		break;
 	}
@@ -6191,6 +6308,55 @@ od_style_prop_chart (GsfXMLIn *xin, xmlChar const **attrs)
 }
 
 static void
+od_style_prop_text (GsfXMLIn *xin, xmlChar const **attrs)
+{
+	static OOEnum const style_types [] = {
+		{ "normal",	   PANGO_STYLE_NORMAL},
+		{ "italic",	   PANGO_STYLE_ITALIC},
+		{ "oblique",       PANGO_STYLE_OBLIQUE},
+		{ NULL,	0 },
+	};
+
+	OOParseState *state = (OOParseState *)xin->user_state;
+	PangoAttribute *attr;
+	int	  tmp;
+
+	g_return_if_fail (state->cur_style.text != NULL);
+
+	for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
+		if (oo_attr_font_weight (xin, attrs, &tmp)) {
+			attr = pango_attr_weight_new (tmp);
+			attr->start_index = 0;
+			attr->end_index = 0;
+			pango_attr_list_insert (state->cur_style.text, attr);
+		} else if (oo_attr_enum (xin, attrs, OO_NS_FO, "font-style", style_types, &tmp)) {
+			attr = pango_attr_style_new (tmp);
+			attr->start_index = 0;
+			attr->end_index = 0;
+			pango_attr_list_insert (state->cur_style.text, attr);
+		} else if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]),
+					       OO_NS_STYLE, "text-position")) {
+			attr = NULL;
+			if (g_str_has_prefix (attrs[1],"super"))
+				attr = go_pango_attr_superscript_new (1);
+			else if (g_str_has_prefix (attrs[1], "sub"))
+				attr = go_pango_attr_subscript_new (1);
+			else if (g_str_has_prefix (attrs[1], "0")) {
+				attr = go_pango_attr_superscript_new (0);
+				attr->start_index = 0;
+				attr->end_index = 0;
+				pango_attr_list_insert (state->cur_style.text, attr);
+				attr = go_pango_attr_subscript_new (0);
+			}
+			if (attr != NULL) {
+				attr->start_index = 0;
+				attr->end_index = 0;
+				pango_attr_list_insert (state->cur_style.text, attr);
+			}
+		}
+}
+
+static void
 oo_style_prop (GsfXMLIn *xin, xmlChar const **attrs)
 {
 	OOParseState *state = (OOParseState *)xin->user_state;
@@ -6199,6 +6365,7 @@ oo_style_prop (GsfXMLIn *xin, xmlChar const **attrs)
 	case OO_STYLE_COL   :
 	case OO_STYLE_ROW   : oo_style_prop_col_row (xin, attrs); break;
 	case OO_STYLE_SHEET : oo_style_prop_table (xin, attrs); break;
+	case OO_STYLE_TEXT  : od_style_prop_text (xin, attrs); break;
 	case OO_STYLE_CHART :
 	case OO_STYLE_GRAPHICS :
 		od_style_prop_chart (xin, attrs); break;
@@ -9398,7 +9565,7 @@ static GsfXMLInNode const opendoc_content_dtd [] =
 		    GSF_XML_IN_NODE (CELL_TEXT, CELL_TEXT_ADDR, OO_NS_TEXT, "a", GSF_XML_SHARED_CONTENT, &oo_cell_content_link, NULL),
 	            GSF_XML_IN_NODE_FULL (CELL_TEXT, CELL_TEXT_LINE_BREAK, OO_NS_TEXT, "line-break", GSF_XML_NO_CONTENT, FALSE, FALSE, &oo_cell_content_symbol, NULL, .v_str = "\n"),
 	            GSF_XML_IN_NODE_FULL (CELL_TEXT, CELL_TEXT_TAB, OO_NS_TEXT, "tab", GSF_XML_SHARED_CONTENT, FALSE, FALSE, oo_cell_content_symbol, NULL, .v_str = "\t"),
-		    GSF_XML_IN_NODE (CELL_TEXT, CELL_TEXT_SPAN, OO_NS_TEXT, "span", GSF_XML_SHARED_CONTENT, NULL, NULL),
+		    GSF_XML_IN_NODE (CELL_TEXT, CELL_TEXT_SPAN, OO_NS_TEXT, "span", GSF_XML_SHARED_CONTENT, &oo_cell_content_span_start, &oo_cell_content_span_end),
 		      GSF_XML_IN_NODE (CELL_TEXT_SPAN, CELL_TEXT_SPAN, OO_NS_TEXT, "span", GSF_XML_NO_CONTENT, NULL, NULL),/* 2nd def */
 		      GSF_XML_IN_NODE (CELL_TEXT_SPAN, CELL_TEXT_S,    OO_NS_TEXT, "s", GSF_XML_NO_CONTENT, NULL, NULL),/* 2nd def */
 		      GSF_XML_IN_NODE (CELL_TEXT_SPAN, CELL_TEXT_LINE_BREAK,    OO_NS_TEXT, "line-break", GSF_XML_NO_CONTENT, NULL, NULL),/* 2nd def */
@@ -10353,6 +10520,9 @@ openoffice_file_open (G_GNUC_UNUSED GOFileOpener const *fo, GOIOContext *io_cont
 	state.styles.sheet = g_hash_table_new_full (g_str_hash, g_str_equal,
 		(GDestroyNotify) g_free,
 		(GDestroyNotify) oo_sheet_style_free);
+	state.styles.text = g_hash_table_new_full (g_str_hash, g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) pango_attr_list_unref);
 	state.styles.col = g_hash_table_new_full (g_str_hash, g_str_equal,
 		(GDestroyNotify) g_free,
 		(GDestroyNotify) g_free);
@@ -10438,6 +10608,7 @@ openoffice_file_open (G_GNUC_UNUSED GOFileOpener const *fo, GOIOContext *io_cont
 	state.last_progress_update = 0;
 	state.last_error = NULL;
 	state.cur_control = NULL;
+	state.span_style_stack = NULL;
 
 	go_io_progress_message (state.context, _("Reading file..."));
 	go_io_value_progress_set (state.context, gsf_input_size (contents), 0);
@@ -10556,6 +10727,7 @@ openoffice_file_open (G_GNUC_UNUSED GOFileOpener const *fo, GOIOContext *io_cont
 	g_free (state.default_style.rows);
 	g_free (state.default_style.columns);
 	g_hash_table_destroy (state.styles.sheet);
+	g_hash_table_destroy (state.styles.text);
 	g_hash_table_destroy (state.styles.col);
 	g_hash_table_destroy (state.styles.row);
 	g_hash_table_destroy (state.styles.cell);
@@ -10576,6 +10748,7 @@ openoffice_file_open (G_GNUC_UNUSED GOFileOpener const *fo, GOIOContext *io_cont
 	g_hash_table_destroy (state.validations);
 	g_hash_table_destroy (state.strings);
 	g_hash_table_destroy (state.chart.arrow_markers);
+	go_slist_free_custom (state.span_style_stack, g_free);
 	g_object_unref (contents);
 
 	g_object_unref (zip);



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