summaryrefslogtreecommitdiffstats
path: root/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx')
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx186
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 ");
+}