diff --git a/src/liborcus/Makefile.am b/src/liborcus/Makefile.am index e24a6dccf1cb60e002e8a732742cd265212fe3cd..746f3b98f00f62c00d0b7263f23434caa43bd1e4 100644 --- a/src/liborcus/Makefile.am +++ b/src/liborcus/Makefile.am @@ -195,6 +195,8 @@ liborcus_@ORCUS_API_VERSION@_la_SOURCES += \ odf_styles.cpp \ odf_styles_context.hpp \ odf_styles_context.cpp \ + odf_number_formatting_context.hpp \ + odf_number_formatting_context.cpp \ odf_token_constants.hpp \ odf_token_constants.inl \ odf_tokens.hpp \ diff --git a/src/liborcus/odf_number_formatting_context.cpp b/src/liborcus/odf_number_formatting_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58ba9c58ea2caf1ee28205e39a110f2edde93110 --- /dev/null +++ b/src/liborcus/odf_number_formatting_context.cpp @@ -0,0 +1,750 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "odf_number_formatting_context.hpp" +#include "odf_namespace_types.hpp" +#include "odf_token_constants.hpp" +#include "odf_helper.hpp" +#include "orcus/measurement.hpp" +#include "orcus/spreadsheet/import_interface.hpp" +#include + +#include +#include +#include + +using namespace std; + +namespace orcus { + +namespace { + +class number_style_attr_parser : std::unary_function +{ + pstring m_country_code; + pstring m_style_name; + pstring m_language; + bool m_volatile; + +public: + + number_style_attr_parser(): + m_volatile(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + switch(attr.name) + { + case XML_country: + m_country_code = attr.value; + break; + case XML_language: + m_language = attr.value; + break; + default: + ; + } + } + else if (attr.ns == NS_odf_style) + { + switch (attr.name) + { + case XML_name: + m_style_name = attr.value; + break; + case XML_volatile: + m_volatile = attr.value == "true"; + break; + default: + ; + } + } + } + + pstring get_style_name() const { return m_style_name;} + pstring get_country_code() const { return m_country_code;} + bool is_volatile() const { return m_volatile;} + pstring get_language() const { return m_language;} +}; + +class number_attr_parser : std::unary_function +{ + size_t m_decimal_places; + size_t m_min_int_digits; + bool m_grouping; + bool m_has_decimal_places; + +public: + + number_attr_parser() : + m_grouping(false), + m_has_decimal_places(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + switch (attr.name) + { + case XML_decimal_places: + { + m_decimal_places = to_long(attr.value); + if (m_decimal_places > 0) + m_has_decimal_places = true; + } + break; + case XML_grouping: + m_grouping = attr.value == "true"; + break; + case XML_min_integer_digits: + m_min_int_digits = to_long(attr.value); + break; + default: + ; + } + } + } + + size_t get_decimal_places() const { return m_decimal_places;} + bool is_grouped() const { return m_grouping;} + size_t get_min_int_digits() const { return m_min_int_digits;} + bool has_decimal_places() const { return m_has_decimal_places;} +}; + +class scientific_number_attr_parser : std::unary_function +{ + size_t m_decimal_places; + bool m_grouping; + size_t m_min_exp_digits; + size_t m_min_int_digits; + +public: + + scientific_number_attr_parser() : + m_grouping(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + switch(attr.name) + { + case XML_decimal_places: + m_decimal_places = to_long(attr.value); + break; + case XML_grouping: + m_grouping = attr.value == "true"; + break; + case XML_min_exponent_digits: + m_min_exp_digits = to_long(attr.value); + break; + case XML_min_integer_digits: + m_min_int_digits = to_long(attr.value); + break; + default: + ; + } + } + } + + size_t get_decimal_places() const { return m_decimal_places;} + bool is_grouped() const { return m_grouping;} + size_t get_min_exp_digits() const { return m_min_exp_digits;} + size_t get_min_int_digits() const { return m_min_int_digits;} +}; + +class generic_style_attr_parser : std::unary_function +{ + pstring m_style_name; + bool m_volatile; + bool m_long; + +public: + generic_style_attr_parser() : + m_volatile(false), + m_long(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_style) + { + switch (attr.name) + { + case XML_name: + m_style_name = attr.value; + break; + case XML_volatile: + m_volatile = attr.value == "true"; + break; + default: + ; + } + } + else if (attr.ns == NS_odf_number) + if (attr.name == XML_style) + m_long = attr.value == "long"; + } + + pstring get_style_name() const { return m_style_name;} + bool is_volatile() const { return m_volatile;} + bool has_long() const { return m_long;} +}; + +class month_attr_parser : std::unary_function +{ + bool m_style_name; + bool m_textual; + +public: + month_attr_parser(): + m_textual(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + if (attr.name == XML_style) + m_style_name = attr.value == "long"; + if (attr.name == XML_textual) + m_textual = attr.value == "true"; + } + } + + bool has_long() const { return m_style_name;} + bool is_textual() const { return m_textual;} +}; + +class seconds_attr_parser : std::unary_function +{ + size_t m_decimal_places; + bool m_style_name; + bool m_has_decimal_places; + +public: + seconds_attr_parser(): + m_style_name(false), + m_has_decimal_places(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + if (attr.name == XML_style) + m_style_name = attr.value == "long"; + if (attr.name == XML_decimal_places) + { + m_decimal_places = to_long(attr.value); + m_has_decimal_places = true; + } + } + } + + bool has_long() const { return m_style_name;} + size_t get_decimal_places() const { return m_decimal_places;} + bool has_decimal_places() const { return m_has_decimal_places;} +}; + + +class fraction_attr_parser : std::unary_function +{ + size_t m_min_int_digits; + size_t m_min_deno_digits; + size_t m_min_num_digits; + pstring m_deno_value; + + bool m_predefined_deno; + +public: + fraction_attr_parser(): + m_predefined_deno(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_number) + { + switch(attr.name) + { + case XML_min_integer_digits: + m_min_int_digits = to_long(attr.value); + break; + case XML_min_numerator_digits: + m_min_num_digits = to_long(attr.value); + break; + case XML_min_denominator_digits: + m_min_deno_digits = to_long(attr.value); + break; + case XML_denominator_value: + { + m_deno_value = attr.value; + m_predefined_deno = true; + } + break; + default: + ; + } + } + } + + size_t get_min_int_digits() const { return m_min_int_digits;} + size_t get_min_num_digits() const { return m_min_num_digits;} + size_t get_min_deno_digits() const { return m_min_deno_digits;} + pstring get_deno_value() const { return m_deno_value;} + bool has_predefined_deno() const { return m_predefined_deno;} +}; + +class text_properties_attr_parser : std::unary_function +{ + pstring m_color; + bool color_absent; + +public: + text_properties_attr_parser(): + color_absent(true) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_fo) + { + switch (attr.name) + { + case XML_color: + { + if (attr.value == "#000000") + m_color = "BLACK"; + if (attr.value == "#ff0000") + m_color = "RED"; + if (attr.value == "#00ff00") + m_color = "GREEN"; + if (attr.value == "#0000ff") + m_color = "BLUE"; + if (attr.value == "#ffff00") + m_color = "YELLOW"; + if (attr.value == "#00ffff") + m_color = "CYAN"; + if (attr.value == "#ff00ff") + m_color = "MAGENTA"; + if (attr.value == "#ffffff") + m_color = "WHITE"; + else + color_absent = false; + } + } + } + } + + pstring get_color() const { return m_color;} + bool has_color() const { return !color_absent;} +}; + +class map_attr_parser : std::unary_function +{ + string m_value; + string m_sign; + bool m_has_map; + +public: + map_attr_parser(): + m_has_map(false) + {} + + void operator() (const xml_token_attr_t& attr) + { + if (attr.ns == NS_odf_style) + { + if (attr.name == XML_condition) + { + for (size_t i = 0; i < attr.value.size(); i++) + { + if (attr.value[i] == '<' || attr.value[i] == '>' || attr.value[i] == '=') + m_sign = m_sign + attr.value[i]; + if (isdigit(attr.value[i])) + m_value = m_value + attr.value[i]; + } + m_has_map = true; + } + } + } + string get_value() const { return m_value;} + string get_sign() const { return m_sign;} + bool has_map() const { return m_has_map;} +}; + +} + +number_formatting_context::number_formatting_context( + session_context& session_cxt, const tokens& tk, odf_styles_map_type& styles, + spreadsheet::iface::import_styles* iface_styles, number_formatting_style* number_format_style) : + xml_context_base(session_cxt, tk), + mp_styles(iface_styles), + m_styles(styles), + m_current_style(number_format_style) +{} + +bool number_formatting_context::can_handle_element(xmlns_id_t ns, xml_token_t name) const +{ + return true; +} + +xml_context_base* number_formatting_context::create_child_context(xmlns_id_t ns, xml_token_t name) +{ + return NULL; +} + +void number_formatting_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) +{ +} + +void number_formatting_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector& attrs) +{ + if (ns == NS_odf_number) + { + switch(name) + { + case XML_number_style: + { + number_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_number: + { + number_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + if (func.is_grouped()) + { + if (func.get_min_int_digits() < 4) + { + m_current_style->number_formatting_code += "#,"; + for (size_t i = 0; i < 3 - func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "#"; + } + for (size_t i = 0; i < func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "0"; + } + } + else + { + std:: string temporary_code; + for(size_t i = 0; i < func.get_min_int_digits(); i++) + { + if (i % 3 == 0 && i != 0) + temporary_code += ","; + temporary_code += "0"; + } + std::reverse(temporary_code.begin(), temporary_code.end()); + m_current_style->number_formatting_code += temporary_code; + } + } + else + { + if (func.get_min_int_digits() == 0) + m_current_style->number_formatting_code += "#"; + + for (size_t i = 0; i < func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "0"; + } + } + if (func.has_decimal_places()) + { + m_current_style->number_formatting_code += "."; + for(size_t i = 0; i < func.get_decimal_places() ; i++) + m_current_style->number_formatting_code += "0"; + } + } + break; + case XML_currency_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_percentage_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_scientific_number: + { + scientific_number_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + + if (func.is_grouped()) + { + if (func.get_min_int_digits() < 4) + { + m_current_style->number_formatting_code += "#,"; + for (size_t i = 0; i < 3 - func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "#"; + } + for (size_t i = 0; i < func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "0"; + } + } + else + { + std:: string temporary_code; + for(size_t i = 0; i < func.get_min_int_digits(); i++) + { + if (i % 3 == 0 && i != 0) + temporary_code += ","; + temporary_code += "0"; + } + std::reverse(temporary_code.begin(), temporary_code.end()); + m_current_style->number_formatting_code += temporary_code; + } + } + else + { + if (func.get_min_int_digits() == 0) + m_current_style->number_formatting_code += "#"; + + for (size_t i = 0; i < func.get_min_int_digits(); i++) + { + m_current_style->number_formatting_code += "0"; + } + } + + m_current_style->number_formatting_code += "."; + for(size_t i = 0; i < func.get_decimal_places() ; i++) + m_current_style->number_formatting_code += "0"; + + m_current_style->number_formatting_code += "E+"; + for(size_t i = 0; i < func.get_min_exp_digits() ; i++) + m_current_style->number_formatting_code += "0"; + } + break; + case XML_boolean_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_boolean: + { + m_current_style->number_formatting_code += "BOOLEAN"; + } + break; + case XML_fraction: + { + fraction_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + + for (size_t i = 0; i < func.get_min_int_digits(); i++) + m_current_style->number_formatting_code += "#"; + + if (func.get_min_int_digits() != 0) + m_current_style->number_formatting_code += " "; + + for (size_t i = 0; i < func.get_min_num_digits(); i++) + m_current_style->number_formatting_code += "?"; + + m_current_style->number_formatting_code += "/"; + if (func.has_predefined_deno()) + m_current_style->number_formatting_code += func.get_deno_value(); + else + for(size_t i = 0; i < func.get_min_deno_digits(); i++) + m_current_style->number_formatting_code += "?"; + } + break; + case XML_date_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_day: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "D"; + if (func.has_long()) + m_current_style->number_formatting_code += "D"; + } + break; + case XML_month: + { + month_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "M"; + if (func.has_long()) + m_current_style->number_formatting_code += "M"; + if (func.is_textual()) + m_current_style->number_formatting_code += "M"; + if (func.has_long() && func.is_textual()) + m_current_style->number_formatting_code += "M"; + } + break; + case XML_year: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "YY"; + if (func.has_long()) + m_current_style->number_formatting_code += "YY"; + } + break; + case XML_time_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_hours: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "H"; + if (func.has_long()) + m_current_style->number_formatting_code += "H"; + } + break; + case XML_minutes: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "M"; + if (func.has_long()) + m_current_style->number_formatting_code += "M"; + } + break; + case XML_seconds: + { + seconds_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->number_formatting_code += "S"; + if (func.has_long()) + m_current_style->number_formatting_code += "S"; + if (func.has_decimal_places()) + for (size_t i = 0; i < func.get_decimal_places(); i++) + m_current_style->number_formatting_code += "S"; + } + break; + case XML_am_pm: + { + m_current_style->number_formatting_code += " AM/PM"; + } + break; + case XML_text_style: + { + generic_style_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + m_current_style->name = func.get_style_name(); + m_current_style->is_volatile = func.is_volatile(); + } + break; + case XML_text_content: + { + m_current_style->number_formatting_code += "@"; + } + break; + default: + ; + } + } + if (ns == NS_odf_style) + { + switch (name) + { + case XML_text_properties: + { + text_properties_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + if (func.has_color()) + m_current_style->number_formatting_code = m_current_style->number_formatting_code + "[" + func.get_color() + "]"; + } + break; + case XML_map: + { + map_attr_parser func; + func = std::for_each(attrs.begin(), attrs.end(), func); + if (func.has_map()) + { + m_current_style->number_formatting_code = "[" + func.get_sign() + func.get_value() + "]" + + m_current_style->number_formatting_code; + } + } + break; + default: + ; + } + } +} + +bool number_formatting_context::end_element(xmlns_id_t ns, xml_token_t name) +{ + if (ns == NS_odf_number) + { + if (name == XML_number_style || name == XML_currency_style || name == XML_percentage_style + || name == XML_text_style || name == XML_boolean_style || name == XML_date_style + || name == XML_time_style) + { + if (m_current_style->is_volatile) + { + m_current_style->number_formatting_code += ";"; + } + else + { + mp_styles->set_number_format_code(m_current_style->number_formatting_code.c_str(), + m_current_style->number_formatting_code.size()); + mp_styles->set_xf_number_format(mp_styles->commit_number_format()); + + mp_styles->set_cell_style_name( m_current_style->name.get(), m_current_style->name.size()); + mp_styles->set_cell_style_xf(mp_styles->commit_cell_style_xf()); + mp_styles->commit_cell_style(); + return true; + } + } + else if (name == XML_currency_symbol) + m_current_style->number_formatting_code = m_current_style->number_formatting_code + "[$" + + m_current_style->character_stream + "]"; + + else if (name == XML_text) + m_current_style->number_formatting_code += m_current_style->character_stream; + } + m_current_style->character_stream.clear(); + return false; +} + + +void number_formatting_context::characters(const pstring& str, bool transient) +{ + if (str != "\n") + m_current_style->character_stream = str; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/liborcus/odf_number_formatting_context.hpp b/src/liborcus/odf_number_formatting_context.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7b191407ea0d429c22684ab60de9002807c58f3b --- /dev/null +++ b/src/liborcus/odf_number_formatting_context.hpp @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef ODF_NUMBER_FORMATTING_CONTEXT_HPP +#define ODF_NUMBER_FORMATTING_CONTEXT_HPP + +#include "xml_context_base.hpp" +#include "odf_styles.hpp" +#include "odf_styles_context.hpp" +#include "orcus/global.hpp" + +namespace orcus { + +namespace spreadsheet { namespace iface { + class import_styles; +}} + + +/** + * Context that handles scope. + */ +class number_formatting_context : public xml_context_base +{ +public: + number_formatting_context( + session_context& session_cxt, const tokens& tk, odf_styles_map_type& styles, spreadsheet::iface::import_styles* iface_styles, number_formatting_style*); + + virtual bool can_handle_element(xmlns_id_t ns, xml_token_t name) const; + virtual xml_context_base* create_child_context(xmlns_id_t ns, xml_token_t name); + virtual void end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child); + virtual void start_element(xmlns_id_t ns, xml_token_t name, const std::vector& attrs); + virtual bool end_element(xmlns_id_t ns, xml_token_t name); + virtual void characters(const pstring& str, bool transient); + +private: + + spreadsheet::iface::import_styles* mp_styles; + odf_styles_map_type& m_styles; + number_formatting_style* m_current_style; +}; + +} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/liborcus/odf_styles.cpp b/src/liborcus/odf_styles.cpp index 15b2448f353ce76879e7b5aefc3b74aba63047df..cbbf3f8bec4b0cbf9fc3c5e41e342eb39d080967 100644 --- a/src/liborcus/odf_styles.cpp +++ b/src/liborcus/odf_styles.cpp @@ -75,5 +75,12 @@ odf_style::~odf_style() } } +number_formatting_style::number_formatting_style(const pstring& style_name, const bool volatile_style) +{ + name = style_name; + is_volatile = volatile_style; +} + + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/liborcus/odf_styles.hpp b/src/liborcus/odf_styles.hpp index 62a392b69ecfa41dea5bb6912571350bfcff6e55..c89f464aab93c536c6b6829621a95c087d35f80a 100644 --- a/src/liborcus/odf_styles.hpp +++ b/src/liborcus/odf_styles.hpp @@ -97,6 +97,22 @@ struct odf_style ~odf_style(); }; +struct number_formatting_style +{ + size_t number_formatting; + + pstring name; + std::string number_formatting_code; + bool is_volatile; + pstring character_stream; + + number_formatting_style(): + is_volatile(false) + {} + + number_formatting_style(const pstring& style_name, const bool volatile_style); +}; + typedef std::map> odf_styles_map_type; } diff --git a/src/liborcus/odf_styles_context.cpp b/src/liborcus/odf_styles_context.cpp index c0847fbd8580797c8db7edd2ed72180f05feb34a..752f7faa435e794a2bec81ee9a9ce594d4c1d6b0 100644 --- a/src/liborcus/odf_styles_context.cpp +++ b/src/liborcus/odf_styles_context.cpp @@ -11,7 +11,7 @@ #include "odf_helper.hpp" #include "orcus/measurement.hpp" #include "orcus/spreadsheet/import_interface.hpp" - +#include "odf_number_formatting_context.hpp" #include using namespace std; @@ -431,16 +431,28 @@ styles_context::styles_context( bool styles_context::can_handle_element(xmlns_id_t ns, xml_token_t name) const { + if (ns == NS_odf_number) + return false; + return true; } xml_context_base* styles_context::create_child_context(xmlns_id_t ns, xml_token_t name) { - return NULL; + number_formatting_style* number_formatting = new number_formatting_style; + if (ns == NS_odf_number ) + { + mp_child.reset(new number_formatting_context(get_session_context(), get_tokens(), m_styles, mp_styles, number_formatting)); + mp_child->transfer_common(*this); + return mp_child.get(); + } + + return nullptr; } void styles_context::end_child_context(xmlns_id_t ns, xml_token_t name, xml_context_base* child) { + return; } void styles_context::start_element(xmlns_id_t ns, xml_token_t name, const std::vector& attrs) diff --git a/src/liborcus/odf_styles_context.hpp b/src/liborcus/odf_styles_context.hpp index fe9923ecf879d4219b44154381c92f07e9bf6f9f..a1eb45e093aa53fd91c3011a97dd5db91392d2ba 100644 --- a/src/liborcus/odf_styles_context.hpp +++ b/src/liborcus/odf_styles_context.hpp @@ -54,6 +54,7 @@ private: private: spreadsheet::iface::import_styles* mp_styles; odf_styles_map_type& m_styles; + std::unique_ptr mp_child; style_value_converter m_converter; diff --git a/src/liborcus/odf_styles_context_test.cpp b/src/liborcus/odf_styles_context_test.cpp index a283b23c09f50e4e76e7c2a0ac119d64ff46dd10..95d57971a84453b54006c5b7fee033fc2f328f84 100644 --- a/src/liborcus/odf_styles_context_test.cpp +++ b/src/liborcus/odf_styles_context_test.cpp @@ -28,17 +28,8 @@ const orcus::spreadsheet::cell_style_t* find_cell_style_by_name(const orcus::pst } -int main() +void test_odf_fill(orcus::spreadsheet::import_styles &styles) { - orcus::string_pool string_pool; - const char* path = SRCDIR"/test/ods/styles/cell-styles.xml"; - std::string content = orcus::load_file_content(path); - orcus::spreadsheet::import_styles styles(string_pool); - orcus::import_ods::read_styles(content.c_str(), content.size(), &styles); - -/* Test for Cell Fill - ===================================================== -*/ const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name1", &styles); assert(style->parent_name == "Text"); size_t xf = style->xf; @@ -54,16 +45,16 @@ int main() assert(cell_fill->bg_color.red == 0xfe); assert(cell_fill->bg_color.green == 0xff); assert(cell_fill->bg_color.blue == 0xcc); +} -/* Test for Border Styles - ===================================================== -*/ +void test_odf_border(orcus::spreadsheet::import_styles &styles) +{ assert(styles.get_border_count() == 8); /* Test that border style applies to all the sides when not specified */ - style = find_cell_style_by_name("Name1", &styles); - xf = style->xf; - cell_format = styles.get_cell_style_format(xf); + const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name1", &styles); + size_t xf = style->xf; + const orcus::spreadsheet::cell_format_t* cell_format = styles.get_cell_style_format(xf); size_t border = cell_format->border; assert(cell_format); @@ -109,14 +100,14 @@ int main() assert(cell_border->diagonal_bl_tr.border_color.red == 0xff); assert(cell_border->diagonal_tl_br.border_color.green == 0x00); assert(cell_border->diagonal_tl_br.border_width.value == 0.74); +} -/* Test for Cell Protection - ======================================================== -*/ +void test_odf_cell_protection(orcus::spreadsheet::import_styles& styles) +{ /* Test that Cell is only protected and not hidden , Print Content is true */ - style = find_cell_style_by_name("Name5", &styles); - xf = style->xf; - cell_format = styles.get_cell_style_format(xf); + const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name5", &styles); + size_t xf = style->xf; + const orcus::spreadsheet::cell_format_t* cell_format = styles.get_cell_style_format(xf); size_t protection = cell_format->protection; assert(cell_format); @@ -151,13 +142,13 @@ int main() assert(cell_protection->hidden == false); assert(cell_protection->print_content == true); assert(cell_protection->formula_hidden == false); +} -/* Test for Font and underline - ================================================== -*/ - style = find_cell_style_by_name("Name8", &styles); - xf = style->xf; - cell_format = styles.get_cell_style_format(xf); +void test_odf_font(orcus::spreadsheet::import_styles& styles) +{ + const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name8", &styles); + size_t xf = style->xf; + const orcus::spreadsheet::cell_format_t* cell_format = styles.get_cell_style_format(xf); size_t font = cell_format->font; assert(cell_format); @@ -192,6 +183,113 @@ int main() assert(cell_font->underline_color.red == (int)0x18); assert(cell_font->underline_color.green == (int)0x56); assert(cell_font->underline_color.blue == (int)0xff); +} + +void test_odf_number_formatting(orcus::spreadsheet::import_styles& styles) +{ + const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name10", &styles); + size_t xf = style->xf; + const orcus::spreadsheet::cell_format_t* cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + size_t number_format = cell_format->number_format; + const orcus::spreadsheet::number_format_t* cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "#.000000"); + + style = find_cell_style_by_name("Name11", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "[$₹]#,##0.00;[RED]-[$₹]#,##0.00"); + + style = find_cell_style_by_name("Name12", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "0.00%"); + + style = find_cell_style_by_name("Name13", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "#.00E+00"); + + style = find_cell_style_by_name("Name15", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "BOOLEAN"); + + style = find_cell_style_by_name("Name16", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "#### ?/11"); + + style = find_cell_style_by_name("Name17", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "MM/DD/YY"); + + style = find_cell_style_by_name("Name18", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + std::cerr<format_string.str(); + assert(cell_number_format->format_string.str() == "HH:MM:SS AM/PM"); + + style = find_cell_style_by_name("Name19", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + assert(cell_format); + + number_format = cell_format->number_format; + cell_number_format = styles.get_number_format(number_format); + assert(cell_number_format->format_string.str() == "[>=0]0.00;[RED]-0.00"); + +} +int main() +{ + orcus::string_pool string_pool; + const char* path = SRCDIR"/test/ods/styles/cell-styles.xml"; + std::string content = orcus::load_file_content(path); + orcus::spreadsheet::import_styles styles(string_pool); + orcus::import_ods::read_styles(content.c_str(), content.size(), &styles); + + test_odf_fill(styles); + test_odf_border(styles); + test_odf_cell_protection(styles); + test_odf_font(styles); + + orcus::string_pool string_pool2; + path = SRCDIR"/test/ods/styles/number-format.xml"; + std::string content2 = orcus::load_file_content(path); + orcus::spreadsheet::import_styles styles2(string_pool2); + orcus::import_ods::read_styles(content2.c_str(), content2.size(), &styles2); + + test_odf_number_formatting(styles2); return 0; } diff --git a/src/liborcus/orcus_import_ods.cpp b/src/liborcus/orcus_import_ods.cpp index 2d76dbb780787f7fda1d598550de76782d482cc8..f929fe095234bd0415d7b083f9e3242689bacfa8 100644 --- a/src/liborcus/orcus_import_ods.cpp +++ b/src/liborcus/orcus_import_ods.cpp @@ -18,7 +18,6 @@ #include "session_context.hpp" #include "xml_stream_parser.hpp" -#include "xml_simple_stream_handler.hpp" namespace orcus { @@ -34,7 +33,7 @@ void import_ods::read_styles(const char* p, size_t n, spreadsheet::iface::import odf_styles_map_type styles_map; auto context = orcus::make_unique(cxt, odf_tokens, styles_map, styles); - xml_simple_stream_handler stream_handler(context.release()); + xml_stream_handler stream_handler(context.release()); xmlns_repository ns_repo; ns_repo.add_predefined_values(NS_odf_all); diff --git a/src/liborcus/xml_stream_handler.hpp b/src/liborcus/xml_stream_handler.hpp index 25c7de3412f20e8df2e27cad891bb2cd0ecc165d..cf0dc38f2ed8d84faec1a10f310ff26f683180c9 100644 --- a/src/liborcus/xml_stream_handler.hpp +++ b/src/liborcus/xml_stream_handler.hpp @@ -31,7 +31,7 @@ class xml_stream_handler xml_stream_handler(); // disabled public: xml_stream_handler(xml_context_base* root_context); - virtual ~xml_stream_handler() = 0; + virtual ~xml_stream_handler() ; virtual void start_document(); virtual void end_document(); diff --git a/test/ods/styles/number-format.xml b/test/ods/styles/number-format.xml new file mode 100644 index 0000000000000000000000000000000000000000..ecc1fbc9aed170de23247812d0ee402bf674b803 --- /dev/null +++ b/test/ods/styles/number-format.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + - + + + + + + % + + + + + + + December + + + + + + + + + + / + + / + + + + + : + + : + + + + + + + + + + - + + + +