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 0 : OString OutHex(sal_uLong nHex, sal_uInt8 nLen)
20 : {
21 0 : sal_Char aNToABuf[] = "0000000000000000";
22 :
23 : OSL_ENSURE(nLen < sizeof(aNToABuf), "nLen is too big");
24 0 : if (nLen >= sizeof(aNToABuf))
25 0 : nLen = (sizeof(aNToABuf)-1);
26 :
27 : // Set pointer to the buffer end
28 0 : sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
29 0 : for (sal_uInt8 n = 0; n < nLen; ++n)
30 : {
31 0 : *(--pStr) = (sal_Char)(nHex & 0xf) + 48;
32 0 : if (*pStr > '9')
33 0 : *pStr += 39;
34 0 : nHex >>= 4;
35 : }
36 0 : return OString(pStr);
37 : }
38 :
39 0 : OString OutChar(sal_Unicode c, int* pUCMode, rtl_TextEncoding eDestEnc, bool* pSuccess, bool bUnicode)
40 : {
41 0 : if (pSuccess)
42 0 : *pSuccess = true;
43 0 : OStringBuffer aBuf;
44 0 : const sal_Char* pStr = 0;
45 : // 0x0b instead of \n, etc because of the replacements in SwWW8AttrIter::GetSnippet()
46 0 : 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 0 : pStr = OOO_STRING_SVTOOLS_RTF_TAB;
54 0 : break;
55 : case '\\':
56 : case '}':
57 : case '{':
58 0 : aBuf.append('\\');
59 0 : aBuf.append((sal_Char)c);
60 0 : break;
61 : case 0xa0:
62 : // non-breaking space
63 0 : pStr = "\\~";
64 0 : break;
65 : case 0x1e:
66 : // non-breaking hyphen
67 0 : pStr = "\\_";
68 0 : break;
69 : case 0x1f:
70 : // optional hyphen
71 0 : pStr = "\\-";
72 0 : break;
73 : default:
74 0 : if (c >= ' ' && c <= '~')
75 0 : aBuf.append((sal_Char)c);
76 : else
77 : {
78 0 : OUString sBuf(&c, 1);
79 0 : OString sConverted;
80 0 : if (pSuccess)
81 0 : *pSuccess &= sBuf.convertToString(&sConverted, eDestEnc, RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
82 : else
83 0 : sBuf.convertToString(&sConverted, eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
84 0 : const sal_Int32 nLen = sConverted.getLength();
85 :
86 0 : if (pUCMode && bUnicode)
87 : {
88 0 : if (*pUCMode != nLen)
89 : {
90 0 : aBuf.append("\\uc");
91 0 : aBuf.append((sal_Int32)nLen);
92 : // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
93 0 : aBuf.append(' ');
94 0 : *pUCMode = nLen;
95 : }
96 0 : aBuf.append("\\u");
97 0 : aBuf.append((sal_Int32)c);
98 : }
99 :
100 0 : for (sal_Int32 nI = 0; nI < nLen; ++nI)
101 : {
102 0 : aBuf.append("\\'");
103 0 : aBuf.append(OutHex(sConverted[nI], 2));
104 0 : }
105 : }
106 : }
107 0 : if (pStr)
108 : {
109 0 : aBuf.append(pStr);
110 0 : switch (c)
111 : {
112 : case 0xa0:
113 : case 0x1e:
114 : case 0x1f:
115 0 : break;
116 : default:
117 0 : aBuf.append(' ');
118 : }
119 : }
120 0 : return aBuf.makeStringAndClear();
121 : }
122 :
123 0 : OString OutString(const OUString& rStr, rtl_TextEncoding eDestEnc, bool bUnicode)
124 : {
125 : SAL_INFO("filter.ms", OSL_THIS_FUNC << ", rStr = '" << OUString(rStr) << "'");
126 0 : OStringBuffer aBuf;
127 0 : int nUCMode = 1;
128 0 : for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
129 0 : aBuf.append(OutChar(rStr[n], &nUCMode, eDestEnc, 0, bUnicode));
130 0 : 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 0 : return aBuf.makeStringAndClear();
137 : }
138 :
139 : /// Checks if lossless conversion of the string to eDestEnc is possible or not.
140 0 : static bool TryOutString(const OUString& rStr, rtl_TextEncoding eDestEnc)
141 : {
142 0 : int nUCMode = 1;
143 0 : for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
144 : {
145 : bool bRet;
146 0 : OutChar(rStr[n], &nUCMode, eDestEnc, &bRet);
147 0 : if (!bRet)
148 0 : return false;
149 : }
150 0 : return true;
151 : }
152 :
153 0 : OString OutStringUpr(const sal_Char* pToken, const OUString& rStr, rtl_TextEncoding eDestEnc)
154 : {
155 0 : if (TryOutString(rStr, eDestEnc))
156 0 : return OString("{") + pToken + " " + OutString(rStr, eDestEnc) + "}";
157 :
158 0 : OStringBuffer aRet;
159 0 : aRet.append("{" OOO_STRING_SVTOOLS_RTF_UPR "{");
160 0 : aRet.append(pToken);
161 0 : aRet.append(" ");
162 0 : aRet.append(OutString(rStr, eDestEnc, /*bUnicode =*/ false));
163 0 : aRet.append("}{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_UD "{");
164 0 : aRet.append(pToken);
165 0 : aRet.append(" ");
166 0 : aRet.append(OutString(rStr, eDestEnc));
167 0 : aRet.append("}}}");
168 0 : return aRet.makeStringAndClear();
169 : }
170 : }
171 : }
172 :
173 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|