cmake/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx

187 lines
4.0 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2013-03-16 19:13:01 +02:00
#include "cmWIXRichTextFormatWriter.h"
2017-07-20 19:35:53 +02:00
#include "cmVersion.h"
2013-03-16 19:13:01 +02:00
cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
2016-07-09 11:21:54 +02:00
std::string const& filename)
: File(filename.c_str(), std::ios::binary)
2013-03-16 19:13:01 +02:00
{
StartGroup();
WriteHeader();
WriteDocumentPrefix();
}
cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
{
EndGroup();
/* I haven't seen this in the RTF spec but
* wordpad terminates its RTF like this */
2014-08-03 19:52:23 +02:00
File << "\r\n";
File.put(0);
2013-03-16 19:13:01 +02:00
}
2015-04-27 22:25:09 +02:00
void cmWIXRichTextFormatWriter::AddText(std::string const& text)
2013-03-16 19:13:01 +02:00
{
2020-02-01 23:06:01 +01:00
using rtf_byte_t = unsigned char;
2013-03-16 19:13:01 +02:00
2016-07-09 11:21:54 +02:00
for (size_t i = 0; i < text.size(); ++i) {
2013-03-16 19:13:01 +02:00
rtf_byte_t c = rtf_byte_t(text[i]);
2016-07-09 11:21:54 +02:00
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) {
2014-08-03 19:52:23 +02:00
File << c;
2016-07-09 11:21:54 +02:00
} 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);
2013-03-16 19:13:01 +02:00
}
}
2016-07-09 11:21:54 +02:00
} break;
2013-03-16 19:13:01 +02:00
}
2016-07-09 11:21:54 +02:00
}
2013-03-16 19:13:01 +02:00
}
void cmWIXRichTextFormatWriter::WriteHeader()
{
ControlWord("rtf1");
ControlWord("ansi");
ControlWord("ansicpg1252");
ControlWord("deff0");
2021-09-14 00:13:48 +02:00
ControlWord("deflang1033");
2013-03-16 19:13:01 +02:00
WriteFontTable();
2014-08-03 19:52:23 +02:00
WriteColorTable();
2013-03-16 19:13:01 +02:00
WriteGenerator();
}
void cmWIXRichTextFormatWriter::WriteFontTable()
{
StartGroup();
ControlWord("fonttbl");
StartGroup();
ControlWord("f0");
ControlWord("fswiss");
2021-09-14 00:13:48 +02:00
ControlWord("fcharset0 Consolas;");
2013-03-16 19:13:01 +02:00
EndGroup();
EndGroup();
}
2014-08-03 19:52:23 +02:00
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();
}
2013-03-16 19:13:01 +02:00
void cmWIXRichTextFormatWriter::WriteGenerator()
{
StartGroup();
NewControlWord("generator");
2014-08-03 19:52:23 +02:00
File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
2013-03-16 19:13:01 +02:00
EndGroup();
}
void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
{
ControlWord("viewkind4");
ControlWord("uc1");
ControlWord("pard");
ControlWord("f0");
2021-09-14 00:13:48 +02:00
ControlWord("fs14");
2013-03-16 19:13:01 +02:00
}
2015-04-27 22:25:09 +02:00
void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
2013-03-16 19:13:01 +02:00
{
2014-08-03 19:52:23 +02:00
File << "\\" << keyword;
2013-03-16 19:13:01 +02:00
}
2015-04-27 22:25:09 +02:00
void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
2013-03-16 19:13:01 +02:00
{
2014-08-03 19:52:23 +02:00
File << "\\*\\" << keyword;
2013-03-16 19:13:01 +02:00
}
void cmWIXRichTextFormatWriter::StartGroup()
{
2014-08-03 19:52:23 +02:00
File.put('{');
2013-03-16 19:13:01 +02:00
}
void cmWIXRichTextFormatWriter::EndGroup()
{
2014-08-03 19:52:23 +02:00
File.put('}');
}
void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c)
{
// Do not emit byte order mark (BOM)
2016-07-09 11:21:54 +02:00
if (c == 0xFEFF) {
2014-08-03 19:52:23 +02:00
return;
2016-07-09 11:21:54 +02:00
} else if (c <= 0xFFFF) {
2014-08-03 19:52:23 +02:00
EmitUnicodeSurrogate(c);
2016-07-09 11:21:54 +02:00
} else {
2014-08-03 19:52:23 +02:00
c -= 0x10000;
EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800);
EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00);
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
}
void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c)
{
ControlWord("u");
2016-07-09 11:21:54 +02:00
if (c <= 32767) {
2014-08-03 19:52:23 +02:00
File << c;
2016-07-09 11:21:54 +02:00
} else {
2014-08-03 19:52:23 +02:00
File << (c - 65536);
2016-07-09 11:21:54 +02:00
}
2014-08-03 19:52:23 +02:00
File << "?";
}
void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c)
{
ControlWord("cf1 ");
File << "[INVALID-BYTE-" << int(c) << "]";
ControlWord("cf0 ");
2013-03-16 19:13:01 +02:00
}