Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <filter/msfilter/rtfutil.hxx>
11 : #include <rtl/strbuf.hxx>
12 : #include <svtools/rtfkeywd.hxx>
13 :
14 : namespace msfilter
15 : {
16 : namespace rtfutil
17 : {
18 :
19 335 : OString OutHex(sal_uLong nHex, sal_uInt8 nLen)
20 : {
21 335 : sal_Char aNToABuf[] = "0000000000000000";
22 :
23 : OSL_ENSURE(nLen < sizeof(aNToABuf), "nLen is too big");
24 335 : if (nLen >= sizeof(aNToABuf))
25 0 : nLen = (sizeof(aNToABuf)-1);
26 :
27 : // Set pointer to the buffer end
28 335 : sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
29 1005 : for (sal_uInt8 n = 0; n < nLen; ++n)
30 : {
31 670 : *(--pStr) = (sal_Char)(nHex & 0xf) + 48;
32 670 : if (*pStr > '9')
33 142 : *pStr += 39;
34 670 : nHex >>= 4;
35 : }
36 335 : return OString(pStr);
37 : }
38 :
39 12305 : OString OutChar(sal_Unicode c, int* pUCMode, rtl_TextEncoding eDestEnc, bool* pSuccess, bool bUnicode)
40 : {
41 12305 : if (pSuccess)
42 9 : *pSuccess = true;
43 12305 : OStringBuffer aBuf;
44 12305 : const sal_Char* pStr = 0;
45 : // 0x0b instead of \n, etc because of the replacements in SwWW8AttrIter::GetSnippet()
46 12305 : switch (c)
47 : {
48 : case 0x0b:
49 : // hard line break
50 0 : pStr = OOO_STRING_SVTOOLS_RTF_LINE;
51 0 : break;
52 : case '\t':
53 36 : pStr = OOO_STRING_SVTOOLS_RTF_TAB;
54 36 : break;
55 : case '\\':
56 : case '}':
57 : case '{':
58 6 : aBuf.append('\\');
59 6 : aBuf.append((sal_Char)c);
60 6 : break;
61 : case 0xa0:
62 : // non-breaking space
63 1 : pStr = "\\~";
64 1 : break;
65 : case 0x1e:
66 : // non-breaking hyphen
67 1 : pStr = "\\_";
68 1 : break;
69 : case 0x1f:
70 : // optional hyphen
71 1 : pStr = "\\-";
72 1 : break;
73 : default:
74 12260 : if (c >= ' ' && c <= '~')
75 12047 : aBuf.append((sal_Char)c);
76 : else
77 : {
78 213 : OUString sBuf(&c, 1);
79 426 : OString sConverted;
80 213 : if (pSuccess)
81 4 : *pSuccess &= sBuf.convertToString(&sConverted, eDestEnc, RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
82 : else
83 209 : sBuf.convertToString(&sConverted, eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
84 213 : const sal_Int32 nLen = sConverted.getLength();
85 :
86 213 : if (pUCMode && bUnicode)
87 : {
88 154 : if (*pUCMode != nLen)
89 : {
90 2 : aBuf.append("\\uc");
91 2 : aBuf.append((sal_Int32)nLen);
92 : // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
93 2 : aBuf.append(' ');
94 2 : *pUCMode = nLen;
95 : }
96 154 : aBuf.append("\\u");
97 154 : aBuf.append((sal_Int32)c);
98 : }
99 :
100 424 : for (sal_Int32 nI = 0; nI < nLen; ++nI)
101 : {
102 211 : aBuf.append("\\'");
103 211 : aBuf.append(OutHex(sConverted[nI], 2));
104 213 : }
105 : }
106 : }
107 12305 : if (pStr)
108 : {
109 39 : aBuf.append(pStr);
110 39 : switch (c)
111 : {
112 : case 0xa0:
113 : case 0x1e:
114 : case 0x1f:
115 3 : break;
116 : default:
117 36 : aBuf.append(' ');
118 : }
119 : }
120 12305 : return aBuf.makeStringAndClear();
121 : }
122 :
123 1647 : OString OutString(const OUString& rStr, rtl_TextEncoding eDestEnc, bool bUnicode)
124 : {
125 : SAL_INFO("filter.ms", OSL_THIS_FUNC << ", rStr = '" << OUString(rStr) << "'");
126 1647 : OStringBuffer aBuf;
127 1647 : int nUCMode = 1;
128 13943 : for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
129 12296 : aBuf.append(OutChar(rStr[n], &nUCMode, eDestEnc, 0, bUnicode));
130 1647 : if (nUCMode != 1)
131 : {
132 0 : aBuf.append(OOO_STRING_SVTOOLS_RTF_UC);
133 0 : aBuf.append((sal_Int32)1);
134 0 : aBuf.append(" "); // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
135 : }
136 1647 : return aBuf.makeStringAndClear();
137 : }
138 :
139 : /// Checks if lossless conversion of the string to eDestEnc is possible or not.
140 3 : static bool TryOutString(const OUString& rStr, rtl_TextEncoding eDestEnc)
141 : {
142 3 : int nUCMode = 1;
143 10 : for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
144 : {
145 : bool bRet;
146 9 : OutChar(rStr[n], &nUCMode, eDestEnc, &bRet);
147 9 : if (!bRet)
148 2 : return false;
149 : }
150 1 : return true;
151 : }
152 :
153 3 : OString OutStringUpr(const sal_Char* pToken, const OUString& rStr, rtl_TextEncoding eDestEnc)
154 : {
155 3 : if (TryOutString(rStr, eDestEnc))
156 1 : return OString("{") + pToken + " " + OutString(rStr, eDestEnc) + "}";
157 :
158 2 : OStringBuffer aRet;
159 2 : aRet.append("{" OOO_STRING_SVTOOLS_RTF_UPR "{");
160 2 : aRet.append(pToken);
161 2 : aRet.append(" ");
162 2 : aRet.append(OutString(rStr, eDestEnc, /*bUnicode =*/ false));
163 2 : aRet.append("}{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_UD "{");
164 2 : aRet.append(pToken);
165 2 : aRet.append(" ");
166 2 : aRet.append(OutString(rStr, eDestEnc));
167 2 : aRet.append("}}}");
168 2 : return aRet.makeStringAndClear();
169 : }
170 : }
171 : }
172 :
173 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|