| /* 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; |
| } 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 "); |
| } |