1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 file Copyright.txt or https://cmake.org/licensing for details. */ 3 #include "cmWIXRichTextFormatWriter.h" 4 5 #include "cmVersion.h" 6 cmWIXRichTextFormatWriter(std::string const & filename)7cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( 8 std::string const& filename) 9 : File(filename.c_str(), std::ios::binary) 10 { 11 StartGroup(); 12 WriteHeader(); 13 WriteDocumentPrefix(); 14 } 15 ~cmWIXRichTextFormatWriter()16cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter() 17 { 18 EndGroup(); 19 20 /* I haven't seen this in the RTF spec but 21 * wordpad terminates its RTF like this */ 22 File << "\r\n"; 23 File.put(0); 24 } 25 AddText(std::string const & text)26void cmWIXRichTextFormatWriter::AddText(std::string const& text) 27 { 28 using rtf_byte_t = unsigned char; 29 30 for (size_t i = 0; i < text.size(); ++i) { 31 rtf_byte_t c = rtf_byte_t(text[i]); 32 33 switch (c) { 34 case '\\': 35 File << "\\\\"; 36 break; 37 case '{': 38 File << "\\{"; 39 break; 40 case '}': 41 File << "\\}"; 42 break; 43 case '\n': 44 File << "\\par\r\n"; 45 break; 46 case '\r': 47 continue; 48 default: { 49 if (c <= 0x7F) { 50 File << c; 51 } else { 52 if (c <= 0xC0) { 53 EmitInvalidCodepoint(c); 54 } else if (c < 0xE0 && i + 1 < text.size()) { 55 EmitUnicodeCodepoint((text[i + 1] & 0x3F) | ((c & 0x1F) << 6)); 56 i += 1; 57 } else if (c < 0xF0 && i + 2 < text.size()) { 58 EmitUnicodeCodepoint((text[i + 2] & 0x3F) | 59 ((text[i + 1] & 0x3F) << 6) | 60 ((c & 0xF) << 12)); 61 i += 2; 62 } else if (c < 0xF8 && i + 3 < text.size()) { 63 EmitUnicodeCodepoint( 64 (text[i + 3] & 0x3F) | ((text[i + 2] & 0x3F) << 6) | 65 ((text[i + 1] & 0x3F) << 12) | ((c & 0x7) << 18)); 66 i += 3; 67 } else { 68 EmitInvalidCodepoint(c); 69 } 70 } 71 } break; 72 } 73 } 74 } 75 WriteHeader()76void cmWIXRichTextFormatWriter::WriteHeader() 77 { 78 ControlWord("rtf1"); 79 ControlWord("ansi"); 80 ControlWord("ansicpg1252"); 81 ControlWord("deff0"); 82 ControlWord("deflang1033"); 83 84 WriteFontTable(); 85 WriteColorTable(); 86 WriteGenerator(); 87 } 88 WriteFontTable()89void cmWIXRichTextFormatWriter::WriteFontTable() 90 { 91 StartGroup(); 92 ControlWord("fonttbl"); 93 94 StartGroup(); 95 ControlWord("f0"); 96 ControlWord("fswiss"); 97 ControlWord("fcharset0 Consolas;"); 98 EndGroup(); 99 100 EndGroup(); 101 } 102 WriteColorTable()103void cmWIXRichTextFormatWriter::WriteColorTable() 104 { 105 StartGroup(); 106 ControlWord("colortbl ;"); 107 ControlWord("red255"); 108 ControlWord("green0"); 109 ControlWord("blue0;"); 110 ControlWord("red0"); 111 ControlWord("green255"); 112 ControlWord("blue0;"); 113 ControlWord("red0"); 114 ControlWord("green0"); 115 ControlWord("blue255;"); 116 EndGroup(); 117 } 118 WriteGenerator()119void cmWIXRichTextFormatWriter::WriteGenerator() 120 { 121 StartGroup(); 122 NewControlWord("generator"); 123 File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");"; 124 EndGroup(); 125 } 126 WriteDocumentPrefix()127void cmWIXRichTextFormatWriter::WriteDocumentPrefix() 128 { 129 ControlWord("viewkind4"); 130 ControlWord("uc1"); 131 ControlWord("pard"); 132 ControlWord("f0"); 133 ControlWord("fs14"); 134 } 135 ControlWord(std::string const & keyword)136void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword) 137 { 138 File << "\\" << keyword; 139 } 140 NewControlWord(std::string const & keyword)141void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword) 142 { 143 File << "\\*\\" << keyword; 144 } 145 StartGroup()146void cmWIXRichTextFormatWriter::StartGroup() 147 { 148 File.put('{'); 149 } 150 EndGroup()151void cmWIXRichTextFormatWriter::EndGroup() 152 { 153 File.put('}'); 154 } 155 EmitUnicodeCodepoint(int c)156void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c) 157 { 158 // Do not emit byte order mark (BOM) 159 if (c == 0xFEFF) { 160 return; 161 } else if (c <= 0xFFFF) { 162 EmitUnicodeSurrogate(c); 163 } else { 164 c -= 0x10000; 165 EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800); 166 EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00); 167 } 168 } 169 EmitUnicodeSurrogate(int c)170void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c) 171 { 172 ControlWord("u"); 173 if (c <= 32767) { 174 File << c; 175 } else { 176 File << (c - 65536); 177 } 178 File << "?"; 179 } 180 EmitInvalidCodepoint(int c)181void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c) 182 { 183 ControlWord("cf1 "); 184 File << "[INVALID-BYTE-" << int(c) << "]"; 185 ControlWord("cf0 "); 186 } 187