summaryrefslogtreecommitdiffstats
path: root/src/ods.c
diff options
context:
space:
mode:
authorAndrés <andmarti@gmail.com>2021-03-27 22:58:09 -0300
committerAndrés <andmarti@gmail.com>2021-03-27 22:58:09 -0300
commit38ad38763c2ca5181dc1f9501b7de42c1e41ea29 (patch)
tree81b5b60d39108f0c0cef5582004e2b8807ae1c4d /src/ods.c
parent8f44ee1051155287292b410545edb27ba4132955 (diff)
Added ODS file import
Diffstat (limited to 'src/ods.c')
-rw-r--r--src/ods.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/ods.c b/src/ods.c
new file mode 100644
index 0000000..ec938f9
--- /dev/null
+++ b/src/ods.c
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * Copyright (c) 2013-2021, Andrés Martinelli <andmarti@gmail.com> *
+ * All rights reserved. *
+ * *
+ * This file is a part of SC-IM *
+ * *
+ * SC-IM is a spreadsheet program that is based on SC. The original authors *
+ * of SC are James Gosling and Mark Weiser, and mods were later added by *
+ * Chuck Martin. *
+ * *
+ * Redistribution and use in source and binary forms, with or without *
+ * modification, are permitted provided that the following conditions are met: *
+ * 1. Redistributions of source code must retain the above copyright *
+ * notice, this list of conditions and the following disclaimer. *
+ * 2. Redistributions in binary form must reproduce the above copyright *
+ * notice, this list of conditions and the following disclaimer in the *
+ * documentation and/or other materials provided with the distribution. *
+ * 3. All advertising materials mentioning features or use of this software *
+ * must display the following acknowledgement: *
+ * This product includes software developed by Andrés Martinelli *
+ * <andmarti@gmail.com>. *
+ * 4. Neither the name of the Andrés Martinelli nor the *
+ * names of other contributors may be used to endorse or promote products *
+ * derived from this software without specific prior written permission. *
+ * *
+ * THIS SOFTWARE IS PROVIDED BY ANDRES MARTINELLI ''AS IS'' AND ANY *
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
+ * DISCLAIMED. IN NO EVENT SHALL ANDRES MARTINELLI BE LIABLE FOR ANY *
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;*
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
+ *******************************************************************************/
+
+/**
+ * \file xlsx.c
+ * \author Andrés Martinelli <andmarti@gmail.com>
+ * \date 2021-03-27
+ * \brief TODO Write a brief file description.
+ *
+ * \details ods import requires:
+ * - libzip-dev
+ * - libxml2-dev
+ */
+
+#ifdef ODS
+#include <errno.h>
+#include <zip.h>
+#include "tui.h"
+#include "cmds.h"
+#include "sc.h"
+#include "utils/string.h"
+#include <libxml/parser.h>
+//#include <libxml/tree.h>
+#endif
+/**
+ * \brief TODO Document open_ods()
+ *
+ * \param[in] fname
+ * \param[in] encoding
+ *
+ * \return none
+ */
+
+int open_ods(char * fname, char * encoding) {
+ struct zip * za;
+ struct zip_file * zf;
+ struct zip_stat sb_content;
+
+ char buf[100];
+ int err;
+ int len;
+
+ // open zip file
+ if ((za = zip_open(fname, 0, &err)) == NULL) {
+ zip_error_to_str(buf, sizeof(buf), err, errno);
+ sc_error("can't open zip archive `%s': %s", fname, buf);
+ return -1;
+ }
+
+ // open content.xml
+ char * name = "content.xml";
+ zf = zip_fopen(za, name, ZIP_FL_UNCHANGED);
+ char * content = NULL;
+ if (zf) {
+ // some files may not have strings
+ zip_stat(za, name, ZIP_FL_UNCHANGED, &sb_content);
+ content = (char *) malloc(sb_content.size);
+ len = zip_fread(zf, content, sb_content.size);
+ if (len < 0) {
+ sc_error("cannot read file %s.\n", name);
+ free(content);
+ return -1;
+ }
+ zip_fclose(zf);
+ }
+
+ // XML parse for the sheet file
+ xmlDoc * doc = NULL;
+
+ // this initialize the library and check potential ABI mismatches
+ // between the version it was compiled for and the actual shared
+ // library used.
+ LIBXML_TEST_VERSION
+
+
+ doc = xmlReadMemory(content, sb_content.size, "noname.xml", NULL, XML_PARSE_NOBLANKS);
+
+ if (doc == NULL) {
+ sc_error("error: could not parse ods file");
+ if (content != NULL) free(content);
+ return -1;
+ }
+
+ // parse here
+ xmlNode * cur_node = xmlDocGetRootElement(doc)->xmlChildrenNode;
+ xmlNode * child_node = NULL;
+ wchar_t line_interp[FBUFLEN] = L"";
+ int r=0, c=-1;
+ while (cur_node != NULL && strcmp((char *) cur_node->name, "body")) cur_node = cur_node->next; // forward until reach body
+ cur_node = cur_node->xmlChildrenNode;
+ while (cur_node != NULL && strcmp((char *) cur_node->name, "spreadsheet")) cur_node = cur_node->next; // forward until reach spreadsheet
+ cur_node = cur_node->xmlChildrenNode;
+ while (cur_node != NULL && strcmp((char *) cur_node->name, "table")) cur_node = cur_node->next; // forward until reach table
+ cur_node = cur_node->xmlChildrenNode;
+
+ char * strvalue = NULL;
+ char * st = NULL;
+ char * strtype = NULL;
+ char * value = NULL;
+ char * strf;
+
+ // here traverse table content
+ //while (cur_node != NULL && strcmp((char *) cur_node->name, "table-row")) cur_node = cur_node->next; // forward until reach table
+ while (cur_node != NULL) {
+ if (! strcmp((char *) cur_node->name, "table-row")) {
+ // we are inside a table-row
+ // each of these is a row
+ child_node = cur_node->xmlChildrenNode;
+ r++;
+ c=-1;
+
+ while (child_node != NULL) {
+ c++;
+ if (xmlGetProp(child_node, (xmlChar *) "value-type") == NULL) { child_node = child_node->next; continue; };
+ // each of these is table-cell (a column)
+
+ //sc_debug("node name: %s", child_node->name);
+ //sc_debug("type: %s", (char *) xmlGetProp(child_node, (xmlChar *) "value-type")); // type
+ strtype = (char *) xmlGetProp(child_node, (xmlChar *) "value-type"); // type
+
+ //if (!strcmp(strtype, "time") //get time-value
+ //if (!strcmp(strtype, "date") //get date-value
+ if (!strcmp(strtype, "float")) {
+ char * formula = (char *) xmlGetProp(child_node, (xmlChar *) "formula");
+ if (formula != NULL) {
+ strf = str_replace (formula, "of:=","");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "[.","");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, ";",",");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, ":.",":");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "]","");
+ strcpy(formula, strf);
+ free(strf);
+ // we take some excel common function and adds a @ to them
+ // we replace count sum avg with @count, @sum, @prod, @avg, @min, @max
+ strf = str_replace (formula, "COUNT","@COUNT");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "SUM","@SUM");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "PRODUCT","@PROD");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "AVERAGE","@AVG");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "MIN","@MIN");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "MAX","@MAX");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "ABS","@ABS");
+ strcpy(formula, strf);
+ free(strf);
+ strf = str_replace (formula, "STDEV","@STDDEV");
+ strcpy(formula, strf);
+ free(strf);
+ swprintf(line_interp, FBUFLEN, L"let %s%d=%s", coltoa(c), r, formula);
+ } else {
+ //value = (char *) xmlNodeGetContent(child_node->xmlChildrenNode);
+ value = (char *) xmlGetProp(child_node, (xmlChar *) "value"); // type
+ //sc_debug("value: %s", value);
+ double l = atof((char *) value);
+ swprintf(line_interp, FBUFLEN, L"let %s%d=%.15f", coltoa(c), r, l);
+ }
+ send_to_interp(line_interp);
+ } else if (!strcmp(strtype, "string") && !strcmp((char *) child_node->xmlChildrenNode->name, "p")) {
+ strvalue = (char *) xmlNodeGetContent(child_node->xmlChildrenNode);
+ //sc_debug("string: %s", strvalue);
+ st = str_replace (strvalue, "\"", "''");
+ clean_carrier(st); // we handle padding
+ swprintf(line_interp, FBUFLEN, L"label %s%d=\"%s\"", coltoa(c), r, st);
+ send_to_interp(line_interp);
+ free(st);
+ }
+ child_node = child_node->next;
+ }
+ }
+ cur_node = cur_node->next; // forward until reach table
+ }
+ int_deleterow(currow, 1); /* delete the first row */
+
+
+ //char * style = NULL;
+ //char * style = (char *) xmlGetProp(child_node, (xmlChar *) "s"); // style
+
+
+
+
+
+
+ // free the document
+ xmlFreeDoc(doc);
+
+ // Free the global variables that may have been allocated by the parser
+ xmlCleanupParser();
+
+ free(content);
+
+ // close zip file
+ if (zip_close(za) == -1) {
+ sc_error("cannot close zip archive `%s'", fname);
+ return -1;
+ }
+
+ return 0;
+}