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)); }
/* * 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; } } }
/** * 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; }
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; }
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; } } }
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); } } }
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; }
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_init (r, col + 1, tc->row, col + colspan, tc->row + rowspan - 1); gnm_sheet_merge_add (tc->sheet, r, FALSE, NULL); } col += colspan; } } }
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; } }