Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Initial Developer of the Original Code is
16 : * Miklos Vajna <vmiklos@frugalware.org>
17 : * Portions created by the Initial Developer are Copyright (C) 2011 the
18 : * Initial Developer. All Rights Reserved.
19 : *
20 : * Contributor(s):
21 : *
22 : * Alternatively, the contents of this file may be used under the terms of
23 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : * instead of those above.
27 : */
28 :
29 : #include <tools/stream.hxx>
30 : #include <tools/resmgr.hxx>
31 : #include <svx/dialogs.hrc>
32 : #include <vcl/svapp.hxx>
33 :
34 : #include <rtftokenizer.hxx>
35 : #include <rtfskipdestination.hxx>
36 :
37 : using rtl::OString;
38 : using rtl::OStringBuffer;
39 : using rtl::OUString;
40 : using rtl::OUStringBuffer;
41 : using rtl::OUStringToOString;
42 :
43 : namespace writerfilter {
44 : namespace rtftok {
45 :
46 5 : std::vector<RTFSymbol> RTFTokenizer::m_aRTFControlWords;
47 : bool RTFTokenizer::m_bControlWordsSorted;
48 :
49 138 : RTFTokenizer::RTFTokenizer(RTFDocumentImpl& rImport, SvStream* pInStream, uno::Reference<task::XStatusIndicator> const& xStatusIndicator)
50 : : m_rImport(rImport),
51 : m_pInStream(pInStream),
52 : m_xStatusIndicator(xStatusIndicator),
53 : m_nGroup(0),
54 : m_nLineNumber(0),
55 138 : m_nLineStartPos(0)
56 : {
57 138 : if (!RTFTokenizer::m_bControlWordsSorted)
58 : {
59 3 : RTFTokenizer::m_bControlWordsSorted = true;
60 3 : m_aRTFControlWords = std::vector<RTFSymbol>(aRTFControlWords, aRTFControlWords + nRTFControlWords);
61 3 : std::sort(m_aRTFControlWords.begin(), m_aRTFControlWords.end());
62 : }
63 138 : }
64 :
65 276 : RTFTokenizer::~RTFTokenizer()
66 : {
67 276 : }
68 :
69 886154 : SvStream& RTFTokenizer::Strm()
70 : {
71 886154 : return *m_pInStream;
72 : }
73 :
74 138 : int RTFTokenizer::resolveParse()
75 : {
76 : SAL_INFO( "writerfilter", OSL_THIS_FUNC );
77 : char ch;
78 : int ret;
79 : // for hex chars
80 138 : int b = 0, count = 2;
81 138 : sal_uInt32 nPercentSize = 0;
82 138 : sal_uInt32 nLastPos = 0;
83 :
84 138 : if (m_xStatusIndicator.is())
85 : {
86 127 : static ResMgr* pResMgr = ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag().getLocale());
87 127 : OUString sDocLoad(ResId(RID_SVXSTR_DOC_LOAD, *pResMgr).toString());
88 :
89 127 : sal_uInt32 nCurrentPos = Strm().Tell();
90 127 : Strm().Seek(STREAM_SEEK_TO_END);
91 127 : sal_uInt32 nEndPos = Strm().Tell();
92 127 : Strm().Seek(nCurrentPos);
93 127 : m_xStatusIndicator->start(sDocLoad, nEndPos);
94 127 : nPercentSize = nEndPos / 100;
95 :
96 127 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
97 : }
98 :
99 124695 : while ((Strm() >> ch, !Strm().IsEof()))
100 : {
101 : //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
102 :
103 124555 : sal_uInt32 nCurrentPos = Strm().Tell();
104 124555 : if (m_xStatusIndicator.is() && nCurrentPos > (nLastPos + nPercentSize))
105 4862 : m_xStatusIndicator->setValue(nLastPos = nCurrentPos);
106 :
107 124555 : if (m_nGroup < 0)
108 0 : return ERROR_GROUP_UNDER;
109 124555 : if (m_nGroup > 0 && m_rImport.getState().nInternalState == INTERNAL_BIN)
110 : {
111 1 : ret = m_rImport.resolveChars(ch);
112 1 : if (ret)
113 0 : return ret;
114 : }
115 : else
116 : {
117 124554 : switch (ch)
118 : {
119 : case '{':
120 5386 : ret = m_rImport.pushState();
121 5386 : if (ret)
122 0 : return ret;
123 5386 : break;
124 : case '}':
125 5383 : ret = m_rImport.popState();
126 5383 : if (ret)
127 0 : return ret;
128 5383 : if (m_nGroup == 0)
129 : {
130 135 : if (m_rImport.isSubstream())
131 9 : m_rImport.finishSubstream();
132 135 : return 0;
133 : }
134 5248 : break;
135 : case '\\':
136 54505 : ret = resolveKeyword();
137 54504 : if (ret)
138 0 : return ret;
139 54504 : break;
140 : case 0x0d:
141 3275 : break; // ignore this
142 : case 0x0a:
143 4753 : m_nLineNumber++;
144 4753 : m_nLineStartPos = nCurrentPos;
145 4753 : break;
146 : default:
147 51252 : if (m_nGroup == 0)
148 0 : return ERROR_CHAR_OVER;
149 51252 : if (m_rImport.getState().nInternalState == INTERNAL_NORMAL)
150 : {
151 4534 : ret = m_rImport.resolveChars(ch);
152 4534 : if (ret)
153 0 : return ret;
154 : }
155 : else
156 : {
157 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": hex internal state");
158 46718 : b = b << 4;
159 46718 : sal_Int8 parsed = asHex(ch);
160 46718 : if (parsed == -1)
161 0 : return ERROR_HEX_INVALID;
162 46718 : b += parsed;
163 46718 : count--;
164 46718 : if (!count)
165 : {
166 23359 : ret = m_rImport.resolveChars(b);
167 23359 : if (ret)
168 0 : return ret;
169 23359 : count = 2;
170 23359 : b = 0;
171 23359 : m_rImport.getState().nInternalState = INTERNAL_NORMAL;
172 : }
173 : }
174 51252 : break;
175 : }
176 : }
177 : }
178 :
179 2 : if (m_nGroup < 0)
180 0 : return ERROR_GROUP_UNDER;
181 2 : else if (m_nGroup > 0)
182 2 : return ERROR_GROUP_OVER;
183 0 : return 0;
184 : }
185 :
186 86406 : int RTFTokenizer::asHex(char ch)
187 : {
188 86406 : int ret = 0;
189 86406 : if (isdigit(ch))
190 64840 : ret = ch - '0';
191 : else
192 : {
193 21566 : if (islower(ch))
194 : {
195 21566 : if (ch < 'a' || ch > 'f')
196 0 : return -1;
197 21566 : ret = ch - 'a';
198 : }
199 : else
200 : {
201 0 : if (ch < 'A' || ch > 'F')
202 0 : return -1;
203 0 : ret = ch - 'A';
204 : }
205 21566 : ret += 10;
206 : }
207 86406 : return ret;
208 : }
209 :
210 5383 : int RTFTokenizer::getGroup() const
211 : {
212 5383 : return m_nGroup;
213 : }
214 :
215 5386 : void RTFTokenizer::pushGroup()
216 : {
217 5386 : m_nGroup++;
218 5386 : }
219 :
220 5383 : void RTFTokenizer::popGroup()
221 : {
222 5383 : m_nGroup--;
223 5383 : }
224 :
225 54505 : int RTFTokenizer::resolveKeyword()
226 : {
227 : char ch;
228 54505 : OStringBuffer aBuf;
229 54505 : bool bNeg = false;
230 54505 : bool bParam = false;
231 54505 : int nParam = 0;
232 :
233 54505 : Strm() >> ch;
234 54505 : if (Strm().IsEof())
235 0 : return ERROR_EOF;
236 :
237 54505 : if (!isalpha(ch))
238 : {
239 24123 : aBuf.append(ch);
240 24123 : OString aKeyword = aBuf.makeStringAndClear();
241 : // control symbols aren't followed by a space, so we can return here
242 : // without doing any SeekRel()
243 24123 : return dispatchKeyword(aKeyword, bParam, nParam);
244 : }
245 212594 : while(isalpha(ch))
246 : {
247 151831 : aBuf.append(ch);
248 151831 : Strm() >> ch;
249 151831 : if (Strm().IsEof())
250 : {
251 1 : ch = ' ';
252 1 : break;
253 : }
254 : }
255 30382 : if (aBuf.getLength() > 32)
256 : // See RTF spec v1.9.1, page 7
257 : // A control word's name cannot be longer than 32 letters.
258 1 : throw io::BufferSizeExceededException();
259 :
260 30381 : if (ch == '-')
261 : {
262 : // in case we'll have a parameter, that will be negative
263 115 : bNeg = true;
264 115 : Strm() >> ch;
265 115 : if (Strm().IsEof())
266 0 : return ERROR_EOF;
267 : }
268 30381 : if (isdigit(ch))
269 : {
270 17057 : OStringBuffer aParameter;
271 :
272 : // we have a parameter
273 17057 : bParam = true;
274 72521 : while(isdigit(ch))
275 : {
276 38407 : aParameter.append(ch);
277 38407 : Strm() >> ch;
278 38407 : if (Strm().IsEof())
279 : {
280 0 : ch = ' ';
281 0 : break;
282 : }
283 : }
284 17057 : nParam = aParameter.makeStringAndClear().toInt32();
285 17057 : if (bNeg)
286 115 : nParam = -nParam;
287 : }
288 30381 : if (ch != ' ')
289 22259 : Strm().SeekRel(-1);
290 30381 : OString aKeyword = aBuf.makeStringAndClear();
291 30381 : return dispatchKeyword(aKeyword, bParam, nParam);
292 : }
293 :
294 54504 : int RTFTokenizer::dispatchKeyword(OString& rKeyword, bool bParam, int nParam)
295 : {
296 54504 : if (m_rImport.getState().nDestinationState == DESTINATION_SKIP)
297 3254 : return 0;
298 : /*SAL_INFO("writefilter", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
299 : "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");*/
300 : RTFSymbol aSymbol;
301 51250 : aSymbol.sKeyword = rKeyword.getStr();
302 51250 : std::vector<RTFSymbol>::iterator low = std::lower_bound(m_aRTFControlWords.begin(), m_aRTFControlWords.end(), aSymbol);
303 51250 : int i = low - m_aRTFControlWords.begin();
304 51250 : if (low == m_aRTFControlWords.end() || aSymbol < *low)
305 : {
306 : SAL_INFO("writerfilter", OSL_THIS_FUNC << ": unknown keyword '\\" << rKeyword.getStr() << "'");
307 210 : RTFSkipDestination aSkip(m_rImport);
308 210 : aSkip.setParsed(false);
309 210 : return 0;
310 : }
311 :
312 : int ret;
313 51040 : switch (m_aRTFControlWords[i].nControlType)
314 : {
315 : case CONTROL_FLAG:
316 : // flags ignore any parameter by definition
317 8420 : ret = m_rImport.dispatchFlag(m_aRTFControlWords[i].nIndex);
318 8420 : if (ret)
319 0 : return ret;
320 8420 : break;
321 : case CONTROL_DESTINATION:
322 : // same for destinations
323 2962 : ret = m_rImport.dispatchDestination(m_aRTFControlWords[i].nIndex);
324 2962 : if (ret)
325 0 : return ret;
326 2962 : break;
327 : case CONTROL_SYMBOL:
328 : // and symbols
329 24713 : ret = m_rImport.dispatchSymbol(m_aRTFControlWords[i].nIndex);
330 24713 : if (ret)
331 0 : return ret;
332 24713 : break;
333 : case CONTROL_TOGGLE:
334 484 : ret = m_rImport.dispatchToggle(m_aRTFControlWords[i].nIndex, bParam, nParam);
335 484 : if (ret)
336 0 : return ret;
337 484 : break;
338 : case CONTROL_VALUE:
339 : // values require a parameter by definition
340 14461 : if (bParam) {
341 14421 : ret = m_rImport.dispatchValue(m_aRTFControlWords[i].nIndex, nParam);
342 14421 : if (ret)
343 0 : return ret;
344 : }
345 14461 : break;
346 : }
347 :
348 51040 : return 0;
349 : }
350 :
351 2 : OUString RTFTokenizer::getPosition()
352 : {
353 2 : OUStringBuffer aRet;
354 2 : aRet.append(m_nLineNumber + 1);
355 2 : aRet.append(",");
356 2 : aRet.append(sal_Int32(Strm().Tell() - m_nLineStartPos + 1));
357 2 : return aRet.makeStringAndClear();
358 : }
359 :
360 : } // namespace rtftok
361 15 : } // namespace writerfilter
362 :
363 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|