1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svtools.hxx" 26 #include <tools/debug.hxx> 27 #include <tools/stream.hxx> 28 #include <tools/string.hxx> 29 #include <rtl/string.hxx> 30 #include <rtl/ustrbuf.hxx> 31 #include <svtools/rtfkeywd.hxx> 32 #include <svtools/rtfout.hxx> 33 34 using namespace rtl; 35 36 #if defined(UNX) 37 const sal_Char RTFOutFuncs::sNewLine = '\012'; 38 #else 39 const sal_Char __FAR_DATA RTFOutFuncs::sNewLine[] = "\015\012"; 40 #endif 41 42 43 SvStream& RTFOutFuncs::Out_Char(SvStream& rStream, sal_Unicode c, 44 int *pUCMode, rtl_TextEncoding eDestEnc, sal_Bool bWriteHelpFile) 45 { 46 const sal_Char* pStr = 0; 47 switch (c) 48 { 49 case 0x1: 50 case 0x2: 51 // this are control character of our textattributes and will never be 52 // written 53 break; 54 case 0xA0: 55 rStream << "\\~"; 56 break; 57 case 0xAD: 58 rStream << "\\-"; 59 break; 60 case 0x2011: 61 rStream << "\\_"; 62 break; 63 case '\n': 64 pStr = OOO_STRING_SVTOOLS_RTF_LINE; 65 break; 66 case '\t': 67 pStr = OOO_STRING_SVTOOLS_RTF_TAB; 68 break; 69 default: 70 if(!bWriteHelpFile) 71 { 72 switch(c) 73 { 74 case 149: 75 pStr = OOO_STRING_SVTOOLS_RTF_BULLET; 76 break; 77 case 150: 78 pStr = OOO_STRING_SVTOOLS_RTF_ENDASH; 79 break; 80 case 151: 81 pStr = OOO_STRING_SVTOOLS_RTF_EMDASH; 82 break; 83 case 145: 84 pStr = OOO_STRING_SVTOOLS_RTF_LQUOTE; 85 break; 86 case 146: 87 pStr = OOO_STRING_SVTOOLS_RTF_RQUOTE; 88 break; 89 case 147: 90 pStr = OOO_STRING_SVTOOLS_RTF_LDBLQUOTE; 91 break; 92 case 148: 93 pStr = OOO_STRING_SVTOOLS_RTF_RDBLQUOTE; 94 break; 95 } 96 97 if (pStr) 98 break; 99 } 100 101 switch (c) 102 { 103 case '\\': 104 case '}': 105 case '{': 106 rStream << '\\' << (sal_Char)c; 107 break; 108 default: 109 if (c >= ' ' && c <= '~') 110 rStream << (sal_Char)c; 111 else 112 { 113 //If we can't convert to the dest encoding, or if 114 //its an uncommon multibyte sequence which most 115 //readers won't be able to handle correctly, then 116 //If we can't convert to the dest encoding, then 117 //export as unicode 118 OUString sBuf(&c, 1); 119 OString sConverted; 120 sal_uInt32 nFlags = 121 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | 122 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR; 123 bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted, 124 eDestEnc, nFlags)) 125 || (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF; 126 if (bWriteAsUnicode) 127 { 128 sBuf.convertToString(&sConverted, 129 eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS); 130 } 131 const sal_Int32 nLen = sConverted.getLength(); 132 133 if (bWriteAsUnicode && pUCMode) 134 { 135 // then write as unicode - character 136 if (*pUCMode != nLen) 137 { 138 rStream << "\\uc" << ByteString::CreateFromInt32(nLen).GetBuffer() << " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.; 139 *pUCMode = nLen; 140 } 141 ByteString sNo(ByteString::CreateFromInt32(c)); 142 rStream << "\\u" << sNo.GetBuffer(); 143 } 144 145 for (sal_Int32 nI = 0; nI < nLen; ++nI) 146 { 147 rStream << "\\'"; 148 Out_Hex(rStream, sConverted.getStr()[nI], 2); 149 } 150 } 151 break; 152 } 153 break; 154 } 155 156 if (pStr) 157 rStream << pStr << ' '; 158 159 return rStream; 160 } 161 162 SvStream& RTFOutFuncs::Out_String( SvStream& rStream, const String& rStr, 163 rtl_TextEncoding eDestEnc, sal_Bool bWriteHelpFile) 164 { 165 int nUCMode = 1; 166 for (xub_StrLen n = 0; n < rStr.Len(); ++n) 167 Out_Char(rStream, rStr.GetChar(n), &nUCMode, eDestEnc, bWriteHelpFile); 168 if (nUCMode != 1) 169 rStream << "\\uc1"<< " "; // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.; 170 return rStream; 171 } 172 173 SvStream& RTFOutFuncs::Out_Fontname(SvStream& rStream, const String& rStr, 174 rtl_TextEncoding eDestEnc, sal_Bool bWriteHelpFile) 175 { 176 //Fontnames in word have a quirk in that \uc and usage of ansi replacement 177 //chars after a \u don't work and in wordpad \u doesn't work, so we are 178 //left with forcing ansi characters only for fontnames 179 for (xub_StrLen n = 0; n < rStr.Len(); ++n) 180 Out_Char(rStream, rStr.GetChar(n), 0, eDestEnc, bWriteHelpFile); 181 return rStream; 182 } 183 184 SvStream& RTFOutFuncs::Out_Hex( SvStream& rStream, sal_uLong nHex, sal_uInt8 nLen ) 185 { 186 sal_Char aNToABuf[] = "0000000000000000"; 187 188 DBG_ASSERT( nLen < sizeof(aNToABuf), "zu viele Stellen" ); 189 if( nLen >= sizeof(aNToABuf) ) 190 nLen = (sizeof(aNToABuf)-1); 191 192 // Pointer an das Bufferende setzen 193 sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1); 194 for( sal_uInt8 n = 0; n < nLen; ++n ) 195 { 196 *(--pStr) = (sal_Char)(nHex & 0xf ) + 48; 197 if( *pStr > '9' ) 198 *pStr += 39; 199 nHex >>= 4; 200 } 201 return rStream << pStr; 202 } 203 204 205 206