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