/* * Some of this code is based in the ODT output of OpenOffice.org 2 * http://books.evc-cit.info/odbook/book.html was also really helpful */ #include "ODTExporter.h" #include #include #include #include #include #include using std::strlen; using std::ostringstream; using std::hex; using std::setw; using std::setfill; using std::uppercase; using std::size_t; namespace { // Helper function to convert i to a string inline string to_string(int i) { ostringstream ostr; ostr << i; return ostr.str(); } // Helper function that returns a number of spaces as or " " and updates the index // When called, str[*index] must be a space // If force is true, it'll return in the form even if it's one space inline string fix_spaces(const char *str, size_t *index, size_t max, bool force = false) { int counter = 0; while (*index < max && str[*index] == ' ') { ++counter; *index += 2; } *index -= 2; if (counter == 1 && !force) { return string(" "); } return string(""); } }; const char *ODTExporter::ODTManifestFile = "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" ""; const char *ODTExporter::ODTMetaFile = "\n" "\n" " \n" " Code::Blocks Source Exporter plugin\n" " Source file exported from Code::Blocks Source Exporter plugin\n" " \n" ""; const char *ODTExporter::ODTMIMETypeFile = "application/vnd.oasis.opendocument.text"; const char *ODTExporter::ODTSettingsFile = "\n" "\n" "\n" ""; const char *ODTExporter::ODTStylesFileBEG = "\n" "\n"; string ODTExporter::ODTStylesFileMID(wxZipOutputStream &zout) { static const char *t1 = "\n" " \n" "\n" "\n" "\n" " \n" "\n"; string theFont("Courier New"); string thePt("8"); wxString fontstring = ConfigManager::Get()->Read(_T("/editor/font"), wxEmptyString); if (!fontstring.IsEmpty()) { wxFont tmpFont; wxNativeFontInfo nfi; nfi.FromString(fontstring); tmpFont.SetNativeFontInfo(nfi); thePt = to_string(tmpFont.GetPointSize()); wxString faceName = tmpFont.GetFaceName(); if (!faceName.IsEmpty()) { theFont = string(faceName.c_str()); } } zout.Write(t1, strlen(t1)); zout.Write(theFont.c_str(), theFont.size()); zout.Write(t2, strlen(t2)); zout.Write(theFont.c_str(), theFont.size()); zout.Write(t3, strlen(t3)); zout.Write(theFont.c_str(), theFont.size()); zout.Write(t4, strlen(t4)); zout.Write(thePt.c_str(), thePt.size()); zout.Write(t5, strlen(t5)); return theFont; } const char *ODTExporter::ODTStylesFileEND = "\n" ""; const char *ODTExporter::ODTContentFileBEG = "\n" "\n" "\n" "\n" "\n" "\n"; const char *ODTExporter::ODTContentFileEND = "\n" "\n" ""; void ODTExporter::ODTCreateDirectoryStructure(wxZipOutputStream &zout) { zout.PutNextEntry(_T("META-INF/")); zout.PutNextEntry(_T("Thumbnails/")); zout.PutNextEntry(_T("Pictures/")); zout.PutNextEntry(_T("Configurations2/")); } void ODTExporter::ODTCreateCommonFiles(wxZipOutputStream &zout) { zout.PutNextEntry(_T("META-INF/manifest.xml")); zout.Write(ODTManifestFile, strlen(ODTManifestFile)); zout.PutNextEntry(_T("meta.xml")); zout.Write(ODTMetaFile, strlen(ODTMetaFile)); zout.PutNextEntry(_T("mimetype")); zout.Write(ODTMIMETypeFile, strlen(ODTMIMETypeFile)); zout.PutNextEntry(_T("settings.xml")); zout.Write(ODTSettingsFile, strlen(ODTSettingsFile)); } void ODTExporter::ODTCreateStylesFile(wxZipOutputStream &zout, const EditorColorSet *color_set, HighlightLanguage lang) { zout.PutNextEntry(_T("styles.xml")); zout.Write(ODTStylesFileBEG, strlen(ODTStylesFileBEG)); string fontName = ODTStylesFileMID(zout); if (lang != HL_NONE) { const int count = const_cast(color_set)->GetOptionCount(lang); for (int i = 0; i < count; ++i) { OptionColor *optc = const_cast(color_set)->GetOptionByIndex(lang, i); if (!optc->isStyle) { continue; } ostringstream ostr; ostr << "value << "\" style:family=\"text\">\n" << " (optc->fore.Red()) << setw(2) << static_cast(optc->fore.Green()) << setw(2) << static_cast(optc->fore.Blue()) << "\""; if (optc->back.Ok()) { ostr << "\n fo:background-color=\"#" << setw(2) << static_cast(optc->back.Red()) << setw(2) << static_cast(optc->back.Green()) << setw(2) << static_cast(optc->back.Blue()) << "\""; } if (optc->bold) { ostr << "\n fo:font-weight=\"bold\""; } if (optc->italics) { ostr << "\n fo:font-style=\"italic\""; } if (optc->underlined) { ostr << "\n style:text-underline-style=\"solid\"" << "\n style:text-underline-width=\"normal\"" << "\n style:text-underline-color=\"font-color\"" << "\n style:text-underline-mode=\"skip-white-space\""; } ostr << " />\n" << "\n"; zout.Write(ostr.str().c_str(), ostr.str().size()); } } zout.Write(ODTStylesFileEND, strlen(ODTStylesFileEND)); } void ODTExporter::ODTCreateContentFile(wxZipOutputStream &zout, const wxMemoryBuffer &styled_text) { const char *buffer = reinterpret_cast(styled_text.GetData()); const size_t buffer_size = styled_text.GetDataLen(); zout.PutNextEntry(_T("content.xml")); zout.Write(ODTContentFileBEG, strlen(ODTContentFileBEG)); if (buffer_size) { char current_style = buffer[1]; string content(""); size_t first = 0; if (buffer_size > 0 && buffer[0] == ' ') { content += fix_spaces(buffer, &first, buffer_size, true); } if (current_style != 0) { content += string(""); } for (size_t i = first; i < buffer_size; i += 2) { if (buffer[i + 1] != current_style) { if (!isspace(buffer[i])) { if (current_style != 0) { content += string(""); } current_style = buffer[i + 1]; if (current_style != 0) { content += string(""); } } } switch (buffer[i]) { case '<': content += "<"; break; case '>': content += ">"; break; case '&': content += "&"; break; case '\'': content += "'"; break; case '"': content += """; break; case ' ': content += fix_spaces(buffer, &i, buffer_size); break; case '\r': break; case '\n': if (current_style != 0) { content += string(""); current_style = 0; } content += "\n"; content += ""; if (i + 2 < buffer_size && buffer[i + 2] == ' ') { i += 2; content += fix_spaces(buffer, &i, buffer_size, true); } break; default: content += buffer[i]; break; } } if (current_style != 0) { content += string(""); } content += "\n"; zout.Write(content.c_str(), content.size()); } zout.Write(ODTContentFileEND, strlen(ODTContentFileEND)); } void ODTExporter::Export(const wxString &filename, const wxString &title, const wxMemoryBuffer &styled_text, const EditorColorSet *color_set) { HighlightLanguage lang = const_cast(color_set)->GetLanguageForFilename(title); wxFileOutputStream file(filename); wxZipOutputStream zout(file); ODTCreateDirectoryStructure(zout); ODTCreateCommonFiles(zout); ODTCreateStylesFile(zout, color_set, lang); ODTCreateContentFile(zout, styled_text); }