diff options
Diffstat (limited to 'src/spreadsheet')
48 files changed, 9672 insertions, 0 deletions
diff --git a/src/spreadsheet/Makefile.am b/src/spreadsheet/Makefile.am new file mode 100644 index 0000000..8f1e0fb --- /dev/null +++ b/src/spreadsheet/Makefile.am @@ -0,0 +1,90 @@ +if BUILD_SPREADSHEET_MODEL + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/include \ + -D__ORCUS_SPM_BUILDING_DLL + +AM_CPPFLAGS += $(BOOST_CPPFLAGS) $(LIBIXION_CFLAGS) + +if HAVE_FILESYSTEM +AM_CPPFLAGS += "-DHAVE_FILESYSTEM=1" +endif + +if HAVE_EXPERIMENTAL_FILESYSTEM +AM_CPPFLAGS += "-DHAVE_EXPERIMENTAL_FILESYSTEM=1" +endif + +COMMON_CPPFLAGS = $(AM_CPPFLAGS) + +if HAVE_STATIC_LIB +AM_CPPFLAGS += -D__ORCUS_STATIC_LIB=1 +endif + +lib_LTLIBRARIES = liborcus-spreadsheet-model-@ORCUS_API_VERSION@.la +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES = \ + auto_filter.cpp \ + check_dumper.hpp \ + check_dumper.cpp \ + config.cpp \ + debug_state_dumper.hpp \ + debug_state_dumper.cpp \ + document.cpp \ + document_impl.hpp \ + document_impl.cpp \ + document_types.cpp \ + dumper_global.hpp \ + dumper_global.cpp \ + factory.cpp \ + factory_pivot.hpp \ + factory_pivot.cpp \ + factory_shared_strings.hpp \ + factory_shared_strings.cpp \ + factory_sheet.hpp \ + factory_sheet.cpp \ + factory_styles.cpp \ + factory_table.hpp \ + factory_table.cpp \ + flat_dumper.hpp \ + flat_dumper.cpp \ + formula_global.hpp \ + formula_global.cpp \ + html_dumper.hpp \ + html_dumper.cpp \ + impl_types.hpp \ + csv_dumper.hpp \ + csv_dumper.cpp \ + json_dumper.hpp \ + json_dumper.cpp \ + number_format.hpp \ + number_format.cpp \ + pivot.cpp \ + shared_formula.hpp \ + shared_formula.cpp \ + shared_strings.cpp \ + sheet.cpp \ + sheet_impl.hpp \ + sheet_impl.cpp \ + styles.cpp \ + view.cpp \ + global_settings.hpp \ + global_settings.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBIXION_CFLAGS) +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LDFLAGS = -no-undefined +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LIBADD = \ + $(LIBIXION_LIBS) \ + $(BOOST_DATE_TIME_LIBS) \ + $(BOOST_SYSTEM_LIBS) \ + ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \ + ../liborcus/liborcus-@ORCUS_API_VERSION@.la + +if !HAVE_FILESYSTEM +if HAVE_EXPERIMENTAL_FILESYSTEM +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LIBADD += -lstdc++fs +else +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LIBADD += $(BOOST_FILESYSTEM_LIBS) +endif +endif + +endif diff --git a/src/spreadsheet/Makefile.in b/src/spreadsheet/Makefile.in new file mode 100644 index 0000000..f1fabb8 --- /dev/null +++ b/src/spreadsheet/Makefile.in @@ -0,0 +1,1134 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_FILESYSTEM_TRUE@am__append_1 = "-DHAVE_FILESYSTEM=1" +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@am__append_2 = "-DHAVE_EXPERIMENTAL_FILESYSTEM=1" +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_STATIC_LIB_TRUE@am__append_3 = -D__ORCUS_STATIC_LIB=1 +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_EXPERIMENTAL_FILESYSTEM_TRUE@@HAVE_FILESYSTEM_FALSE@am__append_4 = -lstdc++fs +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__append_5 = $(BOOST_FILESYSTEM_LIBS) +subdir = src/spreadsheet +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/m4_ax_valgrind_check.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +@BUILD_SPREADSHEET_MODEL_TRUE@@HAVE_EXPERIMENTAL_FILESYSTEM_FALSE@@HAVE_FILESYSTEM_FALSE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +@BUILD_SPREADSHEET_MODEL_TRUE@liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_DEPENDENCIES = \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__DEPENDENCIES_1) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__DEPENDENCIES_1) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__DEPENDENCIES_1) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \ +@BUILD_SPREADSHEET_MODEL_TRUE@ ../liborcus/liborcus-@ORCUS_API_VERSION@.la \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__DEPENDENCIES_1) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__DEPENDENCIES_2) +am__liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES_DIST = \ + auto_filter.cpp check_dumper.hpp check_dumper.cpp config.cpp \ + debug_state_dumper.hpp debug_state_dumper.cpp document.cpp \ + document_impl.hpp document_impl.cpp document_types.cpp \ + dumper_global.hpp dumper_global.cpp factory.cpp \ + factory_pivot.hpp factory_pivot.cpp factory_shared_strings.hpp \ + factory_shared_strings.cpp factory_sheet.hpp factory_sheet.cpp \ + factory_styles.cpp factory_table.hpp factory_table.cpp \ + flat_dumper.hpp flat_dumper.cpp formula_global.hpp \ + formula_global.cpp html_dumper.hpp html_dumper.cpp \ + impl_types.hpp csv_dumper.hpp csv_dumper.cpp json_dumper.hpp \ + json_dumper.cpp number_format.hpp number_format.cpp pivot.cpp \ + shared_formula.hpp shared_formula.cpp shared_strings.cpp \ + sheet.cpp sheet_impl.hpp sheet_impl.cpp styles.cpp view.cpp \ + global_settings.hpp global_settings.cpp +@BUILD_SPREADSHEET_MODEL_TRUE@am_liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_OBJECTS = liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo \ +@BUILD_SPREADSHEET_MODEL_TRUE@ liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_OBJECTS = $(am_liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LINK = $(LIBTOOL) \ + $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LDFLAGS) \ + $(LDFLAGS) -o $@ +@BUILD_SPREADSHEET_MODEL_TRUE@am_liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_rpath = \ +@BUILD_SPREADSHEET_MODEL_TRUE@ -rpath $(libdir) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Plo \ + ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Plo +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = \ + $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES) +DIST_SOURCES = $(am__liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__extra_recursive_targets = check-valgrind-recursive \ + check-valgrind-memcheck-recursive \ + check-valgrind-helgrind-recursive check-valgrind-drd-recursive \ + check-valgrind-sgcheck-recursive +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_DATE_TIME_LDFLAGS = @BOOST_DATE_TIME_LDFLAGS@ +BOOST_DATE_TIME_LDPATH = @BOOST_DATE_TIME_LDPATH@ +BOOST_DATE_TIME_LIBS = @BOOST_DATE_TIME_LIBS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_IOSTREAMS_LDFLAGS = @BOOST_IOSTREAMS_LDFLAGS@ +BOOST_IOSTREAMS_LDPATH = @BOOST_IOSTREAMS_LDPATH@ +BOOST_IOSTREAMS_LIBS = @BOOST_IOSTREAMS_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_VALGRIND_drd = @ENABLE_VALGRIND_drd@ +ENABLE_VALGRIND_helgrind = @ENABLE_VALGRIND_helgrind@ +ENABLE_VALGRIND_memcheck = @ENABLE_VALGRIND_memcheck@ +ENABLE_VALGRIND_sgcheck = @ENABLE_VALGRIND_sgcheck@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_REQUIRED_API_VERSION = @IXION_REQUIRED_API_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBIXION_CFLAGS = @LIBIXION_CFLAGS@ +LIBIXION_LIBS = @LIBIXION_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +ORCUS_API_VERSION = @ORCUS_API_VERSION@ +ORCUS_MAJOR_VERSION = @ORCUS_MAJOR_VERSION@ +ORCUS_MICRO_VERSION = @ORCUS_MICRO_VERSION@ +ORCUS_MINOR_VERSION = @ORCUS_MINOR_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PARQUET_CFLAGS = @PARQUET_CFLAGS@ +PARQUET_LIBS = @PARQUET_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VALGRIND = @VALGRIND@ +VALGRIND_ENABLED = @VALGRIND_ENABLED@ +VERSION = @VERSION@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +valgrind_enabled_tools = @valgrind_enabled_tools@ +valgrind_tools = @valgrind_tools@ +@BUILD_SPREADSHEET_MODEL_TRUE@AM_CPPFLAGS = -I$(top_srcdir)/include \ +@BUILD_SPREADSHEET_MODEL_TRUE@ -I$(top_srcdir)/src/include \ +@BUILD_SPREADSHEET_MODEL_TRUE@ -D__ORCUS_SPM_BUILDING_DLL \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(BOOST_CPPFLAGS) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(LIBIXION_CFLAGS) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__append_1) $(am__append_2) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__append_3) +@BUILD_SPREADSHEET_MODEL_TRUE@COMMON_CPPFLAGS = $(AM_CPPFLAGS) +@BUILD_SPREADSHEET_MODEL_TRUE@lib_LTLIBRARIES = liborcus-spreadsheet-model-@ORCUS_API_VERSION@.la +@BUILD_SPREADSHEET_MODEL_TRUE@liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_SOURCES = \ +@BUILD_SPREADSHEET_MODEL_TRUE@ auto_filter.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ check_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ check_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ config.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ debug_state_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ debug_state_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ document.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ document_impl.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ document_impl.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ document_types.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ dumper_global.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ dumper_global.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_pivot.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_pivot.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_shared_strings.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_shared_strings.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_sheet.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_sheet.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_styles.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_table.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ factory_table.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ flat_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ flat_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ formula_global.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ formula_global.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ html_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ html_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ impl_types.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ csv_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ csv_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ json_dumper.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ json_dumper.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ number_format.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ number_format.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ pivot.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ shared_formula.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ shared_formula.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ shared_strings.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ sheet.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ sheet_impl.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ sheet_impl.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ styles.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ view.cpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ global_settings.hpp \ +@BUILD_SPREADSHEET_MODEL_TRUE@ global_settings.cpp + +@BUILD_SPREADSHEET_MODEL_TRUE@liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBIXION_CFLAGS) +@BUILD_SPREADSHEET_MODEL_TRUE@liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LDFLAGS = -no-undefined +@BUILD_SPREADSHEET_MODEL_TRUE@liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LIBADD = \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(LIBIXION_LIBS) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(BOOST_DATE_TIME_LIBS) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(BOOST_SYSTEM_LIBS) \ +@BUILD_SPREADSHEET_MODEL_TRUE@ ../parser/liborcus-parser-@ORCUS_API_VERSION@.la \ +@BUILD_SPREADSHEET_MODEL_TRUE@ ../liborcus/liborcus-@ORCUS_API_VERSION@.la \ +@BUILD_SPREADSHEET_MODEL_TRUE@ $(am__append_4) $(am__append_5) +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/spreadsheet/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/spreadsheet/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +liborcus-spreadsheet-model-@ORCUS_API_VERSION@.la: $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_DEPENDENCIES) $(EXTRA_liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_DEPENDENCIES) + $(AM_V_CXXLD)$(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LINK) $(am_liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_rpath) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_OBJECTS) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo: auto_filter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo `test -f 'auto_filter.cpp' || echo '$(srcdir)/'`auto_filter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='auto_filter.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.lo `test -f 'auto_filter.cpp' || echo '$(srcdir)/'`auto_filter.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo: check_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo `test -f 'check_dumper.cpp' || echo '$(srcdir)/'`check_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='check_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.lo `test -f 'check_dumper.cpp' || echo '$(srcdir)/'`check_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo: config.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo `test -f 'config.cpp' || echo '$(srcdir)/'`config.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='config.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.lo `test -f 'config.cpp' || echo '$(srcdir)/'`config.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo: debug_state_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo `test -f 'debug_state_dumper.cpp' || echo '$(srcdir)/'`debug_state_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='debug_state_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.lo `test -f 'debug_state_dumper.cpp' || echo '$(srcdir)/'`debug_state_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo: document.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='document.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo: document_impl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo `test -f 'document_impl.cpp' || echo '$(srcdir)/'`document_impl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='document_impl.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.lo `test -f 'document_impl.cpp' || echo '$(srcdir)/'`document_impl.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo: document_types.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo `test -f 'document_types.cpp' || echo '$(srcdir)/'`document_types.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='document_types.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.lo `test -f 'document_types.cpp' || echo '$(srcdir)/'`document_types.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo: dumper_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo `test -f 'dumper_global.cpp' || echo '$(srcdir)/'`dumper_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='dumper_global.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.lo `test -f 'dumper_global.cpp' || echo '$(srcdir)/'`dumper_global.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo: factory.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo `test -f 'factory.cpp' || echo '$(srcdir)/'`factory.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.lo `test -f 'factory.cpp' || echo '$(srcdir)/'`factory.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo: factory_pivot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo `test -f 'factory_pivot.cpp' || echo '$(srcdir)/'`factory_pivot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory_pivot.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.lo `test -f 'factory_pivot.cpp' || echo '$(srcdir)/'`factory_pivot.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo: factory_shared_strings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo `test -f 'factory_shared_strings.cpp' || echo '$(srcdir)/'`factory_shared_strings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory_shared_strings.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.lo `test -f 'factory_shared_strings.cpp' || echo '$(srcdir)/'`factory_shared_strings.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo: factory_sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo `test -f 'factory_sheet.cpp' || echo '$(srcdir)/'`factory_sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory_sheet.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.lo `test -f 'factory_sheet.cpp' || echo '$(srcdir)/'`factory_sheet.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo: factory_styles.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo `test -f 'factory_styles.cpp' || echo '$(srcdir)/'`factory_styles.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory_styles.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.lo `test -f 'factory_styles.cpp' || echo '$(srcdir)/'`factory_styles.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo: factory_table.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo `test -f 'factory_table.cpp' || echo '$(srcdir)/'`factory_table.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='factory_table.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.lo `test -f 'factory_table.cpp' || echo '$(srcdir)/'`factory_table.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo: flat_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo `test -f 'flat_dumper.cpp' || echo '$(srcdir)/'`flat_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='flat_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.lo `test -f 'flat_dumper.cpp' || echo '$(srcdir)/'`flat_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo: formula_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo `test -f 'formula_global.cpp' || echo '$(srcdir)/'`formula_global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='formula_global.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.lo `test -f 'formula_global.cpp' || echo '$(srcdir)/'`formula_global.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo: html_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo `test -f 'html_dumper.cpp' || echo '$(srcdir)/'`html_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='html_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.lo `test -f 'html_dumper.cpp' || echo '$(srcdir)/'`html_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo: csv_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo `test -f 'csv_dumper.cpp' || echo '$(srcdir)/'`csv_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='csv_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.lo `test -f 'csv_dumper.cpp' || echo '$(srcdir)/'`csv_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo: json_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo `test -f 'json_dumper.cpp' || echo '$(srcdir)/'`json_dumper.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='json_dumper.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.lo `test -f 'json_dumper.cpp' || echo '$(srcdir)/'`json_dumper.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo: number_format.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo `test -f 'number_format.cpp' || echo '$(srcdir)/'`number_format.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='number_format.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.lo `test -f 'number_format.cpp' || echo '$(srcdir)/'`number_format.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo: pivot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo `test -f 'pivot.cpp' || echo '$(srcdir)/'`pivot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='pivot.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.lo `test -f 'pivot.cpp' || echo '$(srcdir)/'`pivot.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo: shared_formula.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo `test -f 'shared_formula.cpp' || echo '$(srcdir)/'`shared_formula.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shared_formula.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.lo `test -f 'shared_formula.cpp' || echo '$(srcdir)/'`shared_formula.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo: shared_strings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo `test -f 'shared_strings.cpp' || echo '$(srcdir)/'`shared_strings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='shared_strings.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.lo `test -f 'shared_strings.cpp' || echo '$(srcdir)/'`shared_strings.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo: sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sheet.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo: sheet_impl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo `test -f 'sheet_impl.cpp' || echo '$(srcdir)/'`sheet_impl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sheet_impl.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.lo `test -f 'sheet_impl.cpp' || echo '$(srcdir)/'`sheet_impl.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo: styles.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo `test -f 'styles.cpp' || echo '$(srcdir)/'`styles.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='styles.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.lo `test -f 'styles.cpp' || echo '$(srcdir)/'`styles.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo: view.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo `test -f 'view.cpp' || echo '$(srcdir)/'`view.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='view.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.lo `test -f 'view.cpp' || echo '$(srcdir)/'`view.cpp + +liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo: global_settings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo -MD -MP -MF $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Tpo -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo `test -f 'global_settings.cpp' || echo '$(srcdir)/'`global_settings.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Tpo $(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='global_settings.cpp' object='liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.lo `test -f 'global_settings.cpp' || echo '$(srcdir)/'`global_settings.cpp + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +check-valgrind-local: +check-valgrind-memcheck-local: +check-valgrind-helgrind-local: +check-valgrind-drd-local: +check-valgrind-sgcheck-local: +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +check-valgrind: check-valgrind-am + +check-valgrind-am: check-valgrind-local + +check-valgrind-drd: check-valgrind-drd-am + +check-valgrind-drd-am: check-valgrind-drd-local + +check-valgrind-helgrind: check-valgrind-helgrind-am + +check-valgrind-helgrind-am: check-valgrind-helgrind-local + +check-valgrind-memcheck: check-valgrind-memcheck-am + +check-valgrind-memcheck-am: check-valgrind-memcheck-local + +check-valgrind-sgcheck: check-valgrind-sgcheck-am + +check-valgrind-sgcheck-am: check-valgrind-sgcheck-local + +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-auto_filter.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-check_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-config.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-csv_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-debug_state_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_impl.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-document_types.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-dumper_global.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_pivot.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_shared_strings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_sheet.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_styles.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-factory_table.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-flat_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-formula_global.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-global_settings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-html_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-json_dumper.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-number_format.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-pivot.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_formula.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-shared_strings.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-sheet_impl.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-styles.Plo + -rm -f ./$(DEPDIR)/liborcus_spreadsheet_model_@ORCUS_API_VERSION@_la-view.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: all all-am am--depfiles check check-am check-valgrind-am \ + check-valgrind-drd-am check-valgrind-drd-local \ + check-valgrind-helgrind-am check-valgrind-helgrind-local \ + check-valgrind-local check-valgrind-memcheck-am \ + check-valgrind-memcheck-local check-valgrind-sgcheck-am \ + check-valgrind-sgcheck-local clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags-am \ + distclean distclean-compile distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am uninstall-libLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/spreadsheet/auto_filter.cpp b/src/spreadsheet/auto_filter.cpp new file mode 100644 index 0000000..3262305 --- /dev/null +++ b/src/spreadsheet/auto_filter.cpp @@ -0,0 +1,116 @@ +/* -*- 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 "orcus/spreadsheet/auto_filter.hpp" + +namespace orcus { namespace spreadsheet { + +auto_filter_column_t::auto_filter_column_t() = default; +auto_filter_column_t::auto_filter_column_t(const auto_filter_column_t& other) = default; +auto_filter_column_t::auto_filter_column_t(auto_filter_column_t&& other) = default; +auto_filter_column_t::~auto_filter_column_t() = default; + +auto_filter_column_t& auto_filter_column_t::operator=(const auto_filter_column_t& other) = default; +auto_filter_column_t& auto_filter_column_t::operator=(auto_filter_column_t&& other) = default; + +void auto_filter_column_t::reset() +{ + match_values.clear(); +} + +void auto_filter_column_t::swap(auto_filter_column_t& r) +{ + match_values.swap(r.match_values); +} + +auto_filter_t::auto_filter_t() : range(ixion::abs_range_t::invalid) {} +auto_filter_t::auto_filter_t(const auto_filter_t& other) = default; +auto_filter_t::auto_filter_t(auto_filter_t&& other) = default; +auto_filter_t::~auto_filter_t() = default; + +auto_filter_t& auto_filter_t::operator=(const auto_filter_t& other) = default; +auto_filter_t& auto_filter_t::operator=(auto_filter_t&& other) = default; + +void auto_filter_t::reset() +{ + range = ixion::abs_range_t(ixion::abs_range_t::invalid); + columns.clear(); +} + +void auto_filter_t::swap(auto_filter_t& r) +{ + std::swap(range, r.range); + columns.swap(r.columns); +} + +void auto_filter_t::commit_column(col_t col, auto_filter_column_t data) +{ + if (col < 0) + // Invalid column index. Nothing happens. + return; + + columns.insert_or_assign(col, std::move(data)); +} + +table_column_t::table_column_t() : identifier(0), totals_row_function(totals_row_function_t::none) {} + +table_column_t::table_column_t(const table_column_t& other) = default; +table_column_t::~table_column_t() = default; + +table_column_t& table_column_t::operator=(const table_column_t& other) = default; + +void table_column_t::reset() +{ + identifier = 0; + name = std::string_view{}; + totals_row_label = std::string_view{}; + totals_row_function = totals_row_function_t::none; +} + +table_style_t::table_style_t() : + show_first_column(false), + show_last_column(false), + show_row_stripes(false), + show_column_stripes(false) {} + +table_style_t::table_style_t(const table_style_t& other) = default; +table_style_t::~table_style_t() = default; + +table_style_t& table_style_t::operator=(const table_style_t& other) = default; + +void table_style_t::reset() +{ + name = std::string_view{}; + show_first_column = false; + show_last_column = false; + show_row_stripes = false; + show_column_stripes = false; +} + +table_t::table_t() : identifier(0), range(ixion::abs_range_t::invalid), totals_row_count(0) {} +table_t::table_t(const table_t& other) = default; +table_t::table_t(table_t&& other) = default; +table_t::~table_t() = default; + +table_t& table_t::operator=(const table_t& other) = default; +table_t& table_t::operator=(table_t&& other) = default; + +void table_t::reset() +{ + identifier = 0; + name = std::string_view{}; + display_name = std::string_view{}; + range = ixion::abs_range_t(ixion::abs_range_t::invalid); + totals_row_count = 0; + filter.reset(); + columns.clear(); + style.reset(); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/check_dumper.cpp b/src/spreadsheet/check_dumper.cpp new file mode 100644 index 0000000..191b5a0 --- /dev/null +++ b/src/spreadsheet/check_dumper.cpp @@ -0,0 +1,209 @@ +/* -*- 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 "check_dumper.hpp" +#include "sheet_impl.hpp" +#include "number_format.hpp" +#include "orcus/spreadsheet/document.hpp" + +#include <ixion/model_context.hpp> +#include <ixion/cell.hpp> +#include <ixion/formula.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> + +#include <string> +#include <algorithm> + +namespace orcus { namespace spreadsheet { namespace detail { + +namespace { + +void write_cell_position(std::ostream& os, std::string_view sheet_name, row_t row, col_t col) +{ + os << sheet_name << '/' << row << '/' << col << ':'; +} + +std::string escape_chars(const std::string& str) +{ + if (str.empty()) + return str; + + std::string ret; + const char* p = &str[0]; + const char* p_end = p + str.size(); + for (; p != p_end; ++p) + { + if (*p == '"') + ret.push_back('\\'); + ret.push_back(*p); + } + return ret; +} + +} + +check_dumper::check_dumper(const detail::sheet_impl& sheet, std::string_view sheet_name) : + m_sheet(sheet), m_sheet_name(sheet_name) +{ +} + +void check_dumper::dump(std::ostream& os) const +{ + dump_cell_values(os); + dump_merged_cell_info(os); +} + +void check_dumper::dump_cell_values(std::ostream& os) const +{ + ixion::abs_range_t range = m_sheet.get_data_range(); + if (!range.valid()) + // Sheet is empty. Nothing to print. + return; + + const ixion::model_context& cxt = m_sheet.doc.get_model_context(); + const ixion::formula_name_resolver* resolver = + m_sheet.doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + + size_t row_count = range.last.row + 1; + size_t col_count = range.last.column + 1; + + for (size_t row = 0; row < row_count; ++row) + { + for (size_t col = 0; col < col_count; ++col) + { + ixion::abs_address_t pos(m_sheet.sheet_id, row, col); + switch (cxt.get_celltype(pos)) + { + case ixion::celltype_t::string: + { + write_cell_position(os, m_sheet_name, row, col); + size_t sindex = cxt.get_string_identifier(pos); + const std::string* p = cxt.get_string(sindex); + assert(p); + os << "string:\"" << escape_chars(*p) << '"' << std::endl; + break; + } + case ixion::celltype_t::numeric: + { + write_cell_position(os, m_sheet_name, row, col); + os << "numeric:"; + detail::format_to_file_output(os, cxt.get_numeric_value(pos)); + os << std::endl; + break; + } + case ixion::celltype_t::boolean: + { + write_cell_position(os, m_sheet_name, row, col); + os << "boolean:" << (cxt.get_boolean_value(pos) ? "true" : "false") << std::endl; + break; + } + case ixion::celltype_t::formula: + { + write_cell_position(os, m_sheet_name, row, col); + os << "formula"; + + // print the formula and the formula result. + const ixion::formula_cell* cell = cxt.get_formula_cell(pos); + assert(cell); + const ixion::formula_tokens_store_ptr_t& ts = cell->get_tokens(); + if (ts) + { + const ixion::formula_tokens_t& tokens = ts->get(); + std::string formula; + if (resolver) + { + pos = cell->get_parent_position(pos); + formula = ixion::print_formula_tokens( + m_sheet.doc.get_model_context(), pos, *resolver, tokens); + } + else + formula = "???"; + + os << ':'; + + ixion::formula_group_t fg = cell->get_group_properties(); + + if (fg.grouped) + os << '{' << formula << '}'; + else + os << formula; + + try + { + ixion::formula_result res = cell->get_result_cache( + ixion::formula_result_wait_policy_t::throw_exception); + os << ':' << res.str(m_sheet.doc.get_model_context()); + } + catch (const std::exception&) + { + os << ":#RES!"; + } + } + + os << std::endl; + break; + } + default: + ; + } + } + } +} + +void check_dumper::dump_merged_cell_info(std::ostream& os) const +{ + // Sort by rows first then by columns. + + struct _entry + { + row_t row; + col_t col; + const merge_size* ms; + + _entry(row_t _row, col_t _col, const merge_size* _ms) : + row(_row), col(_col), ms(_ms) {} + }; + + std::vector<_entry> entries; + + for (const auto& col_entry : m_sheet.merge_ranges) + { + col_t col = col_entry.first; + + for (const auto& row_entry : *col_entry.second) + { + row_t row = row_entry.first; + const merge_size& ms = row_entry.second; + + entries.emplace_back(row, col, &ms); + } + } + + std::sort(entries.begin(), entries.end(), + [](const _entry& left, const _entry& right) -> bool + { + if (left.row != right.row) + return left.row < right.row; + + if (left.col != right.col) + return left.col < right.col; + + return left.ms < right.ms; + } + ); + + for (const _entry e : entries) + { + os << m_sheet_name << '/' << e.row << '/' << e.col << ":merge-width:" << e.ms->width << std::endl; + os << m_sheet_name << '/' << e.row << '/' << e.col << ":merge-height:" << e.ms->height << std::endl; + } +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/check_dumper.hpp b/src/spreadsheet/check_dumper.hpp new file mode 100644 index 0000000..3a55a2c --- /dev/null +++ b/src/spreadsheet/check_dumper.hpp @@ -0,0 +1,38 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_CHECK_DUMPER_HPP +#define INCLUDED_ORCUS_SPREADSHEET_CHECK_DUMPER_HPP + +#include <ostream> +#include <string_view> + +namespace orcus { namespace spreadsheet { + +namespace detail { + +struct sheet_impl; + +class check_dumper +{ + const sheet_impl& m_sheet; + std::string_view m_sheet_name; + +public: + check_dumper(const sheet_impl& sheet, std::string_view sheet_name); + void dump(std::ostream& os) const; + +private: + void dump_cell_values(std::ostream& os) const; + void dump_merged_cell_info(std::ostream& os) const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/config.cpp b/src/spreadsheet/config.cpp new file mode 100644 index 0000000..45a7934 --- /dev/null +++ b/src/spreadsheet/config.cpp @@ -0,0 +1,28 @@ +/* -*- 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 "orcus/spreadsheet/config.hpp" + +namespace orcus { namespace spreadsheet { + +document_config::document_config() : + output_precision(-1) {} + +document_config::document_config(const document_config& r) : + output_precision(r.output_precision) {} + +document_config::~document_config() {} + +document_config& document_config::operator= (const document_config& r) +{ + output_precision = r.output_precision; + return *this; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/csv_dumper.cpp b/src/spreadsheet/csv_dumper.cpp new file mode 100644 index 0000000..5aa5a4e --- /dev/null +++ b/src/spreadsheet/csv_dumper.cpp @@ -0,0 +1,95 @@ +/* -*- 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 "csv_dumper.hpp" +#include "dumper_global.hpp" +#include "orcus/spreadsheet/document.hpp" + +#include <ixion/model_context.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> +#include <mdds/multi_type_vector/collection.hpp> + +#include <fstream> +#include <sstream> +#include <iostream> + +namespace orcus { namespace spreadsheet { namespace detail { + +namespace { + +void dump_string(std::ostream& os, const std::string& s) +{ + // Scan for any special characters that necessitate quoting. + bool outer_quotes = s.find_first_of(",\"") != std::string::npos; + + if (outer_quotes) + os << '"'; + + for (const char c : s) + { + switch (c) + { + case '"': + { + os << c << c; + break; + } + default: + os << c; + } + } + + if (outer_quotes) + os << '"'; +} + +void dump_empty(std::ostream& /*os*/) +{ + // Do nothing. +} + +} + +csv_dumper::csv_dumper(const document& doc) : + m_doc(doc), m_sep(','), m_quote('"') +{ +} + +void csv_dumper::dump(std::ostream& os, ixion::sheet_t sheet_id) const +{ + const ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_range_t data_range = cxt.get_data_range(sheet_id); + if (!data_range.valid()) + return; + + ixion::abs_rc_range_t iter_range; + iter_range.first.column = 0; + iter_range.first.row = 0; + iter_range.last.column = data_range.last.column; + iter_range.last.row = data_range.last.row; + + auto iter = cxt.get_model_iterator( + sheet_id, ixion::rc_direction_t::horizontal, iter_range); + + for (; iter.has(); iter.next()) + { + const auto& cell = iter.get(); + + if (cell.col == 0 && cell.row > 0) + os << std::endl; + + if (cell.col > 0) + os << m_sep; + + dump_cell_value(os, cxt, cell, dump_string, dump_empty); + } +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/csv_dumper.hpp b/src/spreadsheet/csv_dumper.hpp new file mode 100644 index 0000000..a03bbe9 --- /dev/null +++ b/src/spreadsheet/csv_dumper.hpp @@ -0,0 +1,38 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_CSV_DUMPER_HPP +#define INCLUDED_ORCUS_SPREADSHEET_CSV_DUMPER_HPP + +#include <string> +#include <ostream> +#include <ixion/types.hpp> + +namespace orcus { namespace spreadsheet { + +class document; + +namespace detail { + +class csv_dumper +{ + const document& m_doc; + const char m_sep; + const char m_quote; + +public: + csv_dumper(const document& doc); + + void dump(std::ostream& os, ixion::sheet_t sheet_id) const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/src/spreadsheet/debug_state_dumper.cpp b/src/spreadsheet/debug_state_dumper.cpp new file mode 100644 index 0000000..c748924 --- /dev/null +++ b/src/spreadsheet/debug_state_dumper.cpp @@ -0,0 +1,460 @@ +/* -*- 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 "debug_state_dumper.hpp" +#include "check_dumper.hpp" +#include "document_impl.hpp" +#include "sheet_impl.hpp" +#include "ostream_utils.hpp" + +#include <ixion/formula_name_resolver.hpp> +#include <ixion/named_expressions_iterator.hpp> + +#include <fstream> +#include <algorithm> + +namespace orcus { namespace spreadsheet { namespace detail { + +namespace { + +void print_named_expressions(const ixion::model_context& cxt, ixion::named_expressions_iterator iter, std::ostream& os) +{ + auto resolver = ixion::formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &cxt); + + if (!resolver) + return; + + const ixion::abs_address_t origin{0, 0, 0}; + ixion::print_config config; + config.display_sheet = ixion::display_sheet_t::always; + + for (; iter.has(); iter.next()) + { + auto name = iter.get(); + + std::string exp = ixion::print_formula_tokens( + config, cxt, origin, *resolver, name.expression->tokens); + + os << "- name: " << *name.name << std::endl; + os << " origin: " << resolver->get_name(name.expression->origin, origin, true) << std::endl; + os << " expression: " << exp << std::endl; + } +} + +} // anonymous namespace + +doc_debug_state_dumper::doc_debug_state_dumper(const document_impl& doc) : m_doc(doc) +{ +} + +void doc_debug_state_dumper::dump(const fs::path& outdir) const +{ + dump_properties(outdir); + dump_styles(outdir); + dump_named_expressions(outdir); +} + +void doc_debug_state_dumper::dump_properties(const fs::path& outdir) const +{ + const fs::path outpath = outdir / "properties.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + of << "formula-grammar: " << m_doc.grammar << std::endl; + of << "origin-date: " << m_doc.origin_date << std::endl; + of << "output-precision: " << short(m_doc.doc_config.output_precision) << std::endl; +} + +void doc_debug_state_dumper::dump_styles(const fs::path& outdir) const +{ + const fs::path outpath = outdir / "styles.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + of << std::boolalpha; + + auto to_string = [](std::optional<bool> v) -> std::string + { + if (!v) + return "(unset)"; + + return *v ? "true" : "false"; + }; + + auto dump_xf = [&of,to_string](std::size_t i, const cell_format_t& xf) + { + of << " - id: " << i << std::endl + << " font: " << xf.font << std::endl + << " fill: " << xf.fill << std::endl + << " border: " << xf.border << std::endl + << " protection: " << xf.protection << std::endl + << " number-format: " << xf.number_format << std::endl + << " style-xf: " << xf.style_xf << std::endl + << " horizontal-alignment: " << xf.hor_align << std::endl + << " vertical-alignment: " << xf.ver_align << std::endl + << " apply-number-format: " << xf.apply_num_format << std::endl + << " apply-font: " << xf.apply_font << std::endl + << " apply-fill: " << xf.apply_fill << std::endl + << " apply-border: " << xf.apply_border << std::endl + << " apply-alignment: " << xf.apply_alignment << std::endl + << " apply-protection: " << xf.apply_protection << std::endl + << " wrap-text: " << to_string(xf.wrap_text) << std::endl + << " shrink-to-fit: " << to_string(xf.shrink_to_fit) << std::endl; + }; + + auto optional_value = [&of](std::string_view name, const auto& v, int level=2) + { + // v is of type std::optional<T>. + + constexpr char q = '"'; + constexpr const char* indent_unit_s = " "; + + std::string indent = indent_unit_s; + for (int i = 0; i < level - 1; ++i) + indent += indent_unit_s; + + of << indent << name << ": "; + + if (v) + { + std::ostringstream os; + os << *v; + std::string s = os.str(); + bool quote = s.find_first_of("#:-") != s.npos; + if (quote) + of << q << s << q; + else + of << s; + } + else + of << "(unset)"; + + of << std::endl; + }; + + auto dump_border = [&optional_value](const border_attrs_t& _attrs) + { + optional_value("style", _attrs.style, 3); + optional_value("color", _attrs.border_color, 3); + optional_value("width", _attrs.border_width, 3); + }; + + of << "cell-styles:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_cell_styles_count(); ++i) + { + const cell_style_t* cs = m_doc.styles_store.get_cell_style(i); + assert(cs); + + of << " - id: " << i << std::endl + << " name: " << cs->name << std::endl + << " display-name: " << cs->display_name << std::endl + << " parent: " << cs->parent_name << std::endl + << " xf: " << cs->xf << std::endl + << " builtin: " << cs->builtin << std::endl; + } + + of << "cell-style-formats:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_cell_style_formats_count(); ++i) + { + const cell_format_t* xf = m_doc.styles_store.get_cell_style_format(i); + assert(xf); + dump_xf(i, *xf); + } + + of << "cell-formats:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_cell_formats_count(); ++i) + { + const cell_format_t* xf = m_doc.styles_store.get_cell_format(i); + assert(xf); + dump_xf(i, *xf); + } + + of << "fonts:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_font_count(); ++i) + { + const font_t* font = m_doc.styles_store.get_font(i); + assert(font); + + of << " - id: " << i << std::endl; + optional_value("name", font->name, 2); + optional_value("name-asian", font->name_asian, 2); + optional_value("name-complex", font->name_complex, 2); + optional_value("size", font->size, 2); + optional_value("size-asian", font->size_asian, 2); + optional_value("size-complex", font->size_complex, 2); + optional_value("bold", font->bold, 2); + optional_value("bold-asian", font->bold_asian, 2); + optional_value("bold-complex", font->bold_complex, 2); + optional_value("italic", font->italic, 2); + optional_value("italic-asian", font->italic_asian, 2); + optional_value("italic-complex", font->italic_complex, 2); + optional_value("underline-style", font->underline_style, 2); + optional_value("underline-width", font->underline_width, 2); + optional_value("underline-mode", font->underline_mode, 2); + optional_value("underline-type", font->underline_type, 2); + optional_value("underline-color", font->underline_color, 2); + optional_value("color", font->color, 2); + optional_value("strikethrough-style", font->strikethrough_style, 2); + optional_value("strikethrough-width", font->strikethrough_width, 2); + optional_value("strikethrough-type", font->strikethrough_type, 2); + optional_value("strikethrough-text", font->strikethrough_text, 2); + } + + of << "fills:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_fill_count(); ++i) + { + const fill_t* fill = m_doc.styles_store.get_fill(i); + assert(fill); + + of << " - id: " << i << std::endl; + optional_value("pattern", fill->pattern_type, 2); + optional_value("fg-color", fill->fg_color, 2); + optional_value("bg-color", fill->bg_color, 2); + } + + of << "borders:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_border_count(); ++i) + { + const border_t* border = m_doc.styles_store.get_border(i); + assert(border); + + of << " - id: " << i << std::endl; + + of << " top:" << std::endl; + dump_border(border->top); + of << " bottom:" << std::endl; + dump_border(border->bottom); + of << " left:" << std::endl; + dump_border(border->left); + of << " right:" << std::endl; + dump_border(border->right); + of << " diagonal:" << std::endl; + dump_border(border->diagonal); + of << " diagonal-bl-tr:" << std::endl; + dump_border(border->diagonal_bl_tr); + of << " diagonal-tl-br:" << std::endl; + dump_border(border->diagonal_tl_br); + } + + of << "protections:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_protection_count(); ++i) + { + const protection_t* prot = m_doc.styles_store.get_protection(i); + assert(prot); + + of << " - id: " << i << std::endl; + optional_value("locked", prot->locked, 2); + optional_value("hidden", prot->hidden, 2); + optional_value("print-content", prot->print_content, 2); + optional_value("formula-hidden", prot->formula_hidden, 2); + } + + of << "number-formats:" << std::endl; + + for (std::size_t i = 0; i < m_doc.styles_store.get_number_format_count(); ++i) + { + const number_format_t* numfmt = m_doc.styles_store.get_number_format(i); + assert(numfmt); + + of << " - id: " << i << std::endl; + optional_value("identifier", numfmt->identifier, 2); + optional_value("format-string", numfmt->format_string, 2); + } +} + +void doc_debug_state_dumper::dump_named_expressions(const fs::path& outdir) const +{ + const fs::path outpath = outdir / "named-expressions.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + print_named_expressions(m_doc.context, m_doc.context.get_named_expressions_iterator(), of); +} + +sheet_debug_state_dumper::sheet_debug_state_dumper(const sheet_impl& sheet, std::string_view sheet_name) : + m_sheet(sheet), m_sheet_name(sheet_name) {} + +void sheet_debug_state_dumper::dump(const fs::path& outdir) const +{ + dump_cell_values(outdir); + dump_cell_formats(outdir); + dump_column_formats(outdir); + dump_row_formats(outdir); + dump_column_widths(outdir); + dump_row_heights(outdir); + dump_auto_filter(outdir); + dump_named_expressions(outdir); +} + +void sheet_debug_state_dumper::dump_cell_values(const fs::path& outdir) const +{ + check_dumper dumper{m_sheet, m_sheet_name}; + fs::path outpath = outdir / "cell-values.txt"; + std::ofstream of{outpath.native()}; + if (of) + dumper.dump(of); +} + +void sheet_debug_state_dumper::dump_cell_formats(const fs::path& outdir) const +{ + fs::path outpath = outdir / "cell-formats.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + std::vector<col_t> columns; + for (const auto& node : m_sheet.cell_formats) + columns.push_back(node.first); + + std::sort(columns.begin(), columns.end()); + + for (const col_t col : columns) + { + of << "column: " << col << std::endl; + + auto it = m_sheet.cell_formats.find(col); + assert(it != m_sheet.cell_formats.end()); + const segment_row_index_type& rows = *it->second; + + for (const auto& seg : rows.segment_range()) + { + // NB: end position is not inclusive. + of << " - rows: " << seg.start << '-' << (seg.end - 1) << std::endl; + of << " xf: " << seg.value << std::endl; + } + } +} + +void sheet_debug_state_dumper::dump_column_formats(const fs::path& outdir) const +{ + fs::path outpath = outdir / "column-formats.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + for (const auto& seg : m_sheet.column_formats.segment_range()) + { + of << "- columns: " << seg.start << '-' << (seg.end - 1) << std::endl; + of << " xf: " << seg.value << std::endl; + } +} + +void sheet_debug_state_dumper::dump_row_formats(const fs::path& outdir) const +{ + fs::path outpath = outdir / "row-formats.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + for (const auto& seg : m_sheet.row_formats.segment_range()) + { + of << "- rows: " << seg.start << '-' << (seg.end - 1) << std::endl; + of << " xf: " << seg.value << std::endl; + } +} + +void sheet_debug_state_dumper::dump_column_widths(const fs::path& outdir) const +{ + fs::path outpath = outdir / "column-widths.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + for (const auto& seg : m_sheet.col_widths.segment_range()) + { + of << "- columns: " << seg.start << '-' << (seg.end - 1) << std::endl; + of << " width: "; + + if (seg.value == get_default_column_width()) + of << "(default)"; + else + of << seg.value; + + of << std::endl; + } +} + +void sheet_debug_state_dumper::dump_row_heights(const fs::path& outdir) const +{ + fs::path outpath = outdir / "row-heights.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + for (const auto& seg : m_sheet.row_heights.segment_range()) + { + of << "- rows: " << seg.start << '-' << (seg.end - 1) << std::endl; + of << " height: "; + + if (seg.value == get_default_row_height()) + of << "(default)"; + else + of << seg.value; + + of << std::endl; + } +} + +void sheet_debug_state_dumper::dump_auto_filter(const fs::path& outdir) const +{ + if (!m_sheet.auto_filter_data) + return; + + fs::path outpath = outdir / "auto-filter.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + const auto_filter_t& data = *m_sheet.auto_filter_data; + + auto resolver = ixion::formula_name_resolver::get( + ixion::formula_name_resolver_t::excel_a1, nullptr); + + if (!resolver) + return; + + ixion::abs_address_t origin; + ixion::range_t name{data.range}; + name.set_absolute(false); + + of << "range: " << resolver->get_name(name, origin, false) << "\n"; + of << "columns:\n"; + + for (const auto& [col, cdata] : data.columns) + { + of << "- column: " << col << "\n"; + of << " match-values:\n"; + + for (const auto& v : cdata.match_values) + of << " - " << v << std::endl; + } +} + +void sheet_debug_state_dumper::dump_named_expressions(const fs::path& outdir) const +{ + const fs::path outpath = outdir / "named-expressions.yaml"; + std::ofstream of{outpath.native()}; + if (!of) + return; + + const ixion::model_context& cxt = m_sheet.doc.get_model_context(); + print_named_expressions(cxt, cxt.get_named_expressions_iterator(m_sheet.sheet_id), of); +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/debug_state_dumper.hpp b/src/spreadsheet/debug_state_dumper.hpp new file mode 100644 index 0000000..7e895ca --- /dev/null +++ b/src/spreadsheet/debug_state_dumper.hpp @@ -0,0 +1,61 @@ +/* -*- 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/. + */ + +#pragma once + +#include "filesystem_env.hpp" + +#include <string_view> + +namespace orcus { namespace spreadsheet { + +class document; + +namespace detail { + +struct document_impl; +struct sheet_impl; + +class doc_debug_state_dumper +{ + const document_impl& m_doc; + +public: + doc_debug_state_dumper(const document_impl& doc); + + void dump(const fs::path& outdir) const; + +private: + void dump_properties(const fs::path& outdir) const; + void dump_styles(const fs::path& outdir) const; + void dump_named_expressions(const fs::path& outdir) const; +}; + +class sheet_debug_state_dumper +{ + const sheet_impl& m_sheet; + std::string_view m_sheet_name; + +public: + sheet_debug_state_dumper(const sheet_impl& sheet, std::string_view sheet_name); + + void dump(const fs::path& outdir) const; + +private: + void dump_cell_values(const fs::path& outdir) const; + void dump_cell_formats(const fs::path& outdir) const; + void dump_column_formats(const fs::path& outdir) const; + void dump_row_formats(const fs::path& outdir) const; + void dump_column_widths(const fs::path& outdir) const; + void dump_row_heights(const fs::path& outdir) const; + void dump_auto_filter(const fs::path& outdir) const; + void dump_named_expressions(const fs::path& outdir) const; +}; + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/document.cpp b/src/spreadsheet/document.cpp new file mode 100644 index 0000000..dc8daec --- /dev/null +++ b/src/spreadsheet/document.cpp @@ -0,0 +1,526 @@ +/* -*- 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 "document_impl.hpp" +#include "debug_state_dumper.hpp" + +#include <iostream> +#include <fstream> +#include <sstream> +#include <map> +#include <algorithm> + +using namespace std; + +namespace orcus { namespace spreadsheet { + +namespace { + +class find_sheet_by_name +{ + std::string_view m_name; +public: + find_sheet_by_name(std::string_view name) : m_name(name) {} + bool operator() (const std::unique_ptr<detail::sheet_item>& v) const + { + return v->name == m_name; + } +}; + +} + +document::document(const range_size_t& sheet_size) : mp_impl(std::make_unique<detail::document_impl>(*this, sheet_size)) {} + +document::~document() {} + +shared_strings& document::get_shared_strings() +{ + return mp_impl->ss_store; +} + +const shared_strings& document::get_shared_strings() const +{ + return mp_impl->ss_store; +} + +styles& document::get_styles() +{ + return mp_impl->styles_store; +} + +const styles& document::get_styles() const +{ + return mp_impl->styles_store; +} + +pivot_collection& document::get_pivot_collection() +{ + return mp_impl->pivots; +} + +const pivot_collection& document::get_pivot_collection() const +{ + return mp_impl->pivots; +} + +ixion::model_context& document::get_model_context() +{ + return mp_impl->context; +} + +const ixion::model_context& document::get_model_context() const +{ + return mp_impl->context; +} + +const document_config& document::get_config() const +{ + return mp_impl->doc_config; +} + +void document::set_config(const document_config& cfg) +{ + mp_impl->doc_config = cfg; + ixion::config ixion_cfg = mp_impl->context.get_config(); + ixion_cfg.output_precision = cfg.output_precision; + mp_impl->context.set_config(ixion_cfg); +} + +string_pool& document::get_string_pool() +{ + return mp_impl->string_pool_store; +} + +const string_pool& document::get_string_pool() const +{ + return mp_impl->string_pool_store; +} + +void document::insert_table(table_t* p) +{ + if (!p) + return; + + std::string_view name = p->name; + mp_impl->tables.emplace(name, std::unique_ptr<table_t>(p)); +} + +const table_t* document::get_table(std::string_view name) const +{ + auto it = mp_impl->tables.find(name); + return it == mp_impl->tables.end() ? nullptr : it->second.get(); +} + +void document::finalize_import() +{ + std::for_each(mp_impl->sheets.begin(), mp_impl->sheets.end(), + [](std::unique_ptr<detail::sheet_item>& sh) + { + sh->data.finalize_import(); + } + ); + + mp_impl->styles_store.finalize_import(); +} + +sheet* document::append_sheet(std::string_view sheet_name) +{ + std::string_view sheet_name_safe = mp_impl->string_pool_store.intern(sheet_name).first; + sheet_t sheet_index = static_cast<sheet_t>(mp_impl->sheets.size()); + + mp_impl->sheets.push_back( + std::make_unique<detail::sheet_item>(*this, sheet_name_safe, sheet_index)); + + mp_impl->context.append_sheet(std::string{sheet_name_safe}); + + return &mp_impl->sheets.back()->data; +} + +sheet* document::get_sheet(std::string_view sheet_name) +{ + const sheet* sh = const_cast<const document*>(this)->get_sheet(sheet_name); + return const_cast<sheet*>(sh); +} + +const sheet* document::get_sheet(std::string_view sheet_name) const +{ + auto it = std::find_if( + mp_impl->sheets.begin(), mp_impl->sheets.end(), find_sheet_by_name(sheet_name)); + + if (it == mp_impl->sheets.end()) + return nullptr; + + return &(*it)->data; +} + +sheet* document::get_sheet(sheet_t sheet_pos) +{ + const sheet* sh = const_cast<const document*>(this)->get_sheet(sheet_pos); + return const_cast<sheet*>(sh); +} + +const sheet* document::get_sheet(sheet_t sheet_pos) const +{ + if (static_cast<size_t>(sheet_pos) >= mp_impl->sheets.size()) + return nullptr; + + return &mp_impl->sheets[sheet_pos]->data; +} + +void document::recalc_formula_cells() +{ + ixion::abs_range_set_t empty; + + ixion::model_context& cxt = get_model_context(); + std::vector<ixion::abs_range_t> sorted = ixion::query_and_sort_dirty_cells( + cxt, empty, &mp_impl->dirty_cells); + ixion::calculate_sorted_cells(cxt, sorted, 0); +} + +void document::clear() +{ + mp_impl = std::make_unique<detail::document_impl>(*this, get_sheet_size()); +} + +void document::dump(dump_format_t format, const std::string& output) const +{ + if (format == dump_format_t::none) + return; + + if (format == dump_format_t::check) + { + // For this output, we write to a single file. + std::ostream* ostrm = &std::cout; + std::unique_ptr<std::ofstream> fs; + + if (!output.empty()) + { + if (fs::is_directory(output)) + { + std::ostringstream os; + os << "Output file path points to an existing directory."; + throw std::invalid_argument(os.str()); + } + + // Output to stdout when output path is not given. + fs = std::make_unique<std::ofstream>(output.data()); + ostrm = fs.get(); + } + + dump_check(*ostrm); + return; + } + + if (output.empty()) + throw std::invalid_argument("No output directory."); + + if (fs::exists(output)) + { + if (!fs::is_directory(output)) + { + std::ostringstream os; + os << "A file named '" << output << "' already exists, and is not a directory."; + throw std::invalid_argument(os.str()); + } + } + else + fs::create_directory(output); + + switch (format) + { + case dump_format_t::csv: + dump_csv(output); + break; + case dump_format_t::flat: + dump_flat(output); + break; + case dump_format_t::html: + dump_html(output); + break; + case dump_format_t::json: + dump_json(output); + break; + case dump_format_t::debug_state: + dump_debug_state(output); + break; + // coverity[dead_error_line] - following conditions exist to avoid compiler warning + case dump_format_t::none: + case dump_format_t::unknown: + break; + default: + ; + } +} + +void document::dump_check(ostream& os) const +{ + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + sheet->data.dump_check(os, sheet->name); +} + +void document::dump_flat(const string& outdir) const +{ + cout << "----------------------------------------------------------------------" << endl; + cout << " Document content summary" << endl; + cout << "----------------------------------------------------------------------" << endl; + mp_impl->ss_store.dump(cout); + + cout << "number of sheets: " << mp_impl->sheets.size() << endl; + + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + { + fs::path outpath{outdir}; + outpath /= std::string{sheet->name}; + outpath.replace_extension(".txt"); + + std::ofstream file(outpath.native()); + if (!file) + { + cerr << "failed to create file: " << outpath << endl; + return; + } + + file << "---" << endl; + file << "Sheet name: " << sheet->name << endl; + sheet->data.dump_flat(file); + } +} + +void document::dump_html(const string& outdir) const +{ + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + { + fs::path outpath{outdir}; + outpath /= std::string{sheet->name}; + outpath.replace_extension(".html"); + + std::ofstream file(outpath.native()); + if (!file) + { + cerr << "failed to create file: " << outpath << endl; + return; + } + + sheet->data.dump_html(file); + } +} + +void document::dump_json(const string& outdir) const +{ + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + { + fs::path outpath{outdir}; + outpath /= std::string{sheet->name}; + outpath.replace_extension(".json"); + + std::ofstream file(outpath.native()); + if (!file) + { + cerr << "failed to create file: " << outpath << endl; + return; + } + + sheet->data.dump_json(file); + } +} + +void document::dump_csv(const std::string& outdir) const +{ + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + { + fs::path outpath{outdir}; + outpath /= std::string{sheet->name}; + outpath.replace_extension(".csv"); + + ofstream file(outpath.c_str()); + if (!file) + { + cerr << "failed to create file: " << outpath << endl; + return; + } + + sheet->data.dump_csv(file); + } +} + +void document::dump_debug_state(const std::string& outdir) const +{ + detail::doc_debug_state_dumper dumper{*mp_impl}; + fs::path output_dir{outdir}; + dumper.dump(output_dir); + + for (const std::unique_ptr<detail::sheet_item>& sheet : mp_impl->sheets) + { + fs::path outpath = output_dir; + outpath /= std::string{sheet->name}; + fs::create_directories(outpath); + sheet->data.dump_debug_state(outpath.string(), sheet->name); + } +} + +sheet_t document::get_sheet_index(std::string_view name) const +{ + auto it = std::find_if( + mp_impl->sheets.begin(), mp_impl->sheets.end(), find_sheet_by_name(name)); + + if (it == mp_impl->sheets.end()) + return ixion::invalid_sheet; + + auto it_beg = mp_impl->sheets.begin(); + size_t pos = std::distance(it_beg, it); + return static_cast<sheet_t>(pos); +} + +std::string_view document::get_sheet_name(sheet_t sheet_pos) const +{ + if (sheet_pos < 0) + return std::string_view{}; + + size_t pos = static_cast<size_t>(sheet_pos); + if (pos >= mp_impl->sheets.size()) + return std::string_view{}; + + return mp_impl->sheets[pos]->name; +} + +void document::set_sheet_name(sheet_t sheet_pos, std::string name) +{ + assert(mp_impl->sheets.size() == mp_impl->context.get_sheet_count()); + + std::string_view name_interned = mp_impl->string_pool_store.intern(name).first; + mp_impl->context.set_sheet_name(sheet_pos, std::move(name)); // will throw on invalid name or position + mp_impl->sheets[sheet_pos]->name = name_interned; +} + +range_size_t document::get_sheet_size() const +{ + ixion::rc_size_t ss = mp_impl->context.get_sheet_size(); + range_size_t ret; + ret.rows = ss.row; + ret.columns = ss.column; + return ret; +} + +void document::set_sheet_size(const range_size_t& sheet_size) +{ + mp_impl->context.set_sheet_size({sheet_size.rows, sheet_size.columns}); +} + +size_t document::get_sheet_count() const +{ + return mp_impl->sheets.size(); +} + +void document::set_origin_date(int year, int month, int day) +{ + mp_impl->origin_date.year = year; + mp_impl->origin_date.month = month; + mp_impl->origin_date.day = day; +} + +date_time_t document::get_origin_date() const +{ + return mp_impl->origin_date; +} + +void document::set_formula_grammar(formula_grammar_t grammar) +{ + if (mp_impl->grammar == grammar) + return; + + mp_impl->grammar = grammar; + + ixion::formula_name_resolver_t resolver_type_global = ixion::formula_name_resolver_t::unknown; + ixion::formula_name_resolver_t resolver_type_named_exp_base = ixion::formula_name_resolver_t::unknown; + ixion::formula_name_resolver_t resolver_type_named_range = ixion::formula_name_resolver_t::unknown; + char arg_sep = 0; + + switch (mp_impl->grammar) + { + case formula_grammar_t::xls_xml: + resolver_type_global = ixion::formula_name_resolver_t::excel_r1c1; + arg_sep = ','; + break; + case formula_grammar_t::xlsx: + resolver_type_global = ixion::formula_name_resolver_t::excel_a1; + arg_sep = ','; + break; + case formula_grammar_t::ods: + resolver_type_global = ixion::formula_name_resolver_t::odff; + resolver_type_named_exp_base = ixion::formula_name_resolver_t::calc_a1; + resolver_type_named_range = ixion::formula_name_resolver_t::odf_cra; + arg_sep = ';'; + break; + case formula_grammar_t::gnumeric: + // TODO : Use Excel A1 name resolver for now. + resolver_type_global = ixion::formula_name_resolver_t::excel_a1; + arg_sep = ','; + break; + default: + ; + } + + mp_impl->name_resolver_global.reset(); + mp_impl->name_resolver_named_exp_base.reset(); + + if (resolver_type_global != ixion::formula_name_resolver_t::unknown) + { + mp_impl->name_resolver_global = + ixion::formula_name_resolver::get(resolver_type_global, &mp_impl->context); + + if (resolver_type_named_exp_base != ixion::formula_name_resolver_t::unknown) + { + mp_impl->name_resolver_named_exp_base = + ixion::formula_name_resolver::get(resolver_type_named_exp_base, &mp_impl->context); + } + + if (resolver_type_named_range != ixion::formula_name_resolver_t::unknown) + { + mp_impl->name_resolver_named_range = + ixion::formula_name_resolver::get(resolver_type_named_range, &mp_impl->context); + } + + ixion::config cfg = mp_impl->context.get_config(); + cfg.sep_function_arg = arg_sep; + cfg.output_precision = mp_impl->doc_config.output_precision; + mp_impl->context.set_config(cfg); + } +} + +formula_grammar_t document::get_formula_grammar() const +{ + return mp_impl->grammar; +} + +const ixion::formula_name_resolver* document::get_formula_name_resolver(formula_ref_context_t cxt) const +{ + switch (cxt) + { + case formula_ref_context_t::global: + return mp_impl->name_resolver_global.get(); + case formula_ref_context_t::named_expression_base: + if (mp_impl->name_resolver_named_exp_base) + return mp_impl->name_resolver_named_exp_base.get(); + break; + case formula_ref_context_t::named_range: + if (mp_impl->name_resolver_named_range) + return mp_impl->name_resolver_named_range.get(); + break; + default: + ; + } + + return mp_impl->name_resolver_global.get(); +} + +void document::insert_dirty_cell(const ixion::abs_address_t& pos) +{ + mp_impl->dirty_cells.insert(pos); +} + +}} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/document_impl.cpp b/src/spreadsheet/document_impl.cpp new file mode 100644 index 0000000..db6050a --- /dev/null +++ b/src/spreadsheet/document_impl.cpp @@ -0,0 +1,232 @@ +/* -*- 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 "document_impl.hpp" + +#include <algorithm> + +namespace orcus { namespace spreadsheet { namespace detail { + +namespace { + +class find_column_by_name +{ + std::string_view m_name; +public: + find_column_by_name(std::string_view name) : m_name(name) {} + + bool operator() (const table_column_t& col) const + { + return col.name == m_name; + } +}; + +void adjust_row_range(ixion::abs_range_t& range, const table_t& tab, ixion::table_areas_t areas) +{ + bool headers = (areas & ixion::table_area_headers); + bool data = (areas & ixion::table_area_data); + bool totals = (areas & ixion::table_area_totals); + + if (headers) + { + if (data) + { + if (totals) + { + // All areas. + return; + } + + // Headers + data + range.last.row -= tab.totals_row_count; + return; + } + + if (totals) + { + // Header + total is invalid. + range = ixion::abs_range_t(ixion::abs_range_t::invalid); + return; + } + + // Headers only. + range.last.row = range.first.row; + return; + } + + if (data) + { + ++range.first.row; + + if (totals) + { + // Data + total + return; + } + + // Data only + range.last.row -= tab.totals_row_count; + return; + } + + if (totals) + { + // Total only + if (!tab.totals_row_count) + { + // This table has not total rows. Return empty range. + range = ixion::abs_range_t(); + return; + } + + range.first.row = range.last.row - tab.totals_row_count - 1; + return; + } + + // Empty range. + range = ixion::abs_range_t(); +} + +} + +sheet_item::sheet_item(document& doc, std::string_view _name, sheet_t sheet_index) : + name(_name), data(doc, sheet_index) {} + + +const table_t* ixion_table_handler::find_table(const ixion::abs_address_t& pos) const +{ + auto it = m_tables.begin(), it_end = m_tables.end(); + for (; it != it_end; ++it) + { + const table_t* p = it->second.get(); + if (p->range.contains(pos)) + return p; + } + + return nullptr; +} + +std::string_view ixion_table_handler::get_string(ixion::string_id_t sid) const +{ + if (sid == ixion::empty_string_id) + return std::string_view{}; + + const std::string* p = m_context.get_string(sid); + if (!p || p->empty()) + return std::string_view{}; + + return std::string_view(p->data(), p->size()); +} + +col_t ixion_table_handler::find_column(const table_t& tab, std::string_view name, size_t offset) const +{ + if (offset >= tab.columns.size()) + return -1; + + table_t::columns_type::const_iterator it_beg = tab.columns.begin(); + table_t::columns_type::const_iterator it_end = tab.columns.end(); + + std::advance(it_beg, offset); + table_t::columns_type::const_iterator it = + std::find_if(it_beg, it_end, find_column_by_name(name)); + + if (it == it_end) + // not found. + return -1; + + size_t dist = std::distance(tab.columns.begin(), it); + return tab.range.first.column + dist; +} + +ixion::abs_range_t ixion_table_handler::get_range_from_table( + const table_t& tab, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const +{ + if (column_first != ixion::empty_string_id) + { + std::string_view col1_name = get_string(column_first); + if (col1_name.empty()) + return ixion::abs_range_t(ixion::abs_range_t::invalid); + + col_t col1_index = find_column(tab, col1_name, 0); + if (col1_index < 0) + return ixion::abs_range_t(ixion::abs_range_t::invalid); + + if (column_last != ixion::empty_string_id) + { + std::string_view col2_name = get_string(column_last); + if (!col2_name.empty()) + { + // column range table reference. + col_t col2_index = find_column(tab, col2_name, col1_index); + ixion::abs_range_t range = tab.range; + range.first.column = col1_index; + range.last.column = col2_index; + adjust_row_range(range, tab, areas); + return range; + } + } + + // single column table reference. + ixion::abs_range_t range = tab.range; + range.first.column = range.last.column = col1_index; + adjust_row_range(range, tab, areas); + return range; + } + + return ixion::abs_range_t(); +} + +ixion_table_handler::ixion_table_handler(const ixion::model_context& cxt, const table_store_type& tables) : + m_context(cxt), m_tables(tables) {} + +ixion::abs_range_t ixion_table_handler::get_range( + const ixion::abs_address_t& pos, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const +{ + const table_t* tab = find_table(pos); + if (!tab) + return ixion::abs_range_t(ixion::abs_range_t::invalid); + + return get_range_from_table(*tab, column_first, column_last, areas); + +} + +ixion::abs_range_t ixion_table_handler::get_range( + ixion::string_id_t table, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const +{ + std::string_view tab_name = get_string(table); + if (tab_name.empty()) + // no table name given. + return ixion::abs_range_t(ixion::abs_range_t::invalid); + + auto it = m_tables.find(tab_name); + if (it == m_tables.end()) + // no table by this name found. + return ixion::abs_range_t(ixion::abs_range_t::invalid); + + const table_t* tab = it->second.get(); + return get_range_from_table(*tab, column_first, column_last, areas); +} + +document_impl::document_impl(document& _doc, const range_size_t& sheet_size) : + doc(_doc), + context({sheet_size.rows, sheet_size.columns}), + styles_store(), + ss_store(context), + pivots(doc), + name_resolver_global(ixion::formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &context)), + grammar(formula_grammar_t::xlsx), + table_handler(context, tables) +{ + context.set_table_handler(&table_handler); +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/document_impl.hpp b/src/spreadsheet/document_impl.hpp new file mode 100644 index 0000000..44ee91f --- /dev/null +++ b/src/spreadsheet/document_impl.hpp @@ -0,0 +1,104 @@ +/* -*- 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/. + */ + +#pragma once + +#include <orcus/spreadsheet/auto_filter.hpp> +#include <orcus/spreadsheet/config.hpp> +#include <orcus/spreadsheet/document.hpp> +#include <orcus/spreadsheet/pivot.hpp> +#include <orcus/spreadsheet/shared_strings.hpp> +#include <orcus/spreadsheet/sheet.hpp> +#include <orcus/spreadsheet/styles.hpp> +#include <orcus/string_pool.hpp> +#include <orcus/types.hpp> + +#include <ixion/config.hpp> +#include <ixion/formula.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> +#include <ixion/interface/table_handler.hpp> +#include <ixion/matrix.hpp> +#include <ixion/model_context.hpp> + +namespace orcus { namespace spreadsheet { namespace detail { + +/** + * Single sheet entry which consists of a sheet name and a sheet data. + */ +struct sheet_item +{ + sheet_item(const sheet_item&) = delete; + sheet_item& operator=(const sheet_item&) = delete; + + std::string_view name; + sheet data; + sheet_item(document& doc, std::string_view _name, sheet_t sheet_index); +}; + +typedef std::map<std::string_view, std::unique_ptr<table_t>> table_store_type; +typedef std::vector<std::unique_ptr<sheet_item>> sheet_items_type; + +class ixion_table_handler : public ixion::iface::table_handler +{ + const ixion::model_context& m_context; + const table_store_type& m_tables; + + const table_t* find_table(const ixion::abs_address_t& pos) const; + + std::string_view get_string(ixion::string_id_t sid) const; + + col_t find_column(const table_t& tab, std::string_view name, size_t offset) const; + + ixion::abs_range_t get_range_from_table( + const table_t& tab, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const; + +public: + ixion_table_handler(const ixion::model_context& cxt, const table_store_type& tables); + + virtual ixion::abs_range_t get_range( + const ixion::abs_address_t& pos, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const override; + + virtual ixion::abs_range_t get_range( + ixion::string_id_t table, ixion::string_id_t column_first, ixion::string_id_t column_last, + ixion::table_areas_t areas) const override; +}; + +struct document_impl +{ + document_impl(const document_impl&) = delete; + document_impl& operator=(const document_impl&) = delete; + + document& doc; + + document_config doc_config; + string_pool string_pool_store; + ixion::model_context context; + date_time_t origin_date; + sheet_items_type sheets; + styles styles_store; + shared_strings ss_store; + ixion::abs_range_set_t dirty_cells; + + pivot_collection pivots; + + std::unique_ptr<ixion::formula_name_resolver> name_resolver_global; + std::unique_ptr<ixion::formula_name_resolver> name_resolver_named_exp_base; + std::unique_ptr<ixion::formula_name_resolver> name_resolver_named_range; + formula_grammar_t grammar; + + table_store_type tables; + ixion_table_handler table_handler; + + document_impl(document& _doc, const range_size_t& sheet_size); +}; + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/document_types.cpp b/src/spreadsheet/document_types.cpp new file mode 100644 index 0000000..88e0724 --- /dev/null +++ b/src/spreadsheet/document_types.cpp @@ -0,0 +1,77 @@ +/* -*- 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 <orcus/spreadsheet/document_types.hpp> + +namespace orcus { namespace spreadsheet { + +color_t::color_t() : + alpha(0), red(0), green(0), blue(0) +{ +} + +color_t::color_t(color_elem_t _red, color_elem_t _green, color_elem_t _blue) : + alpha(255), red(_red), green(_green), blue(_blue) +{ +} + +color_t::color_t(color_elem_t _alpha, color_elem_t _red, color_elem_t _green, color_elem_t _blue) : + alpha(_alpha), red(_red), green(_green), blue(_blue) +{ +} + +void color_t::reset() +{ + *this = color_t(); +} + +bool color_t::operator==(const color_t& other) const +{ + return alpha == other.alpha && red == other.red && green == other.green && blue == other.blue; +} + +bool color_t::operator!=(const color_t& other) const +{ + return !operator==(other); +} + +format_run::format_run() : + pos(0), size(0), + font_size(0), + bold(false), italic(false) {} + +void format_run::reset() +{ + pos = 0; + size = 0; + font = std::string_view{}; + font_size = 0; + bold = false; + italic = false; + color = color_t(); +} + +bool format_run::formatted() const +{ + if (bold || italic) + return true; + + if (font_size) + return true; + + if (!font.empty()) + return true; + + if (color.alpha || color.red || color.green || color.blue) + return true; + + return false; +} + +}} // namespace orcus::spreadsheet + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/dumper_global.cpp b/src/spreadsheet/dumper_global.cpp new file mode 100644 index 0000000..f500f3c --- /dev/null +++ b/src/spreadsheet/dumper_global.cpp @@ -0,0 +1,87 @@ +/* -*- 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 "dumper_global.hpp" +#include "number_format.hpp" + +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> +#include <ixion/cell.hpp> + +namespace orcus { namespace spreadsheet { namespace detail { + +void dump_cell_value( + std::ostream& os, const ixion::model_context& cxt, const ixion::model_iterator::cell& cell, + func_str_handler str_handler, + func_empty_handler empty_handler) +{ + switch (cell.type) + { + case ixion::celltype_t::empty: + empty_handler(os); + break; + case ixion::celltype_t::boolean: + { + os << (std::get<bool>(cell.value) ? "true" : "false"); + break; + } + case ixion::celltype_t::numeric: + { + format_to_file_output(os, std::get<double>(cell.value)); + break; + } + case ixion::celltype_t::string: + { + const std::string* p = cxt.get_string(std::get<ixion::string_id_t>(cell.value)); + assert(p); + str_handler(os, *p); + break; + } + case ixion::celltype_t::formula: + { + const ixion::formula_cell* fc = std::get<const ixion::formula_cell*>(cell.value); + assert(fc); + ixion::formula_result res; + + try + { + res = fc->get_result_cache( + ixion::formula_result_wait_policy_t::throw_exception); + } + catch (const std::exception&) + { + os << "\"#RES!\""; + break; + } + + switch (res.get_type()) + { + case ixion::formula_result::result_type::value: + format_to_file_output(os, res.get_value()); + break; + case ixion::formula_result::result_type::string: + { + const std::string& s = res.get_string(); + str_handler(os, s); + } + break; + case ixion::formula_result::result_type::error: + os << "\"#ERR!\""; + break; + default: + ; + } + break; + } + default: + ; + } +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/dumper_global.hpp b/src/spreadsheet/dumper_global.hpp new file mode 100644 index 0000000..96c5afc --- /dev/null +++ b/src/spreadsheet/dumper_global.hpp @@ -0,0 +1,31 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_DUMPER_GLOBAL_HPP +#define INCLUDED_ORCUS_SPREADSHEET_DUMPER_GLOBAL_HPP + +#include <ixion/model_context.hpp> +#include <ixion/model_iterator.hpp> + +#include <ostream> +#include <functional> + +namespace orcus { namespace spreadsheet { namespace detail { + +using func_str_handler = std::function<void(std::ostream&, const std::string&)>; +using func_empty_handler = std::function<void(std::ostream&)>; + +void dump_cell_value( + std::ostream& os, const ixion::model_context& cxt, const ixion::model_iterator::cell& cell, + func_str_handler str_handler, + func_empty_handler empty_handler); + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory.cpp b/src/spreadsheet/factory.cpp new file mode 100644 index 0000000..9cd7884 --- /dev/null +++ b/src/spreadsheet/factory.cpp @@ -0,0 +1,410 @@ +/* -*- 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 "orcus/spreadsheet/factory.hpp" + +#include <orcus/spreadsheet/shared_strings.hpp> +#include <orcus/spreadsheet/styles.hpp> +#include <orcus/spreadsheet/sheet.hpp> +#include <orcus/spreadsheet/document.hpp> +#include <orcus/spreadsheet/view.hpp> +#include <orcus/exception.hpp> +#include <orcus/string_pool.hpp> + +#include "factory_pivot.hpp" +#include "factory_shared_strings.hpp" +#include "factory_sheet.hpp" +#include "global_settings.hpp" + +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_tokens.hpp> +#include <ixion/formula.hpp> +#include <ixion/model_context.hpp> +#include <sstream> +#include <iostream> +#include <unordered_map> + +namespace orcus { namespace spreadsheet { + +namespace { + +class import_ref_resolver : public iface::import_reference_resolver +{ + document& m_doc; + const ixion::formula_name_resolver* m_resolver; + +public: + import_ref_resolver(document& doc) : m_doc(doc), m_resolver(nullptr) {} + + void set_formula_ref_context(formula_ref_context_t cxt) + { + m_resolver = m_doc.get_formula_name_resolver(cxt); + } + + virtual src_address_t resolve_address(std::string_view address) override + { + if (!m_resolver) + throw std::runtime_error("import_ref_resolver::resolve_address: formula resolver is null!"); + + ixion::formula_name_t name = m_resolver->resolve(address, ixion::abs_address_t()); + + if (name.type != ixion::formula_name_t::cell_reference) + { + std::ostringstream os; + os << address << " is not a valid cell address."; + throw orcus::invalid_arg_error(os.str()); + } + + auto addr = std::get<ixion::address_t>(name.value); + src_address_t ret; + ret.sheet = addr.sheet; + ret.column = addr.column; + ret.row = addr.row; + return ret; + } + + virtual src_range_t resolve_range(std::string_view range) override + { + if (!m_resolver) + throw std::runtime_error("import_ref_resolver::resolve_range: formula resolver is null!"); + + ixion::formula_name_t name = m_resolver->resolve(range, ixion::abs_address_t()); + + switch (name.type) + { + case ixion::formula_name_t::range_reference: + { + auto v = std::get<ixion::range_t>(name.value); + src_range_t ret; + ret.first.sheet = v.first.sheet; + ret.first.column = v.first.column; + ret.first.row = v.first.row; + ret.last.sheet = v.last.sheet; + ret.last.column = v.last.column; + ret.last.row = v.last.row; + return ret; + } + case ixion::formula_name_t::cell_reference: + { + // Single cell address is still considered a valid "range". + auto addr = std::get<ixion::address_t>(name.value); + src_address_t cell; + cell.sheet = addr.sheet; + cell.column = addr.column; + cell.row = addr.row; + + src_range_t ret; + ret.first = cell; + ret.last = cell; + return ret; + } + default: + ; + } + + std::ostringstream os; + os << "'" << range << "' is not a valid range address."; + throw orcus::invalid_arg_error(os.str()); + } +}; + +class import_global_named_exp : public iface::import_named_expression +{ + document& m_doc; + std::string_view m_name; + ixion::abs_address_t m_base; + ixion::formula_tokens_t m_tokens; + + void define(std::string_view name, std::string_view expression, formula_ref_context_t ref_cxt) + { + string_pool& sp = m_doc.get_string_pool(); + m_name = sp.intern(name).first; + + const ixion::formula_name_resolver* resolver = m_doc.get_formula_name_resolver(ref_cxt); + assert(resolver); + + ixion::model_context& cxt = m_doc.get_model_context(); + m_tokens = ixion::parse_formula_string(cxt, m_base, *resolver, expression); + } +public: + import_global_named_exp(document& doc) : m_doc(doc), m_base(0, 0, 0) {} + virtual ~import_global_named_exp() override {} + + virtual void set_base_position(const src_address_t& pos) override + { + m_base.sheet = pos.sheet; + m_base.row = pos.row; + m_base.column = pos.column; + } + + virtual void set_named_expression(std::string_view name, std::string_view expression) override + { + define(name, expression, formula_ref_context_t::global); + } + + virtual void set_named_range(std::string_view name, std::string_view range) override + { + define(name, range, formula_ref_context_t::named_range); + } + + virtual void commit() override + { + ixion::model_context& cxt = m_doc.get_model_context(); + cxt.set_named_expression(std::string{m_name}, m_base, std::move(m_tokens)); + + m_name = std::string_view{}; + m_base.sheet = 0; + m_base.row = 0; + m_base.column = 0; + } +}; + +using sheet_ifaces_type = std::vector<std::unique_ptr<import_sheet>>; + +} // anonymous namespace + +import_factory_config::import_factory_config() = default; +import_factory_config::import_factory_config(const import_factory_config& other) = default; +import_factory_config::~import_factory_config() = default; + +import_factory_config& import_factory_config::operator=(const import_factory_config& other) = default; + +struct import_factory::impl +{ + std::shared_ptr<import_factory_config> m_config; + import_factory& m_envelope; + document& m_doc; + view* m_view; + character_set_t m_charset; + + import_global_settings m_global_settings; + import_pivot_cache_def m_pc_def; + import_pivot_cache_records m_pc_records; + import_ref_resolver m_ref_resolver; + import_global_named_exp m_global_named_exp; + import_styles m_styles; + detail::import_shared_strings shared_strings; + + sheet_ifaces_type m_sheets; + + bool m_recalc_formula_cells; + formula_error_policy_t m_error_policy; + + impl(import_factory& envelope, document& doc) : + m_config(std::make_shared<import_factory_config>()), + m_envelope(envelope), + m_doc(doc), + m_view(nullptr), + m_charset(character_set_t::unspecified), + m_global_settings(envelope, doc), + m_pc_def(doc), + m_pc_records(doc), + m_ref_resolver(doc), + m_global_named_exp(doc), + m_styles(m_config, doc.get_styles(), doc.get_string_pool()), + shared_strings(doc.get_string_pool(), doc.get_model_context(), doc.get_styles(), doc.get_shared_strings()), + m_recalc_formula_cells(false), + m_error_policy(formula_error_policy_t::fail) + { + } +}; + +import_factory::import_factory(document& doc) : + mp_impl(std::make_unique<impl>(*this, doc)) {} + +import_factory::import_factory(document& doc, view& view_store) : + mp_impl(std::make_unique<impl>(*this, doc)) +{ + // Store the optional view store. + mp_impl->m_view = &view_store; +} + +import_factory::~import_factory() {} + +iface::import_global_settings* import_factory::get_global_settings() +{ + return &mp_impl->m_global_settings; +} + +iface::import_shared_strings* import_factory::get_shared_strings() +{ + return &mp_impl->shared_strings; +} + +iface::import_styles* import_factory::get_styles() +{ + return &mp_impl->m_styles; +} + +iface::import_named_expression* import_factory::get_named_expression() +{ + return &mp_impl->m_global_named_exp; +} + +iface::import_reference_resolver* import_factory::get_reference_resolver(formula_ref_context_t cxt) +{ + mp_impl->m_ref_resolver.set_formula_ref_context(cxt); + return &mp_impl->m_ref_resolver; +} + +iface::import_pivot_cache_definition* import_factory::create_pivot_cache_definition( + pivot_cache_id_t cache_id) +{ + mp_impl->m_pc_def.create_cache(cache_id); + return &mp_impl->m_pc_def; +} + +iface::import_pivot_cache_records* import_factory::create_pivot_cache_records( + orcus::spreadsheet::pivot_cache_id_t cache_id) +{ + pivot_collection& pcs = mp_impl->m_doc.get_pivot_collection(); + pivot_cache* pc = pcs.get_cache(cache_id); + if (!pc) + return nullptr; + + mp_impl->m_pc_records.set_cache(pc); + return &mp_impl->m_pc_records; +} + +iface::import_sheet* import_factory::append_sheet(sheet_t sheet_index, std::string_view name) +{ + assert(sheet_index == static_cast<sheet_t>(mp_impl->m_doc.get_sheet_count())); + + sheet* sh = mp_impl->m_doc.append_sheet(name); + + if (!sh) + return nullptr; + + sheet_view* sv = nullptr; + if (mp_impl->m_view) + sv = mp_impl->m_view->get_or_create_sheet_view(sheet_index); + + mp_impl->m_sheets.push_back( + std::make_unique<import_sheet>(mp_impl->m_doc, *sh, sv)); + + import_sheet* p = mp_impl->m_sheets.back().get(); + p->set_character_set(mp_impl->m_charset); + p->set_fill_missing_formula_results(!mp_impl->m_recalc_formula_cells); + p->set_formula_error_policy(mp_impl->m_error_policy); + return p; +} + +iface::import_sheet* import_factory::get_sheet(std::string_view name) +{ + sheet_t si = mp_impl->m_doc.get_sheet_index(name); + if (si == ixion::invalid_sheet) + return nullptr; + + return mp_impl->m_sheets.at(si).get(); +} + +iface::import_sheet* import_factory::get_sheet(sheet_t sheet_index) +{ + if (sheet_index < 0 || size_t(sheet_index) >= mp_impl->m_sheets.size()) + return nullptr; + + return mp_impl->m_sheets[sheet_index].get(); +} + +void import_factory::finalize() +{ + mp_impl->m_doc.finalize_import(); + + if (mp_impl->m_recalc_formula_cells) + mp_impl->m_doc.recalc_formula_cells(); +} + +void import_factory::set_config(const import_factory_config& config) +{ + // NB: update the object state. + *mp_impl->m_config = config; +} + +void import_factory::set_default_row_size(row_t row_size) +{ + range_size_t ss = mp_impl->m_doc.get_sheet_size(); + ss.rows = row_size; + mp_impl->m_doc.set_sheet_size(ss); +} + +void import_factory::set_default_column_size(col_t col_size) +{ + range_size_t ss = mp_impl->m_doc.get_sheet_size(); + ss.columns = col_size; + mp_impl->m_doc.set_sheet_size(ss); +} + +void import_factory::set_character_set(character_set_t charset) +{ + mp_impl->m_charset = charset; + + for (std::unique_ptr<import_sheet>& sheet : mp_impl->m_sheets) + sheet->set_character_set(charset); +} + +character_set_t import_factory::get_character_set() const +{ + return mp_impl->m_charset; +} + +void import_factory::set_recalc_formula_cells(bool b) +{ + mp_impl->m_recalc_formula_cells = b; +} + +void import_factory::set_formula_error_policy(formula_error_policy_t policy) +{ + mp_impl->m_error_policy = policy; +} + +struct export_factory::impl +{ + const document& m_doc; + + std::vector<std::unique_ptr<export_sheet>> m_sheets; + std::unordered_map<std::string_view, sheet_t> m_sheet_index_map; + + impl(const document& doc) : m_doc(doc) {} + + export_sheet* get_sheet(std::string_view name) + { + auto it = m_sheet_index_map.find(name); + if (it != m_sheet_index_map.end()) + { + // Instance for this sheet already exists. + sheet_t sheet_pos = it->second; + assert(size_t(sheet_pos) < m_sheets.size()); + return m_sheets[sheet_pos].get(); + } + + const sheet* sh = m_doc.get_sheet(name); + if (!sh) + return nullptr; + + sheet_t sheet_pos = m_sheets.size(); + m_sheets.emplace_back(std::make_unique<export_sheet>(m_doc, *sh)); + + m_sheet_index_map.insert( + std::make_pair(name, sheet_pos)); + + return m_sheets[sheet_pos].get(); + } +}; + +export_factory::export_factory(const document& doc) : + mp_impl(std::make_unique<impl>(doc)) {} + +export_factory::~export_factory() {} + +const iface::export_sheet* export_factory::get_sheet(std::string_view sheet_name) const +{ + return mp_impl->get_sheet(sheet_name); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_pivot.cpp b/src/spreadsheet/factory_pivot.cpp new file mode 100644 index 0000000..2761da5 --- /dev/null +++ b/src/spreadsheet/factory_pivot.cpp @@ -0,0 +1,303 @@ +/* -*- 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 "factory_pivot.hpp" + +#include "orcus/string_pool.hpp" +#include "orcus/exception.hpp" + +#include <sstream> +#include <iostream> +#include <cassert> + +namespace orcus { namespace spreadsheet { + +class import_pc_field_group : public iface::import_pivot_cache_field_group +{ + using range_grouping_type = pivot_cache_group_data_t::range_grouping_type; + + document& m_doc; + pivot_cache_field_t& m_parent_field; + std::unique_ptr<pivot_cache_group_data_t> m_data; + pivot_cache_item_t m_current_field_item; + +private: + std::string_view intern(std::string_view s) + { + return m_doc.get_string_pool().intern(s).first; + } + + range_grouping_type& get_range_grouping() + { + if (!m_data->range_grouping) + m_data->range_grouping = range_grouping_type(); + + return *m_data->range_grouping; + } + +public: + import_pc_field_group(document& doc, pivot_cache_field_t& parent, size_t base_index) : + m_doc(doc), + m_parent_field(parent), + m_data(std::make_unique<pivot_cache_group_data_t>(base_index)) {} + + ~import_pc_field_group() override {} + + void link_base_to_group_items(size_t group_item_index) override + { + pivot_cache_indices_t& b2g = m_data->base_to_group_indices; + b2g.push_back(group_item_index); + } + + void set_field_item_string(std::string_view value) override + { + m_current_field_item.type = pivot_cache_item_t::item_type::character; + m_current_field_item.value = intern(value); + } + + void set_field_item_numeric(double v) override + { + m_current_field_item.type = pivot_cache_item_t::item_type::numeric; + m_current_field_item.value = v; + } + + void commit_field_item() override + { + m_data->items.push_back(std::move(m_current_field_item)); + } + + void set_range_grouping_type(pivot_cache_group_by_t group_by) override + { + get_range_grouping().group_by = group_by; + } + + void set_range_auto_start(bool b) override + { + get_range_grouping().auto_start = b; + } + + void set_range_auto_end(bool b) override + { + get_range_grouping().auto_end = b; + } + + void set_range_start_number(double v) override + { + get_range_grouping().start = v; + } + + void set_range_end_number(double v) override + { + get_range_grouping().end = v; + } + + void set_range_start_date(const date_time_t& dt) override + { + get_range_grouping().start_date = dt; + } + + void set_range_end_date(const date_time_t& dt) override + { + get_range_grouping().end_date = dt; + } + + void set_range_interval(double v) override + { + get_range_grouping().interval = v; + } + + void commit() override + { + m_parent_field.group_data = std::move(m_data); + } +}; + +std::string_view import_pivot_cache_def::intern(std::string_view s) +{ + return m_doc.get_string_pool().intern(s).first; +} + +import_pivot_cache_def::import_pivot_cache_def(document& doc) : m_doc(doc) {} + +import_pivot_cache_def::~import_pivot_cache_def() {} + +void import_pivot_cache_def::create_cache(pivot_cache_id_t cache_id) +{ + m_src_type = unknown; + m_cache = std::make_unique<pivot_cache>(cache_id, m_doc.get_string_pool()); +} + +void import_pivot_cache_def::set_worksheet_source(std::string_view ref, std::string_view sheet_name) +{ + assert(m_cache); + + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + assert(resolver); + + m_src_type = worksheet; + m_src_sheet_name = intern(sheet_name); + + ixion::formula_name_t fn = resolver->resolve(ref, ixion::abs_address_t(0,0,0)); + + if (fn.type != ixion::formula_name_t::range_reference) + { + std::ostringstream os; + os << "'" << ref << "' is not a valid range."; + throw xml_structure_error(os.str()); + } + + m_src_range = std::get<ixion::range_t>(fn.value).to_abs(ixion::abs_address_t(0,0,0)); +} + +void import_pivot_cache_def::set_worksheet_source(std::string_view table_name) +{ + assert(m_cache); + + m_src_table_name = intern(table_name); +} + +void import_pivot_cache_def::set_field_count(size_t n) +{ + m_current_fields.reserve(n); +} + +void import_pivot_cache_def::set_field_name(std::string_view name) +{ + m_current_field.name = intern(name); +} + +iface::import_pivot_cache_field_group* import_pivot_cache_def::start_field_group(size_t base_index) +{ + m_current_field_group = + std::make_unique<import_pc_field_group>(m_doc, m_current_field, base_index); + + return m_current_field_group.get(); +} + +void import_pivot_cache_def::set_field_min_value(double v) +{ + m_current_field.min_value = v; +} + +void import_pivot_cache_def::set_field_max_value(double v) +{ + m_current_field.max_value = v; +} + +void import_pivot_cache_def::set_field_min_date(const date_time_t& dt) +{ + m_current_field.min_date = dt; +} + +void import_pivot_cache_def::set_field_max_date(const date_time_t& dt) +{ + m_current_field.max_date = dt; +} + +void import_pivot_cache_def::commit_field() +{ + m_current_fields.push_back(std::move(m_current_field)); +} + +void import_pivot_cache_def::set_field_item_string(std::string_view value) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::character; + m_current_field_item.value = intern(value); +} + +void import_pivot_cache_def::set_field_item_numeric(double v) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::numeric; + m_current_field_item.value = v; +} + +void import_pivot_cache_def::set_field_item_date_time(const date_time_t& dt) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::date_time; + m_current_field_item.value = dt; +} + +void import_pivot_cache_def::set_field_item_error(error_value_t ev) +{ + m_current_field_item.type = pivot_cache_item_t::item_type::error; + m_current_field_item.value = ev; +} + +void import_pivot_cache_def::commit_field_item() +{ + m_current_field.items.push_back(std::move(m_current_field_item)); +} + +void import_pivot_cache_def::commit() +{ + m_cache->insert_fields(std::move(m_current_fields)); + assert(m_current_fields.empty()); + + if (!m_src_table_name.empty()) + { + m_doc.get_pivot_collection().insert_worksheet_cache( + m_src_table_name, std::move(m_cache)); + return; + } + + m_doc.get_pivot_collection().insert_worksheet_cache( + m_src_sheet_name, m_src_range, std::move(m_cache)); +} + +import_pivot_cache_records::import_pivot_cache_records(document& doc) : + m_doc(doc), m_cache(nullptr) {} + +import_pivot_cache_records::~import_pivot_cache_records() {} + +void import_pivot_cache_records::set_cache(pivot_cache* p) +{ + m_cache = p; +} + +void import_pivot_cache_records::set_record_count(size_t n) +{ + m_records.reserve(n); +} + +void import_pivot_cache_records::append_record_value_numeric(double v) +{ + m_current_record.emplace_back(v); +} + +void import_pivot_cache_records::append_record_value_character(std::string_view s) +{ + m_current_record.emplace_back(s); +} + +void import_pivot_cache_records::append_record_value_shared_item(size_t index) +{ + m_current_record.emplace_back(index); +} + +void import_pivot_cache_records::commit_record() +{ + if (!m_cache) + { + m_current_record.clear(); + return; + } + + m_records.push_back(std::move(m_current_record)); +} + +void import_pivot_cache_records::commit() +{ + if (!m_cache) + return; + + m_cache->insert_records(std::move(m_records)); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_pivot.hpp b/src/spreadsheet/factory_pivot.hpp new file mode 100644 index 0000000..465fef1 --- /dev/null +++ b/src/spreadsheet/factory_pivot.hpp @@ -0,0 +1,120 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_FACTORY_PIVOT_HPP +#define INCLUDED_ORCUS_SPREADSHEET_FACTORY_PIVOT_HPP + +#include "orcus/spreadsheet/pivot.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/spreadsheet/import_interface_pivot.hpp" + +#include <ixion/formula_name_resolver.hpp> + +namespace orcus { namespace spreadsheet { + +class import_pc_field_group; + +/** + * Concrete implementation of the import_pivot_cache_definition interface. + */ +class import_pivot_cache_def : public iface::import_pivot_cache_definition +{ + enum source_type { unknown = 0, worksheet, external, consolidation, scenario }; + + document& m_doc; + + pivot_cache_id_t m_cache_id = 0; + + source_type m_src_type = unknown; + std::string_view m_src_sheet_name; + ixion::abs_range_t m_src_range; + std::string_view m_src_table_name; + + std::unique_ptr<pivot_cache> m_cache; + pivot_cache::fields_type m_current_fields; + pivot_cache_field_t m_current_field; + pivot_cache_item_t m_current_field_item; + + std::unique_ptr<import_pc_field_group> m_current_field_group; + +private: + std::string_view intern(std::string_view s); + +public: + import_pivot_cache_def(document& doc); + ~import_pivot_cache_def(); + + void create_cache(pivot_cache_id_t cache_id); + + virtual void set_worksheet_source(std::string_view ref, std::string_view sheet_name) override; + + virtual void set_worksheet_source(std::string_view table_name) override; + + virtual void set_field_count(size_t n) override; + + virtual void set_field_name(std::string_view name) override; + + virtual iface::import_pivot_cache_field_group* start_field_group(size_t base_index) override; + + virtual void set_field_min_value(double v) override; + + virtual void set_field_max_value(double v) override; + + virtual void set_field_min_date(const date_time_t& dt) override; + + virtual void set_field_max_date(const date_time_t& dt) override; + + virtual void commit_field() override; + + virtual void set_field_item_string(std::string_view value) override; + + virtual void set_field_item_numeric(double v) override; + + virtual void set_field_item_date_time(const date_time_t& dt) override; + + virtual void set_field_item_error(error_value_t ev) override; + + virtual void commit_field_item() override; + + virtual void commit() override; +}; + +/** + * Concrete implementation of the import_pivot_cache_records interface. + */ +class import_pivot_cache_records : public iface::import_pivot_cache_records +{ + document& m_doc; + pivot_cache* m_cache; //< cache to push the records to at the very end. + + pivot_cache_record_t m_current_record; + pivot_cache::records_type m_records; + +public: + import_pivot_cache_records(document& doc); + ~import_pivot_cache_records(); + + void set_cache(pivot_cache* p); + + virtual void set_record_count(size_t n) override; + + virtual void append_record_value_numeric(double v) override; + + virtual void append_record_value_character(std::string_view s) override; + + virtual void append_record_value_shared_item(size_t index) override; + + virtual void commit_record() override; + + virtual void commit() override; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_shared_strings.cpp b/src/spreadsheet/factory_shared_strings.cpp new file mode 100644 index 0000000..a8375c0 --- /dev/null +++ b/src/spreadsheet/factory_shared_strings.cpp @@ -0,0 +1,118 @@ +/* -*- 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 "factory_shared_strings.hpp" + +#include <orcus/spreadsheet/shared_strings.hpp> +#include <orcus/spreadsheet/styles.hpp> +#include <orcus/string_pool.hpp> +#include <ixion/model_context.hpp> + +namespace orcus { namespace spreadsheet { namespace detail { + +import_shared_strings::import_shared_strings( + string_pool& sp, ixion::model_context& cxt, styles& st, shared_strings& ss_store) : + m_string_pool(sp), + m_cxt(cxt), + m_styles(st), + m_ss_store(ss_store) +{ +} + +import_shared_strings::~import_shared_strings() {} + +size_t import_shared_strings::append(std::string_view s) +{ + return m_cxt.append_string(s); +} + +size_t import_shared_strings::add(std::string_view s) +{ + return m_cxt.add_string(s); +} + +void import_shared_strings::set_segment_font(size_t font_index) +{ + const font_t* font_data = m_styles.get_font(font_index); + if (!font_data) + return; + + m_cur_format.bold = font_data->bold ? *font_data->bold : false; + m_cur_format.italic = font_data->italic ? *font_data->italic : false; + + if (font_data->name) + m_cur_format.font = *font_data->name; // font names are already interned when set. + + if (font_data->size) + m_cur_format.font_size = *font_data->size; + + if (font_data->color) + m_cur_format.color = *font_data->color; +} + +void import_shared_strings::set_segment_bold(bool b) +{ + m_cur_format.bold = b; +} + +void import_shared_strings::set_segment_italic(bool b) +{ + m_cur_format.italic = b; +} + +void import_shared_strings::set_segment_font_name(std::string_view s) +{ + m_cur_format.font = m_string_pool.intern(s).first; +} + +void import_shared_strings::set_segment_font_size(double point) +{ + m_cur_format.font_size = point; +} + +void import_shared_strings::set_segment_font_color( + color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + m_cur_format.color = color_t(alpha, red, green, blue); +} + +void import_shared_strings::append_segment(std::string_view s) +{ + if (s.empty()) + return; + + size_t start_pos = m_cur_segment_string.size(); + m_cur_segment_string += s; + + if (m_cur_format.formatted()) + { + // This segment is formatted. + // Record the position and size of the format run. + m_cur_format.pos = start_pos; + m_cur_format.size = s.size(); + + if (!mp_cur_format_runs) + mp_cur_format_runs = std::make_unique<format_runs_t>(); + + mp_cur_format_runs->push_back(m_cur_format); + m_cur_format.reset(); + } +} + +size_t import_shared_strings::commit_segments() +{ + ixion::string_id_t sindex = m_cxt.append_string(m_cur_segment_string); + m_cur_segment_string.clear(); + m_ss_store.set_format_runs(sindex, std::move(mp_cur_format_runs)); + mp_cur_format_runs.reset(); + + return sindex; +} + +}}} // namespace orcus::spreadsheet::detail + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_shared_strings.hpp b/src/spreadsheet/factory_shared_strings.hpp new file mode 100644 index 0000000..b49d274 --- /dev/null +++ b/src/spreadsheet/factory_shared_strings.hpp @@ -0,0 +1,64 @@ +/* -*- 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/. + */ + +#pragma once + +#include <orcus/spreadsheet/import_interface.hpp> +#include <orcus/spreadsheet/document_types.hpp> + +#include <memory> + +namespace ixion { + +class model_context; + +} + +namespace orcus { + +class string_pool; + +namespace spreadsheet { + +class styles; +class shared_strings; + +namespace detail { + +class import_shared_strings : public iface::import_shared_strings +{ + orcus::string_pool& m_string_pool; + ixion::model_context& m_cxt; + styles& m_styles; + shared_strings& m_ss_store; + + std::string m_cur_segment_string; + format_run m_cur_format; + std::unique_ptr<format_runs_t> mp_cur_format_runs; + +public: + import_shared_strings( + string_pool& sp, ixion::model_context& cxt, styles& st, + orcus::spreadsheet::shared_strings& ss_store); + virtual ~import_shared_strings() override; + + virtual size_t append(std::string_view s) override; + virtual size_t add(std::string_view s) override; + + virtual void set_segment_font(size_t font_index) override; + virtual void set_segment_bold(bool b) override; + virtual void set_segment_italic(bool b) override; + virtual void set_segment_font_name(std::string_view s) override; + virtual void set_segment_font_size(double point) override; + virtual void set_segment_font_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual void append_segment(std::string_view s) override; + virtual size_t commit_segments() override; +}; + +}}} // namespace orcus::spreadsheet::detail + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_sheet.cpp b/src/spreadsheet/factory_sheet.cpp new file mode 100644 index 0000000..dcc6639 --- /dev/null +++ b/src/spreadsheet/factory_sheet.cpp @@ -0,0 +1,640 @@ +/* -*- 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 "factory_sheet.hpp" +#include "orcus/spreadsheet/sheet.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/spreadsheet/view.hpp" +#include "orcus/measurement.hpp" +#include "orcus/string_pool.hpp" + +#include "formula_global.hpp" + +#include <ixion/formula_name_resolver.hpp> +#include <ixion/model_context.hpp> +#include <ixion/formula.hpp> + +namespace orcus { namespace spreadsheet { + +import_sheet_named_exp::import_sheet_named_exp(document& doc, sheet_t sheet_index) : + m_doc(doc), m_sheet_index(sheet_index), m_base(sheet_index, 0, 0) {} + +import_sheet_named_exp::~import_sheet_named_exp() {} + +void import_sheet_named_exp::define( + std::string_view name, std::string_view expression, formula_ref_context_t ref_cxt) +{ + string_pool& sp = m_doc.get_string_pool(); + m_name = sp.intern(name).first; + + const ixion::formula_name_resolver* resolver = m_doc.get_formula_name_resolver(ref_cxt); + assert(resolver); + + ixion::model_context& cxt = m_doc.get_model_context(); + m_tokens = ixion::parse_formula_string(cxt, m_base, *resolver, expression); +} + +void import_sheet_named_exp::set_base_position(const src_address_t& pos) +{ + m_base.sheet = pos.sheet; + m_base.row = pos.row; + m_base.column = pos.column; +} + +void import_sheet_named_exp::set_named_expression(std::string_view name, std::string_view expression) +{ + define(name, expression, formula_ref_context_t::global); +} + +void import_sheet_named_exp::set_named_range(std::string_view name, std::string_view range) +{ + define(name, range, formula_ref_context_t::named_range); +} + +void import_sheet_named_exp::commit() +{ + ixion::model_context& cxt = m_doc.get_model_context(); + cxt.set_named_expression(m_sheet_index, std::string{m_name}, m_base, std::move(m_tokens)); + + m_name = std::string_view{}; + m_base.sheet = 0; + m_base.row = 0; + m_base.column = 0; +} + +import_data_table::import_data_table(sheet& sh) : m_sheet(sh) {} +import_data_table::~import_data_table() {} + +void import_data_table::reset() +{ +} + +void import_data_table::set_type(data_table_type_t /*type*/) +{ +} + +void import_data_table::set_range(const range_t& /*range*/) +{ +} + +void import_data_table::set_first_reference(std::string_view /*ref*/, bool /*deleted*/) +{ +} + +void import_data_table::set_second_reference(std::string_view /*ref*/, bool /*deleted*/) +{ +} + +void import_data_table::commit() +{ +} + +import_auto_filter::import_auto_filter(sheet& sh, string_pool& sp) : + m_sheet(sh), + m_string_pool(sp), + m_cur_col(-1) {} + +void import_auto_filter::reset() +{ + mp_data.reset(new auto_filter_t); + m_cur_col = -1; + m_cur_col_data.reset(); +} + +void import_auto_filter::set_range(const range_t& range) +{ + mp_data->range = to_abs_range(range, m_sheet.get_index()); +} + +void import_auto_filter::set_column(col_t col) +{ + m_cur_col = col; +} + +void import_auto_filter::append_column_match_value(std::string_view value) +{ + // The string pool belongs to the document. + value = m_string_pool.intern(value).first; + m_cur_col_data.match_values.insert(value); +} + +void import_auto_filter::commit_column() +{ + if (!mp_data) + return; + + mp_data->commit_column(m_cur_col, m_cur_col_data); + m_cur_col_data.reset(); +} + +void import_auto_filter::commit() +{ + m_sheet.set_auto_filter_data(mp_data.release()); +} + +import_array_formula::import_array_formula(document& doc, sheet& sheet) : + m_doc(doc), m_sheet(sheet), m_missing_formula_result(), m_error_policy(formula_error_policy_t::fail) +{ + m_range.first.column = -1; + m_range.first.row = -1; + m_range.last = m_range.first; +} + +import_array_formula::~import_array_formula() +{ +} + +void import_array_formula::set_range(const range_t& range) +{ + m_range = range; + + // Initialize the result matrix with the missing result value. + switch (m_missing_formula_result.get_type()) + { + case ixion::formula_result::result_type::value: + { + ixion::matrix _mtx( + m_range.last.row - m_range.first.row + 1, + m_range.last.column - m_range.first.column + 1, + m_missing_formula_result.get_value()); + m_result_mtx.swap(_mtx); + break; + } + case ixion::formula_result::result_type::error: + { + ixion::matrix _mtx( + m_range.last.row - m_range.first.row + 1, + m_range.last.column - m_range.first.column + 1, + m_missing_formula_result.get_error()); + m_result_mtx.swap(_mtx); + break; + } + case ixion::formula_result::result_type::string: + { + ixion::matrix _mtx( + m_range.last.row - m_range.first.row + 1, + m_range.last.column - m_range.first.column + 1, + m_missing_formula_result.get_string()); + m_result_mtx.swap(_mtx); + break; + } + default: + { + ixion::matrix _mtx( + m_range.last.row - m_range.first.row + 1, + m_range.last.column - m_range.first.column + 1); + m_result_mtx.swap(_mtx); + } + } +} + +void import_array_formula::set_formula(formula_grammar_t /*grammar*/, std::string_view formula) +{ + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + if (!resolver) + return; + + // Tokenize the formula string and store it. + ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_address_t pos(m_sheet.get_index(), m_range.first.row, m_range.first.column); + + try + { + m_tokens = ixion::parse_formula_string(cxt, pos, *resolver, formula); + } + catch (const std::exception& e) + { + if (m_error_policy == formula_error_policy_t::fail) + throw; + + std::string_view error_s = e.what(); + m_tokens = ixion::create_formula_error_tokens(cxt, formula, error_s); + } +} + +void import_array_formula::set_result_value(row_t row, col_t col, double value) +{ + m_result_mtx.set(row, col, value); +} + +void import_array_formula::set_result_string(row_t /*row*/, col_t /*col*/, std::string_view /*value*/) +{ + // TODO : handle this +} + +void import_array_formula::set_result_empty(row_t /*row*/, col_t /*col*/) +{ + // TODO : handle this +} + +void import_array_formula::set_result_bool(row_t row, col_t col, bool value) +{ + m_result_mtx.set(row, col, value); +} + +void import_array_formula::commit() +{ + ixion::formula_result cached_results(std::move(m_result_mtx)); + m_sheet.set_grouped_formula(m_range, std::move(m_tokens), std::move(cached_results)); +} + +void import_array_formula::set_missing_formula_result(ixion::formula_result result) +{ + m_missing_formula_result = std::move(result); +} + +void import_array_formula::set_formula_error_policy(formula_error_policy_t policy) +{ + m_error_policy = policy; +} + +void import_array_formula::reset() +{ + m_tokens.clear(); + m_result_mtx = ixion::matrix(); + m_range.first.row = -1; + m_range.first.column = -1; + m_range.last.row = -1; + m_range.last.column = -1; +} + +import_formula::import_formula(document& doc, sheet& sheet, shared_formula_pool& pool) : + m_doc(doc), + m_sheet(sheet), + m_shared_formula_pool(pool), + m_row(-1), + m_col(-1), + m_shared_index(0), + m_shared(false), + m_error_policy(formula_error_policy_t::fail) {} + +import_formula::~import_formula() {} + +void import_formula::set_position(row_t row, col_t col) +{ + m_row = row; + m_col = col; +} + +void import_formula::set_formula(formula_grammar_t /*grammar*/, std::string_view formula) +{ + if (m_row < 0 || m_col < 0) + return; + + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + if (!resolver) + return; + + // Tokenize the formula string and store it. + ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_address_t pos(m_sheet.get_index(), m_row, m_col); + + ixion::formula_tokens_t tokens; + try + { + tokens = ixion::parse_formula_string(cxt, pos, *resolver, formula); + } + catch (const std::exception& e) + { + if (m_error_policy == formula_error_policy_t::fail) + throw; + + std::string_view error_s = e.what(); + tokens = ixion::create_formula_error_tokens(cxt, formula, error_s); + } + + m_tokens_store = ixion::formula_tokens_store::create(); + m_tokens_store->get() = std::move(tokens); +} + +void import_formula::set_shared_formula_index(size_t index) +{ + m_shared = true; + m_shared_index = index; +} + +void import_formula::set_result_value(double value) +{ + m_result = ixion::formula_result(value); +} + +void import_formula::set_result_string(std::string_view value) +{ + m_result = ixion::formula_result(std::string{value}); +} + +void import_formula::set_result_empty() {} +void import_formula::set_result_bool(bool /*value*/) {} + +void import_formula::commit() +{ + if (m_row < 0 || m_col < 0) + return; + + if (m_shared) + { + if (m_tokens_store) + { + if (m_result) + m_sheet.set_formula(m_row, m_col, m_tokens_store, *m_result); + else + m_sheet.set_formula(m_row, m_col, m_tokens_store); + + m_shared_formula_pool.add(m_shared_index, m_tokens_store); + } + else + { + ixion::formula_tokens_store_ptr_t ts = m_shared_formula_pool.get(m_shared_index); + if (!ts) + return; + + if (m_result) + m_sheet.set_formula(m_row, m_col, ts, *m_result); + else + m_sheet.set_formula(m_row, m_col, ts); + } + return; + } + + if (m_result) + m_sheet.set_formula(m_row, m_col, m_tokens_store, *m_result); + else + m_sheet.set_formula(m_row, m_col, m_tokens_store); +} + +void import_formula::set_missing_formula_result(ixion::formula_result result) +{ + m_result = std::move(result); +} + +void import_formula::set_formula_error_policy(formula_error_policy_t policy) +{ + m_error_policy = policy; +} + +void import_formula::reset() +{ + m_tokens_store.reset(); + m_result.reset(); + m_row = -1; + m_col = -1; + m_shared_index = 0; + m_shared = false; +} + +import_sheet::import_sheet(document& doc, sheet& sh, sheet_view* view) : + m_doc(doc), + m_sheet(sh), + m_formula(doc, sh, m_shared_formula_pool), + m_array_formula(doc, sh), + m_named_exp(doc, sh.get_index()), + m_sheet_properties(doc, sh), + m_data_table(sh), + m_auto_filter(sh, doc.get_string_pool()), + m_table(doc, sh), + m_charset(character_set_t::unspecified), + m_fill_missing_formula_results(false) +{ + if (view) + m_sheet_view = std::make_unique<import_sheet_view>(*view, sh.get_index()); +} + +import_sheet::~import_sheet() {} + +iface::import_sheet_view* import_sheet::get_sheet_view() +{ + return m_sheet_view.get(); +} + +iface::import_auto_filter* import_sheet::get_auto_filter() +{ + m_auto_filter.reset(); + return &m_auto_filter; +} + +iface::import_conditional_format* import_sheet::get_conditional_format() +{ + return nullptr; +} + +iface::import_data_table* import_sheet::get_data_table() +{ + return &m_data_table; +} + +iface::import_named_expression* import_sheet::get_named_expression() +{ + return &m_named_exp; +} + +iface::import_sheet_properties* import_sheet::get_sheet_properties() +{ + return &m_sheet_properties; +} + +iface::import_table* import_sheet::get_table() +{ + m_table.reset(); + return &m_table; +} + +iface::import_formula* import_sheet::get_formula() +{ + m_formula.reset(); + + if (m_fill_missing_formula_results) + { + m_formula.set_missing_formula_result( + ixion::formula_result(ixion::formula_error_t::no_result_error)); + } + + return &m_formula; +} + +iface::import_array_formula* import_sheet::get_array_formula() +{ + m_array_formula.reset(); + + if (m_fill_missing_formula_results) + { + m_array_formula.set_missing_formula_result( + ixion::formula_result(ixion::formula_error_t::no_result_error)); + } + + return &m_array_formula; +} + +void import_sheet::set_auto(row_t row, col_t col, std::string_view s) +{ + m_sheet.set_auto(row, col, s); +} + +void import_sheet::set_bool(row_t row, col_t col, bool value) +{ + m_sheet.set_bool(row, col, value); +} + +void import_sheet::set_date_time(row_t row, col_t col, int year, int month, int day, int hour, int minute, double second) +{ + m_sheet.set_date_time(row, col, year, month, day, hour, minute, second); +} + +void import_sheet::set_format(row_t row, col_t col, size_t xf_index) +{ + m_sheet.set_format(row, col, xf_index); +} + +void import_sheet::set_format( + row_t row_start, col_t col_start, row_t row_end, col_t col_end, size_t xf_index) +{ + m_sheet.set_format(row_start, col_start, row_end, col_end, xf_index); +} + +void import_sheet::set_column_format(col_t col, col_t col_span, std::size_t xf_index) +{ + m_sheet.set_column_format(col, col_span, xf_index); +} + +void import_sheet::set_row_format(row_t row, std::size_t xf_index) +{ + m_sheet.set_row_format(row, xf_index); +} + +void import_sheet::set_string(row_t row, col_t col, string_id_t sindex) +{ + m_sheet.set_string(row, col, sindex); +} + +void import_sheet::set_value(row_t row, col_t col, double value) +{ + m_sheet.set_value(row, col, value); +} + +void import_sheet::fill_down_cells(row_t src_row, col_t src_col, row_t range_size) +{ + m_sheet.fill_down_cells(src_row, src_col, range_size); +} + +range_size_t import_sheet::get_sheet_size() const +{ + return m_doc.get_sheet_size(); +} + +void import_sheet::set_character_set(character_set_t charset) +{ + m_charset = charset; +} + +void import_sheet::set_fill_missing_formula_results(bool b) +{ + m_fill_missing_formula_results = b; +} + +void import_sheet::set_formula_error_policy(formula_error_policy_t policy) +{ + m_formula.set_formula_error_policy(policy); + m_array_formula.set_formula_error_policy(policy); +} + +import_sheet_view::import_sheet_view(sheet_view& view, sheet_t si) : + m_view(view), m_sheet_index(si) {} + +import_sheet_view::~import_sheet_view() {} + +void import_sheet_view::set_split_pane( + double hor_split, double ver_split, + const orcus::spreadsheet::address_t& top_left_cell, + orcus::spreadsheet::sheet_pane_t active_pane) +{ + m_view.set_split_pane(hor_split, ver_split, top_left_cell); + m_view.set_active_pane(active_pane); +} + +void import_sheet_view::set_frozen_pane( + orcus::spreadsheet::col_t visible_columns, + orcus::spreadsheet::row_t visible_rows, + const orcus::spreadsheet::address_t& top_left_cell, + orcus::spreadsheet::sheet_pane_t active_pane) +{ + m_view.set_frozen_pane(visible_columns, visible_rows, top_left_cell); + m_view.set_active_pane(active_pane); +} + +void import_sheet_view::set_selected_range(sheet_pane_t pane, range_t range) +{ + m_view.set_selection(pane, range); +} + +void import_sheet_view::set_sheet_active() +{ + m_view.get_document_view().set_active_sheet(m_sheet_index); +} + +import_sheet_properties::import_sheet_properties(document& doc, sheet& sh) : + m_doc(doc), m_sheet(sh) {} + +import_sheet_properties::~import_sheet_properties() {} + +void import_sheet_properties::set_column_width(col_t col, col_t col_span, double width, orcus::length_unit_t unit) +{ + col_width_t w = orcus::convert(width, unit, length_unit_t::twip); + m_sheet.set_col_width(col, col_span, w); +} + +void import_sheet_properties::set_column_hidden(col_t col, col_t col_span, bool hidden) +{ + m_sheet.set_col_hidden(col, col_span, hidden); +} + +void import_sheet_properties::set_row_height(row_t row, double height, orcus::length_unit_t unit) +{ + row_height_t h = orcus::convert(height, unit, length_unit_t::twip); + m_sheet.set_row_height(row, h); +} + +void import_sheet_properties::set_row_hidden(row_t row, bool hidden) +{ + m_sheet.set_row_hidden(row, hidden); +} + +void import_sheet_properties::set_merge_cell_range(const range_t& range) +{ + m_sheet.set_merge_cell_range(range); +} + +export_sheet::export_sheet(const document& doc, const sheet& sh) : m_doc(doc), m_sheet(sh) {} +export_sheet::~export_sheet() {} + +void export_sheet::write_string(std::ostream& os, row_t row, col_t col) const +{ + const ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_address_t pos(m_sheet.get_index(), row, col); + + switch (cxt.get_celltype(pos)) + { + case ixion::celltype_t::string: + { + size_t str_id = cxt.get_string_identifier(pos); + const std::string* p = cxt.get_string(str_id); + if (p) + os << *p; + } + break; + case ixion::celltype_t::numeric: + os << cxt.get_numeric_value(pos); + break; + default: + ; + } +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/src/spreadsheet/factory_sheet.hpp b/src/spreadsheet/factory_sheet.hpp new file mode 100644 index 0000000..ded4d10 --- /dev/null +++ b/src/spreadsheet/factory_sheet.hpp @@ -0,0 +1,275 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_FACTORY_SHEET_HPP +#define INCLUDED_ORCUS_SPREADSHEET_FACTORY_SHEET_HPP + +#include <orcus/spreadsheet/import_interface.hpp> +#include <orcus/spreadsheet/import_interface_view.hpp> +#include <orcus/spreadsheet/auto_filter.hpp> + +#include <orcus/spreadsheet/export_interface.hpp> + +#include "factory_table.hpp" +#include "shared_formula.hpp" + +#include <memory> +#include <optional> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> +#include <ixion/matrix.hpp> + +namespace orcus { + +class string_pool; + +namespace spreadsheet { + +class document; +class sheet_view; +class sheet; +class import_sheet_view; + +class import_sheet_named_exp : public iface::import_named_expression +{ + document& m_doc; + sheet_t m_sheet_index; + std::string_view m_name; + ixion::abs_address_t m_base; + ixion::formula_tokens_t m_tokens; + + void define(std::string_view name, std::string_view expression, formula_ref_context_t ref_cxt); + +public: + import_sheet_named_exp(document& doc, sheet_t sheet_index); + virtual ~import_sheet_named_exp() override; + + virtual void set_base_position(const src_address_t& pos) override; + virtual void set_named_expression(std::string_view name, std::string_view expression) override; + virtual void set_named_range(std::string_view name, std::string_view range) override; + virtual void commit(); +}; + +/** + * Implement the sheet properties import interface, but the actual + * properties are stored in sheet. + */ +class import_sheet_properties : public iface::import_sheet_properties +{ + document& m_doc; + sheet& m_sheet; +public: + import_sheet_properties(document& doc, sheet& sh); + ~import_sheet_properties(); + + virtual void set_column_width(col_t col, col_t col_span, double width, orcus::length_unit_t unit); + virtual void set_column_hidden(col_t col, col_t col_span, bool hidden); + virtual void set_row_height(row_t row, double height, orcus::length_unit_t unit); + virtual void set_row_hidden(row_t row, bool hidden); + virtual void set_merge_cell_range(const range_t& range); +}; + +class import_data_table : public iface::import_data_table +{ + sheet& m_sheet; +public: + import_data_table(sheet& sh); + ~import_data_table(); + + void reset(); + + virtual void set_type(data_table_type_t type) override; + + virtual void set_range(const range_t& range) override; + + virtual void set_first_reference(std::string_view ref, bool deleted) override; + + virtual void set_second_reference(std::string_view ref, bool deleted) override; + + virtual void commit() override; +}; + +class import_auto_filter : public orcus::spreadsheet::iface::import_auto_filter +{ + sheet& m_sheet; + string_pool& m_string_pool; + std::unique_ptr<auto_filter_t> mp_data; + col_t m_cur_col; + auto_filter_column_t m_cur_col_data; + +public: + import_auto_filter(sheet& sh, string_pool& sp); + + void reset(); + + virtual void set_range(const range_t& range) override; + + virtual void set_column(col_t col) override; + + virtual void append_column_match_value(std::string_view value) override; + + virtual void commit_column() override; + + virtual void commit() override; +}; + +class import_array_formula : public iface::import_array_formula +{ + document& m_doc; + sheet& m_sheet; + + range_t m_range; + ixion::formula_tokens_t m_tokens; + ixion::formula_result m_missing_formula_result; + ixion::matrix m_result_mtx; + formula_error_policy_t m_error_policy; + +public: + import_array_formula(document& doc, sheet& sheet); + virtual ~import_array_formula() override; + + virtual void set_range(const range_t& range) override; + + virtual void set_formula(formula_grammar_t grammar, std::string_view formula) override; + + virtual void set_result_value(row_t row, col_t col, double value) override; + + virtual void set_result_string(row_t row, col_t col, std::string_view value) override; + + virtual void set_result_empty(row_t row, col_t col) override; + + virtual void set_result_bool(row_t row, col_t col, bool value) override; + + virtual void commit() override; + + void set_missing_formula_result(ixion::formula_result result); + + void set_formula_error_policy(formula_error_policy_t policy); + + void reset(); +}; + +class import_formula : public iface::import_formula +{ + document& m_doc; + sheet& m_sheet; + shared_formula_pool& m_shared_formula_pool; + + row_t m_row; + col_t m_col; + size_t m_shared_index; + bool m_shared; + + ixion::formula_tokens_store_ptr_t m_tokens_store; + std::optional<ixion::formula_result> m_result; + formula_error_policy_t m_error_policy; + +public: + import_formula(document& doc, sheet& sheet, shared_formula_pool& pool); + virtual ~import_formula() override; + + virtual void set_position(row_t row, col_t col) override; + virtual void set_formula(formula_grammar_t grammar, std::string_view formula) override; + virtual void set_shared_formula_index(size_t index) override; + virtual void set_result_value(double value) override; + virtual void set_result_string(std::string_view value) override; + virtual void set_result_empty() override; + virtual void set_result_bool(bool value) override; + virtual void commit() override; + + void set_missing_formula_result(ixion::formula_result result); + void set_formula_error_policy(formula_error_policy_t policy); + + void reset(); +}; + +class import_sheet : public iface::import_sheet +{ + document& m_doc; + sheet& m_sheet; + shared_formula_pool m_shared_formula_pool; + import_formula m_formula; + import_array_formula m_array_formula; + import_sheet_named_exp m_named_exp; + import_sheet_properties m_sheet_properties; + import_data_table m_data_table; + import_auto_filter m_auto_filter; + import_table m_table; + character_set_t m_charset; + + std::unique_ptr<import_sheet_view> m_sheet_view; + + bool m_fill_missing_formula_results; + +public: + import_sheet(document& doc, sheet& sh, sheet_view* view); + virtual ~import_sheet() override; + + virtual iface::import_sheet_view* get_sheet_view() override; + virtual iface::import_auto_filter* get_auto_filter() override; + virtual iface::import_conditional_format* get_conditional_format() override; + virtual iface::import_data_table* get_data_table() override; + virtual iface::import_named_expression* get_named_expression() override; + virtual iface::import_sheet_properties* get_sheet_properties() override; + virtual iface::import_table* get_table() override; + virtual iface::import_formula* get_formula() override; + virtual iface::import_array_formula* get_array_formula() override; + virtual void set_auto(row_t row, col_t col, std::string_view s) override; + virtual void set_bool(row_t row, col_t col, bool value) override; + virtual void set_date_time(row_t row, col_t col, int year, int month, int day, int hour, int minute, double second) override; + virtual void set_format(row_t row, col_t col, size_t xf_index) override; + virtual void set_format(row_t row_start, col_t col_start, row_t row_end, col_t col_end, size_t xf_index) override; + virtual void set_column_format(col_t col, col_t col_span, std::size_t xf_index) override; + virtual void set_row_format(row_t row, std::size_t xf_index) override; + virtual void set_string(row_t row, col_t col, string_id_t sindex) override; + virtual void set_value(row_t row, col_t col, double value) override; + virtual void fill_down_cells(row_t src_row, col_t src_col, row_t range_size) override; + virtual range_size_t get_sheet_size() const override; + + void set_character_set(character_set_t charset); + void set_fill_missing_formula_results(bool b); + void set_formula_error_policy(formula_error_policy_t policy); +}; + +class import_sheet_view : public iface::import_sheet_view +{ + sheet_view& m_view; + sheet_t m_sheet_index; +public: + import_sheet_view(sheet_view& view, sheet_t si); + virtual ~import_sheet_view(); + virtual void set_sheet_active() override; + + virtual void set_split_pane( + double hor_split, double ver_split, + const address_t& top_left_cell, + sheet_pane_t active_pane) override; + + virtual void set_frozen_pane( + col_t visible_columns, row_t visible_rows, + const address_t& top_left_cell, + sheet_pane_t active_pane) override; + + virtual void set_selected_range(sheet_pane_t pane, range_t range) override; +}; + +class export_sheet : public iface::export_sheet +{ + const document& m_doc; + const sheet& m_sheet; +public: + export_sheet(const document& doc, const sheet& sh); + ~export_sheet(); + + virtual void write_string(std::ostream& os, row_t row, col_t col) const override; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_styles.cpp b/src/spreadsheet/factory_styles.cpp new file mode 100644 index 0000000..91c6844 --- /dev/null +++ b/src/spreadsheet/factory_styles.cpp @@ -0,0 +1,870 @@ +/* -*- 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 "orcus/spreadsheet/factory.hpp" +#include "orcus/spreadsheet/styles.hpp" +#include "orcus/string_pool.hpp" + +#include <unordered_map> + +namespace orcus { namespace spreadsheet { + +namespace { + +class import_font_style : public iface::import_font_style +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_font_style() = delete; + import_font_style(styles& _styles_model, string_pool& sp); + import_font_style(std::shared_ptr<import_factory_config> _config, styles& _styles_model, string_pool& sp); + virtual ~import_font_style() override; + + virtual void set_bold(bool b) override; + virtual void set_bold_asian(bool b) override; + virtual void set_bold_complex(bool b) override; + + virtual void set_italic(bool b) override; + virtual void set_italic_asian(bool b) override; + virtual void set_italic_complex(bool b) override; + + virtual void set_name(std::string_view s) override; + virtual void set_name_asian(std::string_view s) override; + virtual void set_name_complex(std::string_view s) override; + + virtual void set_size(double point) override; + virtual void set_size_asian(double point) override; + virtual void set_size_complex(double point) override; + + virtual void set_underline(underline_t e) override; + virtual void set_underline_width(underline_width_t e) override; + virtual void set_underline_mode(underline_mode_t e) override; + virtual void set_underline_type(underline_type_t e) override; + virtual void set_underline_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual void set_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual void set_strikethrough_style(strikethrough_style_t s) override; + virtual void set_strikethrough_type(strikethrough_type_t s) override; + virtual void set_strikethrough_width(strikethrough_width_t s) override; + virtual void set_strikethrough_text(strikethrough_text_t s) override; + virtual std::size_t commit() override; + + void reset(); +}; + +class import_fill_style : public iface::import_fill_style +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_fill_style() = delete; + import_fill_style(styles& _styles_model, string_pool& sp); + virtual ~import_fill_style() override; + + virtual void set_pattern_type(fill_pattern_t fp) override; + virtual void set_fg_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual void set_bg_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual size_t commit() override; + + void reset(); +}; + +class import_border_style : public iface::import_border_style +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_border_style() = delete; + import_border_style(styles& _styles_model, string_pool& sp); + virtual ~import_border_style() override; + + virtual void set_style(border_direction_t dir, border_style_t style) override; + virtual void set_color( + border_direction_t dir, color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) override; + virtual void set_width(border_direction_t dir, double width, orcus::length_unit_t unit) override; + virtual size_t commit() override; + + void reset(); +}; + +class import_cell_protection : public iface::import_cell_protection +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_cell_protection() = delete; + import_cell_protection(styles& _styles_model, string_pool& sp); + virtual ~import_cell_protection() override; + + virtual void set_hidden(bool b) override; + virtual void set_locked(bool b) override; + virtual void set_print_content(bool b) override; + virtual void set_formula_hidden(bool b) override; + virtual size_t commit() override; + + void reset(); +}; + +class import_number_format : public iface::import_number_format +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_number_format() = delete; + import_number_format(styles& _styles_model, string_pool& sp); + virtual ~import_number_format() override; + + virtual void set_identifier(std::size_t id) override; + virtual void set_code(std::string_view s) override; + virtual size_t commit() override; + + void reset(); +}; + +class import_xf : public iface::import_xf +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_xf() = delete; + import_xf(styles& _styles_model, string_pool& sp); + virtual ~import_xf() override; + + virtual void set_font(size_t index) override; + virtual void set_fill(size_t index) override; + virtual void set_border(size_t index) override; + virtual void set_protection(size_t index) override; + virtual void set_number_format(size_t index) override; + virtual void set_style_xf(size_t index) override; + virtual void set_apply_alignment(bool b) override; + virtual void set_horizontal_alignment(hor_alignment_t align) override; + virtual void set_vertical_alignment(ver_alignment_t align) override; + virtual void set_wrap_text(bool b) override; + virtual void set_shrink_to_fit(bool b) override; + virtual size_t commit() override; + + void reset(xf_category_t cat); +}; + +class import_cell_style : public iface::import_cell_style +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_cell_style() = delete; + import_cell_style(styles& _styles_model, string_pool& sp); + virtual ~import_cell_style() override; + + void set_name(std::string_view s) override; + void set_display_name(std::string_view s) override; + void set_xf(size_t index) override; + void set_builtin(size_t index) override; + void set_parent_name(std::string_view s) override; + void commit() override; + + void reset(); +}; + +struct import_font_style::impl +{ + std::shared_ptr<import_factory_config> config; + styles& styles_model; + string_pool& str_pool; + + std::unordered_map<font_t, std::size_t, font_t::hash> font_cache; + font_t cur_font; + + impl(styles& _styles_model, string_pool& sp) : + config(std::make_shared<import_factory_config>()), + styles_model(_styles_model), + str_pool(sp) {} + + impl(std::shared_ptr<import_factory_config> _config, styles& _styles_model, string_pool& sp) : + config(_config), styles_model(_styles_model), str_pool(sp) {} +}; + +import_font_style::import_font_style(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_font_style::import_font_style( + std::shared_ptr<import_factory_config> _config, styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_config, _styles_model, sp)) +{ +} + +import_font_style::~import_font_style() = default; + +void import_font_style::set_bold(bool b) +{ + mp_impl->cur_font.bold = b; +} + +void import_font_style::set_bold_asian(bool b) +{ + mp_impl->cur_font.bold_asian = b; +} + +void import_font_style::set_bold_complex(bool b) +{ + mp_impl->cur_font.bold_complex = b; +} + +void import_font_style::set_italic(bool b) +{ + mp_impl->cur_font.italic = b; +} + +void import_font_style::set_italic_asian(bool b) +{ + mp_impl->cur_font.italic_asian = b; +} + +void import_font_style::set_italic_complex(bool b) +{ + mp_impl->cur_font.italic_complex = b; +} + +void import_font_style::set_name(std::string_view s) +{ + mp_impl->cur_font.name = mp_impl->str_pool.intern(s).first; +} + +void import_font_style::set_name_asian(std::string_view s) +{ + mp_impl->cur_font.name_asian = mp_impl->str_pool.intern(s).first; +} + +void import_font_style::set_name_complex(std::string_view s) +{ + mp_impl->cur_font.name_complex = mp_impl->str_pool.intern(s).first; +} + +void import_font_style::set_size(double point) +{ + mp_impl->cur_font.size = point; +} + +void import_font_style::set_size_asian(double point) +{ + mp_impl->cur_font.size_asian = point; +} + +void import_font_style::set_size_complex(double point) +{ + mp_impl->cur_font.size_complex = point; +} + +void import_font_style::set_underline(underline_t e) +{ + mp_impl->cur_font.underline_style = e; +} + +void import_font_style::set_underline_width(underline_width_t e) +{ + mp_impl->cur_font.underline_width = e; +} + +void import_font_style::set_underline_mode(underline_mode_t e) +{ + mp_impl->cur_font.underline_mode = e; +} + +void import_font_style::set_underline_type(underline_type_t e) +{ + mp_impl->cur_font.underline_type = e; +} + +void import_font_style::set_underline_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + mp_impl->cur_font.underline_color = color_t(alpha, red, green, blue); +} + +void import_font_style::set_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + mp_impl->cur_font.color = color_t(alpha, red, green, blue); +} + +void import_font_style::set_strikethrough_style(strikethrough_style_t s) +{ + mp_impl->cur_font.strikethrough_style = s; +} + +void import_font_style::set_strikethrough_type(strikethrough_type_t s) +{ + mp_impl->cur_font.strikethrough_type = s; +} + +void import_font_style::set_strikethrough_width(strikethrough_width_t s) +{ + mp_impl->cur_font.strikethrough_width = s; +} + +void import_font_style::set_strikethrough_text(strikethrough_text_t s) +{ + mp_impl->cur_font.strikethrough_text = s; +} + +std::size_t import_font_style::commit() +{ + if (mp_impl->config->enable_font_cache) + { + auto it = mp_impl->font_cache.find(mp_impl->cur_font); + if (it != mp_impl->font_cache.end()) + return it->second; + } + + std::size_t font_id = mp_impl->styles_model.append_font(mp_impl->cur_font); + mp_impl->font_cache.insert({mp_impl->cur_font, font_id}); + mp_impl->cur_font.reset(); + return font_id; +} + +void import_font_style::reset() +{ + mp_impl->cur_font.reset(); +} + +struct import_fill_style::impl +{ + styles& styles_model; + string_pool& str_pool; + + fill_t cur_fill; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} +}; + +import_fill_style::import_fill_style(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_fill_style::~import_fill_style() +{ +} + +void import_fill_style::set_pattern_type(fill_pattern_t fp) +{ + mp_impl->cur_fill.pattern_type = fp; +} + +void import_fill_style::set_fg_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + mp_impl->cur_fill.fg_color = color_t{alpha, red, green, blue}; +} + +void import_fill_style::set_bg_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + mp_impl->cur_fill.bg_color = color_t{alpha, red, green, blue}; +} + +size_t import_fill_style::commit() +{ + size_t fill_id = mp_impl->styles_model.append_fill(mp_impl->cur_fill); + mp_impl->cur_fill.reset(); + return fill_id; +} + +void import_fill_style::reset() +{ + mp_impl->cur_fill.reset(); +} + +struct import_border_style::impl +{ + styles& styles_model; + string_pool& str_pool; + + border_t cur_border; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} + + border_attrs_t* get_border_attrs(border_direction_t dir) + { + switch (dir) + { + case border_direction_t::top: + return &cur_border.top; + case border_direction_t::bottom: + return &cur_border.bottom; + case border_direction_t::left: + return &cur_border.left; + case border_direction_t::right: + return &cur_border.right; + case border_direction_t::diagonal: + return &cur_border.diagonal; + case border_direction_t::diagonal_bl_tr: + return &cur_border.diagonal_bl_tr; + case border_direction_t::diagonal_tl_br: + return &cur_border.diagonal_tl_br; + case border_direction_t::unknown: + ; + } + + return nullptr; + } +}; + +import_border_style::import_border_style(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_border_style::~import_border_style() +{ +} + +void import_border_style::set_style(border_direction_t dir, border_style_t style) +{ + border_attrs_t* v = mp_impl->get_border_attrs(dir); + if (!v) + return; + + v->style = style; +} + +void import_border_style::set_color( + border_direction_t dir, color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + border_attrs_t* v = mp_impl->get_border_attrs(dir); + if (!v) + return; + + v->border_color = color_t(alpha, red, green, blue); +} + +void import_border_style::set_width(border_direction_t dir, double width, orcus::length_unit_t unit) +{ + border_attrs_t* v = mp_impl->get_border_attrs(dir); + if (!v) + return; + + length_t bw{unit, width}; + v->border_width = bw; +} + +size_t import_border_style::commit() +{ + size_t border_id = mp_impl->styles_model.append_border(mp_impl->cur_border); + mp_impl->cur_border.reset(); + return border_id; +} + +void import_border_style::reset() +{ + mp_impl->cur_border.reset(); +} + +struct import_cell_protection::impl +{ + styles& styles_model; + string_pool& str_pool; + + protection_t cur_protection; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} +}; + +import_cell_protection::import_cell_protection(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_cell_protection::~import_cell_protection() +{ +} + +void import_cell_protection::set_hidden(bool b) +{ + mp_impl->cur_protection.hidden = b; +} + +void import_cell_protection::set_locked(bool b) +{ + mp_impl->cur_protection.locked = b; +} + +void import_cell_protection::set_print_content(bool b) +{ + mp_impl->cur_protection.print_content = b; +} + +void import_cell_protection::set_formula_hidden(bool b) +{ + mp_impl->cur_protection.formula_hidden = b; +} + +std::size_t import_cell_protection::commit() +{ + std::size_t cp_id = mp_impl->styles_model.append_protection(mp_impl->cur_protection); + mp_impl->cur_protection.reset(); + return cp_id; +} + +void import_cell_protection::reset() +{ + mp_impl->cur_protection.reset(); +} + +struct import_number_format::impl +{ + styles& styles_model; + string_pool& str_pool; + + number_format_t cur_numfmt; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} +}; + +import_number_format::import_number_format(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_number_format::~import_number_format() +{ +} + +void import_number_format::set_identifier(std::size_t id) +{ + mp_impl->cur_numfmt.identifier = id; +} + +void import_number_format::set_code(std::string_view s) +{ + mp_impl->cur_numfmt.format_string = s; +} + +size_t import_number_format::commit() +{ + std::size_t fmt_id = mp_impl->styles_model.append_number_format(mp_impl->cur_numfmt); + mp_impl->cur_numfmt.reset(); + + return fmt_id; +} + +void import_number_format::reset() +{ + mp_impl->cur_numfmt.reset(); +} + +struct import_xf::impl +{ + styles& styles_model; + string_pool& str_pool; + + cell_format_t cur_cell_format; + xf_category_t xf_category = xf_category_t::unknown; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} +}; + +import_xf::import_xf(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_xf::~import_xf() +{ +} + +void import_xf::set_font(size_t index) +{ + mp_impl->cur_cell_format.font = index; +} + +void import_xf::set_fill(size_t index) +{ + mp_impl->cur_cell_format.fill = index; +} + +void import_xf::set_border(size_t index) +{ + mp_impl->cur_cell_format.border = index; + + // TODO : we need to decide whether to have interface methods for these + // apply_foo attributes. For now there is only one, for alignment. + mp_impl->cur_cell_format.apply_border = index > 0; +} + +void import_xf::set_protection(size_t index) +{ + mp_impl->cur_cell_format.protection = index; +} + +void import_xf::set_number_format(size_t index) +{ + mp_impl->cur_cell_format.number_format = index; +} + +void import_xf::set_style_xf(size_t index) +{ + mp_impl->cur_cell_format.style_xf = index; +} + +void import_xf::set_apply_alignment(bool b) +{ + mp_impl->cur_cell_format.apply_alignment = b; +} + +void import_xf::set_horizontal_alignment(hor_alignment_t align) +{ + mp_impl->cur_cell_format.hor_align = align; +} + +void import_xf::set_vertical_alignment(ver_alignment_t align) +{ + mp_impl->cur_cell_format.ver_align = align; +} + +void import_xf::set_wrap_text(bool b) +{ + mp_impl->cur_cell_format.wrap_text = b; +} + +void import_xf::set_shrink_to_fit(bool b) +{ + mp_impl->cur_cell_format.shrink_to_fit = b; +} + + +size_t import_xf::commit() +{ + size_t xf_id = 0; + + switch (mp_impl->xf_category) + { + case xf_category_t::cell: + xf_id = mp_impl->styles_model.append_cell_format(mp_impl->cur_cell_format); + break; + case xf_category_t::cell_style: + xf_id = mp_impl->styles_model.append_cell_style_format(mp_impl->cur_cell_format); + break; + case xf_category_t::differential: + xf_id = mp_impl->styles_model.append_diff_cell_format(mp_impl->cur_cell_format); + break; + case xf_category_t::unknown: + throw std::logic_error("unknown cell format category"); + } + + mp_impl->cur_cell_format.reset(); + return xf_id; +} + +void import_xf::reset(xf_category_t cat) +{ + if (cat == xf_category_t::unknown) + throw std::invalid_argument("The specified category is 'unknown'."); + + mp_impl->cur_cell_format.reset(); + mp_impl->xf_category = cat; +} + +struct import_cell_style::impl +{ + styles& styles_model; + string_pool& str_pool; + + cell_style_t cur_cell_style; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), str_pool(sp) {} +}; + +import_cell_style::import_cell_style(styles& _styles_model, string_pool& sp) : + mp_impl(std::make_unique<impl>(_styles_model, sp)) +{ +} + +import_cell_style::~import_cell_style() {} + +void import_cell_style::set_name(std::string_view s) +{ + mp_impl->cur_cell_style.name = mp_impl->str_pool.intern(s).first; +} + +void import_cell_style::set_display_name(std::string_view s) +{ + mp_impl->cur_cell_style.display_name = mp_impl->str_pool.intern(s).first; +} + +void import_cell_style::set_xf(size_t index) +{ + mp_impl->cur_cell_style.xf = index; +} + +void import_cell_style::set_builtin(size_t index) +{ + mp_impl->cur_cell_style.builtin = index; +} + +void import_cell_style::set_parent_name(std::string_view s) +{ + mp_impl->cur_cell_style.parent_name = mp_impl->str_pool.intern(s).first; +} + +void import_cell_style::commit() +{ + mp_impl->styles_model.append_cell_style(mp_impl->cur_cell_style); + mp_impl->cur_cell_style.reset(); +} + +void import_cell_style::reset() +{ + mp_impl->cur_cell_style.reset(); +} + +} // anonymous namespace + +struct import_styles::impl +{ + styles& styles_model; + string_pool& str_pool; + + import_font_style font_style; + import_fill_style fill_style; + import_border_style border_style; + import_cell_protection cell_protection; + import_number_format number_format; + import_xf xf; + import_cell_style cell_style; + + impl(styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), + str_pool(sp), + font_style(_styles_model, sp), + fill_style(_styles_model, sp), + border_style(_styles_model, sp), + cell_protection(_styles_model, sp), + number_format(_styles_model, sp), + xf(_styles_model, sp), + cell_style(_styles_model, sp) + {} + + impl(std::shared_ptr<import_factory_config> config, styles& _styles_model, string_pool& sp) : + styles_model(_styles_model), + str_pool(sp), + font_style(config, _styles_model, sp), + fill_style(_styles_model, sp), + border_style(_styles_model, sp), + cell_protection(_styles_model, sp), + number_format(_styles_model, sp), + xf(_styles_model, sp), + cell_style(_styles_model, sp) + {} +}; + +import_styles::import_styles(styles& styles_store, string_pool& sp) : + mp_impl(std::make_unique<impl>(styles_store, sp)) {} + +import_styles::import_styles(std::shared_ptr<import_factory_config> config, styles& styles_store, string_pool& sp) : + mp_impl(std::make_unique<impl>(config, styles_store, sp)) {} + +import_styles::~import_styles() = default; + +iface::import_font_style* import_styles::start_font_style() +{ + mp_impl->font_style.reset(); + return &mp_impl->font_style; +} + +iface::import_fill_style* import_styles::start_fill_style() +{ + mp_impl->fill_style.reset(); + return &mp_impl->fill_style; +} + +iface::import_border_style* import_styles::start_border_style() +{ + mp_impl->border_style.reset(); + return &mp_impl->border_style; +} + +iface::import_cell_protection* import_styles::start_cell_protection() +{ + mp_impl->cell_protection.reset(); + return &mp_impl->cell_protection; +} + +iface::import_number_format* import_styles::start_number_format() +{ + mp_impl->number_format.reset(); + return &mp_impl->number_format; +} + +iface::import_xf* import_styles::start_xf(xf_category_t cat) +{ + mp_impl->xf.reset(cat); + return &mp_impl->xf; +} + +iface::import_cell_style* import_styles::start_cell_style() +{ + mp_impl->cell_style.reset(); + return &mp_impl->cell_style; +} + +void import_styles::set_font_count(size_t n) +{ + mp_impl->styles_model.reserve_font_store(n); +} + +void import_styles::set_fill_count(size_t n) +{ + mp_impl->styles_model.reserve_fill_store(n); +} + +void import_styles::set_border_count(size_t n) +{ + mp_impl->styles_model.reserve_border_store(n); +} + +void import_styles::set_number_format_count(size_t n) +{ + mp_impl->styles_model.reserve_number_format_store(n); +} + +void import_styles::set_xf_count(xf_category_t cat, size_t n) +{ + switch (cat) + { + case xf_category_t::cell: + mp_impl->styles_model.reserve_cell_format_store(n); + break; + case xf_category_t::cell_style: + mp_impl->styles_model.reserve_cell_style_format_store(n); + break; + case xf_category_t::differential: + mp_impl->styles_model.reserve_diff_cell_format_store(n); + break; + case xf_category_t::unknown: + break; + } +} + +void import_styles::set_cell_style_count(size_t n) +{ + mp_impl->styles_model.reserve_cell_style_store(n); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_table.cpp b/src/spreadsheet/factory_table.cpp new file mode 100644 index 0000000..a77b7af --- /dev/null +++ b/src/spreadsheet/factory_table.cpp @@ -0,0 +1,213 @@ +/* -*- 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 "factory_table.hpp" +#include "formula_global.hpp" + +#include "orcus/string_pool.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/spreadsheet/sheet.hpp" +#include "orcus/spreadsheet/auto_filter.hpp" + +#include <ixion/formula_name_resolver.hpp> + +namespace orcus { namespace spreadsheet { + +namespace { + +class table_auto_filter : public iface::import_auto_filter +{ + string_pool& m_pool; + sheet_t m_sheet_pos; + col_t m_cur_col; + auto_filter_column_t m_cur_col_data; + auto_filter_t m_filter_data; + + auto_filter_t* mp_data; + +public: + table_auto_filter(document& doc, sheet& sh) : + m_pool(doc.get_string_pool()), + m_sheet_pos(sh.get_index()), + m_cur_col(-1), + mp_data(nullptr) {} + + void reset(auto_filter_t* data) + { + mp_data = data; + m_cur_col = -1; + m_cur_col_data.reset(); + m_filter_data.reset(); + } + + virtual void set_range(const range_t& range) + { + m_filter_data.range = to_abs_range(range, m_sheet_pos); + } + + virtual void set_column(orcus::spreadsheet::col_t col) + { + m_cur_col = col; + } + + virtual void append_column_match_value(std::string_view value) + { + // The string pool belongs to the document. + value = m_pool.intern(value).first; + m_cur_col_data.match_values.insert(value); + }; + + virtual void commit_column() + { + m_filter_data.commit_column(m_cur_col, m_cur_col_data); + m_cur_col_data.reset(); + } + + virtual void commit() + { + if (!mp_data) + return; + + mp_data->swap(m_filter_data); + } +}; + +} + +struct import_table::impl +{ + document& m_doc; + sheet& m_sheet; + + table_auto_filter m_auto_filter; + + std::unique_ptr<table_t> mp_data; + table_column_t m_column; + + impl(const impl&) = delete; + impl& operator=(const impl&) = delete; + + impl(document& doc, sheet& sh) : + m_doc(doc), m_sheet(sh), m_auto_filter(doc, sh) {} +}; + +import_table::import_table(document& doc, sheet& sh) : mp_impl(std::make_unique<impl>(doc, sh)) {} + +import_table::~import_table() {} + +iface::import_auto_filter* import_table::get_auto_filter() +{ + mp_impl->m_auto_filter.reset(&mp_impl->mp_data->filter); + return &mp_impl->m_auto_filter; +} + +void import_table::set_range(const range_t& range) +{ + mp_impl->mp_data->range = to_abs_range(range, mp_impl->m_sheet.get_index()); +} + +void import_table::set_identifier(size_t id) +{ + mp_impl->mp_data->identifier = id; +} + +void import_table::set_name(std::string_view name) +{ + string_pool& sp = mp_impl->m_doc.get_string_pool(); + mp_impl->mp_data->name = sp.intern(name).first; +} + +void import_table::set_display_name(std::string_view name) +{ + string_pool& sp = mp_impl->m_doc.get_string_pool(); + mp_impl->mp_data->display_name = sp.intern(name).first; +} + +void import_table::set_totals_row_count(size_t row_count) +{ + mp_impl->mp_data->totals_row_count = row_count; +} + +void import_table::set_column_count(size_t n) +{ + mp_impl->mp_data->columns.reserve(n); +} + +void import_table::set_column_identifier(size_t id) +{ + mp_impl->m_column.identifier = id; +} + +void import_table::set_column_name(std::string_view name) +{ + string_pool& sp = mp_impl->m_doc.get_string_pool(); + mp_impl->m_column.name = sp.intern(name).first; +} + +void import_table::set_column_totals_row_label(std::string_view label) +{ + string_pool& sp = mp_impl->m_doc.get_string_pool(); + mp_impl->m_column.totals_row_label = sp.intern(label).first; +} + +void import_table::set_column_totals_row_function(orcus::spreadsheet::totals_row_function_t func) +{ + mp_impl->m_column.totals_row_function = func; +} + +void import_table::commit_column() +{ + mp_impl->mp_data->columns.push_back(mp_impl->m_column); + mp_impl->m_column.reset(); +} + +void import_table::set_style_name(std::string_view name) +{ + table_style_t& style = mp_impl->mp_data->style; + string_pool& sp = mp_impl->m_doc.get_string_pool(); + style.name = sp.intern(name).first; +} + +void import_table::set_style_show_first_column(bool b) +{ + table_style_t& style = mp_impl->mp_data->style; + style.show_first_column = b; +} + +void import_table::set_style_show_last_column(bool b) +{ + table_style_t& style = mp_impl->mp_data->style; + style.show_last_column = b; +} + +void import_table::set_style_show_row_stripes(bool b) +{ + table_style_t& style = mp_impl->mp_data->style; + style.show_row_stripes = b; +} + +void import_table::set_style_show_column_stripes(bool b) +{ + table_style_t& style = mp_impl->mp_data->style; + style.show_column_stripes = b; +} + +void import_table::commit() +{ + mp_impl->m_doc.insert_table(mp_impl->mp_data.release()); + mp_impl->mp_data.reset(new table_t); +} + +void import_table::reset() +{ + mp_impl->mp_data.reset(new table_t); + mp_impl->m_column.reset(); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/factory_table.hpp b/src/spreadsheet/factory_table.hpp new file mode 100644 index 0000000..0a274b4 --- /dev/null +++ b/src/spreadsheet/factory_table.hpp @@ -0,0 +1,60 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_TABLE_HPP +#define INCLUDED_ORCUS_SPREADSHEET_TABLE_HPP + +#include "orcus/spreadsheet/import_interface.hpp" + +#include <memory> + +namespace orcus { namespace spreadsheet { + +class document; +class sheet; + +class import_table : public iface::import_table +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_table(document& doc, sheet& sh); + ~import_table(); + + virtual iface::import_auto_filter* get_auto_filter() override; + + virtual void set_range(const range_t& range) override; + virtual void set_identifier(size_t id) override; + virtual void set_name(std::string_view name) override; + virtual void set_display_name(std::string_view name) override; + virtual void set_totals_row_count(size_t row_count) override; + + virtual void set_column_count(size_t n) override; + + virtual void set_column_identifier(size_t id) override; + virtual void set_column_name(std::string_view name) override; + virtual void set_column_totals_row_label(std::string_view label) override; + virtual void set_column_totals_row_function(orcus::spreadsheet::totals_row_function_t func) override; + virtual void commit_column() override; + + virtual void set_style_name(std::string_view name) override; + virtual void set_style_show_first_column(bool b) override; + virtual void set_style_show_last_column(bool b) override; + virtual void set_style_show_row_stripes(bool b) override; + virtual void set_style_show_column_stripes(bool b) override; + + virtual void commit() override; + + void reset(); +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/flat_dumper.cpp b/src/spreadsheet/flat_dumper.cpp new file mode 100644 index 0000000..9be4245 --- /dev/null +++ b/src/spreadsheet/flat_dumper.cpp @@ -0,0 +1,208 @@ +/* -*- 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 "flat_dumper.hpp" +#include "number_format.hpp" +#include <orcus/spreadsheet/document.hpp> +#include <orcus/stream.hpp> + +#include <ixion/formula.hpp> +#include <ixion/model_context.hpp> +#include <ixion/model_iterator.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula_result.hpp> +#include <ixion/cell.hpp> + +#include <iostream> +#include <sstream> +#include <string> +#include <vector> + +using std::cout; +using std::endl; + +namespace orcus { namespace spreadsheet { namespace detail { + +flat_dumper::flat_dumper(const document& doc) : m_doc(doc) {} + +void flat_dumper::dump(std::ostream& os, ixion::sheet_t sheet_id) const +{ + const ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_range_t range = cxt.get_data_range(sheet_id); + if (!range.valid()) + // Sheet is empty. Nothing to print. + return; + + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + if (!resolver) + return; + + size_t row_count = range.last.row + 1; + size_t col_count = range.last.column + 1; + os << "rows: " << row_count << " cols: " << col_count << endl; + + // Always start at the top-left corner. + range.first.row = 0; + range.first.column = 0; + ixion::model_iterator iter = cxt.get_model_iterator( + sheet_id, ixion::rc_direction_t::vertical, range); + + std::vector<std::string> mx(row_count*col_count); + + auto to_pos = [col_count](size_t row, size_t col) -> size_t + { + return col_count * row + col; + }; + + // Calculate column widths as we iterate. + std::vector<size_t> col_widths(col_count, 0); + auto it_colwidth = col_widths.begin(); + col_t current_col = 0; + + for (; iter.has(); iter.next()) + { + const ixion::model_iterator::cell& c = iter.get(); + if (c.col > current_col) + { + ++current_col; + ++it_colwidth; + assert(current_col == c.col); + } + + size_t cell_str_width = 0; + + switch (c.type) + { + case ixion::celltype_t::string: + { + ixion::string_id_t sindex = std::get<ixion::string_id_t>(c.value); + const std::string* p = cxt.get_string(sindex); + assert(p); + cell_str_width = calc_logical_string_length(*p); + mx[to_pos(c.row, c.col)] = std::move(*p); + break; + } + case ixion::celltype_t::numeric: + { + std::ostringstream os2; + format_to_file_output(os2, std::get<double>(c.value)); + os2 << " [v]"; + std::string s = os2.str(); + cell_str_width = calc_logical_string_length(s); + mx[to_pos(c.row, c.col)] = std::move(s); + break; + } + case ixion::celltype_t::boolean: + { + std::ostringstream os2; + os2 << (std::get<bool>(c.value) ? "true" : "false") << " [b]"; + std::string s = os2.str(); + cell_str_width = calc_logical_string_length(s); + mx[to_pos(c.row, c.col)] = std::move(s); + break; + } + case ixion::celltype_t::formula: + { + // print the formula and the formula result. + const ixion::formula_cell* cell = std::get<const ixion::formula_cell*>(c.value); + assert(cell); + const ixion::formula_tokens_store_ptr_t& ts = cell->get_tokens(); + if (ts) + { + const ixion::formula_tokens_t& tokens = ts->get(); + + std::ostringstream os2; + std::string formula; + if (resolver) + { + ixion::abs_address_t pos(sheet_id, c.row, c.col); + pos = cell->get_parent_position(pos); + formula = ixion::print_formula_tokens( + cxt, pos, *resolver, tokens); + } + else + formula = "???"; + + ixion::formula_group_t fg = cell->get_group_properties(); + + if (fg.grouped) + os2 << '{' << formula << '}'; + else + os2 << formula; + + try + { + ixion::formula_result res = cell->get_result_cache( + ixion::formula_result_wait_policy_t::throw_exception); + os2 << " (" << res.str(cxt) << ")"; + } + catch (const std::exception&) + { + os2 << "(#RES!)"; + } + + std::string s = os2.str(); + cell_str_width = calc_logical_string_length(s); + mx[to_pos(c.row, c.col)] = std::move(s); + } + break; + } + default: + ; + } + + if (*it_colwidth < cell_str_width) + *it_colwidth = cell_str_width; + } + + // Create a row separator string; + std::ostringstream os2; + os2 << '+'; + for (size_t i = 0; i < col_widths.size(); ++i) + { + os2 << '-'; + size_t cw = col_widths[i]; + for (size_t j = 0; j < cw; ++j) + os2 << '-'; + os2 << "-+"; + } + + std::string sep = os2.str(); + + // Now print to stdout. + os << sep << endl; + for (size_t r = 0; r < row_count; ++r) + { + os << "|"; + for (size_t c = 0; c < col_count; ++c) + { + size_t cw = col_widths[c]; // column width + const std::string& s = mx[to_pos(r, c)]; + if (s.empty()) + { + for (size_t i = 0; i < cw; ++i) + os << ' '; + os << " |"; + } + else + { + os << ' ' << s; + cw -= calc_logical_string_length(s); + for (size_t i = 0; i < cw; ++i) + os << ' '; + os << " |"; + } + } + os << endl; + os << sep << endl; + } +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/flat_dumper.hpp b/src/spreadsheet/flat_dumper.hpp new file mode 100644 index 0000000..2a72938 --- /dev/null +++ b/src/spreadsheet/flat_dumper.hpp @@ -0,0 +1,36 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_FLAT_DUMPER_HPP +#define INCLUDED_ORCUS_SPREADSHEET_FLAT_DUMPER_HPP + +#include <string> +#include <ostream> +#include <ixion/types.hpp> + +namespace orcus { namespace spreadsheet { + +class document; + +namespace detail { + +class flat_dumper +{ + const document& m_doc; + +public: + flat_dumper(const document& doc); + + void dump(std::ostream& os, ixion::sheet_t sheet_id) const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/src/spreadsheet/formula_global.cpp b/src/spreadsheet/formula_global.cpp new file mode 100644 index 0000000..a4d7c6d --- /dev/null +++ b/src/spreadsheet/formula_global.cpp @@ -0,0 +1,56 @@ +/* -*- 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 "formula_global.hpp" + +#include <ixion/address.hpp> +#include <ixion/formula_name_resolver.hpp> + +namespace orcus { namespace spreadsheet { + +ixion::abs_range_t to_abs_range( + const ixion::formula_name_resolver& resolver, const char* p_ref, size_t n_ref) +{ + ixion::abs_range_t range(ixion::abs_range_t::invalid); + ixion::abs_address_t pos(0,0,0); + + ixion::formula_name_t res = resolver.resolve({p_ref, n_ref}, pos); + switch (res.type) + { + case ixion::formula_name_t::cell_reference: + // Single cell reference. + range.first = std::get<ixion::address_t>(res.value).to_abs(pos); + range.last = range.first; + break; + case ixion::formula_name_t::range_reference: + // Range reference. + range = std::get<ixion::range_t>(res.value).to_abs(pos); + break; + default: + ; // Unsupported range. Leave it invalid. + } + + return range; +} + +ixion::abs_range_t to_abs_range(const range_t& range, sheet_t sheet_pos) +{ + ixion::abs_range_t ret; + ret.first.column = range.first.column; + ret.first.row = range.first.row; + ret.first.sheet = sheet_pos; + + ret.last.column = range.last.column; + ret.last.row = range.last.row; + ret.last.sheet = sheet_pos; + + return ret; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/formula_global.hpp b/src/spreadsheet/formula_global.hpp new file mode 100644 index 0000000..9f43a65 --- /dev/null +++ b/src/spreadsheet/formula_global.hpp @@ -0,0 +1,48 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_FORMULA_GLOBAL_HPP +#define INCLUDED_ORCUS_SPREADSHEET_FORMULA_GLOBAL_HPP + +#include "orcus/spreadsheet/types.hpp" + +#include <cstdlib> + +namespace ixion { + +struct abs_range_t; +class formula_name_resolver; + +} + +namespace orcus { namespace spreadsheet { + +struct range_t; + +/** + * Parse a string representing a 2-dimensional range using the passed name + * resolver, and return an absolute range object. The sheet index will be + * unconditionally set to 0. It returns an invalid range object in case the + * parsing fails. + * + * @param resolver name resolver to use to resolve the range string. + * @param p_ref pointer to the first character of the range string. + * @param n_ref length of the range string. + * + * @return absolute range object, which may be set invalid in case the + * parsing is unsuccessful. + */ +ixion::abs_range_t to_abs_range( + const ixion::formula_name_resolver& resolver, const char* p_ref, size_t n_ref); + +ixion::abs_range_t to_abs_range(const range_t& range, sheet_t sheet_pos); + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/global_settings.cpp b/src/spreadsheet/global_settings.cpp new file mode 100644 index 0000000..71778bd --- /dev/null +++ b/src/spreadsheet/global_settings.cpp @@ -0,0 +1,50 @@ +/* -*- 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 "global_settings.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/spreadsheet/factory.hpp" + +namespace orcus { namespace spreadsheet { + +struct import_global_settings::impl +{ + import_factory& m_factory; + document& m_doc; + + impl(import_factory& factory, document& doc) : + m_factory(factory), m_doc(doc) {} +}; + +import_global_settings::import_global_settings(import_factory& factory, document& doc) : + mp_impl(std::make_unique<impl>(factory, doc)) {} + +import_global_settings::~import_global_settings() {} + +void import_global_settings::set_origin_date(int year, int month, int day) +{ + mp_impl->m_doc.set_origin_date(year, month, day); +} + +void import_global_settings::set_default_formula_grammar(formula_grammar_t grammar) +{ + mp_impl->m_doc.set_formula_grammar(grammar); +} + +formula_grammar_t import_global_settings::get_default_formula_grammar() const +{ + return mp_impl->m_doc.get_formula_grammar(); +} + +void import_global_settings::set_character_set(character_set_t charset) +{ + mp_impl->m_factory.set_character_set(charset); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/global_settings.hpp b/src/spreadsheet/global_settings.hpp new file mode 100644 index 0000000..8213833 --- /dev/null +++ b/src/spreadsheet/global_settings.hpp @@ -0,0 +1,41 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_GLOBAL_SETTINGS_HPP +#define INCLUDED_ORCUS_SPREADSHEET_GLOBAL_SETTINGS_HPP + +#include "orcus/spreadsheet/import_interface.hpp" + +#include <memory> + +namespace orcus { namespace spreadsheet { + +class document; +class import_factory; + +class import_global_settings : public spreadsheet::iface::import_global_settings +{ + struct impl; + std::unique_ptr<impl> mp_impl; + +public: + import_global_settings(import_factory& factory, document& doc); + virtual ~import_global_settings() override; + + virtual void set_origin_date(int year, int month, int day) override; + + virtual void set_default_formula_grammar(orcus::spreadsheet::formula_grammar_t grammar) override; + + virtual orcus::spreadsheet::formula_grammar_t get_default_formula_grammar() const override; + + virtual void set_character_set(character_set_t charset) override; +}; + +}} + +#endif +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/html_dumper.cpp b/src/spreadsheet/html_dumper.cpp new file mode 100644 index 0000000..cdf04de --- /dev/null +++ b/src/spreadsheet/html_dumper.cpp @@ -0,0 +1,695 @@ +/* -*- 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 "html_dumper.hpp" +#include "impl_types.hpp" +#include "number_format.hpp" + +#include "orcus/spreadsheet/styles.hpp" +#include "orcus/spreadsheet/shared_strings.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/spreadsheet/sheet.hpp" + +#include <ixion/address.hpp> +#include <ixion/model_context.hpp> +#include <ixion/formula.hpp> +#include <ixion/formula_result.hpp> +#include <ixion/cell.hpp> + +#include <sstream> + +namespace orcus { namespace spreadsheet { namespace detail { + +namespace { + +void build_rgb_color(std::ostringstream& os, const color_t& color_value) +{ + // Special colors. + if (color_value.alpha == 255 && color_value.red == 0 && color_value.green == 0 && color_value.blue == 0) + { + os << "black"; + return; + } + + if (color_value.alpha == 255 && color_value.red == 255 && color_value.green == 0 && color_value.blue == 0) + { + os << "red"; + return; + } + + if (color_value.alpha == 255 && color_value.red == 0 && color_value.green == 255 && color_value.blue == 0) + { + os << "green"; + return; + } + + if (color_value.alpha == 255 && color_value.red == 0 && color_value.green == 0 && color_value.blue == 255) + { + os << "blue"; + return; + } + + os << "rgb(" + << static_cast<short>(color_value.red) << "," + << static_cast<short>(color_value.green) << "," + << static_cast<short>(color_value.blue) << ")"; +} + +const char* css_style_global = +"table, td { " + "border-collapse : collapse; " +"}\n" + +"table { " + "border-spacing : 0px; " +"}\n" + +"td { " + "width : 1in; border: 1px solid lightgray; " +"}\n" + +"td.empty { " + "color : white; " +"}\n"; + +class html_elem +{ +public: + struct attr + { + std::string name; + std::string value; + + attr(const std::string& _name, const std::string& _value) : name(_name), value(_value) {} + }; + + typedef std::vector<attr> attrs_type; + + html_elem(std::ostream& strm, const char* name, const char* style = nullptr, const char* style_class = nullptr) : + m_strm(strm), m_name(name) + { + m_strm << '<' << m_name; + + if (style) + m_strm << " style=\"" << style << "\""; + + if (style_class) + m_strm << " class=\"" << style_class << "\""; + + m_strm << '>'; + } + + html_elem(std::ostream& strm, const char* name, const attrs_type& attrs) : + m_strm(strm), m_name(name) + { + m_strm << '<' << m_name; + + attrs_type::const_iterator it = attrs.begin(), it_end = attrs.end(); + for (; it != it_end; ++it) + m_strm << " " << it->name << "=\"" << it->value << "\""; + + m_strm << '>'; + } + + ~html_elem() + { + m_strm << "</" << m_name << '>'; + } + +private: + std::ostream& m_strm; + const char* m_name; +}; + +void print_formatted_text(std::ostream& strm, const std::string& text, const format_runs_t& formats) +{ + typedef html_elem elem; + + const char* p_span = "span"; + + size_t pos = 0; + format_runs_t::const_iterator itr = formats.begin(), itr_end = formats.end(); + for (; itr != itr_end; ++itr) + { + const format_run& run = *itr; + if (pos < run.pos) + { + // flush unformatted text. + strm << std::string(&text[pos], run.pos-pos); + pos = run.pos; + } + + if (!run.size) + continue; + + std::string style = ""; + if (run.bold) + style += "font-weight: bold;"; + else + style += "font-weight: normal;"; + + if (run.italic) + style += "font-style: italic;"; + else + style += "font-style: normal;"; + + if (!run.font.empty()) + { + style += "font-family: "; + style += run.font; + style += ";"; + } + + if (run.font_size) + { + std::ostringstream os; + os << "font-size: " << run.font_size << "pt;"; + style += os.str(); + } + + const color_t& col = run.color; + if (col.red || col.green || col.blue) + { + std::ostringstream os; + os << "color: "; + build_rgb_color(os, col); + os << ";"; + style += os.str(); + } + + if (style.empty()) + strm << std::string(&text[pos], run.size); + else + { + elem span(strm, p_span, style.c_str()); + strm << std::string(&text[pos], run.size); + } + + pos += run.size; + } + + if (pos < text.size()) + { + // flush the remaining unformatted text. + strm << std::string(&text[pos], text.size() - pos); + } +} + +void build_border_style(std::ostringstream& os, const char* style_name, const border_attrs_t& attrs) +{ + if (!attrs.style || *attrs.style == border_style_t::none) + return; + + os << style_name << ": "; + switch (*attrs.style) + { + case border_style_t::thin: + { + os << "solid 1px "; + break; + } + case border_style_t::medium: + { + os << "solid 2px "; + break; + } + case border_style_t::thick: + { + os << "solid 3px "; + break; + } + case border_style_t::hair: + { + os << "solid 0.5px "; + break; + } + case border_style_t::dotted: + { + os << "dotted 1px "; + break; + } + case border_style_t::dashed: + { + os << "dashed 1px "; + break; + } + case border_style_t::double_border: + { + os << "3px double "; + break; + } + case border_style_t::dash_dot: + { + // CSS doesn't support dash-dot. + os << "dashed 1px "; + break; + } + case border_style_t::dash_dot_dot: + { + // CSS doesn't support dash-dot-dot. + os << "dashed 1px "; + break; + } + case border_style_t::medium_dashed: + { + os << "dashed 2px "; + break; + } + case border_style_t::medium_dash_dot: + { + // CSS doesn't support dash-dot. + os << "dashed 2px "; + break; + } + case border_style_t::medium_dash_dot_dot: + { + // CSS doesn't support dash-dot-dot. + os << "dashed 2px "; + break; + } + case border_style_t::slant_dash_dot: + { + // CSS doesn't support dash-dot. + os << "dashed 2px "; + break; + } + default:; + } + + build_rgb_color(os, *attrs.border_color); + os << "; "; +} + +void build_style_string(std::string& str, const styles& styles, const cell_format_t& fmt) +{ + std::ostringstream os; + + { + const font_t* p = styles.get_font(fmt.font); + if (p) + { + if (p->name && !p->name.value().empty()) + os << "font-family: " << *p->name << ";"; + if (p->size) + os << "font-size: " << *p->size << "pt;"; + if (p->bold && *p->bold) + os << "font-weight: bold;"; + if (p->italic && *p->italic) + os << "font-style: italic;"; + + if (p->color) + { + const color_t& r = *p->color; + if (r.red || r.green || r.blue) + { + os << "color: "; + build_rgb_color(os, r); + os << ";"; + } + } + } + } + + { + const fill_t* p = styles.get_fill(fmt.fill); + if (p) + { + if (p->pattern_type && *p->pattern_type == fill_pattern_t::solid && p->fg_color) + { + const color_t& r = *p->fg_color; + os << "background-color: "; + build_rgb_color(os, r); + os << ";"; + } + } + } + + { + const border_t* p = styles.get_border(fmt.border); + if (p) + { + build_border_style(os, "border-top", p->top); + build_border_style(os, "border-bottom", p->bottom); + build_border_style(os, "border-left", p->left); + build_border_style(os, "border-right", p->right); + } + } + + if (fmt.apply_alignment) + { + if (fmt.hor_align != hor_alignment_t::unknown) + { + os << "text-align: "; + switch (fmt.hor_align) + { + case hor_alignment_t::left: + os << "left"; + break; + case hor_alignment_t::center: + os << "center"; + break; + case hor_alignment_t::right: + os << "right"; + break; + default: + ; + } + os << ";"; + } + + if (fmt.ver_align != ver_alignment_t::unknown) + { + os << "vertical-align: "; + switch (fmt.ver_align) + { + case ver_alignment_t::top: + os << "top"; + break; + case ver_alignment_t::middle: + os << "middle"; + break; + case ver_alignment_t::bottom: + os << "bottom"; + break; + default: + ; + } + os << ";"; + } + } + + str += os.str(); +} + +void dump_html_head(std::ostream& os) +{ + typedef html_elem elem; + + const char* p_head = "head"; + const char* p_style = "style"; + + elem elem_head(os, p_head); + { + elem elem_style(os, p_style); + os << css_style_global; + } +} + +void build_html_elem_attributes(html_elem::attrs_type& attrs, const std::string& style, const merge_size* p_merge_size) +{ + attrs.push_back(html_elem::attr("style", style)); + if (p_merge_size) + { + if (p_merge_size->width > 1) + { + std::ostringstream os2; + os2 << p_merge_size->width; + attrs.push_back(html_elem::attr("colspan", os2.str())); + } + + if (p_merge_size->height > 1) + { + std::ostringstream os2; + os2 << p_merge_size->height; + attrs.push_back(html_elem::attr("rowspan", os2.str())); + } + } +} + +} + +html_dumper::html_dumper( + const document& doc, + const col_merge_size_type& merge_ranges, + sheet_t sheet_id) : + m_doc(doc), + m_merge_ranges(merge_ranges), + m_sheet_id(sheet_id) +{ + build_overlapped_ranges(); +} + +void html_dumper::dump(std::ostream& os) const +{ + const sheet* sh = m_doc.get_sheet(m_sheet_id); + if (!sh) + return; + + typedef html_elem elem; + + const char* p_html = "html"; + const char* p_body = "body"; + const char* p_table = "table"; + const char* p_tr = "tr"; + const char* p_td = "td"; + + ixion::abs_range_t range = sh->get_data_range(); + + elem root(os, p_html); + dump_html_head(os); + + { + elem elem_body(os, p_body); + + if (!range.valid()) + // Sheet is empty. Nothing to print. + return; + + const ixion::model_context& cxt = m_doc.get_model_context(); + const ixion::formula_name_resolver* resolver = + m_doc.get_formula_name_resolver(spreadsheet::formula_ref_context_t::global); + const shared_strings& sstrings = m_doc.get_shared_strings(); + + elem table(os, p_table); + + row_t row_count = range.last.row + 1; + col_t col_count = range.last.column + 1; + for (row_t row = 0; row < row_count; ++row) + { + // Set the row height. + std::string row_style; + row_height_t rh = sh->get_row_height(row, nullptr, nullptr); + + // Convert height from twip to inches. + if (rh != get_default_row_height()) + { + std::string style; + double val = orcus::convert(rh, length_unit_t::twip, length_unit_t::inch); + std::ostringstream os_style; + os_style << "height: " << val << "in;"; + row_style += os_style.str(); + } + + const char* style_str = nullptr; + if (!row_style.empty()) + style_str = row_style.c_str(); + elem tr(os, p_tr, style_str); + + const detail::overlapped_col_index_type* p_overlapped = get_overlapped_ranges(row); + + for (col_t col = 0; col < col_count; ++col) + { + ixion::abs_address_t pos(m_sheet_id, row, col); + + const merge_size* p_merge_size = get_merge_size(row, col); + if (!p_merge_size && p_overlapped) + { + // Check if this cell is overlapped by a merged cell. + col_t overlapped_origin = -1; + col_t last_col = -1; + if (p_overlapped->search_tree(col, overlapped_origin, nullptr, &last_col).second && overlapped_origin >= 0) + { + // Skip all overlapped cells on this row. + col = last_col - 1; + continue; + } + } + size_t xf_id = sh->get_cell_format(row, col); + std::string style; + + if (row == 0) + { + // Set the column width. + col_width_t cw = sh->get_col_width(col, nullptr, nullptr); + + // Convert width from twip to inches. + if (cw != get_default_column_width()) + { + double val = orcus::convert(cw, length_unit_t::twip, length_unit_t::inch); + std::ostringstream os_style; + os_style << "width: " << val << "in;"; + style += os_style.str(); + } + } + + { + // Apply cell format. + const styles& styles = m_doc.get_styles(); + const cell_format_t* fmt = styles.get_cell_format(xf_id); + if (fmt) + build_style_string(style, styles, *fmt); + } + + ixion::celltype_t ct = cxt.get_celltype(pos); + if (ct == ixion::celltype_t::empty) + { + html_elem::attrs_type attrs; + build_html_elem_attributes(attrs, style, p_merge_size); + attrs.push_back(html_elem::attr("class", "empty")); + elem td(os, p_td, attrs); + os << '-'; // empty cell. + continue; + } + + html_elem::attrs_type attrs; + build_html_elem_attributes(attrs, style, p_merge_size); + elem td(os, p_td, attrs); + + switch (ct) + { + case ixion::celltype_t::string: + { + size_t sindex = cxt.get_string_identifier(pos); + const std::string* p = cxt.get_string(sindex); + assert(p); + const format_runs_t* pformat = sstrings.get_format_runs(sindex); + if (pformat) + print_formatted_text(os, *p, *pformat); + else + os << *p; + + break; + } + case ixion::celltype_t::numeric: + format_to_file_output(os, cxt.get_numeric_value(pos)); + break; + case ixion::celltype_t::boolean: + os << (cxt.get_boolean_value(pos) ? "true" : "false"); + break; + case ixion::celltype_t::formula: + { + // print the formula and the formula result. + const ixion::formula_cell* cell = cxt.get_formula_cell(pos); + assert(cell); + const ixion::formula_tokens_store_ptr_t& ts = cell->get_tokens(); + if (ts) + { + const ixion::formula_tokens_t& tokens = ts->get(); + + std::string formula; + if (resolver) + { + pos = cell->get_parent_position(pos); + formula = ixion::print_formula_tokens( + m_doc.get_model_context(), pos, *resolver, tokens); + } + else + formula = "???"; + + ixion::formula_group_t fg = cell->get_group_properties(); + + if (fg.grouped) + os << '{' << formula << '}'; + else + os << formula; + + try + { + ixion::formula_result res = cell->get_result_cache( + ixion::formula_result_wait_policy_t::throw_exception); + os << " (" << res.str(m_doc.get_model_context()) << ")"; + } + catch (const std::exception&) + { + os << " (#RES!)"; + } + } + + break; + } + default: + ; + } + } + } + } +} + +const overlapped_col_index_type* html_dumper::get_overlapped_ranges(row_t row) const +{ + overlapped_cells_type::const_iterator it = m_overlapped_ranges.find(row); + if (it == m_overlapped_ranges.end()) + return nullptr; + + return it->second.get(); +} + +const merge_size* html_dumper::get_merge_size(row_t row, col_t col) const +{ + col_merge_size_type::const_iterator it_col = m_merge_ranges.find(col); + if (it_col == m_merge_ranges.end()) + return nullptr; + + merge_size_type& col_merge_sizes = *it_col->second; + merge_size_type::const_iterator it_row = col_merge_sizes.find(row); + if (it_row == col_merge_sizes.end()) + return nullptr; + + return &it_row->second; +} + +void html_dumper::build_overlapped_ranges() +{ + const sheet* sh = m_doc.get_sheet(m_sheet_id); + if (!sh) + return; + + range_size_t sheet_size = m_doc.get_sheet_size(); + + detail::col_merge_size_type::const_iterator it_col = m_merge_ranges.begin(), it_col_end = m_merge_ranges.end(); + for (; it_col != it_col_end; ++it_col) + { + col_t col = it_col->first; + const detail::merge_size_type& data = *it_col->second; + detail::merge_size_type::const_iterator it = data.begin(), it_end = data.end(); + for (; it != it_end; ++it) + { + row_t row = it->first; + const detail::merge_size& item = it->second; + for (row_t i = 0; i < item.height; ++i, ++row) + { + // Get the container for this row. + detail::overlapped_cells_type::iterator it_cont = m_overlapped_ranges.find(row); + if (it_cont == m_overlapped_ranges.end()) + { + auto p = std::make_unique<detail::overlapped_col_index_type>(0, sheet_size.columns, -1); + std::pair<detail::overlapped_cells_type::iterator, bool> r = + m_overlapped_ranges.insert(detail::overlapped_cells_type::value_type(row, std::move(p))); + + if (!r.second) + { + // Insertion failed. + return; + } + + it_cont = r.first; + } + + detail::overlapped_col_index_type& cont = *it_cont->second; + cont.insert_back(col, col+item.width, col); + } + } + } + + // Build trees. + for (auto& range : m_overlapped_ranges) + range.second->build_tree(); +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/html_dumper.hpp b/src/spreadsheet/html_dumper.hpp new file mode 100644 index 0000000..4e66809 --- /dev/null +++ b/src/spreadsheet/html_dumper.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 INCLUDED_ORCUS_SPREADSHEET_HTML_DUMPER_HPP +#define INCLUDED_ORCUS_SPREADSHEET_HTML_DUMPER_HPP + +#include <string> +#include <ostream> +#include <ixion/types.hpp> + +#include "impl_types.hpp" + +namespace orcus { namespace spreadsheet { + +class document; + +namespace detail { + +class html_dumper +{ + const document& m_doc; + overlapped_cells_type m_overlapped_ranges; + const col_merge_size_type& m_merge_ranges; + sheet_t m_sheet_id; + + const overlapped_col_index_type* get_overlapped_ranges(row_t row) const; + const merge_size* get_merge_size(row_t row, col_t col) const; + + void build_overlapped_ranges(); + +public: + html_dumper( + const document& doc, + const col_merge_size_type& merge_ranges, + sheet_t sheet_id); + + void dump(std::ostream& os) const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/src/spreadsheet/impl_types.hpp b/src/spreadsheet/impl_types.hpp new file mode 100644 index 0000000..bed30db --- /dev/null +++ b/src/spreadsheet/impl_types.hpp @@ -0,0 +1,40 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_DETAIL_IMPL_TYPES_HPP +#define INCLUDED_ORCUS_SPREADSHEET_DETAIL_IMPL_TYPES_HPP + +#include "orcus/spreadsheet/types.hpp" + +#include <mdds/flat_segment_tree.hpp> +#include <unordered_map> +#include <memory> + +namespace orcus { namespace spreadsheet { namespace detail { + +struct merge_size +{ + col_t width; + row_t height; + + merge_size(col_t _width, row_t _height) : + width(_width), height(_height) {} +}; + +// Merged cell data stored in sheet. +typedef std::unordered_map<row_t, detail::merge_size> merge_size_type; +typedef std::unordered_map<col_t, std::unique_ptr<merge_size_type>> col_merge_size_type; + +// Overlapped cells per row, used when rendering sheet content. +typedef mdds::flat_segment_tree<col_t, col_t> overlapped_col_index_type; +typedef std::unordered_map<row_t, std::unique_ptr<overlapped_col_index_type>> overlapped_cells_type; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/json_dumper.cpp b/src/spreadsheet/json_dumper.cpp new file mode 100644 index 0000000..3fe6184 --- /dev/null +++ b/src/spreadsheet/json_dumper.cpp @@ -0,0 +1,95 @@ +/* -*- 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 "json_dumper.hpp" +#include "dumper_global.hpp" + +#include "orcus/json_global.hpp" +#include "orcus/spreadsheet/document.hpp" + +#include <ixion/model_context.hpp> +#include <ixion/formula_name_resolver.hpp> + +#include <fstream> +#include <sstream> +#include <iostream> + +namespace orcus { namespace spreadsheet { namespace detail { + +json_dumper::json_dumper(const document& doc) : m_doc(doc) {} + +void json_dumper::dump(std::ostream& os, ixion::sheet_t sheet_id) const +{ + const ixion::model_context& cxt = m_doc.get_model_context(); + ixion::abs_range_t data_range = cxt.get_data_range(sheet_id); + if (!data_range.valid()) + return; + + ixion::abs_rc_range_t iter_range; + iter_range.first.column = 0; + iter_range.first.row = 0; + iter_range.last.column = data_range.last.column; + iter_range.last.row = data_range.last.row; + + auto iter = cxt.get_model_iterator( + sheet_id, ixion::rc_direction_t::horizontal, iter_range); + + std::vector<std::string> column_labels; + column_labels.reserve(data_range.last.column+1); + + // Get the column labels. + auto resolver = ixion::formula_name_resolver::get(ixion::formula_name_resolver_t::excel_a1, &cxt); + for (ixion::col_t i = 0; i <= data_range.last.column; ++i) + column_labels.emplace_back(resolver->get_column_name(i)); + + os << "[" << std::endl; + + ixion::row_t row = iter.get().row; + ixion::col_t col = iter.get().col; + assert(row == 0); + assert(col == 0); + + os << " {"; + os << "\"" << column_labels[col] << "\": "; + + func_str_handler str_handler = [](std::ostream& _os, const std::string& s) + { + _os << '"' << json::escape_string(s) << '"'; + }; + + func_empty_handler empty_handler = [](std::ostream& _os) { _os << "null"; }; + + dump_cell_value(os, cxt, iter.get(), str_handler, empty_handler); + + ixion::row_t last_row = row; + + for (iter.next(); iter.has(); iter.next()) + { + const auto& cell = iter.get(); + ixion::row_t this_row = cell.row; + ixion::col_t this_col = cell.col; + + if (this_row > last_row) + os << "}," << std::endl; + + if (this_col == 0) + os << " {"; + else + os << ", "; + + os << "\"" << column_labels.at(this_col) << "\": "; + + dump_cell_value(os, cxt, cell, str_handler, empty_handler); + last_row = this_row; + } + + os << "}" << std::endl << "]" << std::endl; +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/json_dumper.hpp b/src/spreadsheet/json_dumper.hpp new file mode 100644 index 0000000..a695091 --- /dev/null +++ b/src/spreadsheet/json_dumper.hpp @@ -0,0 +1,36 @@ +/* -*- 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 INCLUDED_ORCUS_JSON_DUMPER_HPP +#define INCLUDED_ORCUS_JSON_DUMPER_HPP + +#include <string> +#include <ostream> + +#include <ixion/types.hpp> + +namespace orcus { namespace spreadsheet { + +class document; + +namespace detail { + +class json_dumper +{ + const document& m_doc; + +public: + json_dumper(const document& doc); + + void dump(std::ostream& os, ixion::sheet_t sheet_id) const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/number_format.cpp b/src/spreadsheet/number_format.cpp new file mode 100644 index 0000000..1823ef0 --- /dev/null +++ b/src/spreadsheet/number_format.cpp @@ -0,0 +1,25 @@ +/* -*- 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 "number_format.hpp" +#include "ostream_utils.hpp" + +#include <ostream> +#include <iomanip> +#include <limits> + +namespace orcus { namespace spreadsheet { namespace detail { + +void format_to_file_output(std::ostream& os, double v) +{ + ::orcus::detail::ostream_format_guard guard(os); + os << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v; +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/number_format.hpp b/src/spreadsheet/number_format.hpp new file mode 100644 index 0000000..ea18847 --- /dev/null +++ b/src/spreadsheet/number_format.hpp @@ -0,0 +1,28 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_NUMBER_FORMAT_HPP +#define INCLUDED_ORCUS_SPREADSHEET_NUMBER_FORMAT_HPP + +#include <iosfwd> + +namespace orcus { namespace spreadsheet { namespace detail { + +/** + * Format a numeric value to a lossless string representation appripriate + * for file output. + * + * @param os output stream to add the string representation to. + * @param v source numeric value to format. + */ +void format_to_file_output(std::ostream& os, double v); + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/pivot.cpp b/src/spreadsheet/pivot.cpp new file mode 100644 index 0000000..4bc21ee --- /dev/null +++ b/src/spreadsheet/pivot.cpp @@ -0,0 +1,371 @@ +/* -*- 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 "orcus/spreadsheet/pivot.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/string_pool.hpp" + +#include <ixion/address.hpp> + +#include <unordered_map> +#include <cassert> +#include <sstream> + +namespace orcus { namespace spreadsheet { + +pivot_cache_record_value_t::pivot_cache_record_value_t() : + type(record_type::unknown), value(false) {} + +pivot_cache_record_value_t::pivot_cache_record_value_t(std::string_view s) : + type(record_type::character), value(s) +{ +} + +pivot_cache_record_value_t::pivot_cache_record_value_t(double v) : + type(record_type::numeric), value(v) +{ +} + +pivot_cache_record_value_t::pivot_cache_record_value_t(size_t index) : + type(record_type::shared_item_index), value(index) +{ +} + +bool pivot_cache_record_value_t::operator== (const pivot_cache_record_value_t& other) const +{ + return type == other.type && value == other.value; +} + +bool pivot_cache_record_value_t::operator!= (const pivot_cache_record_value_t& other) const +{ + return !operator==(other); +} + +pivot_cache_item_t::pivot_cache_item_t() : type(item_type::unknown) {} + +pivot_cache_item_t::pivot_cache_item_t(std::string_view s) : + type(item_type::character), value(s) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(double numeric) : + type(item_type::numeric), value(numeric) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(bool boolean) : + type(item_type::boolean), value(boolean) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(const date_time_t& date_time) : + type(item_type::date_time), value(date_time) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(error_value_t error) : + type(item_type::error), value(error) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(const pivot_cache_item_t& other) : + type(other.type), value(other.value) +{ +} + +pivot_cache_item_t::pivot_cache_item_t(pivot_cache_item_t&& other) : + type(other.type), value(std::move(other.value)) +{ + other.type = item_type::unknown; + other.value = false; +} + +bool pivot_cache_item_t::operator< (const pivot_cache_item_t& other) const +{ + if (type != other.type) + return type < other.type; + + return value < other.value; +} + +bool pivot_cache_item_t::operator== (const pivot_cache_item_t& other) const +{ + return type == other.type && value == other.value; +} + +pivot_cache_item_t& pivot_cache_item_t::operator= (pivot_cache_item_t other) +{ + swap(other); + return *this; +} + +void pivot_cache_item_t::swap(pivot_cache_item_t& other) +{ + std::swap(type, other.type); + std::swap(value, other.value); +} + +pivot_cache_group_data_t::pivot_cache_group_data_t(size_t _base_field) : + base_field(_base_field) {} + +pivot_cache_group_data_t::pivot_cache_group_data_t(const pivot_cache_group_data_t& other) : + base_to_group_indices(other.base_to_group_indices), + range_grouping(other.range_grouping), + items(other.items), + base_field(other.base_field) {} + +pivot_cache_group_data_t::pivot_cache_group_data_t(pivot_cache_group_data_t&& other) : + base_to_group_indices(std::move(other.base_to_group_indices)), + range_grouping(std::move(other.range_grouping)), + items(std::move(other.items)), + base_field(other.base_field) {} + +pivot_cache_field_t::pivot_cache_field_t() {} + +pivot_cache_field_t::pivot_cache_field_t(std::string_view _name) : name(_name) {} + +pivot_cache_field_t::pivot_cache_field_t(const pivot_cache_field_t& other) : + name(other.name), + items(other.items), + min_value(other.min_value), + max_value(other.max_value), + min_date(other.min_date), + max_date(other.max_date), + group_data(std::make_unique<pivot_cache_group_data_t>(*other.group_data)) {} + +pivot_cache_field_t::pivot_cache_field_t(pivot_cache_field_t&& other) : + name(other.name), + items(std::move(other.items)), + min_value(std::move(other.min_value)), + max_value(std::move(other.max_value)), + min_date(std::move(other.min_date)), + max_date(std::move(other.max_date)), + group_data(std::move(other.group_data)) +{ + other.name = std::string_view{}; +} + +struct pivot_cache::impl +{ + pivot_cache_id_t m_cache_id; + + string_pool& m_string_pool; + + std::string_view m_src_sheet_name; + + pivot_cache::fields_type m_fields; + + pivot_cache::records_type m_records; + + impl(pivot_cache_id_t cache_id, string_pool& sp) : + m_cache_id(cache_id), m_string_pool(sp) {} +}; + +pivot_cache::pivot_cache(pivot_cache_id_t cache_id, string_pool& sp) : + mp_impl(std::make_unique<impl>(cache_id, sp)) {} + +pivot_cache::~pivot_cache() {} + +void pivot_cache::insert_fields(fields_type fields) +{ + mp_impl->m_fields = std::move(fields); +} + +void pivot_cache::insert_records(records_type records) +{ + mp_impl->m_records = std::move(records); +} + +size_t pivot_cache::get_field_count() const +{ + return mp_impl->m_fields.size(); +} + +const pivot_cache_field_t* pivot_cache::get_field(size_t index) const +{ + return index < mp_impl->m_fields.size() ? &mp_impl->m_fields[index] : nullptr; +} + +pivot_cache_id_t pivot_cache::get_id() const +{ + return mp_impl->m_cache_id; +} + +const pivot_cache::records_type& pivot_cache::get_all_records() const +{ + return mp_impl->m_records; +} + +namespace { + +constexpr const ixion::sheet_t ignored_sheet = -1; + +struct worksheet_range +{ + std::string_view sheet; /// it must be an interned string with the document. + ixion::abs_range_t range; /// sheet indices are ignored. + + worksheet_range(std::string_view _sheet, ixion::abs_range_t _range) : + sheet(std::move(_sheet)), range(std::move(_range)) + { + range.first.sheet = ignored_sheet; + range.last.sheet = ignored_sheet; + } + + bool operator== (const worksheet_range& other) const + { + return sheet == other.sheet && range == other.range; + } + + struct hash + { + std::hash<std::string_view> ps_hasher; + ixion::abs_range_t::hash range_hasher; + + size_t operator() (const worksheet_range& v) const + { + assert(v.range.first.sheet == ignored_sheet); + assert(v.range.last.sheet == ignored_sheet); + + size_t n = ps_hasher(v.sheet); + n ^= range_hasher(v.range); + return n; + } + }; +}; + +using range_map_type = std::unordered_map<worksheet_range, std::unordered_set<pivot_cache_id_t>, worksheet_range::hash>; +using name_map_type = std::unordered_map<std::string_view, std::unordered_set<pivot_cache_id_t>>; + +using caches_type = std::unordered_map<pivot_cache_id_t, std::unique_ptr<pivot_cache>>; + +} + +struct pivot_collection::impl +{ + document& m_doc; + + range_map_type m_worksheet_range_map; /// mapping of sheet name & range pair to cache ID. + name_map_type m_table_map; /// mapping of table name to cache ID. + + caches_type m_caches; + + impl(document& doc) : m_doc(doc) {} + + void ensure_unique_cache(pivot_cache_id_t cache_id) + { + if (m_caches.count(cache_id) > 0) + { + std::ostringstream os; + os << "Pivot cache with the ID of " << cache_id << " already exists."; + throw std::invalid_argument(os.str()); + } + } +}; + +pivot_collection::pivot_collection(document& doc) : mp_impl(std::make_unique<impl>(doc)) {} + +pivot_collection::~pivot_collection() {} + +void pivot_collection::insert_worksheet_cache( + std::string_view sheet_name, const ixion::abs_range_t& range, + std::unique_ptr<pivot_cache>&& cache) +{ + // First, ensure that no caches exist for the cache ID. + pivot_cache_id_t cache_id = cache->get_id(); + mp_impl->ensure_unique_cache(cache_id); + + // Check and see if there is already a cache for this location. If yes, + // overwrite the existing cache. + mp_impl->m_caches[cache_id] = std::move(cache); + + worksheet_range key(sheet_name, range); + + range_map_type& range_map = mp_impl->m_worksheet_range_map; + auto it = range_map.find(key); + + if (it == range_map.end()) + { + // sheet name must be interned with the document it belongs to. + key.sheet = mp_impl->m_doc.get_string_pool().intern(key.sheet).first; + range_map.insert(range_map_type::value_type(std::move(key), {cache_id})); + return; + } + + auto& id_set = it->second; + id_set.insert(cache_id); +} + +void pivot_collection::insert_worksheet_cache( + std::string_view table_name, std::unique_ptr<pivot_cache>&& cache) +{ + // First, ensure that no caches exist for the cache ID. + pivot_cache_id_t cache_id = cache->get_id(); + mp_impl->ensure_unique_cache(cache_id); + + mp_impl->m_caches[cache_id] = std::move(cache); + + name_map_type& name_map = mp_impl->m_table_map; + auto it = name_map.find(table_name); + + if (it == name_map.end()) + { + // First cache to be associated with this name. + std::string_view table_name_interned = + mp_impl->m_doc.get_string_pool().intern(table_name).first; + name_map.insert(name_map_type::value_type(table_name_interned, {cache_id})); + return; + } + + auto& id_set = it->second; + id_set.insert(cache_id); +} + +size_t pivot_collection::get_cache_count() const +{ + return mp_impl->m_caches.size(); +} + +const pivot_cache* pivot_collection::get_cache( + std::string_view sheet_name, const ixion::abs_range_t& range) const +{ + worksheet_range wr(sheet_name, range); + + auto it = mp_impl->m_worksheet_range_map.find(wr); + if (it == mp_impl->m_worksheet_range_map.end()) + return nullptr; + + // Pick the first cache ID. + assert(!it->second.empty()); + pivot_cache_id_t cache_id = *it->second.cbegin(); + return mp_impl->m_caches[cache_id].get(); +} + +namespace { + +template<typename _CachesT, typename _CacheT> +_CacheT* get_cache_impl(_CachesT& caches, pivot_cache_id_t cache_id) +{ + auto it = caches.find(cache_id); + return it == caches.end() ? nullptr : it->second.get(); +} + +} + +pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) +{ + return get_cache_impl<caches_type, pivot_cache>(mp_impl->m_caches, cache_id); +} + +const pivot_cache* pivot_collection::get_cache(pivot_cache_id_t cache_id) const +{ + return get_cache_impl<const caches_type, const pivot_cache>(mp_impl->m_caches, cache_id); +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/shared_formula.cpp b/src/spreadsheet/shared_formula.cpp new file mode 100644 index 0000000..e17a0ee --- /dev/null +++ b/src/spreadsheet/shared_formula.cpp @@ -0,0 +1,32 @@ +/* -*- 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 "shared_formula.hpp" + +namespace orcus { namespace spreadsheet { + +shared_formula_pool::shared_formula_pool() {} +shared_formula_pool::~shared_formula_pool() {} + +void shared_formula_pool::add( + size_t sf_index, const ixion::formula_tokens_store_ptr_t& sf_tokens) +{ + m_store.emplace(sf_index, sf_tokens); +} + +ixion::formula_tokens_store_ptr_t shared_formula_pool::get(size_t sf_index) const +{ + auto it = m_store.find(sf_index); + if (it == m_store.end()) + return ixion::formula_tokens_store_ptr_t(); + + return it->second; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/shared_formula.hpp b/src/spreadsheet/shared_formula.hpp new file mode 100644 index 0000000..a72c9f3 --- /dev/null +++ b/src/spreadsheet/shared_formula.hpp @@ -0,0 +1,36 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_SHARED_FORMULA_HPP +#define INCLUDED_ORCUS_SPREADSHEET_SHARED_FORMULA_HPP + +#include <ixion/formula_tokens.hpp> + +#include <unordered_map> + +namespace orcus { namespace spreadsheet { + +class shared_formula_pool +{ + using store_type = std::unordered_map<size_t, ixion::formula_tokens_store_ptr_t>; + + store_type m_store; + +public: + shared_formula_pool(); + ~shared_formula_pool(); + + void add(size_t sf_index, const ixion::formula_tokens_store_ptr_t& sf_tokens); + + ixion::formula_tokens_store_ptr_t get(size_t sf_index) const; +}; + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/shared_strings.cpp b/src/spreadsheet/shared_strings.cpp new file mode 100644 index 0000000..f133e50 --- /dev/null +++ b/src/spreadsheet/shared_strings.cpp @@ -0,0 +1,61 @@ +/* -*- 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 <orcus/spreadsheet/shared_strings.hpp> +#include <ixion/model_context.hpp> + +#include <iostream> +#include <algorithm> +#include <unordered_map> + +namespace orcus { namespace spreadsheet { + +// format runs for all shared strings, mapped by string IDs. +using format_runs_map_type = std::unordered_map<size_t, std::unique_ptr<format_runs_t>>; + +struct shared_strings::impl +{ + ixion::model_context& context; + + /** + * Container for all format runs of all formatted strings. Format runs + * are mapped with the string IDs. + */ + format_runs_map_type formats; + + impl(ixion::model_context& cxt) : context(cxt) {} +}; + +shared_strings::shared_strings(ixion::model_context& cxt) : mp_impl(std::make_unique<impl>(cxt)) {} + +shared_strings::~shared_strings() = default; + +void shared_strings::set_format_runs(std::size_t sindex, std::unique_ptr<format_runs_t> runs) +{ + mp_impl->formats.insert_or_assign(sindex, std::move(runs)); +} + +const format_runs_t* shared_strings::get_format_runs(std::size_t index) const +{ + auto it = mp_impl->formats.find(index); + if (it != mp_impl->formats.end()) + return it->second.get(); + return nullptr; +} + +const std::string* shared_strings::get_string(std::size_t index) const +{ + return mp_impl->context.get_string(index); +} + +void shared_strings::dump(std::ostream& os) const +{ + os << "number of shared strings: " << mp_impl->context.get_string_count() << std::endl; +} + +}} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/sheet.cpp b/src/spreadsheet/sheet.cpp new file mode 100644 index 0000000..4ffa8df --- /dev/null +++ b/src/spreadsheet/sheet.cpp @@ -0,0 +1,555 @@ +/* -*- 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 "orcus/spreadsheet/sheet.hpp" +#include "orcus/spreadsheet/document.hpp" +#include "orcus/exception.hpp" + +#include "json_dumper.hpp" +#include "check_dumper.hpp" +#include "csv_dumper.hpp" +#include "flat_dumper.hpp" +#include "html_dumper.hpp" +#include "sheet_impl.hpp" +#include "debug_state_dumper.hpp" + +#include <iostream> +#include <algorithm> +#include <vector> +#include <cassert> +#include <cstdlib> + +#include <ixion/exceptions.hpp> +#include <ixion/formula.hpp> +#include <ixion/model_context.hpp> + +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/date_time/gregorian/greg_date.hpp> + +#include "filesystem_env.hpp" + +#define ORCUS_DEBUG_SHEET 0 + +using namespace std; +namespace gregorian = boost::gregorian; +namespace posix_time = boost::posix_time; + +namespace orcus { namespace spreadsheet { + +namespace { + +ixion::abs_range_t to_ixion_range(sheet_t sheet, const range_t& range) +{ + ixion::abs_range_t pos; + + pos.first.sheet = sheet; + pos.first.row = range.first.row; + pos.first.column = range.first.column; + pos.last.sheet = sheet; + pos.last.row = range.last.row; + pos.last.column = range.last.column; + + return pos; +} + +} + +const row_t sheet::max_row_limit = 1048575; +const col_t sheet::max_col_limit = 1023; + +sheet::sheet(document& doc, sheet_t sheet_index) : + mp_impl(std::make_unique<detail::sheet_impl>(doc, *this, sheet_index)) {} + +sheet::~sheet() noexcept +{ +} + +void sheet::set_auto(row_t row, col_t col, std::string_view s) +{ + if (s.empty()) + return; + + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + + // First, see if this can be parsed as a number. + char* endptr = nullptr; + double val = strtod(s.data(), &endptr); + const char* endptr_check = s.data() + s.size(); + if (endptr == endptr_check) + // Treat this as a numeric value. + cxt.set_numeric_cell(ixion::abs_address_t(mp_impl->sheet_id,row,col), val); + else + // Treat this as a string value. + cxt.set_string_cell(ixion::abs_address_t(mp_impl->sheet_id,row,col), s); +} + +void sheet::set_string(row_t row, col_t col, string_id_t sindex) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + cxt.set_string_cell(ixion::abs_address_t(mp_impl->sheet_id,row,col), sindex); + +#if ORCUS_DEBUG_SHEET + cout << "sheet::set_string: sheet=" << mp_impl->sheet_id << "; row=" << row << "; col=" << col << "; si=" << sindex << endl; +#endif +} + +void sheet::set_value(row_t row, col_t col, double value) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + cxt.set_numeric_cell(ixion::abs_address_t(mp_impl->sheet_id,row,col), value); +} + +void sheet::set_bool(row_t row, col_t col, bool value) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + cxt.set_boolean_cell(ixion::abs_address_t(mp_impl->sheet_id,row,col), value); +} + +void sheet::set_date_time(row_t row, col_t col, int year, int month, int day, int hour, int minute, double second) +{ + // Convert this to a double value representing days since epoch. + + date_time_t dt_origin = mp_impl->doc.get_origin_date(); + + gregorian::date origin(dt_origin.year, dt_origin.month, dt_origin.day); + gregorian::date d(year, month, day); + + double days_since_epoch = (d - origin).days(); + + long ms = second * 1000000.0; + + posix_time::time_duration t( + posix_time::hours(hour) + + posix_time::minutes(minute) + + posix_time::microseconds(ms) + ); + + double time_as_day = t.total_microseconds(); + time_as_day /= 1000000.0; // microseconds to seconds + time_as_day /= 60.0 * 60.0 * 24.0; // seconds to day + + set_value(row, col, days_since_epoch + time_as_day); +} + +void sheet::set_format(row_t row, col_t col, size_t index) +{ + set_format(row, col, row, col, index); +} + +void sheet::set_format(row_t row_start, col_t col_start, row_t row_end, col_t col_end, size_t index) +{ + for (col_t col = col_start; col <= col_end; ++col) + { + auto itr = mp_impl->cell_formats.find(col); + if (itr == mp_impl->cell_formats.end()) + { + auto p = std::make_unique<detail::segment_row_index_type>(0, mp_impl->doc.get_sheet_size().rows, 0); + auto r = mp_impl->cell_formats.emplace(col, std::move(p)); + + if (!r.second) + { + cerr << "insertion of new cell format container failed!" << endl; + return; + } + + itr = r.first; + } + + detail::segment_row_index_type& con = *itr->second; + con.insert_back(row_start, row_end+1, index); + } +} + +void sheet::set_column_format(col_t col, col_t col_span, std::size_t index) +{ + if (col_span > 0) + mp_impl->column_formats.insert_back(col, col + col_span, index); +} + +void sheet::set_row_format(row_t row, std::size_t index) +{ + mp_impl->row_formats.insert_back(row, row+1, index); +} + +void sheet::set_formula(row_t row, col_t col, const ixion::formula_tokens_store_ptr_t& tokens) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + ixion::abs_address_t pos(mp_impl->sheet_id, row, col); + + cxt.set_formula_cell(pos, tokens); + try + { + ixion::register_formula_cell(cxt, pos); + mp_impl->doc.insert_dirty_cell(pos); + } + catch ([[maybe_unused]] const ixion::formula_registration_error& e) + { +#if ORCUS_DEBUG_SHEET + cout << "sheet::set_formula: sheet=" << mp_impl->sheet_id << "; row=" << row << "; col=" << col << "; e=" << e.what() << endl; +#endif + } +} + +void sheet::set_formula( + row_t row, col_t col, const ixion::formula_tokens_store_ptr_t& tokens, + ixion::formula_result result) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + ixion::abs_address_t pos(mp_impl->sheet_id, row, col); + + cxt.set_formula_cell(pos, tokens, result); + + try + { + ixion::register_formula_cell(cxt, pos); + mp_impl->doc.insert_dirty_cell(pos); + } + catch ([[maybe_unused]] const ixion::formula_registration_error& e) + { +#if ORCUS_DEBUG_SHEET + cout << "sheet::set_formula: sheet=" << mp_impl->sheet_id << "; row=" << row << "; col=" << col << "; e=" << e.what() << endl; +#endif + } +} + +void sheet::set_grouped_formula(const range_t& range, ixion::formula_tokens_t tokens) +{ + ixion::abs_range_t pos = to_ixion_range(mp_impl->sheet_id, range); + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + + cxt.set_grouped_formula_cells(pos, std::move(tokens)); + try + { + ixion::register_formula_cell(cxt, pos.first); + mp_impl->doc.insert_dirty_cell(pos.first); + } + catch ([[maybe_unused]] const ixion::formula_registration_error& e) + { +#if ORCUS_DEBUG_SHEET + cout << "sheet::set_formula: sheet=" << mp_impl->sheet_id << "; range=" << range << "; e=" << e.what() << endl; +#endif + } +} + +void sheet::set_grouped_formula(const range_t& range, ixion::formula_tokens_t tokens, ixion::formula_result result) +{ + ixion::abs_range_t pos = to_ixion_range(mp_impl->sheet_id, range); + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + + cxt.set_grouped_formula_cells(pos, std::move(tokens), std::move(result)); + try + { + ixion::register_formula_cell(cxt, pos.first); + mp_impl->doc.insert_dirty_cell(pos.first); + } + catch ([[maybe_unused]] const ixion::formula_registration_error& e) + { +#if ORCUS_DEBUG_SHEET + cout << "sheet::set_formula: sheet=" << mp_impl->sheet_id << "; range=" << range << "; e=" << e.what() << endl; +#endif + } +} + +void sheet::set_col_width(col_t col, col_t col_span, col_width_t width) +{ + mp_impl->col_width_pos = + mp_impl->col_widths.insert(mp_impl->col_width_pos, col, col+col_span, width).first; +} + +col_width_t sheet::get_col_width(col_t col, col_t* col_start, col_t* col_end) const +{ + detail::col_widths_store_type& col_widths = mp_impl->col_widths; + if (!col_widths.is_tree_valid()) + col_widths.build_tree(); + + col_width_t ret = 0; + if (!col_widths.search_tree(col, ret, col_start, col_end).second) + throw orcus::general_error("sheet::get_col_width: failed to search tree."); + + return ret; +} + +void sheet::set_col_hidden(col_t col, col_t col_span, bool hidden) +{ + mp_impl->col_hidden_pos = + mp_impl->col_hidden.insert(mp_impl->col_hidden_pos, col, col+col_span, hidden).first; +} + +bool sheet::is_col_hidden(col_t col, col_t* col_start, col_t* col_end) const +{ + detail::col_hidden_store_type& col_hidden = mp_impl->col_hidden; + if (!col_hidden.is_tree_valid()) + col_hidden.build_tree(); + + bool hidden = false; + if (!col_hidden.search_tree(col, hidden, col_start, col_end).second) + throw orcus::general_error("sheet::is_col_hidden: failed to search tree."); + + return hidden; +} + +void sheet::set_row_height(row_t row, row_height_t height) +{ + mp_impl->row_height_pos = + mp_impl->row_heights.insert(mp_impl->row_height_pos, row, row+1, height).first; +} + +row_height_t sheet::get_row_height(row_t row, row_t* row_start, row_t* row_end) const +{ + detail::row_heights_store_type& row_heights = mp_impl->row_heights; + if (!row_heights.is_tree_valid()) + row_heights.build_tree(); + + row_height_t ret = 0; + if (!row_heights.search_tree(row, ret, row_start, row_end).second) + throw orcus::general_error("sheet::get_row_height: failed to search tree."); + + return ret; +} + +void sheet::set_row_hidden(row_t row, bool hidden) +{ + mp_impl->row_hidden_pos = + mp_impl->row_hidden.insert(mp_impl->row_hidden_pos, row, row+1, hidden).first; +} + +bool sheet::is_row_hidden(row_t row, row_t* row_start, row_t* row_end) const +{ + detail::row_hidden_store_type& row_hidden = mp_impl->row_hidden; + if (!row_hidden.is_tree_valid()) + row_hidden.build_tree(); + + bool hidden = false; + if (!row_hidden.search_tree(row, hidden, row_start, row_end).second) + throw orcus::general_error("sheet::is_row_hidden: failed to search tree."); + + return hidden; +} + +void sheet::set_merge_cell_range(const range_t& range) +{ + detail::col_merge_size_type::iterator it_col = mp_impl->merge_ranges.find(range.first.column); + if (it_col == mp_impl->merge_ranges.end()) + { + auto p = std::make_unique<detail::merge_size_type>(); + pair<detail::col_merge_size_type::iterator, bool> r = + mp_impl->merge_ranges.insert( + detail::col_merge_size_type::value_type(range.first.column, std::move(p))); + + if (!r.second) + // Insertion failed. + return; + + it_col = r.first; + } + + detail::merge_size_type& col_data = *it_col->second; + detail::merge_size sz(range.last.column-range.first.column+1, range.last.row-range.first.row+1); + col_data.insert( + detail::merge_size_type::value_type(range.first.row, sz)); +} + +void sheet::fill_down_cells(row_t src_row, col_t src_col, row_t range_size) +{ + ixion::model_context& cxt = mp_impl->doc.get_model_context(); + ixion::abs_address_t src_pos(mp_impl->sheet_id, src_row, src_col); + cxt.fill_down_cells(src_pos, range_size); +} + +range_t sheet::get_merge_cell_range(row_t row, col_t col) const +{ + range_t ret; + ret.first.column = col; + ret.first.row = row; + ret.last.column = col; + ret.last.row = row; + + detail::col_merge_size_type::const_iterator it_col = mp_impl->merge_ranges.find(col); + if (it_col == mp_impl->merge_ranges.end()) + return ret; // not a merged cell + + const detail::merge_size_type& col_data = *it_col->second; + detail::merge_size_type::const_iterator it = col_data.find(row); + if (it == col_data.end()) + return ret; // not a merged cell + + const detail::merge_size& ms = it->second; + ret.last.column += ms.width - 1; + ret.last.row += ms.height - 1; + + return ret; +} + +size_t sheet::get_string_identifier(row_t row, col_t col) const +{ + const ixion::model_context& cxt = mp_impl->doc.get_model_context(); + return cxt.get_string_identifier(ixion::abs_address_t(mp_impl->sheet_id, row, col)); +} + +auto_filter_t* sheet::get_auto_filter_data() +{ + return mp_impl->auto_filter_data.get(); +} + +const auto_filter_t* sheet::get_auto_filter_data() const +{ + return mp_impl->auto_filter_data.get(); +} + +void sheet::set_auto_filter_data(auto_filter_t* p) +{ + mp_impl->auto_filter_data.reset(p); +} + +ixion::abs_range_t sheet::get_data_range() const +{ + return mp_impl->get_data_range(); +} + +sheet_t sheet::get_index() const +{ + return mp_impl->sheet_id; +} + +date_time_t sheet::get_date_time(row_t row, col_t col) const +{ + const ixion::model_context& cxt = mp_impl->doc.get_model_context(); + + // raw value as days since epoch. + double dt_raw = cxt.get_numeric_value( + ixion::abs_address_t(mp_impl->sheet_id, row, col)); + + double days_since_epoch = std::floor(dt_raw); + double time_fraction = dt_raw - days_since_epoch; + + date_time_t dt_origin = mp_impl->doc.get_origin_date(); + + posix_time::ptime origin( + gregorian::date( + gregorian::greg_year(dt_origin.year), + gregorian::greg_month(dt_origin.month), + gregorian::greg_day(dt_origin.day) + ) + ); + + posix_time::ptime date_part = origin + gregorian::days(days_since_epoch); + + long hours = 0; + long minutes = 0; + double seconds = 0.0; + + if (time_fraction) + { + // Convert a fraction day to microseconds. + long long ms = time_fraction * 24.0 * 60.0 * 60.0 * 1000000.0; + posix_time::time_duration td = posix_time::microsec(ms); + + hours = td.hours(); + minutes = td.minutes(); + seconds = td.seconds(); // long to double + + td -= posix_time::hours(hours); + td -= posix_time::minutes(minutes); + td -= posix_time::seconds((long)seconds); + + ms = td.total_microseconds(); // remaining microseconds. + + seconds += ms / 1000000.0; + } + + gregorian::date d = date_part.date(); + + return date_time_t(d.year(), d.month(), d.day(), hours, minutes, seconds); +} + +void sheet::finalize_import() +{ + mp_impl->col_widths.build_tree(); + mp_impl->row_heights.build_tree(); +} + +void sheet::dump_flat(std::ostream& os) const +{ + detail::flat_dumper dumper(mp_impl->doc); + dumper.dump(os, mp_impl->sheet_id); +} + +void sheet::dump_check(ostream& os, std::string_view sheet_name) const +{ + detail::check_dumper dumper(*mp_impl, sheet_name); + dumper.dump(os); +} + +void sheet::dump_html(std::ostream& os) const +{ + if (!mp_impl->col_widths.is_tree_valid()) + mp_impl->col_widths.build_tree(); + + if (!mp_impl->row_heights.is_tree_valid()) + mp_impl->row_heights.build_tree(); + + detail::html_dumper dumper(mp_impl->doc, mp_impl->merge_ranges, mp_impl->sheet_id); + dumper.dump(os); +} + +void sheet::dump_json(std::ostream& os) const +{ + detail::json_dumper dumper(mp_impl->doc); + dumper.dump(os, mp_impl->sheet_id); +} + +void sheet::dump_csv(std::ostream& os) const +{ + detail::csv_dumper dumper(mp_impl->doc); + dumper.dump(os, mp_impl->sheet_id); +} + +void sheet::dump_debug_state(const std::string& output_dir, std::string_view sheet_name) const +{ + fs::path outdir{output_dir}; + detail::sheet_debug_state_dumper dumper(*mp_impl, sheet_name); + dumper.dump(outdir); +} + +size_t sheet::get_cell_format(row_t row, col_t col) const +{ + // Check the cell format store first + auto it = mp_impl->cell_formats.find(col); + if (it != mp_impl->cell_formats.end()) + { + detail::segment_row_index_type& con = *it->second; + if (!con.is_tree_valid()) + con.build_tree(); + + // Return only if the index is not a default index + std::size_t index; + if (con.search_tree(row, index).second && index) + return index; + } + + // Not found in the cell format store. Check the row store. + if (!mp_impl->row_formats.is_tree_valid()) + mp_impl->row_formats.build_tree(); + + std::size_t index; + if (mp_impl->row_formats.search_tree(row, index).second && index) + return index; + + // Not found in the row store. Check the column store. + if (!mp_impl->column_formats.is_tree_valid()) + mp_impl->column_formats.build_tree(); + + if (mp_impl->column_formats.search_tree(col, index).second && index) + return index; + + // Not found. Return the default format index. + return 0; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/sheet_impl.cpp b/src/spreadsheet/sheet_impl.cpp new file mode 100644 index 0000000..1364e25 --- /dev/null +++ b/src/spreadsheet/sheet_impl.cpp @@ -0,0 +1,53 @@ +/* -*- 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 "sheet_impl.hpp" +#include "orcus/spreadsheet/document.hpp" + +#include <ixion/model_context.hpp> + +namespace orcus { namespace spreadsheet { namespace detail { + +sheet_impl::sheet_impl(document& _doc, sheet& /*sh*/, sheet_t sheet_index) : + doc(_doc), + col_widths(0, doc.get_sheet_size().columns, get_default_column_width()), + row_heights(0, doc.get_sheet_size().rows, get_default_row_height()), + col_width_pos(col_widths.begin()), + row_height_pos(row_heights.begin()), + col_hidden(0, doc.get_sheet_size().columns, false), + row_hidden(0, doc.get_sheet_size().rows, false), + col_hidden_pos(col_hidden.begin()), + row_hidden_pos(row_hidden.begin()), + column_formats(0, doc.get_sheet_size().columns, 0), + row_formats(0, doc.get_sheet_size().rows, 0), + sheet_id(sheet_index) {} + +sheet_impl::~sheet_impl() {} + +const detail::merge_size* sheet_impl::get_merge_size(row_t row, col_t col) const +{ + detail::col_merge_size_type::const_iterator it_col = merge_ranges.find(col); + if (it_col == merge_ranges.end()) + return nullptr; + + detail::merge_size_type& col_merge_sizes = *it_col->second; + detail::merge_size_type::const_iterator it_row = col_merge_sizes.find(row); + if (it_row == col_merge_sizes.end()) + return nullptr; + + return &it_row->second; +} + +ixion::abs_range_t sheet_impl::get_data_range() const +{ + const ixion::model_context& cxt = doc.get_model_context(); + return cxt.get_data_range(sheet_id); +} + +}}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/sheet_impl.hpp b/src/spreadsheet/sheet_impl.hpp new file mode 100644 index 0000000..11f691a --- /dev/null +++ b/src/spreadsheet/sheet_impl.hpp @@ -0,0 +1,72 @@ +/* -*- 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 INCLUDED_ORCUS_SPREADSHEET_SHEET_IMPL_HPP +#define INCLUDED_ORCUS_SPREADSHEET_SHEET_IMPL_HPP + +#include "impl_types.hpp" +#include "orcus/spreadsheet/auto_filter.hpp" + +namespace orcus { namespace spreadsheet { + +class document; +class sheet; + +namespace detail { + +using segment_row_index_type = mdds::flat_segment_tree<row_t, std::size_t>; +using segment_col_index_type = mdds::flat_segment_tree<col_t, std::size_t>; +typedef std::unordered_map<col_t, std::unique_ptr<segment_row_index_type>> cell_format_type; + +// Widths and heights are stored in twips. +typedef mdds::flat_segment_tree<col_t, col_width_t> col_widths_store_type; +typedef mdds::flat_segment_tree<row_t, row_height_t> row_heights_store_type; + +// hidden information +typedef mdds::flat_segment_tree<col_t, bool> col_hidden_store_type; +typedef mdds::flat_segment_tree<row_t, bool> row_hidden_store_type; + +struct sheet_impl +{ + document& doc; + + mutable col_widths_store_type col_widths; + mutable row_heights_store_type row_heights; + col_widths_store_type::const_iterator col_width_pos; + row_heights_store_type::const_iterator row_height_pos; + + mutable col_hidden_store_type col_hidden; + mutable row_hidden_store_type row_hidden; + col_hidden_store_type::const_iterator col_hidden_pos; + row_hidden_store_type::const_iterator row_hidden_pos; + + detail::col_merge_size_type merge_ranges; /// 2-dimensional merged cell ranges. + + std::unique_ptr<auto_filter_t> auto_filter_data; + + cell_format_type cell_formats; + segment_col_index_type column_formats; + segment_row_index_type row_formats; + const sheet_t sheet_id; + + sheet_impl() = delete; + sheet_impl(const sheet_impl&) = delete; + sheet_impl& operator=(const sheet_impl&) = delete; + + sheet_impl(document& _doc, sheet& sh, sheet_t sheet_index); + ~sheet_impl(); + + const detail::merge_size* get_merge_size(row_t row, col_t col) const; + + ixion::abs_range_t get_data_range() const; +}; + +}}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/styles.cpp b/src/spreadsheet/styles.cpp new file mode 100644 index 0000000..328814e --- /dev/null +++ b/src/spreadsheet/styles.cpp @@ -0,0 +1,485 @@ +/* -*- 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 "orcus/spreadsheet/styles.hpp" +#include "orcus/string_pool.hpp" + +#include "ostream_utils.hpp" + +#include <functional> +#include <algorithm> +#include <cassert> +#include <iomanip> +#include <vector> +#include <map> + +namespace orcus { namespace spreadsheet { + +font_t::font_t() = default; +font_t::font_t(const font_t& other) = default; +font_t::~font_t() = default; + +font_t& font_t::operator=(const font_t& other) = default; + +bool font_t::operator==(const font_t& other) const +{ + if (name != other.name) + return false; + + if (name_asian != other.name_asian) + return false; + + if (name_complex != other.name_complex) + return false; + + if (size != other.size) + return false; + + if (size_asian != other.size_asian) + return false; + + if (size_complex != other.size_complex) + return false; + + if (bold != other.bold) + return false; + + if (bold_asian != other.bold_asian) + return false; + + if (bold_complex != other.bold_complex) + return false; + + if (italic != other.italic) + return false; + + if (italic_asian != other.italic_asian) + return false; + + if (italic_complex != other.italic_complex) + return false; + + if (underline_style != other.underline_style) + return false; + + if (underline_width != other.underline_width) + return false; + + if (underline_mode != other.underline_mode) + return false; + + if (underline_type != other.underline_type) + return false; + + if (underline_color != other.underline_color) + return false; + + if (color != other.color) + return false; + + if (strikethrough_style != other.strikethrough_style) + return false; + + if (strikethrough_width != other.strikethrough_width) + return false; + + if (strikethrough_type != other.strikethrough_type) + return false; + + if (strikethrough_text != other.strikethrough_text) + return false; + + return true; +} + +bool font_t::operator!=(const font_t& other) const +{ + return !operator==(other); +} + +void font_t::reset() +{ + *this = font_t(); +} + +std::size_t font_t::hash::operator()(const font_t& v) const +{ + std::size_t hash_value = 0u; + + if (v.name) + hash_value |= std::hash<std::string_view>{}(*v.name); + + if (v.size) + hash_value |= std::hash<double>{}(*v.size); + + if (v.bold) + hash_value |= std::hash<bool>{}(*v.bold); + + if (v.italic) + hash_value |= std::hash<bool>{}(*v.italic); + + return hash_value; +} + +fill_t::fill_t() = default; + +void fill_t::reset() +{ + *this = fill_t(); +} + +border_attrs_t::border_attrs_t() = default; + +void border_attrs_t::reset() +{ + *this = border_attrs_t(); +} + +border_t::border_t() = default; + +void border_t::reset() +{ + *this = border_t(); +} + +protection_t::protection_t() = default; + +void protection_t::reset() +{ + *this = protection_t(); +} + +number_format_t::number_format_t() = default; + +void number_format_t::reset() +{ + *this = number_format_t(); +} + +bool number_format_t::operator== (const number_format_t& other) const noexcept +{ + return identifier == other.identifier && format_string == other.format_string; +} + +bool number_format_t::operator!= (const number_format_t& other) const noexcept +{ + return !operator== (other); +} + +cell_format_t::cell_format_t() : + font(0), + fill(0), + border(0), + protection(0), + number_format(0), + style_xf(0), + hor_align(hor_alignment_t::unknown), + ver_align(ver_alignment_t::unknown), + apply_num_format(false), + apply_font(false), + apply_fill(false), + apply_border(false), + apply_alignment(false), + apply_protection(false) +{ +} + +void cell_format_t::reset() +{ + *this = cell_format_t(); +} + +cell_style_t::cell_style_t() : + xf(0), builtin(0) +{ +} + +void cell_style_t::reset() +{ + *this = cell_style_t(); +} + +std::ostream& operator<< (std::ostream& os, const color_t& c) +{ + ::orcus::detail::ostream_format_guard ifs(os); + + os << std::uppercase; + + os << "(ARGB:" + << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.alpha & 0xFF) + << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.red & 0xFF) + << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.green & 0xFF) + << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.blue & 0xFF) + << ")"; + + return os; +} + +struct styles::impl +{ + std::vector<font_t> fonts; + std::vector<fill_t> fills; + std::vector<border_t> borders; + std::vector<protection_t> protections; + std::vector<number_format_t> number_formats; + std::vector<cell_format_t> cell_style_formats; + std::vector<cell_format_t> cell_formats; + std::vector<cell_format_t> dxf_formats; + std::vector<cell_style_t> cell_styles; + std::map<std::size_t, std::size_t> cell_styles_map; // style xf to style position in `cell_styles` + + string_pool str_pool; +}; + +styles::styles() : mp_impl(std::make_unique<impl>()) {} +styles::~styles() {} + +void styles::reserve_font_store(size_t n) +{ + mp_impl->fonts.reserve(n); +} + +std::size_t styles::append_font(const font_t& font) +{ + mp_impl->fonts.emplace_back(font); + return mp_impl->fonts.size() - 1; +} + +void styles::reserve_fill_store(size_t n) +{ + mp_impl->fills.reserve(n); +} + +std::size_t styles::append_fill(const fill_t& fill) +{ + mp_impl->fills.emplace_back(fill); + return mp_impl->fills.size() - 1; +} + +void styles::reserve_border_store(size_t n) +{ + mp_impl->borders.reserve(n); +} + +std::size_t styles::append_border(const border_t& border) +{ + mp_impl->borders.emplace_back(border); + return mp_impl->borders.size() - 1; +} + +std::size_t styles::append_protection(const protection_t& protection) +{ + mp_impl->protections.emplace_back(protection); + return mp_impl->protections.size() - 1; +} + +void styles::reserve_number_format_store(size_t n) +{ + mp_impl->number_formats.reserve(n); +} + +std::size_t styles::append_number_format(const number_format_t& nf) +{ + if (nf.format_string) + { + number_format_t copied = nf; + copied.format_string = mp_impl->str_pool.intern(*nf.format_string).first; + mp_impl->number_formats.emplace_back(copied); + } + else + mp_impl->number_formats.emplace_back(nf); + + return mp_impl->number_formats.size() - 1; +} + +void styles::reserve_cell_style_format_store(size_t n) +{ + mp_impl->cell_style_formats.reserve(n); +} + +size_t styles::append_cell_style_format(const cell_format_t& cf) +{ + mp_impl->cell_style_formats.push_back(cf); + return mp_impl->cell_style_formats.size() - 1; +} + +void styles::reserve_cell_format_store(size_t n) +{ + mp_impl->cell_formats.reserve(n); +} + +size_t styles::append_cell_format(const cell_format_t& cf) +{ + mp_impl->cell_formats.push_back(cf); + return mp_impl->cell_formats.size() - 1; +} + +void styles::reserve_diff_cell_format_store(size_t n) +{ + mp_impl->dxf_formats.reserve(n); +} + +size_t styles::append_diff_cell_format(const cell_format_t& cf) +{ + mp_impl->dxf_formats.push_back(cf); + return mp_impl->dxf_formats.size() - 1; +} + +void styles::reserve_cell_style_store(size_t n) +{ + mp_impl->cell_styles.reserve(n); +} + +void styles::append_cell_style(const cell_style_t& cs) +{ + mp_impl->cell_styles.push_back(cs); +} + +const font_t* styles::get_font(size_t index) const +{ + if (index >= mp_impl->fonts.size()) + return nullptr; + + return &mp_impl->fonts[index]; +} + +const cell_format_t* styles::get_cell_format(size_t index) const +{ + if (index >= mp_impl->cell_formats.size()) + return nullptr; + + return &mp_impl->cell_formats[index]; +} + +const fill_t* styles::get_fill(size_t index) const +{ + if (index >= mp_impl->fills.size()) + return nullptr; + + return &mp_impl->fills[index]; +} + +const border_t* styles::get_border(size_t index) const +{ + if (index >= mp_impl->borders.size()) + return nullptr; + + return &mp_impl->borders[index]; +} + +const protection_t* styles::get_protection(size_t index) const +{ + if (index >= mp_impl->protections.size()) + return nullptr; + + return &mp_impl->protections[index]; +} + +const number_format_t* styles::get_number_format(size_t index) const +{ + if (index >= mp_impl->number_formats.size()) + return nullptr; + + return &mp_impl->number_formats[index]; +} + +const cell_format_t* styles::get_cell_style_format(size_t index) const +{ + if (index >= mp_impl->cell_style_formats.size()) + return nullptr; + + return &mp_impl->cell_style_formats[index]; +} + +const cell_format_t* styles::get_dxf_format(size_t index) const +{ + if (index >= mp_impl->dxf_formats.size()) + return nullptr; + + return &mp_impl->dxf_formats[index]; +} + +const cell_style_t* styles::get_cell_style(size_t index) const +{ + if (index >= mp_impl->cell_styles.size()) + return nullptr; + + return &mp_impl->cell_styles[index]; +} + +const cell_style_t* styles::get_cell_style_by_xf(size_t xfid) const +{ + auto it = mp_impl->cell_styles_map.find(xfid); + if (it == mp_impl->cell_styles_map.end()) + return nullptr; + + auto index = it->second; + return &mp_impl->cell_styles[index]; +} + +size_t styles::get_font_count() const +{ + return mp_impl->fonts.size(); +} + +size_t styles::get_fill_count() const +{ + return mp_impl->fills.size(); +} + +size_t styles::get_border_count() const +{ + return mp_impl->borders.size(); +} + +size_t styles::get_protection_count() const +{ + return mp_impl->protections.size(); +} + +size_t styles::get_number_format_count() const +{ + return mp_impl->number_formats.size(); +} + +size_t styles::get_cell_formats_count() const +{ + return mp_impl->cell_formats.size(); +} + +size_t styles::get_cell_style_formats_count() const +{ + return mp_impl->cell_style_formats.size(); +} + +size_t styles::get_dxf_count() const +{ + return mp_impl->dxf_formats.size(); +} + +size_t styles::get_cell_styles_count() const +{ + return mp_impl->cell_styles.size(); +} + +void styles::clear() +{ + mp_impl = std::make_unique<impl>(); +} + +void styles::finalize_import() +{ + for (std::size_t i = 0; i < mp_impl->cell_styles.size(); ++i) + { + const auto& entry = mp_impl->cell_styles[i]; + mp_impl->cell_styles_map.insert_or_assign(entry.xf, i); + } +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/spreadsheet/view.cpp b/src/spreadsheet/view.cpp new file mode 100644 index 0000000..7e21fff --- /dev/null +++ b/src/spreadsheet/view.cpp @@ -0,0 +1,201 @@ +/* -*- 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 "orcus/spreadsheet/view.hpp" +#include "orcus/spreadsheet/document.hpp" + +#include <cassert> +#include <iostream> + +namespace orcus { namespace spreadsheet { + +struct view::impl +{ + document& m_doc; + + std::vector<std::unique_ptr<sheet_view>> m_sheet_views; + sheet_t m_active_sheet; + + impl(document& doc) : m_doc(doc), m_active_sheet(0) {} +}; + +view::view(document& doc) : mp_impl(std::make_unique<impl>(doc)) {} +view::~view() {} + +sheet_view* view::get_or_create_sheet_view(sheet_t sheet) +{ + if (sheet < 0) + return nullptr; + + sheet_t n = mp_impl->m_doc.get_sheet_count(); + if (sheet >= n) + return nullptr; + + // Make sure the container is large enough for the requested sheet view index. + n = mp_impl->m_sheet_views.size(); + if (sheet >= n) + mp_impl->m_sheet_views.resize(sheet+1); + + if (!mp_impl->m_sheet_views[sheet]) + mp_impl->m_sheet_views[sheet] = std::make_unique<sheet_view>(*this); + + return mp_impl->m_sheet_views[sheet].get(); +} + +const sheet_view* view::get_sheet_view(sheet_t sheet) const +{ + if (sheet < 0) + return nullptr; + + sheet_t n = mp_impl->m_doc.get_sheet_count(); + if (sheet >= n) + return nullptr; + + n = mp_impl->m_sheet_views.size(); + if (sheet >= n) + return nullptr; + + assert(mp_impl->m_sheet_views[sheet]); + return mp_impl->m_sheet_views[sheet].get(); +} + +void view::set_active_sheet(sheet_t sheet) +{ + mp_impl->m_active_sheet = sheet; +} + +sheet_t view::get_active_sheet() const +{ + return mp_impl->m_active_sheet; +} + +namespace { + +/** + * Stores all data for a single sheet pane. + */ +struct sheet_pane_data +{ + range_t m_selection; + + sheet_pane_data() + { + m_selection.first.row = -1; + m_selection.first.column = -1; + m_selection.last = m_selection.first; + } +}; + +size_t to_pane_index(sheet_pane_t pos) +{ + switch (pos) + { + case sheet_pane_t::top_left: + return 0; + case sheet_pane_t::top_right: + return 1; + case sheet_pane_t::bottom_left: + return 2; + case sheet_pane_t::bottom_right: + return 3; + case sheet_pane_t::unspecified: + default: + throw std::runtime_error("invalid sheet pane."); + } +} + +} // anonymous namespace + +struct sheet_view::impl +{ + view& m_doc_view; + sheet_pane_data m_panes[4]; + sheet_pane_t m_active_pane; + split_pane_t m_split_pane; + frozen_pane_t m_frozen_pane; + + sheet_pane_data& get_pane(sheet_pane_t pos) + { + return m_panes[to_pane_index(pos)]; + } + + const sheet_pane_data& get_pane(sheet_pane_t pos) const + { + return m_panes[to_pane_index(pos)]; + } + + impl(view& doc_view) : m_doc_view(doc_view), m_active_pane(sheet_pane_t::top_left) + { + m_split_pane.hor_split = 0.0; + m_split_pane.ver_split = 0.0; + m_split_pane.top_left_cell.row = -1; + m_split_pane.top_left_cell.column = -1; + m_frozen_pane.visible_columns = 0; + m_frozen_pane.visible_rows = 0; + m_frozen_pane.top_left_cell.row = -1; + m_frozen_pane.top_left_cell.column = -1; + } +}; + +sheet_view::sheet_view(view& doc_view) : mp_impl(std::make_unique<impl>(doc_view)) {} +sheet_view::~sheet_view() {} + +const range_t& sheet_view::get_selection(sheet_pane_t pos) const +{ + const sheet_pane_data& pd = mp_impl->get_pane(pos); + return pd.m_selection; +} + +void sheet_view::set_selection(sheet_pane_t pos, const range_t& range) +{ + sheet_pane_data& pd = mp_impl->get_pane(pos); + pd.m_selection = range; +} + +void sheet_view::set_active_pane(sheet_pane_t pos) +{ + mp_impl->m_active_pane = pos; +} + +sheet_pane_t sheet_view::get_active_pane() const +{ + return mp_impl->m_active_pane; +} + +void sheet_view::set_split_pane( + double hor_split, double ver_split, const address_t& top_left_cell) +{ + mp_impl->m_split_pane.hor_split = hor_split; + mp_impl->m_split_pane.ver_split = ver_split; + mp_impl->m_split_pane.top_left_cell = top_left_cell; +} + +const split_pane_t& sheet_view::get_split_pane() const +{ + return mp_impl->m_split_pane; +} + +void sheet_view::set_frozen_pane(col_t visible_cols, row_t visible_rows, const address_t& top_left_cell) +{ + mp_impl->m_frozen_pane.visible_columns = visible_cols; + mp_impl->m_frozen_pane.visible_rows = visible_rows; + mp_impl->m_frozen_pane.top_left_cell = top_left_cell; +} + +const frozen_pane_t& sheet_view::get_frozen_pane() const +{ + return mp_impl->m_frozen_pane; +} + +view& sheet_view::get_document_view() +{ + return mp_impl->m_doc_view; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |