/*============================================================================ 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 cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter( const std::string& 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(const std::string& 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(const std::string& keyword) { File << "\\" << keyword; } void cmWIXRichTextFormatWriter::NewControlWord(const std::string& 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 "); }