Files
core/OdfFile/Reader/Converter/docx_conversion_context.cpp
Alexander Trofimov 76ee07f61c [copyright] Update copyright header
Co-authored-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
Co-committed-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
2026-05-14 08:23:56 +00:00

2856 lines
89 KiB
C++

/*
* Copyright (C) Ascensio System SIA, 2009-2026
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation, together with the
* additional terms provided in the LICENSE file.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: https://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA by email at info@onlyoffice.com
* or by postal mail at 20A-6 Ernesta Birznieka-Upisha Street, Riga,
* LV-1050, Latvia, European Union.
*
* The interactive user interfaces in modified versions of the Program
* are required to display Appropriate Legal Notices in accordance with
* Section 5 of the GNU AGPL version 3.
*
* No trademark rights are granted under this License.
*
* All non-code elements of the Product, including illustrations,
* icon sets, and technical writing content, are licensed under the
* Creative Commons Attribution-ShareAlike 4.0 International License:
* https://creativecommons.org/licenses/by-sa/4.0/legalcode
*
* This license applies only to such non-code elements and does not
* modify or replace the licensing terms applicable to the Program's
* source code, which remains licensed under the GNU Affero General
* Public License v3.
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
#include <iostream>
#include <xml/utils.h>
#include <xml/simple_xml_writer.h>
#include "docx_conversion_context.h"
#include "../Format/odf_document.h"
#include "../Format/odfcontext.h"
#include "../Format/text_content.h"
#include "../Format/calcs_styles.h"
#include "../Format/style_paragraph_properties.h"
#include "../Format/style_text_properties.h"
#include "../Format/style_table_properties.h"
#include "../Format/style_graphic_properties.h"
#include "docx_package.h"
#include "xlsx_package.h"
#include "oox_rels.h"
#include "../Common/logging.h"
#include "../../../DesktopEditor/common/SystemUtils.h"
#include "../../../DesktopEditor/graphics/pro/Fonts.h"
#include "../../../OOXML/Base/Unit.h"
static int current_id_changes = 1;
namespace cpdoccore {
namespace oox {
text_tracked_context::text_tracked_context(docx_conversion_context & context) :
docx_context_(context)
{
current_state_.clear();
}
void text_tracked_context::start_changes_content()
{
docx_stream_ = docx_context_.get_stream_man();
changes_stream_.str((std::wstring(L"")));
docx_context_.set_stream_man( StreamsManPtr( new oox::streams_man(changes_stream_)));
bParaStateDocx_ = docx_context_.get_paragraph_state();
bRunStateDocx_ = docx_context_.get_run_state();
docx_context_.set_paragraph_state (true);
docx_context_.set_run_state (false);
docx_context_.set_delete_text_state (true);
}
void text_tracked_context::end_changes_content()
{
docx_context_.finish_run(); //0106GS-GettingStartedWithWriter_el.odt - deleted heading
current_state_.content.push_back(changes_stream_.str());
docx_context_.set_delete_text_state (false);
docx_context_.set_paragraph_state (bParaStateDocx_);
docx_context_.set_run_state (bRunStateDocx_);
docx_context_.set_stream_man (docx_stream_);
}
void text_tracked_context::start_change (std::wstring id)
{
current_state_.clear();
current_state_.id = id;
}
void text_tracked_context::end_change ()
{
mapChanges_.insert( std::make_pair(current_state_.id, current_state_));
current_state_.clear();
}
void text_tracked_context::set_type(int type)
{
current_state_.type = type;
}
void text_tracked_context::set_user_info (std::wstring &author, std::wstring &date)
{
current_state_.author = author;
current_state_.date = date;
}
void text_tracked_context::set_style_name (std::wstring style_name)
{
current_state_.style_name = style_name;
}
text_tracked_context::_state & text_tracked_context::get_tracked_change(std::wstring id)
{
std::map<std::wstring, _state>::iterator it = mapChanges_.find(id);
if (it != mapChanges_.end())
{
return it->second;
}
else
return current_state_; //empty
}
//----------------------------------------------------------------------------------------------------------------
docx_conversion_context::docx_conversion_context(odf_reader::odf_document * _odf_document) :
last_dump_page_properties_ (true),
next_dump_page_properties_ (false),
page_break_ (false),
page_break_after_ (false),
page_break_before_ (false),
in_automatic_style_ (false),
in_header_ (false),
in_drawing_content_ (false),
in_table_content_ (false),
text_tracked_context_ (*this),
table_context_ (*this),
output_document_ (NULL),
current_process_note_ (noNote),
new_list_style_number_ (0),
current_margin_left_ (0),
current_outline_level_ (-1),
is_rtl_ (false),
is_delete_text_ (false),
delayed_converting_ (false),
process_headers_footers_ (false),
current_process_comment_ (false),
odf_document_ (_odf_document),
math_context_ (_odf_document->odf_context().fontContainer(), false)
{
mediaitems_ = boost::make_shared<mediaitems>(odf_document_->get_folder());
chart_drawing_handle_ = boost::make_shared<xlsx_drawing_context_handle>(mediaitems_);
streams_man_ = streams_man::create(temp_stream_);
}
docx_conversion_context::~docx_conversion_context()
{
}
void docx_conversion_context::set_implicit_end( bool _flag ) // fix bug with convert from docx to odt. Bug with break columns
{
flag_implicit_end = _flag;
}
bool docx_conversion_context::get_implicit_end() const // fix bug with convert from docx to odt. Bug with break columns
{
return flag_implicit_end;
}
void docx_conversion_context::set_inside_frame( bool flag )
{
inside_frame = flag;
}
bool docx_conversion_context::get_inside_frame() const
{
return inside_frame;
}
void docx_conversion_context::set_scale( const int _scale )
{
scale_for_framePr = _scale;
}
int docx_conversion_context::get_scale() const
{
return scale_for_framePr;
}
void docx_conversion_context::set_output_document(package::docx_document * document)
{
output_document_ = document;
}
void docx_conversion_context::set_font_directory(std::wstring pathFonts)
{
mediaitems_->set_font_directory(pathFonts);
}
std::wstring styles_map::get(const std::wstring & Name, odf_types::style_family::type Type)
{
const std::wstring n = name(Name, Type);
//typedef boost::unordered::unordered_map<std::wstring,std::wstring>::iterator _mapIter;
typedef std::multimap<std::wstring,std::wstring>::iterator _mapIter;
_mapIter it = map_.find( n );
if (it != map_.end() )
{
return it->second;
}
else
{
const std::wstring id = std::wstring(L"style") + std::to_wstring(count_++);
map_.insert(std::make_pair(n, id));
return id;
}
}
std::wstring styles_map::name(const std::wstring & Name, odf_types::style_family::type Type)
{
return Name + L":" + boost::lexical_cast<std::wstring>(odf_types::style_family(Type));
}
void docx_conversion_context::add_element_to_run(std::wstring parenStyleId)
{
if (false == current_process_comment_)
{
for (size_t i = 0; i < get_comments_context().ref_start_.size(); i++)
{
output_stream() << L"<w:commentRangeStart w:id=\"" << get_comments_context().ref_start_[i] << L"\"/>";
}
get_comments_context().ref_start_.clear();
if (false == get_comments_context().ref_end_.empty())
{
for (size_t i = 0; i < get_comments_context().ref_end_.size(); i++)
{
output_stream()<< L"<w:commentRangeEnd w:id=\"" << get_comments_context().ref_end_[i] << L"\"/>";
}
for (size_t i = 0; i < get_comments_context().ref_end_.size(); i++)
{
output_stream()<< L"<w:commentReference w:id=\"" << get_comments_context().ref_end_[i] << L"\"/>";
}
get_comments_context().ref_end_.clear();
}
}
if (!state_.in_run_)
{
state_.in_run_ = true;
output_stream() << L"<w:r>";
start_changes(true);
if (!state_.text_properties_stack_.empty() || parenStyleId.length() > 0)
{
if (!state_.text_properties_stack_.empty())
{
odf_reader::style_text_properties_ptr textProp = this->current_text_properties();
get_styles_context().start();
if(( textProp) && (textProp->content_.r_style_)) parenStyleId = _T("");
textProp->content_.docx_convert(*this);
}
get_styles_context().docx_serialize_text_style( output_stream(), parenStyleId, text_tracked_context_.dumpRPr_);
}
}
}
void docx_conversion_context::start_paragraph(bool is_header)
{
if (state_.in_paragraph_)
finish_paragraph();
start_changes(false);
output_stream() << L"<w:p>";
in_header_ = is_header;
is_rtl_ = false;
state_.in_paragraph_ = true;
}
void docx_conversion_context::finish_paragraph()
{
if (state_.in_paragraph_)
{
end_changes(true);
if (false == current_process_comment_ && false == get_comments_context().ref_end_.empty())
{
for (size_t i = 0; i < get_comments_context().ref_end_.size(); i++)
{
output_stream()<< L"<w:commentRangeEnd w:id=\"" << get_comments_context().ref_end_[i] << L"\"/>";
}
for (size_t i = 0; i < get_comments_context().ref_end_.size(); i++)
{
output_stream()<< L"<w:commentReference w:id=\"" << get_comments_context().ref_end_[i] << L"\"/>";
}
get_comments_context().ref_end_.clear();
}
output_stream() << L"</w:p>";
end_changes(false);
}
in_header_ = false;
state_.is_paragraph_keep_ = false;
state_.in_paragraph_ = false;
}
void docx_conversion_context::finish_run()
{
if (false == state_.in_run_) return;
if (false == current_process_comment_)
{
for (size_t i = 0; i < get_comments_context().ref_.size(); i++)
{
output_stream()<< L"<w:commentReference w:id=\"" << get_comments_context().ref_[i] << L"\"/>";
}
get_comments_context().ref_.clear();
}
output_stream() << L"</w:r>";
state_.in_run_ = false;
}
void docx_conversion_context::start_math_formula()
{
math_context_.start();
}
void docx_conversion_context::end_math_formula()
{
std::wstring math_content = math_context_.end();
if (!math_content.empty())
{
output_stream() << math_content;
}
}
void docx_conversion_context::start_sdt(int type)
{
in_table_content_ = true;
table_content_context_.type_table_content = type;
if (table_content_context_.type_table_content < 4)
{
output_stream() << L"<w:sdt><w:sdtPr>";
if (table_content_context_.type_table_content == 3)
{
output_stream() << L"<w:bibliography/>";
}
else
{
output_stream() << L"<w:docPartObj><w:docPartGallery w:val=\"";
if (table_content_context_.type_table_content == 1) output_stream() << L"Table of Contents";
if (table_content_context_.type_table_content == 2) output_stream() << L"List od Illustrations";
output_stream() << L"\"/><w:docPartUnique/></w:docPartObj>";
}
output_stream() << L"</w:sdtPr><w:sdtContent>";
}
}
void docx_conversion_context::start_index_content()
{
if (!in_table_content_) return;
start_paragraph(false);
std::wstring sInstrText;
if (table_content_context_.type_table_content == 3)
{
sInstrText = L" BIBLIOGRAPHY ";
}
else if (table_content_context_.type_table_content == 5)
{
sInstrText = L" INDEX";
if (table_content_context_.bSeparators)
sInstrText += L" \\h \"A\"";
}
else
{
sInstrText += L" TOC";
bool bLink = false, bPages = false;
if (table_content_context_.current_template.empty())
{
bLink = true;
bPages = true;
}
else
{
for (size_t i = 0; i < table_content_context_.current_template.size(); i++)
{
for (size_t j = 0; j < table_content_context_.current_template[i].content.size(); j++)
{
if (table_content_context_.current_template[i].content[j] == 3) bLink = true;
if (table_content_context_.current_template[i].content[j] == 6) bPages = true;
}
}
}
if (bLink)
sInstrText += L" \\h";
if (table_content_context_.type_table_content == 1)
sInstrText += L" \\f \\u";
else
sInstrText += L" \\z";
if (table_content_context_.min_outline_level > 0)
{
if (table_content_context_.max_outline_level > 9)
table_content_context_.max_outline_level = 9;
sInstrText += L" \\o \"" + std::to_wstring(table_content_context_.min_outline_level) + L"-" +
std::to_wstring(table_content_context_.max_outline_level) + L"\"";
if (!bPages)
sInstrText += L" \\n "+ std::to_wstring(table_content_context_.min_outline_level) + L"-" +
std::to_wstring(table_content_context_.max_outline_level);
}
else if (table_content_context_.type_table_content == 1)
sInstrText += L" \\o";
if (false == table_content_context_.outline_level_styles.empty())
{
sInstrText += L" \\t \"";
for (std::map<int, std::wstring>::iterator it = table_content_context_.outline_level_styles.begin();
it != table_content_context_.outline_level_styles.end(); ++it)
{
sInstrText += it->second + L";" + std::to_wstring(it->first) + L";";
}
sInstrText += L"\"";
}
if (!table_content_context_.caption_sequence_name.empty())
{
sInstrText += L" \\c \"" + table_content_context_.caption_sequence_name + L"\"";
}
}
start_field(sInstrText, L"");
finish_paragraph();
}
void docx_conversion_context::end_index_content()
{
if (!in_table_content_) return;
start_paragraph(false);
end_field();
finish_paragraph();
}
void docx_conversion_context::start_field(const std::wstring & sInstrText, const std::wstring & sName)
{
output_stream() << L"<w:r>";
output_stream() << L"<w:fldChar w:fldCharType=\"begin\">";
if (!sName.empty())
{
output_stream() << L"<w:ffData><w:name w:val=\"" << sName << L"\"/><w:enabled/><w:calcOnExit w:val=\"0\"/></w:ffData>";
}
output_stream() << L"</w:fldChar>";
output_stream() << L"</w:r>";
output_stream() << L"<w:r>";
output_stream() << L"<w:instrText xml:space=\"preserve\">" << XmlUtils::EncodeXmlString(sInstrText) << L" </w:instrText>";
output_stream() << L"</w:r>";
output_stream() << L"<w:r>";
output_stream() << L"<w:fldChar w:fldCharType=\"separate\"/>";
output_stream() << L"</w:r>";
if (!sName.empty())
{
start_bookmark(sName);
}
fields_names_stack_.push_back(sName);
}
void docx_conversion_context::end_field()
{
if (fields_names_stack_.empty()) return;
output_stream() << L"<w:r>";
output_stream() << L"<w:fldChar w:fldCharType=\"end\"/>";
output_stream() << L"</w:r>";
std::wstring sName = fields_names_stack_.back();
fields_names_stack_.pop_back();
if (!sName.empty())
{
end_bookmark(sName);
}
}
void docx_conversion_context::end_sdt()
{
if (!in_table_content_) return;
if (table_content_context_.type_table_content < 4)
{
output_stream() << L"</w:sdtContent></w:sdt>";
}
in_table_content_ = false;
table_content_context_.clear_all();
}
void docx_conversion_context::start_index_element()
{
table_content_context_.clear_current_content_template_index();
}
void docx_conversion_context::end_index_element()
{
table_content_context_.clear_current_content_template_index();
}
void docx_conversion_context::add_bibliography_item (const std::wstring & item)
{
arBibliography.push_back(item);
}
void docx_conversion_context::start_bookmark (const std::wstring &name)
{
std::map<std::wstring, int>::iterator pFind = mapBookmarks.find(name);
int id = -1;
if (pFind == mapBookmarks.end())
{
id = mapBookmarks.size() + 1;
mapBookmarks.insert(std::make_pair(name, id));
}
else
{
id = pFind->second;
}
finish_run();
output_stream() << L"<w:bookmarkStart w:id=\"" << std::to_wstring(id) << L"\" w:name=\"" << XmlUtils::EncodeXmlString(name) << L"\"/>";
}
void docx_conversion_context::end_bookmark (const std::wstring &name)
{
std::map<std::wstring, int>::iterator pFind = mapBookmarks.find(name);
int id = -1;
if (pFind == mapBookmarks.end())
{
return; //???
}
else
{
id = pFind->second;
}
finish_run();
output_stream() << L"<w:bookmarkEnd w:id=\"" << std::to_wstring(id) << L"\"/>";
}
void docx_conversion_context::start_alphabetical_index (const std::wstring &id)
{
std::map<std::wstring, std::vector<odf_reader::office_element_ptr>>::iterator pFind = mapAlphabeticals.find(id);
if (pFind != mapAlphabeticals.end()) return;
std::vector<odf_reader::office_element_ptr> texts;
mapAlphabeticals.insert(std::make_pair(id, texts));
current_alphabetic_index_ = id;
}
void docx_conversion_context::add_alphabetical_index_text (odf_reader::office_element_ptr & elem)
{
std::map<std::wstring, std::vector<odf_reader::office_element_ptr>>::iterator pFind = mapAlphabeticals.find(current_alphabetic_index_);
if (pFind == mapAlphabeticals.end())
{
return;
}
pFind->second.push_back(elem);
}
void docx_conversion_context::end_alphabetical_index (const std::wstring &id)
{
std::map<std::wstring, std::vector<odf_reader::office_element_ptr>>::iterator pFind = mapAlphabeticals.find(id);
if (pFind == mapAlphabeticals.end())
{
return;
}
finish_run();
output_stream() << L"<w:r><w:fldChar w:fldCharType=\"begin\"/></w:r>";
output_stream() << L"<w:r><w:instrText>XE \"";
ElementType type;
for (size_t i = 0; i < pFind->second.size(); i++)
{
type = pFind->second[i]->get_type();
pFind->second[i]->text_to_stream(output_stream());
}
output_stream() << L"\"</w:instrText></w:r>";
output_stream() << L"<w:r><w:fldChar w:fldCharType=\"end\"/></w:r>";
for (size_t i = 0; i < pFind->second.size(); i++)
{
pFind->second[i]->docx_convert(*this);
}
mapAlphabeticals.erase(pFind);
if (mapAlphabeticals.empty())
current_alphabetic_index_.clear();
else
current_alphabetic_index_ = mapAlphabeticals.begin()->first; // todooo vector+map+level
}
void docx_conversion_context::start_chart(std::wstring name)
{
charts_.push_back(oox_chart_context_ptr(new oox_chart_context(mediaitems_, name)));
}
void docx_conversion_context::end_chart()
{
//current_chart().set_drawing_link(current_sheet().get_drawing_link());
//redundant info
}
oox_chart_context & docx_conversion_context::current_chart()
{
if (!charts_.empty())
{
return *charts_.back().get();
}
else
{
throw std::runtime_error("internal error");
}
}
void docx_conversion_context::reset_context_state()
{
keep_state_.push_back(state_);
state_.in_paragraph_ = false;
state_.in_run_ = false;
state_.is_paragraph_keep_ = false;
state_.drawing_text_props_.clear();
state_.text_properties_stack_.clear();
get_styles_context().text_style_ext().clear();
}
void docx_conversion_context::back_context_state()
{
state_ = keep_state_.back();
keep_state_.pop_back();
get_styles_context().text_style_ext().clear();
}
void docx_conversion_context::add_new_run(std::wstring parentStyleId)
{
finish_run();
add_element_to_run(parentStyleId);
}
std::wstring docx_conversion_context::add_hyperlink(const std::wstring & href, bool draw)
{
oox::_rels_type_place type_place = get_type_place();
std::wstring href_correct = XmlUtils::EncodeXmlString(href);
XmlUtils::replace_all( href_correct, L" .", L".");//1 (130).odt
return hyperlinks_.add(href_correct, type_place, draw);
}
hyperlinks::_ref docx_conversion_context::last_hyperlink()
{
return hyperlinks_.last();
}
_rels_type_place docx_conversion_context::get_type_place()
{
if (current_process_note_ == footNote ||
current_process_note_ == footNoteRefSet) return oox::footnote_place;
if (current_process_note_ == endNote ||
current_process_note_ == endNoteRefSet ) return oox::endnote_place;
if (current_process_comment_) return oox::comment_place;
if (process_headers_footers_) return oox::header_footer_place;
return oox::document_place;
}
void docx_conversion_context::dump_hyperlinks(rels & Rels, _rels_type_place type)
{
hyperlinks_.dump_rels(Rels, type);
}
void docx_conversion_context::dump_headers_footers(rels & Rels) const
{
headers_footers_.dump_rels(Rels);
}
void docx_conversion_context::dump_notes(rels & Rels) const
{
notes_context_.dump_rels(Rels);
}
void docx_conversion_context::start_document()
{
streams_man_ = streams_man::create(document_xml_);
output_stream() << L"<w:document ";
output_stream() << L"xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" ";
output_stream() << L"xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ";
output_stream() << L"xmlns:o=\"urn:schemas-microsoft-com:office:office\" ";
output_stream() << L"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" ";
output_stream() << L"xmlns:m=\"http://schemas.openxmlformats.org/officeDocument/2006/math\" ";
output_stream() << L"xmlns:v=\"urn:schemas-microsoft-com:vml\" ";
output_stream() << L"xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" ";
output_stream() << L"xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" ";
output_stream() << L"xmlns:w10=\"urn:schemas-microsoft-com:office:word\" ";
output_stream() << L"xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ";
output_stream() << L"xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" ";
output_stream() << L"xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" ";
output_stream() << L"xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" ";
output_stream() << L"xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" ";
output_stream() << L"xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" ";
output_stream() << L"xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" ";
output_stream() << L"xmlns:cx=\"http://schemas.microsoft.com/office/drawing/2014/chartex\" ";
output_stream() << L"xmlns:cx1=\"http://schemas.microsoft.com/office/drawing/2015/9/8/chartex\" ";
output_stream() << L"xmlns:w15=\"http://schemas.microsoft.com/office/word/2012/wordml\" ";
output_stream() << L"xmlns:w16se=\"http://schemas.microsoft.com/office/word/2015/wordml/symex\" ";
output_stream() << L"mc:Ignorable=\"w14 w15 w16se wne wp14\">";
//apply page-default prop
//temporarily put document-wide properties handling here
}
void docx_conversion_context::end_document()
{
output_stream() << L"</w:document>";
output_document_->get_word_files().set_document ( package::simple_element::create(L"document.xml", document_xml_.str()) );
output_document_->get_word_files().set_settings ( package::simple_element::create(L"settings.xml", dump_settings_document()));
output_document_->get_word_files().set_media ( mediaitems_);
output_document_->get_word_files().set_comments ( comments_context_);
output_document_->get_word_files().set_headers_footers( headers_footers_);
package::xl_drawings_ptr drawings = package::xl_drawings::create(chart_drawing_handle_->content(), chart_drawing_handle_->content_vml());
output_document_->get_word_files().set_drawings(drawings);
package::content_types_file & content_file_ = output_document_->get_content_types_file();
content_file_.set_media( mediaitems_);
////////////////////////////////////////////////////////////////////////////
dump_bibliography();
dump_hyperlinks (notes_context_.footnotesRels(), oox::footnote_place);
dump_hyperlinks (notes_context_.endnotesRels(), oox::endnote_place);
get_mediaitems()->dump_rels(notes_context_.footnotesRels(), oox::footnote_place);
get_mediaitems()->dump_rels(notes_context_.endnotesRels(), oox::endnote_place);
output_document_->get_word_files().set_notes(notes_context_);
output_document_->get_docProps_files().set_app(package::simple_element::create(L"app.xml", dump_settings_app()));
output_document_->get_docProps_files().set_core(package::simple_element::create(L"core.xml", dump_settings_core()));
std::wstring settings_custom = dump_settings_custom();
if (false == settings_custom.empty())
{
output_document_->get_docProps_files().set_custom(package::simple_element::create(L"custom.xml", settings_custom));
output_document_->get_content_types_file().content()->add_override(L"/docProps/custom.xml", L"application/vnd.openxmlformats-officedocument.custom-properties+xml");
output_document_->get_rels_files().add(
relationship(L"rCstmId", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties", L"docProps/custom.xml"));
}
for (size_t i = 0; i < charts_.size(); i++)
{
package::chart_content_ptr content = package::chart_content::create();
charts_[i]->serialize(content->content());
charts_[i]->dump_rels(content->get_rel_file()->get_rels());
output_document_->get_word_files().add_charts(content);
}
output_document_->get_word_files().update_rels(*this);
}
void docx_conversion_context::dump_bibliography()
{
if (arBibliography.empty()) return;
std::wstringstream output(L"");
CP_XML_WRITER(output)
{
CP_XML_NODE(L"b:Sources")
{
CP_XML_ATTR(L"Version", 6);
CP_XML_ATTR(L"StyleName", L"APA");
CP_XML_ATTR(L"SelectedStyle", L"\\APASixthEditionOfficeOnline.xsl");
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/officeDocument/2006/bibliography");
CP_XML_ATTR(L"xmlns:b", L"http://schemas.openxmlformats.org/officeDocument/2006/bibliography");
for (size_t i = 0; i < arBibliography.size(); i++)
{
CP_XML_NODE(L"b:Source")
{
CP_XML_STREAM() << arBibliography[i];
CP_XML_NODE(L"b:RefOrder")
{
CP_XML_STREAM() << std::to_wstring(i + 1);
}
}
}
}
}
std::wstringstream output_props(L"");
CP_XML_WRITER(output_props)
{
CP_XML_NODE(L"ds:datastoreItem")
{
CP_XML_ATTR(L"xmlns:ds", L"http://schemas.openxmlformats.org/officeDocument/2006/customXml");
CP_XML_ATTR(L"ds:itemID", L"{28C8D49A-D84A-4837-A0AC-8E2C3AE46B82}");
CP_XML_NODE(L"ds:schemaRefs")
{
CP_XML_NODE(L"ds:schemaRef")
{
CP_XML_ATTR(L"ds:uri", L"http://schemas.openxmlformats.org/officeDocument/2006/bibliography");
}
}
}
}
package::customXml_content_ptr content = package::customXml_content::create(output.str(), output_props.str());
int id = output_document_->add_customXml(content);
const std::wstring sRId = std::wstring(L"cstId") + std::to_wstring(id);
const std::wstring sRel = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml";
const std::wstring sFileRef = std::wstring(L"../customXml/item") + std::to_wstring(id) + L".xml";
output_document_->get_word_files().add_rels(relationship(sRId, sRel, sFileRef));
}
std::wstring docx_conversion_context::dump_settings_app()
{
std::wstringstream output;
CP_XML_WRITER(output)
{
CP_XML_NODE(L"Properties")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties");
CP_XML_ATTR(L"xmlns:vt", L"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
if (!odf_document_->odf_context().DocProps().template_.empty())
{
CP_XML_NODE(L"Template")
{
CP_XML_STREAM() << odf_document_->odf_context().DocProps().template_;
}
}
if (odf_document_->odf_context().DocProps().revision_)
{
CP_XML_NODE(L"TotalTime")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().revision_;
}
}
CP_XML_NODE(L"Application")
{
if (!odf_document_->odf_context().DocProps().application_.empty())
{
CP_XML_STREAM() << odf_document_->odf_context().DocProps().application_;
}
else
{
std::wstring sApplication = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvApplicationName);
if (sApplication.empty())
sApplication = NSSystemUtils::gc_EnvApplicationNameDefault;
CP_XML_STREAM() << sApplication;
#if defined(INTVER)
std::string s = VALUE2STR(INTVER);
CP_XML_STREAM() << L"/" << std::wstring(s.begin(), s.end());
#endif
}
}
if (odf_document_->odf_context().DocProps().page_count_)
{
CP_XML_NODE(L"Pages")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().page_count_;
}
}
if (odf_document_->odf_context().DocProps().word_count_)
{
CP_XML_NODE(L"Words")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().word_count_;
}
}
if (odf_document_->odf_context().DocProps().character_count_)
{
CP_XML_NODE(L"CharactersWithSpaces")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().character_count_;
}
}
if (odf_document_->odf_context().DocProps().non_whitespace_character_count_)
{
CP_XML_NODE(L"Characters")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().non_whitespace_character_count_;
}
}
if (odf_document_->odf_context().DocProps().paragraph_count_)
{
CP_XML_NODE(L"Paragraphs")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().paragraph_count_;
}
}
}
}
return output.str();
}
std::wstring docx_conversion_context::dump_settings_custom()
{
std::wstring user_defined = odf_document_->odf_context().DocProps().dump_user_defined();
if (user_defined.empty()) return L"";
std::wstringstream output;
CP_XML_WRITER(output)
{
CP_XML_NODE(L"Properties")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/officeDocument/2006/custom-properties");
CP_XML_ATTR(L"xmlns:vt", L"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
CP_XML_STREAM() << user_defined;
}
}
return output.str();
}
std::wstring docx_conversion_context::dump_settings_core()
{
std::wstringstream output;
CP_XML_WRITER(output)
{
CP_XML_NODE(L"cp:coreProperties")
{
CP_XML_ATTR(L"xmlns:cp", L"http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
CP_XML_ATTR(L"xmlns:xsi", L"http://www.w3.org/2001/XMLSchema-instance");
CP_XML_ATTR(L"xmlns:dc", L"http://purl.org/dc/elements/1.1/");
CP_XML_ATTR(L"xmlns:dcmitype", L"http://purl.org/dc/dcmitype/");
CP_XML_ATTR(L"xmlns:dcterms", L"http://purl.org/dc/terms/");
if (!odf_document_->odf_context().DocProps().creation_date_.empty())
{
CP_XML_NODE(L"dcterms:created")
{
CP_XML_ATTR(L"xsi:type", L"dcterms:W3CDTF");
CP_XML_STREAM() << odf_document_->odf_context().DocProps().creation_date_;
}
}
if (!odf_document_->odf_context().DocProps().dc_date_.empty())
{
CP_XML_NODE(L"dcterms:modified")
{
CP_XML_ATTR(L"xsi:type", L"dcterms:W3CDTF");
CP_XML_STREAM() << odf_document_->odf_context().DocProps().dc_date_;
}
}
if (!odf_document_->odf_context().DocProps().dc_creator_.empty())
{
CP_XML_NODE(L"dc:creator")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().dc_creator_);
}
}
if (!odf_document_->odf_context().DocProps().dc_title_.empty())
{
CP_XML_NODE(L"dc:title")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().dc_title_);
}
}
if (!odf_document_->odf_context().DocProps().dc_subject_.empty())
{
CP_XML_NODE(L"dc:subject")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().dc_subject_);
}
}
if (!odf_document_->odf_context().DocProps().dc_description_.empty())
{
CP_XML_NODE(L"dc:description")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().dc_description_);
}
}
if (!odf_document_->odf_context().DocProps().dc_language_.empty())
{
CP_XML_NODE(L"dc:language")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().dc_language_);
}
}
CP_XML_NODE(L"cp:lastModifiedBy")
{
std::wstring sApplication = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvApplicationName);
if (sApplication.empty())
sApplication = NSSystemUtils::gc_EnvApplicationNameDefault;
CP_XML_STREAM() << sApplication;
#if defined(INTVER)
std::string s = VALUE2STR(INTVER);
CP_XML_STREAM() << L"/" << std::wstring(s.begin(), s.end());
#endif
}
if (!odf_document_->odf_context().DocProps().keyword_.empty())
{
CP_XML_NODE(L"cp:keywords")
{
CP_XML_STREAM() << XmlUtils::EncodeXmlString(odf_document_->odf_context().DocProps().keyword_);
}
}
if (odf_document_->odf_context().DocProps().revision_)
{
CP_XML_NODE(L"cp:revision")
{
CP_XML_STREAM() << *odf_document_->odf_context().DocProps().revision_;
}
}
}
}
return output.str();
}
std::wstring docx_conversion_context::dump_settings_document()
{
std::wstringstream output;
CP_XML_WRITER(output)
{
CP_XML_NODE(L"w:settings")
{
CP_XML_ATTR(L"xmlns:mc", L"http://schemas.openxmlformats.org/markup-compatibility/2006");
CP_XML_ATTR(L"xmlns:o", L"urn:schemas-microsoft-com:office:office");
CP_XML_ATTR(L"xmlns:r", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships");
CP_XML_ATTR(L"xmlns:m", L"http://schemas.openxmlformats.org/officeDocument/2006/math");
CP_XML_ATTR(L"xmlns:v", L"urn:schemas-microsoft-com:vml");
CP_XML_ATTR(L"xmlns:w10", L"urn:schemas-microsoft-com:office:word");
CP_XML_ATTR(L"xmlns:w", L"http://schemas.openxmlformats.org/wordprocessingml/2006/main");
CP_XML_ATTR(L"xmlns:w14", L"http://schemas.microsoft.com/office/word/2010/wordml");
CP_XML_ATTR(L"xmlns:sl", L"http://schemas.openxmlformats.org/schemaLibrary/2006/main");
CP_XML_ATTR(L"mc:Ignorable", L"w14");
_CP_OPT(bool) boolVal;
_CP_OPT(std::wstring) strVal;
_CP_OPT(int) intVal;
strVal = root()->odf_context().Settings().find_by_name(L"modifyPasswordInfo");
if (strVal)
{
CP_XML_NODE(L"w:writeProtection")
{
strVal = root()->odf_context().Settings().find_by_name(L"modify:crypt-name");
if (strVal)
{
CP_XML_ATTR(L"w:cryptProviderType", *strVal);
CP_XML_ATTR(L"w:cryptAlgorithmClass", L"hash");
CP_XML_ATTR(L"w:cryptAlgorithmType", L"typeAny");
strVal = root()->odf_context().Settings().find_by_name(L"modify:algorithm-name");
if (strVal)
{
if (*strVal == L"SHA-512") CP_XML_ATTR(L"w:cryptAlgorithmSid", L"14");
if (*strVal == L"SHA-386") CP_XML_ATTR(L"w:cryptAlgorithmSid", L"13");
if (*strVal == L"SHA-256") CP_XML_ATTR(L"w:cryptAlgorithmSid", L"12");
if (*strVal == L"SHA-1") CP_XML_ATTR(L"w:cryptAlgorithmSid", L"4");
}
strVal = root()->odf_context().Settings().find_by_name(L"modify:iteration-count");
if (strVal) CP_XML_ATTR(L"w:cryptSpinCount", *strVal);
strVal = root()->odf_context().Settings().find_by_name(L"modify:hash");
if (strVal) CP_XML_ATTR(L"w:hash", *strVal);
strVal = root()->odf_context().Settings().find_by_name(L"modify:salt");
if (strVal) CP_XML_ATTR(L"w:salt", *strVal);
}
else
{
strVal = root()->odf_context().Settings().find_by_name(L"modify:algorithm-name");
if (strVal) CP_XML_ATTR(L"w:algorithmName", *strVal);
strVal = root()->odf_context().Settings().find_by_name(L"modify:hash");
if (strVal) CP_XML_ATTR(L"w:hashValue", *strVal);
strVal = root()->odf_context().Settings().find_by_name(L"modify:salt");
if (strVal) CP_XML_ATTR(L"w:saltValue", *strVal);
strVal = root()->odf_context().Settings().find_by_name(L"modify:iteration-count");
if (strVal) CP_XML_ATTR(L"w:spinCount", *strVal);
}
}
}
if (odf_reader::GetProperty(settings_properties_,L"evenAndOddHeaders", boolVal))
{
CP_XML_NODE(L"w:evenAndOddHeaders");
}
if (odf_reader::GetProperty(settings_properties_,L"displayBackgroundShape", boolVal))
{
CP_XML_NODE(L"w:displayBackgroundShape");
}
if (odf_reader::GetProperty(settings_properties_,L"zoom", intVal))
{
CP_XML_NODE(L"w:zoom")
{
CP_XML_ATTR(L"w:percent",intVal.get());
}
}
if (odf_reader::GetProperty(settings_properties_,L"mirrorMargins", boolVal))
{
CP_XML_NODE(L"w:mirrorMargins");
}
_CP_OPT(double) tabDistance = root()->odf_context().Settings().get_tab_distance();
if (tabDistance)
{
CP_XML_NODE(L"w:defaultTabStop")
{
CP_XML_ATTR(L"w:val", *tabDistance);
}
}
CP_XML_NODE(L"w:compat")
{
CP_XML_NODE(L"w:compatSetting")
{
CP_XML_ATTR(L"w:name", L"compatibilityMode" );
CP_XML_ATTR(L"w:uri", L"http://schemas.microsoft.com/office/word" );
CP_XML_ATTR(L"w:val", L"15" );
}
}
}
}
return output.str();
}
void docx_conversion_context::start_body()
{
output_stream() << L"<w:body>";
}
void docx_conversion_context::end_body()
{
//odf_document_->odf_context.pageLayoutContainer().instances()
output_stream() << L"</w:body>";
}
void docx_conversion_context::start_office_text()
{
}
void docx_conversion_context::end_office_text()
{
finish_paragraph();
if (!delayed_converting_)//otherwise possible infinite loop
{
docx_convert_delayed();
}
}
namespace
{
std::wstring StyleTypeOdf2Docx(odf_types::style_family::type Type)
{
switch(Type)
{
case odf_types::style_family::Text:
return L"character";
case odf_types::style_family::Paragraph:
return L"paragraph";
// TODO
default:
return L"";
}
}
std::wstring StyleDisplayName(const std::wstring & Name, const std::wstring & DisplayName, odf_types::style_family::type Type, bool &bDisplayed)
{
bDisplayed = true;
if (false == DisplayName.empty())
return DisplayName;
if (false == Name.empty())
{
bDisplayed = false;
return Name;
}
else
{
bDisplayed = false;
return std::wstring(L"DStyle_") + boost::lexical_cast<std::wstring>(odf_types::style_family(Type) );
}
}
}
void docx_conversion_context::process_list_styles()
{
streams_man_ = streams_man::create(numbering_xml_);
std::wostream & strm = output_stream();
odf_reader::odf_document * doc = root();
if (!doc)
return;
odf_reader::odf_read_context & context = doc->odf_context();
odf_reader::list_style_container & list_styles = context.listStyleContainer();
if (list_styles.empty())
return;
strm << L"<w:numbering \
xmlns:wpc=\"http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas\" \
xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" \
xmlns:o=\"urn:schemas-microsoft-com:office:office\" \
xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" \
xmlns:v=\"urn:schemas-microsoft-com:vml\" \
xmlns:wp14=\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\" \
xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" \
xmlns:w10=\"urn:schemas-microsoft-com:office:word\" \
xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" \
xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" \
xmlns:wpg=\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\" \
xmlns:wpi=\"http://schemas.microsoft.com/office/word/2010/wordprocessingInk\" \
xmlns:wne=\"http://schemas.microsoft.com/office/word/2006/wordml\" \
xmlns:wps=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\" \
mc:Ignorable=\"w14 wp14\">";
std::vector<int> numIds;
odf_reader::list_style_container::instances_array & arListStyles = list_styles.instances();
for (size_t i = 0; i < arListStyles.size(); i++)
{
odf_reader::office_element_ptr_array & content = arListStyles[i]->get_text_list_style()->content_;
if (content.empty())
continue;
const int abstractNumId = list_styles.id_by_name(arListStyles[i]->get_style_name());
numIds.push_back(abstractNumId);
strm << L"<w:abstractNum w:abstractNumId=\"" << abstractNumId << "\">";
for (size_t j = 0; j < (std::min)( content.size(), (size_t)9); j++)
{
start_text_list_style(arListStyles[i]->get_text_list_style()->attr_.style_name_);
content[j]->docx_convert(*this);
end_text_list_style();
}
strm << L"</w:abstractNum>";
}
if (list_styles.outline_style())
{
const int abstractNumId = list_styles.id_outline();
numIds.push_back(abstractNumId);
strm << L"<w:abstractNum w:abstractNumId=\"" << abstractNumId << "\">";
for (size_t j = 0; j < (std::min)( list_styles.outline_style()->content_.size(), (size_t)9); j++)
{
start_text_list_style(L"Outline");
list_styles.outline_style()->content_[j]->docx_convert(*this);
end_text_list_style();
}
strm << L"</w:abstractNum>";
}
for (size_t i = 0; i < numIds.size(); i++)
{
strm << L"<w:num w:numId=\"" << numIds[i] << L"\">";
strm << L"<w:abstractNumId w:val=\"" << numIds[i] << "\"/>";
strm << L"</w:num>";
}
strm << L"</w:numbering>";
output_document_->get_word_files().set_numbering(package::simple_element::create(L"numbering.xml", numbering_xml_.str()) );
}
void docx_conversion_context::process_fonts()
{
streams_man_ = streams_man::create(fontTable_xml_);
std::wostream & strm = output_stream();
strm << L"<w:fonts xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">";
if (odf_reader::odf_document * doc = root())
{
odf_reader::odf_read_context & context = doc->odf_context();
odf_reader::fonts_container & fonts = context.fontContainer();
odf_reader::fonts_container::instances_array &arFonts = fonts.instances();
for (size_t i = 0; i < arFonts.size(); i++)
{
if (!arFonts[i]) continue;
if (arFonts[i]->name().empty()) continue;
strm << L"<w:font w:name=\"" << arFonts[i]->name() << L"\">";
if (!arFonts[i]->charset().empty())
strm << L"<w:charset w:val=\"" << arFonts[i]->charset() <<"\"/>";
if (!arFonts[i]->family().empty())
strm << L"<w:family w:val=\"" << arFonts[i]->family() << "\"/>";
if (!arFonts[i]->pitch().empty())
strm << L"<w:pitch w:val=\"" << arFonts[i]->pitch() << "\"/>";
if (!arFonts[i]->alt_name().empty())
strm << L"<w:altName w:val=\"" << arFonts[i]->alt_name() << "\"/>";
strm << L"</w:font>";
}
}
strm << L"</w:fonts>";
output_document_->get_word_files().set_fontTable(package::simple_element::create(L"fontTable.xml", fontTable_xml_.str()));
}
void docx_conversion_context::process_styles()
{
streams_man_ = streams_man::create(styles_xml_);
std::wostream & _Wostream = output_stream();
_Wostream << L"<w:styles ";
_Wostream << L"xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" ";
_Wostream << L"xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" ";
_Wostream << L"xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\" ";
_Wostream << L"xmlns:w14=\"http://schemas.microsoft.com/office/word/2010/wordml\" ";
_Wostream << L"mc:Ignorable=\"w14\">";
if (odf_reader::odf_document * doc = root())
{
odf_reader::odf_read_context & context = doc->odf_context();
odf_reader::styles_container & styles = context.styleContainer();
// add all styles to the map
odf_reader::styles_container::instances_array &arStyles = styles.instances();
for (size_t i = 0; i < arStyles.size(); i++)
{
if (!arStyles[i]) continue;
styles_map_.get(arStyles[i]->name(), arStyles[i]->type());
}
_Wostream << L"<w:docDefaults>";
if (odf_reader::style_instance * defaultParStyle = styles.style_default_by_type(odf_types::style_family::Paragraph))
{
_Wostream << L"<w:pPrDefault>";
if ( odf_reader::style_content * content = defaultParStyle->content())
{
if (content->get_style_paragraph_properties())
{
if(content->get_style_paragraph_properties()->content_.fo_background_color_)
{
odf_types::background_color color = *content->get_style_paragraph_properties()->content_.fo_background_color_;
if ((color.get_type() != odf_types::background_color::Transparent &&
color.get_color() == odf_types::color(L"ffffff")) ||
(color.get_type() == odf_types::background_color::Transparent))
{
content->get_style_paragraph_properties()->content_.fo_background_color_ = boost::none;
}
}
}
get_styles_context().start_process_style(defaultParStyle);
content->docx_convert(*this);
get_styles_context().end_process_style();
}
_Wostream << L"</w:pPrDefault>";
}
if (odf_reader::style_instance * defaultParStyle = styles.style_default_by_type(odf_types::style_family::Text))
{
_Wostream << L"<w:rPrDefault>";
if ( odf_reader::style_content * content = defaultParStyle->content())
{
get_styles_context().start_process_style(defaultParStyle);
content->docx_convert(*this);
get_styles_context().end_process_style();
}
_Wostream << L"</w:rPrDefault>";
}
_Wostream << L"</w:docDefaults>";
std::wstring default_style;
std::wstring curr_name_of_normal_style;
bool haveNormalStyle = false;
for (size_t i = 0; i < arStyles.size(); i++)
{
if (false == arStyles[i]->is_automatic() &&
(arStyles[i]->type() == odf_types::style_family::Paragraph ||
arStyles[i]->type() == odf_types::style_family::Text))
{
const std::wstring id = styles_map_.get(arStyles[i]->name(), arStyles[i]->type());
bool bDefault = (arStyles[i]->style_class() == L"default");
bool bDisplayed = (arStyles[i]->type() == odf_types::style_family::Paragraph);
_Wostream << L"<w:style w:styleId=\"" << id << L"\" w:type=\"" << StyleTypeOdf2Docx(arStyles[i]->type()) << L"\"";
status_para[id] = false;
set_temp_style_name(id);
if (bDefault) // style
{
_Wostream << L" w:default=\"1\"";
if (arStyles[i]->type() == odf_types::style_family::Paragraph)
{
default_style = id;
}
}
else if (!arStyles[i]->is_default()) // default-style
{
_Wostream << L" w:customStyle=\"1\"";
}
_Wostream << L">";
const std::wstring displayName = StyleDisplayName(arStyles[i]->name(), arStyles[i]->display_name(), arStyles[i]->type(), bDisplayed);
if( displayName == L"Normal" )
{
haveNormalStyle = true;
curr_name_of_normal_style = id;
}
_Wostream << L"<w:name w:val=\"" << XmlUtils::EncodeXmlString(displayName) << L"\"/>";
if (odf_reader::style_instance * baseOn = arStyles[i]->parent())
{
const std::wstring basedOnId = styles_map_.get(baseOn->name(), baseOn->type());
_Wostream << L"<w:basedOn w:val=\"" << basedOnId << "\"/>";
}
else if (!bDefault && !default_style.empty())
{
_Wostream << L"<w:basedOn w:val=\"" << default_style << "\"/>";
}
// else if (false == bDefault && false == arStyles[i]->is_default() && styles_map_.check(L"", arStyles[i]->type()))
// {
//bDisplayed = false;
// const std::wstring basedOnId = styles_map_.get(L"", arStyles[i]->type());
// _Wostream << L"<w:basedOn w:val=\"" << basedOnId << "\"/>";
// }
if (bDisplayed)
{
_Wostream << L"<w:qFormat/>";
}
if (odf_reader::style_instance * next = arStyles[i]->next())
{
const std::wstring nextId = styles_map_.get(next->name(), next->type());
_Wostream << L"<w:next w:val=\"" << nextId << "\"/>";
}
else
{
if( !arStyles[i]->is_default() && haveNormalStyle)
{
_Wostream << L"<w:next w:val=\"" << curr_name_of_normal_style << "\"/>";
}
}
//else if (arStyles[i]->is_default())
//{
// // self
// _Wostream << L"<w:next w:val=\"" << id << "\"/>";
//}
if (odf_reader::style_content * content = arStyles[i]->content())
{
get_tabs_context().clear();
calc_tab_stops(arStyles[i].get(), get_tabs_context());
get_styles_context().start_process_style(arStyles[i].get());
content->docx_convert(*this, true);
get_styles_context().end_process_style();
}
_Wostream << L"</w:style>";
}
}
}
_Wostream << L"</w:styles>";
output_document_->get_word_files().set_styles( package::simple_element::create(L"styles.xml", styles_xml_.str()) );
}
void docx_conversion_context::start_process_style_content()
{
styles_context_.start();
}
void docx_conversion_context::process_section(std::wostream & strm, odf_reader::style_columns *columns_page)//from page layout
{
if (root()->odf_context().pageLayoutContainer().linenumbering())
{
root()->odf_context().pageLayoutContainer().linenumbering()->docx_serialize(strm, *this);
}
int count_columns = 1;
bool sep_columns = false;
oox::section_context::_section & section = get_section_context().get_last();
odf_reader::style_columns *columns = columns_page;
//if (!columns)
{
if (const odf_reader::style_instance * secStyle = root()->odf_context().styleContainer().style_by_name(section.style_, odf_types::style_family::Section, process_headers_footers_))
{
if (const odf_reader::style_content * content = secStyle->content())
{
if (odf_reader::style_section_properties * sectPr = content->get_style_section_properties())
{
columns = dynamic_cast<odf_reader::style_columns *>( sectPr->style_columns_.get());
section.margin_left_ = sectPr->common_horizontal_margin_attlist_.fo_margin_left_;
section.margin_right_ = sectPr->common_horizontal_margin_attlist_.fo_margin_right_;
}
}
if (section.is_dump_)
{
get_section_context().remove_section();
}
}
}
std::vector<std::pair<double, double>> width_space;
if (columns)
{
if (columns->fo_column_count_)
{
count_columns = *columns->fo_column_count_;
}
if (odf_reader::style_column_sep * columns_sep = dynamic_cast<odf_reader::style_column_sep *>( columns->style_column_sep_.get() ))
{
if (columns_sep->style_style_ != _T("none"))
sep_columns = true;
}
if (!columns->style_columns_.empty())
{
double page_width = 0;
const odf_reader::page_layout_instance * pp = root()->odf_context().pageLayoutContainer().page_layout_first();
if ((pp) && (pp->properties()))
{
odf_reader::style_page_layout_properties_attlist & attr_page = pp->properties()->attlist_;
if (attr_page.fo_page_width_)
{
page_width = attr_page.fo_page_width_->get_value_unit(odf_types::length::pt);
}
if (attr_page.common_horizontal_margin_attlist_.fo_margin_left_)
{
page_width -= attr_page.common_horizontal_margin_attlist_.fo_margin_left_->get_length().get_value_unit(odf_types::length::pt);
}
if (attr_page.common_horizontal_margin_attlist_.fo_margin_right_)
{
page_width -= attr_page.common_horizontal_margin_attlist_.fo_margin_right_->get_length().get_value_unit(odf_types::length::pt);
}
}
for (size_t i = 0; page_width > 0, i < columns->style_columns_.size(); i++)
{
odf_reader::style_column *col = dynamic_cast<odf_reader::style_column*>( columns->style_columns_[i].get());
if (!col) continue;
double percent = col->style_rel_width_ ? col->style_rel_width_->get_value() : 0;
if (percent > 0x7FFE)
{
//auto
break;
}
else
{
if (percent > 1000.) percent /= 100.;
double width = page_width * percent / 100.;
double space_end = col->fo_end_indent_ ? col->fo_end_indent_->get_value_unit(odf_types::length::pt) : 0;
double space_start = col->fo_start_indent_ ? col->fo_start_indent_->get_value_unit(odf_types::length::pt) : 0;
width -= space_end;
width -= space_start;
if (i < columns->style_columns_.size() - 1)
{
col = dynamic_cast<odf_reader::style_column*>(columns->style_columns_[i + 1].get());
space_start = col->fo_start_indent_ ? col->fo_start_indent_->get_value_unit(odf_types::length::pt) : 0;
}
width_space.push_back(std::make_pair(width, space_start + space_end));
}
}
}
}
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"w:cols")
{
CP_XML_ATTR(L"w:equalWidth", width_space.empty());
CP_XML_ATTR(L"w:num", count_columns);
CP_XML_ATTR(L"w:sep", sep_columns);
CP_XML_ATTR(L"w:space", 708);
for (size_t i = 0; i < width_space.size(); i++)
{
CP_XML_NODE(L"w:col")
{
CP_XML_ATTR(L"w:w", (int)(width_space[i].first * 20));
CP_XML_ATTR(L"w:space", (int)(width_space[i].second * 20));
}
}
}
}
}
bool docx_conversion_context::process_page_properties(std::wostream & strm)
{
if ( is_next_dump_page_properties() || get_section_context().get_last().is_dump_ )
{
std::wstring pageProperties = get_page_properties();
odf_reader::page_layout_instance * page_layout_instance_ = root()->odf_context().pageLayoutContainer().page_layout_by_name(pageProperties);
if (page_layout_instance_)
{
page_layout_instance_->docx_serialize(strm, *this);
}
else
{
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"w:sectPr")
{
process_section( CP_XML_STREAM(), NULL);
CP_XML_NODE(L"w:type")
{
CP_XML_ATTR(L"w:val", L"continuous");
}
}
}
}
next_dump_page_properties(false);
return true;
}
return false;
}
void docx_conversion_context::end_process_style_content(bool in_styles)
{
serialize_paragraph_style(output_stream(), automatic_parent_style_, in_styles);
if (automatic_parent_style_.empty())
styles_context_.docx_serialize_text_style( output_stream(), L"", text_tracked_context_.dumpRPr_);
}
void docx_conversion_context::serialize_paragraph_style(std::wostream & strm, const std::wstring & ParentId, bool in_styles)
//in_styles = true -> styles.xml
//for some reason the construct <pPr><rPr/></pPr><rPr/> "doesn't work" in the rPr part in ms2010 )
{
bool in_drawing = false;
if (get_drawing_context().get_current_shape() || get_drawing_context().get_current_frame())
{
in_drawing = true;
}
std::wstringstream & paragraph_style = get_styles_context().paragraph_nodes();
std::wstringstream & run_style = get_styles_context().text_style();
CP_XML_WRITER(strm)
{
////Tutor_Charlotte_Tutor_the_Entire_World_.odt
//if (get_section_context().dump_.empty() == false && (!ParentId.empty() || get_section_context().get().is_dump_ || in_header_)
// && !get_table_context().in_table() && !in_drawing)
//{//two sections in a row or if style is defined and can't push into headers !!!
// CP_XML_NODE(L"w:pPr")
// {
// CP_XML_STREAM() << get_section_context().dump_;
// get_section_context().dump_.clear();
// }
// finish_paragraph();
// start_paragraph();
//}
if (!paragraph_style.str().empty() || !ParentId.empty())
{
CP_XML_NODE(L"w:pPr")
{
if ( !get_table_context().in_table() && !in_drawing)
{
CP_XML_STREAM() << get_section_context().dump_;
get_section_context().dump_.clear();
}
if (!ParentId.empty())
{
CP_XML_NODE(L"w:pStyle")
{
CP_XML_ATTR(L"w:val", ParentId);
}
}
CP_XML_STREAM() << paragraph_style.str();
serialize_list_properties(CP_XML_STREAM());
if ((run_style.tellp() > 0 && in_styles == false) || !get_text_tracked_context().dumpRPrInsDel_.empty())
{
CP_XML_NODE(L"w:rPr")
{
CP_XML_STREAM() << get_text_tracked_context().dumpRPrInsDel_;
const std::wstring & test_str = run_style.str();
CP_XML_STREAM() << test_str;
}
get_text_tracked_context().dumpRPrInsDel_.clear();
}
if (!get_text_tracked_context().dumpPPr_.empty())
{
CP_XML_STREAM() << get_text_tracked_context().dumpPPr_;
get_text_tracked_context().dumpPPr_.clear();
}
}
}
}
}
void docx_conversion_context::start_automatic_style(const std::wstring & ParentId)
{
in_automatic_style_ = true;
automatic_parent_style_ = ParentId;
}
void docx_conversion_context::end_automatic_style()
{
in_automatic_style_ = false;
automatic_parent_style_.clear();
tabs_context_.clear();
current_outline_level_ = -1;
}
bool docx_conversion_context::in_automatic_style()
{
return in_automatic_style_;
}
void docx_conversion_context::push_text_properties(const odf_reader::style_text_properties* TextProperties)
{
state_.text_properties_stack_.push_back(TextProperties);
}
void docx_conversion_context::pop_text_properties()
{
state_.text_properties_stack_.pop_back();
}
odf_reader::style_paragraph_properties_ptr docx_conversion_context::current_paragraph_properties()
{
odf_reader::style_paragraph_properties_ptr cur;
if (paragraph_style_stack_.empty()) return cur;
if (odf_reader::style_instance* styleInst =
root()->odf_context().styleContainer().style_by_name(paragraph_style_stack_.back(), odf_types::style_family::Paragraph, process_headers_footers_))
{
odf_reader::paragraph_format_properties properties = odf_reader::calc_paragraph_properties_content(styleInst);
cur = boost::make_shared<odf_reader::style_paragraph_properties>();
cur->content_.apply_from(properties);
}
return cur;
}
odf_reader::style_text_properties_ptr docx_conversion_context::current_text_properties()
{
odf_reader::style_text_properties_ptr cur = boost::make_shared<odf_reader::style_text_properties>();
for (size_t i = 0; i < state_.text_properties_stack_.size(); i++)
{
if (state_.text_properties_stack_[i])
cur->content_.apply_from( state_.text_properties_stack_[i]->content_);
}
return cur;
}
void docx_conversion_context::set_page_break_after(int val)
{
page_break_after_ = val;
}
int docx_conversion_context::get_page_break_after()
{
return page_break_after_ ;
}
void docx_conversion_context::set_page_break(bool val)
{
page_break_ = val;
}
bool docx_conversion_context::get_page_break()
{
return page_break_;
}
void docx_conversion_context::set_page_break_before(int val)
{
page_break_before_ = val;
}
int docx_conversion_context::get_page_break_before()
{
return page_break_before_;
}
void docx_conversion_context::set_temp_style_name( const std::wstring& _name )
{
temp_name = _name;
}
std::wstring docx_conversion_context::get_temp_style_name() const
{
return temp_name;
}
void docx_conversion_context::add_page_properties(const std::wstring & StyleName)
{
section_context::_section & s = section_context_.get_last();
s.page_properties_.push_back( StyleName);
}
std::wstring docx_conversion_context::get_page_properties()
{
section_context::_section & s = section_context_.get_last();
if (s.page_properties_.size() > 1) return s.page_properties_[1];
else if (s.page_properties_.size() == 1) return s.page_properties_[0];
else return L"";
}
void docx_conversion_context::remove_page_properties()
{
section_context::_section & s = section_context_.get_last();
if (s.page_properties_.size() > 1)
{
//first common one (if exists) for the whole document - keep it
s.page_properties_.erase(s.page_properties_.begin() + 1, s.page_properties_.begin() + 2);
}
else if (s.page_properties_.size() == 1)
{
s.page_properties_.clear();
}
}
void docx_conversion_context::next_dump_page_properties(bool val)
{
if (process_headers_footers_ && val) return;
next_dump_page_properties_ = val;
if (val)
last_dump_page_properties(true);
}
bool docx_conversion_context::is_next_dump_page_properties()
{
return next_dump_page_properties_;
}
void docx_conversion_context::last_dump_page_properties(bool val)
{
last_dump_page_properties_ = val;
}
bool docx_conversion_context::is_last_dump_page_properties()
{
return last_dump_page_properties_;
}
void docx_conversion_context::start_text_list_style(const std::wstring & StyleName)
{
text_list_style_name_ = StyleName;
}
void docx_conversion_context::end_text_list_style()
{
text_list_style_name_ = L"";
}
std::wstring docx_conversion_context::get_text_list_style_name()
{
return text_list_style_name_;
}
void docx_conversion_context::start_list(const std::wstring & StyleName, bool Continue)
{
if (!StyleName.empty())
{
std::wstring name = StyleName;
if (Continue)
name = find_list_rename(name);
list_style_stack_.push_back(name);
}
else if (!list_style_stack_.empty())
list_style_stack_.push_back(list_style_stack_.back());
else
list_style_stack_.push_back(L"");
list_styles_occurances_[list_style_stack_.back()]++;
}
void docx_conversion_context::end_list()
{
list_style_stack_.pop_back();
}
std::wstring docx_conversion_context::current_list_style()
{
if (false == list_style_stack_.empty())
return list_style_stack_.back();
else
return L"";
}
static _CP_PTR(odf_reader::text_list_style) create_restarted_list_style(docx_conversion_context& context, const std::wstring& curStyleName, const std::wstring& newStyleName)
{
odf_reader::list_style_container& lists = context.root()->odf_context().listStyleContainer();
odf_reader::text_list_style* curStyle = lists.list_style_by_name(curStyleName);
_CP_PTR(odf_reader::text_list_style) newStyle = curStyle ? boost::make_shared<odf_reader::text_list_style>(*curStyle) :
boost::make_shared<odf_reader::text_list_style>();
newStyle->attr_.style_name_ = newStyleName;
const std::vector<std::wstring>& style_stack = context.get_list_style_stack();
for (const std::wstring& s : style_stack)
{
for (size_t i = 0; i < newStyle->content_.size() && i < style_stack.size() - 1; i++)
{
odf_reader::text_list_level_style_number* level_style_number =
dynamic_cast<odf_reader::text_list_level_style_number*>(newStyle->content_[i].get());
if (level_style_number)
level_style_number->number_attr_.text_start_value_ = context.get_list_style_occurances(s) + 1;
}
}
return newStyle;
}
void docx_conversion_context::start_list_item(bool restart)
{
first_element_list_item_ = true;
if (restart && !list_style_stack_.empty())
{
const std::wstring curStyleName = current_list_style();
const std::wstring newStyleName = curStyleName + std::to_wstring(new_list_style_number_++);
list_style_renames_[curStyleName] = newStyleName;
odf_reader::list_style_container & lists = root()->odf_context().listStyleContainer();
odf_reader::text_list_style * curStyle = lists.list_style_by_name(curStyleName);
_CP_PTR(odf_reader::text_list_style) newStyle = create_restarted_list_style(*this, curStyleName, newStyleName);
restarted_list_styles.push_back(newStyle);
lists.add_list_style(newStyle.get());
end_list();
start_list(newStyleName);
}
}
std::wstring docx_conversion_context::find_list_rename(const std::wstring & ListStyleName) const
{
std::wstring name = ListStyleName;
while (list_style_renames_.count(name) > 0)
name = list_style_renames_.at(name);
return name;
}
void docx_conversion_context::end_list_item()
{
}
int docx_conversion_context::process_text_attr(odf_reader::text::paragraph_attrs *Attr)
{
if ( Attr->text_style_name_.empty() ) return 0;
odf_reader::style_instance * styleInst =
root()->odf_context().styleContainer().style_by_name(Attr->text_style_name_, odf_types::style_family::Paragraph, process_headers_footers_);
if (!styleInst) return 0;
if (false == styleInst->is_automatic()) return 0;
odf_reader::style_content *styleContent = styleInst->content();
if (!styleContent) return 0;
push_text_properties(styleContent->get_style_text_properties());
return 1;
}
int docx_conversion_context::process_paragraph_style(_CP_OPT(std::wstring) style_name_ptr)
{
if (!style_name_ptr) return 0;
if (style_name_ptr->empty()) return 0;
std::wstring & style_name = *style_name_ptr;
if (odf_reader::style_instance * styleInst =
root()->odf_context().styleContainer().style_by_name(style_name, odf_types::style_family::Paragraph, process_headers_footers_))
{
double font_size = odf_reader::text_format_properties::process_font_size_impl(odf_types::font_size(odf_types::percent(100.0)), styleInst);
if (font_size > 0) current_fontSize.push_back(font_size);
process_page_break_after(styleInst);
if (styleInst->is_automatic())
{
if (odf_reader::style_content * styleContent = styleInst->content())
{
std::wstring id;
//office_element_ptr parent_tab_stops_;
if (const odf_reader::style_instance * parentStyleContent = styleInst->parent())
{
std::wstring parent_name = parentStyleContent->name();
id = styles_map_.get( parent_name, parentStyleContent->type() );
if (in_table_content_ && table_content_context_.empty_current_table_content_level_index())
{
table_content_context_.set_current_level(parent_name);
}
}
start_automatic_style(id);
calc_tab_stops(styleInst, get_tabs_context());
//extracts rtl from style chain !! - can't just write it in inherited style !!
odf_reader::paragraph_format_properties properties = odf_reader::calc_paragraph_properties_content(styleInst);
if (properties.style_writing_mode_)
{
odf_types::writing_mode::type type = properties.style_writing_mode_->get_type();
switch(type)
{
case odf_types::writing_mode::RlTb:
case odf_types::writing_mode::TbRl:
case odf_types::writing_mode::Rl:
set_rtl(true);
break;
default:
set_rtl(false);
}
}
styleContent->docx_convert(*this);
end_automatic_style();
//push_text_properties(styleContent->get_style_text_properties());
return 1;
}
}
else
{
const std::wstring id = styles_map_.get( styleInst->name(), styleInst->type() );
output_stream() << L"<w:pPr>";
output_stream() << L"<w:pStyle w:val=\"" << id << L"\" />";
if (!get_text_tracked_context().dumpPPr_.empty())
{
output_stream() << get_text_tracked_context().dumpPPr_;
get_text_tracked_context().dumpPPr_.clear();
}
serialize_list_properties(output_stream());
if (!get_text_tracked_context().dumpRPrInsDel_.empty())
{
output_stream() << L"<w:rPr>";
output_stream() << get_text_tracked_context().dumpRPrInsDel_;
get_text_tracked_context().dumpRPrInsDel_.clear();
output_stream() << L"</w:rPr>";
}
output_stream() << L"</w:pPr>";
return 2;
}
}
return 0;
}
int docx_conversion_context::process_paragraph_attr(odf_reader::text::paragraph_attrs *Attr)
{
if (!Attr) return 0;
bool in_drawing = false;
if (get_drawing_context().get_current_shape() || get_drawing_context().get_current_frame())
{
in_drawing = true;
}
if (false == Attr->text_style_name_.empty())
{
if (in_table_content_ && Attr->text_style_name_.empty())
{
table_content_context_.set_current_level(Attr->text_style_name_);
}
if (odf_reader::style_instance * styleInst =
root()->odf_context().styleContainer().style_by_name(Attr->text_style_name_, odf_types::style_family::Paragraph, process_headers_footers_)
)
{
double font_size = odf_reader::text_format_properties::process_font_size_impl(odf_types::font_size(odf_types::percent(100.0)), styleInst);
if (font_size > 0) current_fontSize.push_back(font_size);
_CP_OPT(int) outline_level = calc_outline_level(Attr->outline_level_, styleInst);
process_page_break_after(styleInst);
if (styleInst->is_automatic())
{
if (odf_reader::style_content * styleContent = styleInst->content())
{
std::wstring id;
//office_element_ptr parent_tab_stops_;
if (const odf_reader::style_instance * parentStyleContent = styleInst->parent())
{
std::wstring parent_name = parentStyleContent->name();
id = styles_map_.get( parent_name, parentStyleContent->type() );
if (in_table_content_ && table_content_context_.empty_current_table_content_level_index())
{
table_content_context_.set_current_level(parent_name);
}
}
start_automatic_style(id);
calc_tab_stops(styleInst, get_tabs_context());
//extracts rtl from style chain !! - can't just write it in inherited style !!
odf_reader::paragraph_format_properties properties = odf_reader::calc_paragraph_properties_content(styleInst);
if (properties.style_writing_mode_)
{
odf_types::writing_mode::type type = properties.style_writing_mode_->get_type();
switch(type)
{
case odf_types::writing_mode::RlTb:
case odf_types::writing_mode::TbRl:
case odf_types::writing_mode::Rl:
set_rtl(true);
break;
default:
set_rtl(false);
}
}
get_styles_context().start_process_style(styleInst);
if (outline_level)
{
set_outline_level(*outline_level);
}
styleContent->docx_convert(*this);
get_styles_context().end_process_style();
end_automatic_style();
push_text_properties(styleContent->get_style_text_properties());
if (!get_section_context().dump_.empty()
&& !get_table_context().in_table()
&& (get_process_note() == oox::docx_conversion_context::noNote)
&& !in_drawing)
{
output_stream() << L"<w:pPr>";
if (is_paragraph_header() )
{
output_stream() << get_section_context().dump_;
get_section_context().dump_.clear();
output_stream() << L"</w:pPr>";
finish_paragraph();
start_paragraph();
//process_paragraph_style(Context.get_current_paragraph_style()); ??
//if ((Attr->outline_level_) && (*Attr->outline_level_ > 0))
if ((outline_level) && (*outline_level < 10))
{
output_stream() << L"<w:pPr>";
output_stream() << L"<w:outlineLvl w:val=\"" << *outline_level << L"\"/>";
output_stream() << L"</w:pPr>";
}
}
else
{
output_stream() << get_section_context().dump_;
get_section_context().dump_.clear();
//if ((Attr->outline_level_) && (*Attr->outline_level_ > 0))
if ((outline_level) && (*outline_level < 10))
{
output_stream() << L"<w:outlineLvl w:val=\"" << *outline_level << L"\"/>";
}
output_stream() << L"</w:pPr>";
}
}
return 1;
}
}
else
{
const std::wstring id = styles_map_.get( styleInst->name(), styleInst->type() );
output_stream() << L"<w:pPr>";
//todooo clean up
if (!get_section_context().dump_.empty()
&& !get_table_context().in_table()
&& (get_process_note() == oox::docx_conversion_context::noNote)
&& !in_drawing)
{
if (is_paragraph_header() )
{
output_stream() << get_section_context().dump_;
get_section_context().dump_.clear();
output_stream() << L"</w:pPr>";
finish_paragraph();
start_paragraph();
output_stream() << L"<w:pPr>";
}
else
{
output_stream() << get_section_context().dump_;
get_section_context().dump_.clear();
}
}
output_stream() << L"<w:pStyle w:val=\"" << id << L"\" />";
if (!get_text_tracked_context().dumpPPr_.empty())
{
output_stream() << get_text_tracked_context().dumpPPr_;
get_text_tracked_context().dumpPPr_.clear();
}
serialize_list_properties(output_stream());
//if ((Attr->outline_level_) && (*Attr->outline_level_ > 0))
if ( outline_level && status_para[id] == false )
{
odf_reader::list_style_container & list_styles = root()->odf_context().listStyleContainer();
if (/*outline_level < 9 && */list_style_stack_.empty() && list_styles.outline_style() && !get_table_context().in_table())
{
output_stream() << L"<w:numPr>";
output_stream() << L"<w:ilvl w:val=\"" << *outline_level - 1 << L"\"/>";
output_stream() << L"<w:numId w:val=\"" << list_styles.id_outline() << L"\"/>"; // check bug 51965
output_stream() << L"</w:numPr>";
}
output_stream() << L"<w:outlineLvl w:val=\"" << *outline_level << L"\"/>";
}
if (!get_text_tracked_context().dumpRPrInsDel_.empty())
{
output_stream() << L"<w:rPr>";
output_stream() << get_text_tracked_context().dumpRPrInsDel_;
get_text_tracked_context().dumpRPrInsDel_.clear();
output_stream() << L"</w:rPr>";
}
output_stream() << L"</w:pPr>";
return 2;
}
}
}
if (!get_section_context().dump_.empty()
&& !get_table_context().in_table()
&& (get_process_note() == oox::docx_conversion_context::noNote)
&& !in_drawing)
{
output_stream() << L"<w:pPr>";
output_stream() << get_section_context().dump_;
get_section_context().dump_.clear();
//todooo find out if headers without styles and properties are real
output_stream() << L"</w:pPr>";
return 3;
}
return 0;
}
void docx_conversion_context::process_page_break_after(const odf_reader::style_instance * styleInst)
{
if (styleInst)
{
const odf_reader::style_instance * inst = styleInst;
while (inst)
{
if (inst->content() && inst->content()->get_style_paragraph_properties())
{
_CP_OPT(odf_types::fo_break) fo_break_val = inst->content()->get_style_paragraph_properties()->content_.fo_break_after_;
if (fo_break_val)
{
set_page_break_after(fo_break_val->get_type());
break;
}
}
inst = inst->parent();
}
}
}
void docx_conversion_context::serialize_list_properties(std::wostream & strm)
{
if (list_style_stack_.empty()) return;
if (first_element_list_item_)
{
const int id = root()->odf_context().listStyleContainer().id_by_name( current_list_style() );
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"w:numPr")
{
CP_XML_NODE(L"w:ilvl")
{
CP_XML_ATTR(L"w:val", (list_style_stack_.size() - 1));
}
CP_XML_NODE(L"w:numId")
{
CP_XML_ATTR(L"w:val", id );
}
}
}
first_element_list_item_ = false;
}
}
void docx_conversion_context::set_drawing_text_props (const std::wstring &props)
{
get_styles_context().text_style_ext() = props;
}
void docx_conversion_context::add_delayed_element(odf_reader::office_element * Elm)
{
delayed_elements_.push_back(Elm);
}
void docx_conversion_context::docx_convert_delayed()
{
if (delayed_elements_.empty()) return;
if (delayed_converting_) return; //otherwise infinite loop
if (get_drawing_context().get_current_level() > 0 )
return; //nested frame
delayed_converting_ = true;
while(!delayed_elements_.empty())
{
odf_reader::office_element * elm = delayed_elements_.front();
elm->docx_convert(*this);
delayed_elements_.erase(delayed_elements_.begin(), delayed_elements_.begin() + 1);
}
delayed_converting_=false;
}
void section_context::add_section(const std::wstring & SectionName, const std::wstring & Style, const std::wstring & PageProperties)
{
_section newSec(SectionName, Style, PageProperties );
sections_.push_back(newSec);
}
section_context::_section & section_context::get_first()
{
if (sections_.empty())
return main_section_;
else
return sections_[0];
}
section_context::_section & section_context::get_last()
{
if (sections_.empty())
return main_section_;
else
return sections_.back();
}
void section_context::remove_section()
{
if (sections_.empty()) return;
sections_.pop_back();
//sections_.erase(sections_.begin(), sections_.begin() + 1);
if (sections_.empty())
{
//after section markup ends and main section resumes, break is needed (even if page settings don't change)
//currently break on current page
//todooo check - maybe if next is a heading - break
main_section_.is_dump_ = false;
}
}
namespace
{
// Header/Footer processing
// convert header/footer content and save result as string
void process_one_header_footer(docx_conversion_context & Context, const std::wstring & styleName, odf_reader::office_element *elm, headers_footers::Type type)
{
if (!elm) return;
boost::shared_ptr<std::wstringstream> newXml( new std::wstringstream() );
Context.set_stream_man( streams_man::create(*newXml) );
elm->docx_convert(Context);
const std::wstring & dbgStr = newXml->str();
//merge mediaitems if any, add rels and reset them for main document.
rels internal_rels;
Context.get_mediaitems()->dump_rels(internal_rels, oox::header_footer_place);
Context.dump_hyperlinks(internal_rels, oox::header_footer_place);
Context.get_headers_footers().add(styleName, dbgStr, type, internal_rels);
}
}
void docx_conversion_context::set_settings_property(const odf_reader::_property & prop)
{
settings_properties_.push_back(prop);
}
std::vector<odf_reader::_property> & docx_conversion_context::get_settings_properties()
{
return settings_properties_;
}
void docx_conversion_context::process_headers_footers()
{
odf_reader::odf_document * doc = root();
if (!doc)
return;
process_headers_footers_ = true;
odf_reader::odf_read_context & context = doc->odf_context();
odf_reader::page_layout_container & pageLayouts = context.pageLayoutContainer();
// iterate through all page layouts
std::vector<odf_reader::style_master_page*> & master_pages = pageLayouts.master_pages();
bool bOddEvenPages = false;
for (size_t i = 0; i < master_pages.size(); i++)
{
if (master_pages[i]->style_header_left_ || master_pages[i]->style_footer_left_)
bOddEvenPages = true;
}
if (bOddEvenPages)
{
set_settings_property(odf_reader::_property(L"evenAndOddHeaders", true));
}
for (size_t i = 0; i < master_pages.size(); i++)
{
const std::wstring & styleName = master_pages[i]->attlist_.style_name_.get_value_or( L"" );
const std::wstring masterPageNameLayout =context.pageLayoutContainer().page_layout_name_by_style(styleName);
add_page_properties(masterPageNameLayout);
process_one_header_footer(*this, styleName, master_pages[i]->style_header_.get(), headers_footers::header);
process_one_header_footer(*this, styleName, master_pages[i]->style_footer_.get(), headers_footers::footer );
process_one_header_footer(*this, styleName, master_pages[i]->style_header_first_.get(), headers_footers::headerFirst);
process_one_header_footer(*this, styleName, master_pages[i]->style_footer_first_.get(), headers_footers::footerFirst );
process_one_header_footer(*this, styleName, master_pages[i]->style_header_left_.get(), headers_footers::headerLeft );
process_one_header_footer(*this, styleName, master_pages[i]->style_footer_left_.get(), headers_footers::footerLeft );
if (bOddEvenPages && !master_pages[i]->style_header_left_)
process_one_header_footer(*this, styleName, master_pages[i]->style_header_.get(), headers_footers::headerLeft);
if (bOddEvenPages && !master_pages[i]->style_footer_left_)
process_one_header_footer(*this, styleName, master_pages[i]->style_footer_.get(), headers_footers::footerLeft );
if (!master_pages[i]->style_header_ && !master_pages[i]->style_footer_ && !master_pages[i]->style_header_first_ && !master_pages[i]->style_footer_first_
&& !master_pages[i]->style_header_left_ && !master_pages[i]->style_footer_left_)
{
//disabled headers/footers
rels rels_;
get_headers_footers().add(styleName, L"", headers_footers::none, rels_);
}
remove_page_properties();
}
process_headers_footers_ = false;
}
bool docx_conversion_context::set_master_page_name(const std::wstring & MasterPageName)
{
if (current_master_page_name_ == MasterPageName) return false;
current_master_page_name_ = MasterPageName;
return true;
}
const std::wstring & docx_conversion_context::get_master_page_name() const
{
return current_master_page_name_;
}
std::wstring notes_context::add(const std::wstring & Content, const std::wstring & Id)
{
instances_map & map = (type_ == odf_types::noteclass::Endnote) ? instances_endnotes_ : instances_footnotes_;
instance_ptr inst = instance_ptr( new instance(Id, Content) );
map[Id] = inst;
return Id;
}
std::wstring notes_context::next_id()
{
instances_map & map = (type_ == odf_types::noteclass::Endnote) ? instances_endnotes_ : instances_footnotes_;
const std::wstring s = std::to_wstring(map.size() + 1);
return s;
}
void notes_context::dump_rels(rels & Rels) const
{
if (instances_footnotes_.size())
{
Rels.add( relationship(L"rFNId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes", L"footnotes.xml", L"") );
}
if (instances_endnotes_.size())
{
Rels.add( relationship(L"rENId1", L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes", L"endnotes.xml", L"") );
}
}
void docx_conversion_context::add_note_reference ()
{
if (current_process_note_ == footNote || current_process_note_ == endNote)
{
add_element_to_run(_T(""));
output_stream() << ((current_process_note_ == footNote) ? L"<w:footnoteRef />" : L"<w:endnoteRef />");
finish_run();
current_process_note_ = (NoteType) (current_process_note_ + 1); //add ref set
}
}
typedef std::map<std::wstring, text_tracked_context::_state>::iterator map_changes_iterator;
void docx_conversion_context::start_text_changes (const std::wstring &id)
{
text_tracked_context::_state &state_add = text_tracked_context_.get_tracked_change(id);
if (state_add.id != id) return;
map_current_changes_.insert(std::pair<std::wstring, text_tracked_context::_state> (id, state_add));
if ( state_add.type == 1 || state_add.type == 2 )
{
map_changes_iterator it = map_current_changes_.find(id);
text_tracked_context::_state &state = it->second;
if (state_.in_paragraph_)
{
std::wstring format_change = L" w:date=\"" + state.date + L"\" w:author=\"" + XmlUtils::EncodeXmlString(state.author) + L"\"";
finish_run();
state.in_drawing = get_drawing_state_content();
if (state.oox_id == 0)
{
state.oox_id = current_id_changes++;
}
if (state.type == 1 && !state.active)
{
output_stream() << L"<w:ins" << format_change << L" w:id=\"" << std::to_wstring(state.oox_id) << L"\">";
state.active = true;
state.in_para = true;
}
if (state.type == 2)
{
for (size_t i = 0; i < state.content.size(); i++)
{
output_stream() << L"<w:del" << format_change << L" w:id=\"" << std::to_wstring(state.oox_id) << L"\">";
output_stream() << state.content[i];
output_stream() << L"</w:del>";
}
map_current_changes_.erase(it);
}
}
else
{
state.in_drawing = get_drawing_state_content();
state.out_active = true;
}
}
}
void docx_conversion_context::start_changes(bool in_para)
{
if (map_current_changes_.empty()) return;
if (current_process_comment_) return;
if (current_process_note_) return;
text_tracked_context_.dumpPPr_.clear();
text_tracked_context_.dumpRPr_.clear();
text_tracked_context_.dumpRPrInsDel_.clear();
text_tracked_context_.dumpTcPr_.clear();
text_tracked_context_.dumpTblPr_.clear();
for (map_changes_iterator it = map_current_changes_.begin(); it != map_current_changes_.end(); ++it)
{
text_tracked_context::_state &state = it->second;
if (state.type == 0) continue; //unknown change ... todooo
if (state.active) continue;
state.in_para = in_para;
std::wstring change_attr;
change_attr += L" w:date=\"" + state.date + L"\"";
change_attr += L" w:author=\"" + XmlUtils::EncodeXmlString(state.author) + L"\"";
if (state.oox_id == 0)
{
state.oox_id = current_id_changes++;
}
change_attr += L" w:id=\"" + std::to_wstring(state.oox_id) + L"\"";
if (state.out_active)
{
if (state.type == 1)
{
output_stream() << L"<w:ins" + change_attr + L">";
state.active = true;
}
if (state.type == 2)
{
output_stream() << L"<w:del" + change_attr + L">";
state.active = true;
}
}
else
{
if (state.type == 1)
{
text_tracked_context_.dumpRPrInsDel_ = L"<w:ins" + change_attr + L"/>";
}
if (state.type == 2)
{
text_tracked_context_.dumpRPrInsDel_ = L"<w:del" + change_attr + L"/>";
}
if (state.type == 3 && false == state.style_name.empty())
{
odf_reader::style_instance * styleInst = root()->odf_context().styleContainer().style_by_name(state.style_name, odf_types::style_family::Paragraph, false);
if (styleInst)
{
odf_reader::style_paragraph_properties * props = styleInst->content()->get_style_paragraph_properties();
odf_reader::style_text_properties * props_text = styleInst->content()->get_style_text_properties();
text_tracked_context_.dumpPPr_ += L"<w:pPrChange" + change_attr;
if (props)
{
props->docx_convert(*this);
text_tracked_context_.dumpPPr_ += get_styles_context().paragraph_attr().str();
}
text_tracked_context_.dumpPPr_ += L">";
if (props) text_tracked_context_.dumpPPr_ += get_styles_context().paragraph_nodes().str();
if (props_text)
{
props_text->docx_convert(*this);
text_tracked_context_.dumpPPr_ += L"<w:rPr>";
text_tracked_context_.dumpPPr_ += get_styles_context().text_style().str();
text_tracked_context_.dumpPPr_ += L"</w:rPr>";
}
text_tracked_context_.dumpPPr_ += L"</w:pPrChange>";
}
else if (styleInst = root()->odf_context().styleContainer().style_by_name(state.style_name, odf_types::style_family::Text, false))
{
text_tracked_context_.dumpRPr_ = L"<w:rPrChange" + change_attr + L">";
odf_reader::style_text_properties * props = NULL;
props = styleInst->content()->get_style_text_properties();
if (props)
{
props->docx_convert(*this);
text_tracked_context_.dumpRPr_ += get_styles_context().text_style().str();
}
text_tracked_context_.dumpRPr_ += L"</w:rPrChange>";
}
else if (styleInst = root()->odf_context().styleContainer().style_by_name(state.style_name, odf_types::style_family::Table, false))
{
text_tracked_context_.dumpTblPr_ = L"<w:TblPrChange" + change_attr + L">";
odf_reader::style_table_properties * props = styleInst->content()->get_style_table_properties();
odf_reader::style_table_cell_properties * props_cell = styleInst->content()->get_style_table_cell_properties();
if (props)
{
props->docx_convert(*this);
text_tracked_context_.dumpTblPr_ += get_styles_context().table_style().str();
}
text_tracked_context_.dumpTblPr_ += L"</w:TblPrChange>";
}
else if (styleInst = root()->odf_context().styleContainer().style_by_name(state.style_name, odf_types::style_family::TableCell, false))
{
text_tracked_context_.dumpTcPr_ = L"<w:TcPrChange" + change_attr + L">";
odf_reader::style_table_cell_properties * props = styleInst->content()->get_style_table_cell_properties();
if (props)
{
props->docx_convert(*this);
text_tracked_context_.dumpTcPr_ += get_styles_context().table_style().str();
}
text_tracked_context_.dumpTcPr_ += L"</w:TcPrChange>";
}
}
else if (state.type == 3 && state.style_name.empty())
{
if (state_.in_run_)
text_tracked_context_.dumpRPr_ += L"<w:rPrChange" + change_attr + L"/>";
else
text_tracked_context_.dumpPPr_ += L"<w:pPrChange" + change_attr + L"/>";
}
}
}
}
void docx_conversion_context::end_changes(bool in_para)
{
if (current_process_comment_) return;
if (current_process_note_) return;
for (map_changes_iterator it = map_current_changes_.begin(); it != map_current_changes_.end(); ++it)
{
text_tracked_context::_state &state = it->second;
if (state.type == 0) continue; //unknown change ... libra format change skip
if (state.type == 3) continue;
if (!state.active) continue;
if (state.in_para != in_para) continue;
if (state.in_drawing != get_drawing_state_content())
continue;
if (state.type == 1) output_stream() << L"</w:ins>";
if (state.type == 2) output_stream() << L"</w:del>";
state.active = false;
}
text_tracked_context_.dumpTcPr_.clear();
text_tracked_context_.dumpTblPr_.clear();
text_tracked_context_.dumpRPrInsDel_.clear();
text_tracked_context_.dumpPPr_.clear();
text_tracked_context_.dumpRPr_.clear();
}
void docx_conversion_context::end_text_changes (const std::wstring &id)
{
if (map_current_changes_.empty()) return;
map_changes_iterator it = map_current_changes_.find(id);
if (it == map_current_changes_.end()) return;
text_tracked_context::_state &state = it->second;
if (state.active)
{
if (state_.in_paragraph_)
finish_run();
if (state.type == 1) output_stream() << L"</w:ins>";
if (state.type == 2) output_stream() << L"</w:del>";
}
map_current_changes_.erase(it);
}
void docx_conversion_context::add_user_field(const std::wstring & name, const std::wstring & value)
{
map_user_fields.insert(std::make_pair(name, value));
}
std::wstring docx_conversion_context::get_user_field(const std::wstring & name)
{
std::map<std::wstring, std::wstring>::iterator pFind = map_user_fields.find(name);
return pFind != map_user_fields.end() ? pFind->second : L"";
}
void docx_conversion_context::add_jsaProject(const std::string &content)
{
if (content.empty()) return;
output_document_->get_word_files().add_jsaProject(content);
output_document_->get_content_types_file().add_or_find_default(L"bin");
}
const std::wstring docx_conversion_context::get_current_fontName()
{
auto textProps = current_text_properties();
if( textProps )
{
if( textProps->content_.fo_font_family_ )
{
return *textProps->content_.fo_font_family_;
}
else if( textProps->content_.style_font_name_ )
{
return *textProps->content_.style_font_name_;
}
}
return L"";
}
const double docx_conversion_context::get_current_fontSize_from_default_style()
{
auto defaultStyle = root()->odf_context().styleContainer().style_default_by_type(odf_types::style_family::Paragraph);
if( defaultStyle )
{
const auto content = defaultStyle->content();
if( content )
{
const auto textProps = content->get_style_text_properties();
if( textProps && textProps->content_.fo_font_size_ )
{
return textProps->content_.fo_font_size_->get_length().get_value_unit(odf_types::length::pt);
}
}
}
return 0.0;
}
}
}