cmWIXRichTextFormatWriter.cxx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2012 Kitware, Inc.
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmWIXRichTextFormatWriter.h"
  11. #include <cmVersion.h>
  12. cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
  13. std::string const& filename)
  14. : File(filename.c_str(), std::ios::binary)
  15. {
  16. StartGroup();
  17. WriteHeader();
  18. WriteDocumentPrefix();
  19. }
  20. cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
  21. {
  22. EndGroup();
  23. /* I haven't seen this in the RTF spec but
  24. * wordpad terminates its RTF like this */
  25. File << "\r\n";
  26. File.put(0);
  27. }
  28. void cmWIXRichTextFormatWriter::AddText(std::string const& text)
  29. {
  30. typedef unsigned char rtf_byte_t;
  31. for (size_t i = 0; i < text.size(); ++i) {
  32. rtf_byte_t c = rtf_byte_t(text[i]);
  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. void cmWIXRichTextFormatWriter::WriteHeader()
  76. {
  77. ControlWord("rtf1");
  78. ControlWord("ansi");
  79. ControlWord("ansicpg1252");
  80. ControlWord("deff0");
  81. ControlWord("deflang1031");
  82. WriteFontTable();
  83. WriteColorTable();
  84. WriteGenerator();
  85. }
  86. void cmWIXRichTextFormatWriter::WriteFontTable()
  87. {
  88. StartGroup();
  89. ControlWord("fonttbl");
  90. StartGroup();
  91. ControlWord("f0");
  92. ControlWord("fswiss");
  93. ControlWord("fcharset0 Arial;");
  94. EndGroup();
  95. EndGroup();
  96. }
  97. void cmWIXRichTextFormatWriter::WriteColorTable()
  98. {
  99. StartGroup();
  100. ControlWord("colortbl ;");
  101. ControlWord("red255");
  102. ControlWord("green0");
  103. ControlWord("blue0;");
  104. ControlWord("red0");
  105. ControlWord("green255");
  106. ControlWord("blue0;");
  107. ControlWord("red0");
  108. ControlWord("green0");
  109. ControlWord("blue255;");
  110. EndGroup();
  111. }
  112. void cmWIXRichTextFormatWriter::WriteGenerator()
  113. {
  114. StartGroup();
  115. NewControlWord("generator");
  116. File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
  117. EndGroup();
  118. }
  119. void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
  120. {
  121. ControlWord("viewkind4");
  122. ControlWord("uc1");
  123. ControlWord("pard");
  124. ControlWord("f0");
  125. ControlWord("fs20");
  126. }
  127. void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
  128. {
  129. File << "\\" << keyword;
  130. }
  131. void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
  132. {
  133. File << "\\*\\" << keyword;
  134. }
  135. void cmWIXRichTextFormatWriter::StartGroup()
  136. {
  137. File.put('{');
  138. }
  139. void cmWIXRichTextFormatWriter::EndGroup()
  140. {
  141. File.put('}');
  142. }
  143. void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c)
  144. {
  145. // Do not emit byte order mark (BOM)
  146. if (c == 0xFEFF) {
  147. return;
  148. } else if (c <= 0xFFFF) {
  149. EmitUnicodeSurrogate(c);
  150. } else {
  151. c -= 0x10000;
  152. EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800);
  153. EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00);
  154. }
  155. }
  156. void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c)
  157. {
  158. ControlWord("u");
  159. if (c <= 32767) {
  160. File << c;
  161. } else {
  162. File << (c - 65536);
  163. }
  164. File << "?";
  165. }
  166. void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c)
  167. {
  168. ControlWord("cf1 ");
  169. File << "[INVALID-BYTE-" << int(c) << "]";
  170. ControlWord("cf0 ");
  171. }