/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmWIXRichTextFormatWriter.h" #include "cmVersion.h" cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( std::string const& filename) : File(filename.c_str(), std::ios::binary) { StartGroup(); WriteHeader(); WriteDocumentPrefix(); } cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() { EndGroup(); /* I haven't seen this in the RTF spec but * wordpad terminates its RTF like this */ File << "\r\n"; File.put(0); } void cmWIXRichTextFormatWriter::AddText(std::string const& text) { using rtf_byte_t = unsigned char; for (size_t i = 0; i < text.size(); ++i) { rtf_byte_t c = rtf_byte_t(text[i]); switch (c) { case '\\': File << "\\\\"; break; case '{': File << "\\{"; break; case '}': File << "\\}"; break; case '\n': File << "\\par\r\n"; break; case '\r': continue; default: { if (c <= 0x7F) { File << c; } else { if (c <= 0xC0) { EmitInvalidCodepoint(c); } else if (c < 0xE0 && i + 1 < text.size()) { EmitUnicodeCodepoint((text[i + 1] & 0x3F) | ((c & 0x1F) << 6)); i += 1; } else if (c < 0xF0 && i + 2 < text.size()) { EmitUnicodeCodepoint((text[i + 2] & 0x3F) | ((text[i + 1] & 0x3F) << 6) | ((c & 0xF) << 12)); i += 2; } else if (c < 0xF8 && i + 3 < text.size()) { EmitUnicodeCodepoint( (text[i + 3] & 0x3F) | ((text[i + 2] & 0x3F) << 6) | ((text[i + 1] & 0x3F) << 12) | ((c & 0x7) << 18)); i += 3; } else { EmitInvalidCodepoint(c); } } } break; } } } void cmWIXRichTextFormatWriter::WriteHeader() { ControlWord("rtf1"); ControlWord("ansi"); ControlWord("ansicpg1252"); ControlWord("deff0"); ControlWord("deflang1033"); WriteFontTable(); WriteColorTable(); WriteGenerator(); } void cmWIXRichTextFormatWriter::WriteFontTable() { StartGroup(); ControlWord("fonttbl"); StartGroup(); ControlWord("f0"); ControlWord("fswiss"); ControlWord("fcharset0 Consolas;"); EndGroup(); EndGroup(); } void cmWIXRichTextFormatWriter::WriteColorTable() { StartGroup(); ControlWord("colortbl ;"); ControlWord("red255"); ControlWord("green0"); ControlWord("blue0;"); ControlWord("red0"); ControlWord("green255"); ControlWord("blue0;"); ControlWord("red0"); ControlWord("green0"); ControlWord("blue255;"); EndGroup(); } void cmWIXRichTextFormatWriter::WriteGenerator() { StartGroup(); NewControlWord("generator"); File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");"; EndGroup(); } void cmWIXRichTextFormatWriter::WriteDocumentPrefix() { ControlWord("viewkind4"); ControlWord("uc1"); ControlWord("pard"); ControlWord("f0"); ControlWord("fs14"); } void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword) { File << '\\' << keyword; } void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword) { File << "\\*\\" << keyword; } void cmWIXRichTextFormatWriter::StartGroup() { File.put('{'); } void cmWIXRichTextFormatWriter::EndGroup() { File.put('}'); } void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c) { // Do not emit byte order mark (BOM) if (c == 0xFEFF) { return; } if (c <= 0xFFFF) { EmitUnicodeSurrogate(c); } else { c -= 0x10000; EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800); EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00); } } void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c) { ControlWord("u"); if (c <= 32767) { File << c; } else { File << (c - 65536); } File << '?'; } void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c) { ControlWord("cf1 "); File << "[INVALID-BYTE-" << c << ']'; ControlWord("cf0 "); }