cmWIXRichTextFormatWriter.cxx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. {
  33. rtf_byte_t c = rtf_byte_t(text[i]);
  34. switch(c)
  35. {
  36. case '\\':
  37. File << "\\\\";
  38. break;
  39. case '{':
  40. File << "\\{";
  41. break;
  42. case '}':
  43. File << "\\}";
  44. break;
  45. case '\n':
  46. File << "\\par\r\n";
  47. break;
  48. case '\r':
  49. continue;
  50. default:
  51. {
  52. if(c <= 0x7F)
  53. {
  54. File << c;
  55. }
  56. else
  57. {
  58. if(c <= 0xC0)
  59. {
  60. EmitInvalidCodepoint(c);
  61. }
  62. else if(c < 0xE0 && i+1 < text.size())
  63. {
  64. EmitUnicodeCodepoint(
  65. (text[i+1] & 0x3F) |
  66. ((c & 0x1F) << 6)
  67. );
  68. i+= 1;
  69. }
  70. else if(c < 0xF0 && i+2 < text.size())
  71. {
  72. EmitUnicodeCodepoint(
  73. (text[i+2] & 0x3F) |
  74. ((text[i+1] & 0x3F) << 6) |
  75. ((c & 0xF) << 12)
  76. );
  77. i += 2;
  78. }
  79. else if(c < 0xF8 && i+3 < text.size())
  80. {
  81. EmitUnicodeCodepoint(
  82. (text[i+3] & 0x3F) |
  83. ((text[i+2] & 0x3F) << 6) |
  84. ((text[i+1] & 0x3F) << 12) |
  85. ((c & 0x7) << 18)
  86. );
  87. i += 3;
  88. }
  89. else
  90. {
  91. EmitInvalidCodepoint(c);
  92. }
  93. }
  94. }
  95. break;
  96. }
  97. }
  98. }
  99. void cmWIXRichTextFormatWriter::WriteHeader()
  100. {
  101. ControlWord("rtf1");
  102. ControlWord("ansi");
  103. ControlWord("ansicpg1252");
  104. ControlWord("deff0");
  105. ControlWord("deflang1031");
  106. WriteFontTable();
  107. WriteColorTable();
  108. WriteGenerator();
  109. }
  110. void cmWIXRichTextFormatWriter::WriteFontTable()
  111. {
  112. StartGroup();
  113. ControlWord("fonttbl");
  114. StartGroup();
  115. ControlWord("f0");
  116. ControlWord("fswiss");
  117. ControlWord("fcharset0 Arial;");
  118. EndGroup();
  119. EndGroup();
  120. }
  121. void cmWIXRichTextFormatWriter::WriteColorTable()
  122. {
  123. StartGroup();
  124. ControlWord("colortbl ;");
  125. ControlWord("red255");
  126. ControlWord("green0");
  127. ControlWord("blue0;");
  128. ControlWord("red0");
  129. ControlWord("green255");
  130. ControlWord("blue0;");
  131. ControlWord("red0");
  132. ControlWord("green0");
  133. ControlWord("blue255;");
  134. EndGroup();
  135. }
  136. void cmWIXRichTextFormatWriter::WriteGenerator()
  137. {
  138. StartGroup();
  139. NewControlWord("generator");
  140. File << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
  141. EndGroup();
  142. }
  143. void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
  144. {
  145. ControlWord("viewkind4");
  146. ControlWord("uc1");
  147. ControlWord("pard");
  148. ControlWord("f0");
  149. ControlWord("fs20");
  150. }
  151. void cmWIXRichTextFormatWriter::ControlWord(std::string const& keyword)
  152. {
  153. File << "\\" << keyword;
  154. }
  155. void cmWIXRichTextFormatWriter::NewControlWord(std::string const& keyword)
  156. {
  157. File << "\\*\\" << keyword;
  158. }
  159. void cmWIXRichTextFormatWriter::StartGroup()
  160. {
  161. File.put('{');
  162. }
  163. void cmWIXRichTextFormatWriter::EndGroup()
  164. {
  165. File.put('}');
  166. }
  167. void cmWIXRichTextFormatWriter::EmitUnicodeCodepoint(int c)
  168. {
  169. // Do not emit byte order mark (BOM)
  170. if(c == 0xFEFF)
  171. {
  172. return;
  173. }
  174. else if(c <= 0xFFFF)
  175. {
  176. EmitUnicodeSurrogate(c);
  177. }
  178. else
  179. {
  180. c -= 0x10000;
  181. EmitUnicodeSurrogate(((c >> 10) & 0x3FF) + 0xD800);
  182. EmitUnicodeSurrogate((c & 0x3FF) + 0xDC00);
  183. }
  184. }
  185. void cmWIXRichTextFormatWriter::EmitUnicodeSurrogate(int c)
  186. {
  187. ControlWord("u");
  188. if(c <= 32767)
  189. {
  190. File << c;
  191. }
  192. else
  193. {
  194. File << (c - 65536);
  195. }
  196. File << "?";
  197. }
  198. void cmWIXRichTextFormatWriter::EmitInvalidCodepoint(int c)
  199. {
  200. ControlWord("cf1 ");
  201. File << "[INVALID-BYTE-" << int(c) << "]";
  202. ControlWord("cf0 ");
  203. }