cmWIXRichTextFormatWriter.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmWIXRichTextFormatWriter.h"
  4. #include "cmVersion.h"
  5. cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
  6. std::string const& filename)
  7. : File(filename.c_str(), std::ios::binary)
  8. {
  9. StartGroup();
  10. WriteHeader();
  11. WriteDocumentPrefix();
  12. }
  13. cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
  14. {
  15. EndGroup();
  16. /* I haven't seen this in the RTF spec but
  17. * wordpad terminates its RTF like this */
  18. File << "\r\n";
  19. File.put(0);
  20. }
  21. void cmWIXRichTextFormatWriter::AddText(std::string const& text)
  22. {
  23. typedef unsigned char rtf_byte_t;
  24. for (size_t i = 0; i < text.size(); ++i) {
  25. rtf_byte_t c = rtf_byte_t(text[i]);
  26. switch (c) {
  27. case '\\':
  28. File << "\\\\";
  29. break;
  30. case '{':
  31. File << "\\{";
  32. break;
  33. case '}':
  34. File << "\\}";
  35. break;
  36. case '\n':
  37. File << "\\par\r\n";
  38. break;
  39. case '\r':
  40. continue;
  41. default: {
  42. if (c <= 0x7F) {
  43. File << c;
  44. } else {
  45. if (c <= 0xC0) {
  46. EmitInvalidCodepoint(c);
  47. } else if (c < 0xE0 && i + 1 < text.size()) {
  48. EmitUnicodeCodepoint((text[i + 1] & 0x3F) | ((c & 0x1F) << 6));
  49. i += 1;
  50. } else if (c < 0xF0 && i + 2 < text.size()) {
  51. EmitUnicodeCodepoint((text[i + 2] & 0x3F) |
  52. ((text[i + 1] & 0x3F) << 6) |
  53. ((c & 0xF) << 12));
  54. i += 2;
  55. } else if (c < 0xF8 && i + 3 < text.size()) {
  56. EmitUnicodeCodepoint(
  57. (text[i + 3] & 0x3F) | ((text[i + 2] & 0x3F) << 6) |
  58. ((text[i + 1] & 0x3F) << 12) | ((c & 0x7) << 18));
  59. i += 3;
  60. } else {
  61. EmitInvalidCodepoint(c);
  62. }
  63. }
  64. } break;
  65. }
  66. }
  67. }
  68. void cmWIXRichTextFormatWriter::WriteHeader()
  69. {
  70. ControlWord("rtf1");
  71. ControlWord("ansi");
  72. ControlWord("ansicpg1252");
  73. ControlWord("deff0");
  74. ControlWord("deflang1031");
  75. WriteFontTable();
  76. WriteColorTable();
  77. WriteGenerator();
  78. }
  79. void cmWIXRichTextFormatWriter::WriteFontTable()
  80. {
  81. StartGroup();
  82. ControlWord("fonttbl");
  83. StartGroup();
  84. ControlWord("f0");
  85. ControlWord("fswiss");
  86. ControlWord("fcharset0 Arial;");
  87. EndGroup();
  88. EndGroup();
  89. }
  90. void cmWIXRichTextFormatWriter::WriteColorTable()
  91. {
  92. StartGroup();
  93. ControlWord("colortbl ;");
  94. ControlWord("red255");
  95. ControlWord("green0");
  96. ControlWord("blue0;");
  97. ControlWord("red0");
  98. ControlWord("green255");
  99. ControlWord("blue0;");
  100. ControlWord("red0");
  101. ControlWord("green0");
  102. ControlWord("blue255;");
  103. EndGroup();
  104. }
  105. void cmWIXRichTextFormatWriter::WriteGenerator()
  106. {
  107. StartGroup();
  108. NewControlWord("generator");
  109. File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
  110. EndGroup();
  111. }
  112. void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
  113. {
  114. ControlWord("viewkind4");
  115. ControlWord("uc1");
  116. ControlWord("pard");
  117. ControlWord("f0");
  118. ControlWord("fs20");
  119. }
  120. void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
  121. {
  122. File << "\\" << keyword;
  123. }
  124. void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
  125. {
  126. File << "\\*\\" << keyword;
  127. }
  128. void cmWIXRichTextFormatWriter::StartGroup()
  129. {
  130. File.put('{');
  131. }
  132. void cmWIXRichTextFormatWriter::EndGroup()
  133. {
  134. File.put('}');
  135. }
  136. void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c)
  137. {
  138. // Do not emit byte order mark (BOM)
  139. if (c == 0xFEFF) {
  140. return;
  141. } else if (c <= 0xFFFF) {
  142. EmitUnicodeSurrogate(c);
  143. } else {
  144. c -= 0x10000;
  145. EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800);
  146. EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00);
  147. }
  148. }
  149. void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c)
  150. {
  151. ControlWord("u");
  152. if (c <= 32767) {
  153. File << c;
  154. } else {
  155. File << (c - 65536);
  156. }
  157. File << "?";
  158. }
  159. void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c)
  160. {
  161. ControlWord("cf1 ");
  162. File << "[INVALID-BYTE-" << int(c) << "]";
  163. ControlWord("cf0 ");
  164. }