blob: f27caa941d22a0e7cb55ed54c32058d12e2c4330 [file] [log] [blame]
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2012 Kitware, Inc.
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#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 ");
}