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 <svx/dialogs.hrc>
11 : #include <vcl/svapp.hxx>
12 : #include <vcl/settings.hxx>
13 : #include <rtl/strbuf.hxx>
14 : #include <rtftokenizer.hxx>
15 : #include <rtfskipdestination.hxx>
16 : #include <com/sun/star/io/BufferSizeExceededException.hpp>
17 :
18 : using namespace com::sun::star;
19 :
20 : namespace writerfilter
21 : {
22 : namespace rtftok
23 : {
24 :
25 38 : std::vector<RTFSymbol> RTFTokenizer::m_aRTFControlWords;
26 : bool RTFTokenizer::m_bControlWordsSorted;
27 38 : std::vector<RTFMathSymbol> RTFTokenizer::m_aRTFMathControlWords;
28 : bool RTFTokenizer::m_bMathControlWordsSorted;
29 :
30 828 : RTFTokenizer::RTFTokenizer(RTFListener& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
31 : : m_rImport(rImport),
32 : m_pInStream(pInStream),
33 : m_xStatusIndicator(xStatusIndicator),
34 : m_nGroup(0),
35 : m_nLineNumber(0),
36 : m_nLineStartPos(0),
37 828 : m_nGroupStart(0)
38 : {
39 828 : if (!RTFTokenizer::m_bControlWordsSorted)
40 : {
41 10 : RTFTokenizer::m_bControlWordsSorted = true;
42 10 : m_aRTFControlWords = std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords);
43 10 : std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
44 : }
45 828 : if (!RTFTokenizer::m_bMathControlWordsSorted)
46 : {
47 10 : RTFTokenizer::m_bMathControlWordsSorted = true;
48 10 : m_aRTFMathControlWords = std::vector<RTFMathSymbol>(aRTFMathControlWords, aRTFMathControlWords + nRTFMathControlWords);
49 10 : std::sort(m_aRTFMathControlWords.begin(), m_aRTFMathControlWords.end());
50 : }
51 828 : }
52 :
53 1656 : RTFTokenizer::~RTFTokenizer()
54 : {
55 1656 : }
56 :
57 :
58 828 : int RTFTokenizer::resolveParse()
59 : {
60 : SAL_INFO("writerfilter", OSL_THIS_FUNC);
61 : char ch;
62 : int ret;
63 : // for hex chars
64 828 : int b = 0, count = 2;
65 828 : sal_uInt32 nPercentSize = 0;
66 828 : sal_uInt32 nLastPos = 0;
67 :
68 828 : if (m_xStatusIndicator.is())
69 : {
70 712 : static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag());
71 712 : OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
72 :
73 712 : sal_Size nCurrentPos = Strm().Tell();
74 712 : sal_Size nEndPos = nCurrentPos + Strm().remainingSize();
75 712 : m_xStatusIndicator->start(sDocLoad, nEndPos);
76 712 : nPercentSize = nEndPos / 100;
77 :
78 712 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
79 : }
80 :
81 423190 : while ((Strm().ReadChar(ch), !Strm().IsEof()))
82 : {
83 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
84 :
85 422356 : sal_Size nCurrentPos = Strm().Tell();
86 422356 : if (m_xStatusIndicator.is() && nCurrentPos > (nLastPos + nPercentSize))
87 30854 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
88 :
89 422356 : if (m_nGroup < 0)
90 0 : return ERROR_GROUP_UNDER;
91 422356 : if (m_nGroup > 0 && m_rImport.getInternalState() == INTERNAL_BIN)
92 : {
93 4 : ret = m_rImport.resolveChars(ch);
94 4 : if (ret)
95 0 : return ret;
96 : }
97 : else
98 : {
99 422352 : switch (ch)
100 : {
101 : case '{':
102 32250 : m_nGroupStart = Strm().Tell() - 1;
103 32250 : ret = m_rImport.pushState();
104 32250 : if (ret)
105 0 : return ret;
106 32250 : break;
107 : case '}':
108 32242 : ret = m_rImport.popState();
109 32242 : if (ret)
110 0 : return ret;
111 32242 : if (m_nGroup == 0)
112 : {
113 820 : if (m_rImport.isSubstream())
114 82 : m_rImport.finishSubstream();
115 820 : return 0;
116 : }
117 31422 : break;
118 : case '\\':
119 205290 : ret = resolveKeyword();
120 205288 : if (ret)
121 0 : return ret;
122 205288 : break;
123 : case 0x0d:
124 9134 : break; // ignore this
125 : case 0x0a:
126 24354 : m_nLineNumber++;
127 24354 : m_nLineStartPos = nCurrentPos;
128 24354 : break;
129 : default:
130 119082 : if (m_nGroup == 0)
131 0 : return ERROR_CHAR_OVER;
132 119082 : if (m_rImport.getInternalState() == INTERNAL_NORMAL)
133 : {
134 24382 : ret = m_rImport.resolveChars(ch);
135 24382 : if (ret)
136 0 : return ret;
137 : }
138 : else
139 : {
140 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
141 94700 : b = b << 4;
142 94700 : sal_Int8 parsed = asHex(ch);
143 94700 : if (parsed == -1)
144 0 : return ERROR_HEX_INVALID;
145 94700 : b += parsed;
146 94700 : count--;
147 94700 : if (!count)
148 : {
149 47350 : ret = m_rImport.resolveChars(b);
150 47350 : if (ret)
151 0 : return ret;
152 47350 : count = 2;
153 47350 : b = 0;
154 47350 : m_rImport.setInternalState(INTERNAL_NORMAL);
155 : }
156 : }
157 119082 : break;
158 : }
159 : }
160 : }
161 :
162 6 : if (m_nGroup < 0)
163 0 : return ERROR_GROUP_UNDER;
164 6 : else if (m_nGroup > 0)
165 6 : return ERROR_GROUP_OVER;
166 0 : return 0;
167 : }
168 :
169 739636 : int RTFTokenizer::asHex(char ch)
170 : {
171 739636 : int ret = 0;
172 739636 : if (isdigit(ch))
173 433942 : ret = ch - '0';
174 : else
175 : {
176 305694 : if (islower(ch))
177 : {
178 305686 : if (ch < 'a' || ch > 'f')
179 0 : return -1;
180 305686 : ret = ch - 'a';
181 : }
182 : else
183 : {
184 8 : if (ch < 'A' || ch > 'F')
185 0 : return -1;
186 8 : ret = ch - 'A';
187 : }
188 305694 : ret += 10;
189 : }
190 739636 : return ret;
191 : }
192 :
193 :
194 32250 : void RTFTokenizer::pushGroup()
195 : {
196 32250 : m_nGroup++;
197 32250 : }
198 :
199 32242 : void RTFTokenizer::popGroup()
200 : {
201 32242 : m_nGroup--;
202 32242 : }
203 :
204 205290 : int RTFTokenizer::resolveKeyword()
205 : {
206 : char ch;
207 205290 : OStringBuffer aBuf;
208 205290 : bool bNeg = false;
209 205290 : bool bParam = false;
210 205290 : int nParam = 0;
211 :
212 205290 : Strm().ReadChar(ch);
213 205290 : if (Strm().IsEof())
214 0 : return ERROR_EOF;
215 :
216 205290 : if (!isalpha(ch))
217 : {
218 51340 : aBuf.append(ch);
219 51340 : OString aKeyword = aBuf.makeStringAndClear();
220 : // control symbols aren't followed by a space, so we can return here
221 : // without doing any SeekRel()
222 51340 : return dispatchKeyword(aKeyword, bParam, nParam);
223 : }
224 1041918 : while (isalpha(ch))
225 : {
226 734020 : aBuf.append(ch);
227 734020 : Strm().ReadChar(ch);
228 734020 : if (Strm().IsEof())
229 : {
230 2 : ch = ' ';
231 2 : break;
232 : }
233 : }
234 153950 : if (aBuf.getLength() > 32)
235 : // See RTF spec v1.9.1, page 7
236 : // A control word's name cannot be longer than 32 letters.
237 2 : throw io::BufferSizeExceededException();
238 :
239 153948 : if (ch == '-')
240 : {
241 : // in case we'll have a parameter, that will be negative
242 1918 : bNeg = true;
243 1918 : Strm().ReadChar(ch);
244 1918 : if (Strm().IsEof())
245 0 : return ERROR_EOF;
246 : }
247 153948 : if (isdigit(ch))
248 : {
249 85192 : OStringBuffer aParameter;
250 :
251 : // we have a parameter
252 85192 : bParam = true;
253 359902 : while (isdigit(ch))
254 : {
255 189518 : aParameter.append(ch);
256 189518 : Strm().ReadChar(ch);
257 189518 : if (Strm().IsEof())
258 : {
259 0 : ch = ' ';
260 0 : break;
261 : }
262 : }
263 85192 : nParam = aParameter.makeStringAndClear().toInt32();
264 85192 : if (bNeg)
265 1918 : nParam = -nParam;
266 : }
267 153948 : if (ch != ' ')
268 114384 : Strm().SeekRel(-1);
269 307896 : OString aKeyword = aBuf.makeStringAndClear();
270 359238 : return dispatchKeyword(aKeyword, bParam, nParam);
271 : }
272 :
273 2790 : bool RTFTokenizer::lookupMathKeyword(RTFMathSymbol& rSymbol)
274 : {
275 2790 : std::vector<RTFMathSymbol>::iterator low = std::lower_bound(m_aRTFMathControlWords.begin(), m_aRTFMathControlWords.end(), rSymbol);
276 2790 : int i = low - m_aRTFMathControlWords.begin();
277 2790 : if (low == m_aRTFMathControlWords.end() || rSymbol < *low)
278 472 : return false;
279 2318 : rSymbol = m_aRTFMathControlWords[i];
280 2318 : return true;
281 : }
282 :
283 205288 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
284 : {
285 205288 : if (m_rImport.getDestinationState() == DESTINATION_SKIP)
286 20710 : return 0;
287 : SAL_INFO("writerfilter.rtf", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
288 : "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");
289 : RTFSymbol aSymbol;
290 184578 : aSymbol.sKeyword = rKeyword.getStr();
291 184578 : std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
292 184578 : int i = low - m_aRTFControlWords.begin();
293 184578 : if (low == m_aRTFControlWords.end() || aSymbol < *low)
294 : {
295 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
296 1220 : RTFSkipDestination aSkip(m_rImport);
297 1220 : aSkip.setParsed(false);
298 1220 : return 0;
299 : }
300 :
301 : int ret;
302 183358 : switch (m_aRTFControlWords[i].nControlType)
303 : {
304 : case CONTROL_FLAG:
305 : // flags ignore any parameter by definition
306 36914 : ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
307 36914 : if (ret)
308 0 : return ret;
309 36914 : break;
310 : case CONTROL_DESTINATION:
311 : // same for destinations
312 16358 : ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
313 16358 : if (ret)
314 0 : return ret;
315 16358 : break;
316 : case CONTROL_SYMBOL:
317 : // and symbols
318 54188 : ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
319 54188 : if (ret)
320 0 : return ret;
321 54188 : break;
322 : case CONTROL_TOGGLE:
323 2772 : ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
324 2772 : if (ret)
325 0 : return ret;
326 2772 : break;
327 : case CONTROL_VALUE:
328 : // values require a parameter by definition
329 73126 : if (bParam)
330 : {
331 72746 : ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
332 72746 : if (ret)
333 0 : return ret;
334 : }
335 73126 : break;
336 : }
337 :
338 183358 : return 0;
339 : }
340 :
341 6 : OUString RTFTokenizer::getPosition()
342 : {
343 6 : OUStringBuffer aRet;
344 6 : aRet.append(m_nLineNumber + 1);
345 6 : aRet.append(",");
346 6 : aRet.append(sal_Int32(Strm().Tell() - m_nLineStartPos + 1));
347 6 : return aRet.makeStringAndClear();
348 : }
349 :
350 :
351 : } // namespace rtftok
352 114 : } // namespace writerfilter
353 :
354 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|