diff options
Diffstat (limited to 'Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx')
-rw-r--r-- | Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx new file mode 100644 index 0000000..2c99a22 --- /dev/null +++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx @@ -0,0 +1,186 @@ +/* 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) +{ + typedef unsigned char rtf_byte_t; + + 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("deflang1031"); + + WriteFontTable(); + WriteColorTable(); + WriteGenerator(); +} + +void cmWIXRichTextFormatWriter::WriteFontTable() +{ + StartGroup(); + ControlWord("fonttbl"); + + StartGroup(); + ControlWord("f0"); + ControlWord("fswiss"); + ControlWord("fcharset0 Arial;"); + 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("fs20"); +} + +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; + } else 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-" << int(c) << "]"; + ControlWord("cf0 "); +} |