Beispiel #1
0
void
go_xml_node_set_cstr (xmlNodePtr node, char const *name, char const *val)
{
	if (name)
		xmlSetProp (node, CC2XML (name), CC2XML (val));
	else
		xmlNodeSetContent (node, CC2XML (val));
}
Beispiel #2
0
/*
 * Handles incomplete html fragments as may occur on the clipboard,
 * e.g. a <td> without <tr> and <table> in front of it.
 */
static void
html_search_for_tables (htmlNodePtr cur, htmlDocPtr doc,
			WorkbookView *wb_view, GnmHtmlTableCtxt *tc)
{
	htmlNodePtr ptr;

	if (cur == NULL) {
		xmlGenericError(xmlGenericErrorContext,
				"htmlNodeDumpFormatOutput : node == NULL\n");
		return;
	}

	if (cur->type != XML_ELEMENT_NODE)
		return;

	if (xmlStrEqual (cur->name, CC2XML ("table"))) {
		html_read_table (cur, doc, wb_view, tc);
	} else if (starts_inferred_table (cur) || starts_inferred_row (cur)) {
		htmlNodePtr tnode = xmlNewNode (NULL, "table");

		/* Link in a table node */
		xmlAddPrevSibling (cur, tnode);
		if (starts_inferred_row (cur)) {
			htmlNodePtr rnode = xmlNewNode (NULL, "tr");

			/* Link in a row node */
			xmlAddChild (tnode, rnode);
			/* Make following elements children of the row node,
			 * until we meet one which isn't legal in a row. */
			while ((ptr = tnode->next) != NULL) {
				if (ends_inferred_row (ptr))
					break;
				xmlUnlinkNode (ptr);
				xmlAddChild (rnode, ptr);
			}
		}
		/* Make following elements children of the row node,
		 * until we meet one which isn't legal in a table. */
		while ((ptr = tnode->next) != NULL) {
			if (ends_inferred_table (ptr))
				break;
			xmlUnlinkNode (ptr);
			xmlAddChild (tnode, ptr);
		}
		html_read_table (tnode, doc, wb_view, tc);
	} else {
		for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
			html_search_for_tables (ptr, doc, wb_view, tc);
			/* ptr may now have been pushed down in the tree,
			 * if so, ptr->next is not the right pointer to
			 * follow */
			while (ptr->parent != cur)
				ptr = ptr->parent;
		}
	}
}
Beispiel #3
0
/**
 * go_xml_node_get_cstr: (skip)
 * @node: #xmlNodePtr
 * @name: attribute name
 * Get an xmlChar * value for a node carried as an attibute
 * result must be xmlFree
 *
 * Returns: (transfer full): the attribute value
 */
xmlChar *
go_xml_node_get_cstr (xmlNodePtr node, char const *name)
{
	if (name != NULL)
		return xmlGetProp (node, CC2XML (name));
	/* in libxml1 <foo/> would return NULL
	 * in libxml2 <foo/> would return ""
	 */
	if (node->xmlChildrenNode != NULL)
		return xmlNodeGetContent (node);
	return NULL;
}
Beispiel #4
0
static gboolean
is_elt_type (htmlNodePtr ptr, char const ** types)
{
	char const **p;
	gboolean ret = FALSE;

	for (p = types; *p; p++)
		if (xmlStrEqual (ptr->name, CC2XML ((*p)))) {
			ret = TRUE;
			break;
		}

	return ret;
}
Beispiel #5
0
static void
html_read_table (htmlNodePtr cur, htmlDocPtr doc, WorkbookView *wb_view,
		 GnmHtmlTableCtxt *tc)
{
	Workbook *wb;
	htmlNodePtr ptr, ptr2;

	g_return_if_fail (cur != NULL);
	g_return_if_fail (wb_view != NULL);

	wb = wb_view_get_workbook (wb_view);
	for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
		if (ptr->type != XML_ELEMENT_NODE)
			continue;
		if (xmlStrEqual (ptr->name, CC2XML ("caption"))) {
			xmlBufferPtr buf;
			buf = xmlBufferCreate ();
			for (ptr2 = ptr->children; ptr2 != NULL ; ptr2 = ptr2->next) {
				htmlNodeDump (buf, doc, ptr2);
			}
			if (buf->use > 0) {
				char *name;
				name = g_strndup (CXML2C (buf->content), buf->use);
				tc->sheet = html_get_sheet (name, wb);
				g_free (name);
			}
			xmlBufferFree (buf);
		} else if (xmlStrEqual (ptr->name, CC2XML ("thead")) ||
			   xmlStrEqual (ptr->name, CC2XML ("tfoot")) ||
			   xmlStrEqual (ptr->name, CC2XML ("tbody"))) {
			html_read_rows (ptr, doc, wb, tc);
		} else if (xmlStrEqual (ptr->name, CC2XML ("tr"))) {
			html_read_rows (cur, doc, wb, tc);
			break;
		}
	}
}
Beispiel #6
0
static void
html_read_rows (htmlNodePtr cur, htmlDocPtr doc, Workbook *wb,
		GnmHtmlTableCtxt *tc)
{
	htmlNodePtr ptr;

	for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
		if (ptr->type != XML_ELEMENT_NODE)
			continue;
		if (xmlStrEqual (ptr->name, CC2XML ("tr"))) {
			tc->row++;
			if (tc->sheet == NULL)
				tc->sheet = html_get_sheet (NULL, wb);
			html_read_row (ptr, doc, tc);
		}
	}
}
Beispiel #7
0
gboolean
go_xml_node_get_gocolor (xmlNodePtr node, char const *name, GOColor *res)
{
	xmlChar *color;
	int r, g, b;

	color = xmlGetProp (node, CC2XML (name));
	if (color == NULL)
		return FALSE;
	if (sscanf (CXML2C (color), "%X:%X:%X", &r, &g, &b) == 3) {
		r >>= 8;
		g >>= 8;
		b >>= 8;
		*res = GO_COLOR_FROM_RGBA (r,g,b,0xff);
		xmlFree (color);
		return TRUE;
	}
Beispiel #8
0
static void
html_read_row (htmlNodePtr cur, htmlDocPtr doc, GnmHtmlTableCtxt *tc)
{
	htmlNodePtr ptr;
	int col = -1;

	for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
		if (xmlStrEqual (ptr->name, CC2XML ("td")) ||
		    xmlStrEqual (ptr->name, CC2XML ("th"))) {
			GString *buf;
			xmlBufferPtr a_buf;
			xmlAttrPtr   props;
			int colspan = 1;
			int rowspan = 1;
			GnmCellPos pos;
			GnmStyle *mstyle;
			GSList *hrefs = NULL;
			GnmHLink *lnk = NULL;

			/* Check whether we need to skip merges from above */
			pos.row = tc->row;
			pos.col = col + 1;
			while (gnm_sheet_merge_contains_pos (tc->sheet, &pos)) {
				col++;
				pos.col++;
			}

			/* Do we span across multiple rows or cols? */
			props = ptr->properties;
			while (props) {
				if (xmlStrEqual (props->name, CC2XML ("colspan")) && props->children)
				    colspan = atoi (CXML2C (props->children->content));
				if (xmlStrEqual (props->name, CC2XML ("rowspan")) && props->children)
				    rowspan = atoi (CXML2C (props->children->content));
				props = props->next;
			}
			if (colspan < 1)
				colspan = 1;
			if (rowspan < 1)
				rowspan = 1;

			/* Let's figure out the content of the cell */
			buf = g_string_new (NULL);
			a_buf = xmlBufferCreate ();

			mstyle = gnm_style_new_default ();
			if (xmlStrEqual (ptr->name, CC2XML ("th")))
				gnm_style_set_font_bold (mstyle, TRUE);

			html_read_content (ptr, buf, mstyle, a_buf,
					   &hrefs, TRUE, doc, tc);


			if (g_slist_length (hrefs) >= 1 &&
			    buf->len > 0) {
				/* One hyperlink, and text to make it
				 * visible */
				char *url;
				xmlBufferPtr h_buf = xmlBufferCreate ();

				hrefs = g_slist_reverse (hrefs);
				htmlNodeDump (
					h_buf, doc, (htmlNodePtr)hrefs->data);
				url = g_strndup (
					CXML2C (h_buf->content), h_buf->use);
				if (strncmp (url, "mailto:",
					     strlen ("mailto:")) == 0)
					lnk = gnm_hlink_new (
						gnm_hlink_email_get_type (),
						tc->sheet);
				else
					lnk = gnm_hlink_new (
						gnm_hlink_url_get_type (),
						tc->sheet);
				gnm_hlink_set_target (lnk, url);
				gnm_style_set_hlink (mstyle, lnk);
				gnm_style_set_font_uline (mstyle,
							  UNDERLINE_SINGLE);
				gnm_style_set_font_color (mstyle,
							  gnm_color_new_go (GO_COLOR_BLUE));
				g_free (url);
				xmlBufferFree (h_buf);
			}
			if (g_slist_length (hrefs) > 1 || buf->len <= 0) {
				/* Multiple links,
				 * or no text to give hyperlink style,
				 * so put them in a comment */
				GSList *l;

				for (l = hrefs; l != NULL; l = l->next) {
					htmlNodeDump (a_buf, doc,
						      (htmlNodePtr)l->data);
					xmlBufferAdd (a_buf, CC2XML ("\n"),
						      -1);
				}
			}
			g_slist_free (hrefs);
			if (buf->len > 0) {
				GnmCell *cell = sheet_cell_fetch (tc->sheet, col + 1, tc->row);
				sheet_style_set_pos (tc->sheet, col + 1, tc->row, mstyle);
				gnm_cell_set_text (cell, buf->str);
			} else
				gnm_style_unref (mstyle);

			if (a_buf->use > 0) {
				char *name;

				name = g_strndup (CXML2C (a_buf->content), a_buf->use);
				cell_set_comment (tc->sheet, &pos, NULL, name, NULL);
				g_free (name);
			}
			g_string_free (buf, TRUE);
			xmlBufferFree (a_buf);

			/* If necessary create the merge */
			if (colspan > 1 || rowspan > 1) {
				GnmRange range;
				GnmRange *r = &range;

				range_init (r, col + 1, tc->row, col + colspan, tc->row + rowspan - 1);
				gnm_sheet_merge_add (tc->sheet, r, FALSE, NULL);
			}

			col += colspan;
		}
	}
}
Beispiel #9
0
static void
html_read_content (htmlNodePtr cur, GString *buf, GnmStyle *mstyle,
		   xmlBufferPtr a_buf, GSList **hrefs, gboolean first,
		   htmlDocPtr doc, GnmHtmlTableCtxt *tc)
{
	htmlNodePtr ptr;

	for (ptr = cur->children; ptr != NULL ; ptr = ptr->next) {
		if (ptr->type == XML_TEXT_NODE) {
			if (g_utf8_validate (ptr->content, -1, NULL))
				html_append_text (buf, ptr->content);
			else
				g_string_append (buf, _("[Warning: Invalid text string has been removed.]"));
		} else if (ptr->type == XML_ELEMENT_NODE) {
			if (first) {
				if (xmlStrEqual (ptr->name, CC2XML ("i"))
				    || xmlStrEqual (ptr->name, CC2XML ("em")))
					gnm_style_set_font_italic (mstyle, TRUE);
				if (xmlStrEqual (ptr->name, CC2XML ("b")))
					gnm_style_set_font_bold (mstyle, TRUE);
			}
			if (xmlStrEqual (ptr->name, CC2XML ("a"))) {
				xmlAttrPtr   props;
				props = ptr->properties;
				while (props) {
					if (xmlStrEqual (props->name, CC2XML ("href")) && props->children) {
						*hrefs = g_slist_prepend (
							*hrefs, props->children);

					}
					props = props->next;
				}
			}
			if (xmlStrEqual (ptr->name, CC2XML ("img"))) {
				xmlAttrPtr   props;
				props = ptr->properties;
				while (props) {
					if (xmlStrEqual (props->name, CC2XML ("src")) && props->children) {
						htmlNodeDump (a_buf, doc, props->children);
						xmlBufferAdd (a_buf, CC2XML ("\n"), -1);
					}
					props = props->next;
				}
			}
			if (xmlStrEqual (ptr->name, CC2XML ("table"))) {
				Sheet *last_sheet = tc->sheet;
				int   last_row = tc->row;
				tc->sheet = NULL;
				tc->row   = -1;
				html_read_table (ptr, doc, tc->wb_view, tc);
				if (tc->sheet) {
					g_string_append_printf (buf, _("[see sheet %s]"), tc->sheet->name_quoted);
					xmlBufferAdd (a_buf, CC2XML (_("The original html file is\n"
								       "using nested tables.")), -1);
				}
				tc->sheet = last_sheet;
				tc->row = last_row;
			} else
				html_read_content
					(ptr, buf, mstyle, a_buf, hrefs, first, doc, tc);
		}
		first = FALSE;
	}
}