1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <tools/stream.hxx>
11 #include <tools/resmgr.hxx>
12 #include <svx/dialogs.hrc>
13 #include <vcl/svapp.hxx>
15 #include <rtftokenizer.hxx>
16 #include <rtfskipdestination.hxx>
19 namespace writerfilter
{
22 std::vector
<RTFSymbol
> RTFTokenizer::m_aRTFControlWords
;
23 bool RTFTokenizer::m_bControlWordsSorted
;
25 RTFTokenizer::RTFTokenizer(RTFDocumentImpl
& rImport
, SvStream
* pInStream
, uno::Reference
<task::XStatusIndicator
> const& xStatusIndicator
)
27 m_pInStream(pInStream
),
28 m_xStatusIndicator(xStatusIndicator
),
33 if (!RTFTokenizer::m_bControlWordsSorted
)
35 RTFTokenizer::m_bControlWordsSorted
= true;
36 m_aRTFControlWords
= std::vector
<RTFSymbol
>(aRTFControlWords
, aRTFControlWords
+ nRTFControlWords
);
37 std::sort(m_aRTFControlWords
.begin(), m_aRTFControlWords
.end());
41 RTFTokenizer::~RTFTokenizer()
45 SvStream
& RTFTokenizer::Strm()
50 int RTFTokenizer::resolveParse()
52 SAL_INFO( "writerfilter", OSL_THIS_FUNC
);
57 sal_uInt32 nPercentSize
= 0;
58 sal_uInt32 nLastPos
= 0;
60 if (m_xStatusIndicator
.is())
62 static ResMgr
* pResMgr
= ResMgr::CreateResMgr("svx", Application::GetSettings().GetUILanguageTag());
63 OUString
sDocLoad(ResId(RID_SVXSTR_DOC_LOAD
, *pResMgr
).toString());
65 sal_uInt32 nCurrentPos
= Strm().Tell();
66 Strm().Seek(STREAM_SEEK_TO_END
);
67 sal_uInt32 nEndPos
= Strm().Tell();
68 Strm().Seek(nCurrentPos
);
69 m_xStatusIndicator
->start(sDocLoad
, nEndPos
);
70 nPercentSize
= nEndPos
/ 100;
72 m_xStatusIndicator
->setValue(nLastPos
= nCurrentPos
);
75 while ((Strm() >> ch
, !Strm().IsEof()))
77 //SAL_INFO("writerfilter", OSL_THIS_FUNC << ": parsing character '" << ch << "'");
79 sal_uInt32 nCurrentPos
= Strm().Tell();
80 if (m_xStatusIndicator
.is() && nCurrentPos
> (nLastPos
+ nPercentSize
))
81 m_xStatusIndicator
->setValue(nLastPos
= nCurrentPos
);
84 return ERROR_GROUP_UNDER
;
85 if (m_nGroup
> 0 && m_rImport
.getState().nInternalState
== INTERNAL_BIN
)
87 ret
= m_rImport
.resolveChars(ch
);
96 ret
= m_rImport
.pushState();
101 ret
= m_rImport
.popState();
106 if (m_rImport
.isSubstream())
107 m_rImport
.finishSubstream();
112 ret
= resolveKeyword();
117 break; // ignore this
120 m_nLineStartPos
= nCurrentPos
;
124 return ERROR_CHAR_OVER
;
125 if (m_rImport
.getState().nInternalState
== INTERNAL_NORMAL
)
127 ret
= m_rImport
.resolveChars(ch
);
133 SAL_INFO("writerfilter", OSL_THIS_FUNC
<< ": hex internal state");
135 sal_Int8 parsed
= asHex(ch
);
137 return ERROR_HEX_INVALID
;
142 ret
= m_rImport
.resolveChars(b
);
147 m_rImport
.getState().nInternalState
= INTERNAL_NORMAL
;
156 return ERROR_GROUP_UNDER
;
157 else if (m_nGroup
> 0)
158 return ERROR_GROUP_OVER
;
162 int RTFTokenizer::asHex(char ch
)
171 if (ch
< 'a' || ch
> 'f')
177 if (ch
< 'A' || ch
> 'F')
186 int RTFTokenizer::getGroup() const
191 void RTFTokenizer::pushGroup()
196 void RTFTokenizer::popGroup()
201 int RTFTokenizer::resolveKeyword()
216 OString aKeyword
= aBuf
.makeStringAndClear();
217 // control symbols aren't followed by a space, so we can return here
218 // without doing any SeekRel()
219 return dispatchKeyword(aKeyword
, bParam
, nParam
);
231 if (aBuf
.getLength() > 32)
232 // See RTF spec v1.9.1, page 7
233 // A control word's name cannot be longer than 32 letters.
234 throw io::BufferSizeExceededException();
238 // in case we'll have a parameter, that will be negative
246 OStringBuffer aParameter
;
248 // we have a parameter
252 aParameter
.append(ch
);
260 nParam
= aParameter
.makeStringAndClear().toInt32();
266 OString aKeyword
= aBuf
.makeStringAndClear();
267 return dispatchKeyword(aKeyword
, bParam
, nParam
);
270 int RTFTokenizer::dispatchKeyword(OString
& rKeyword
, bool bParam
, int nParam
)
272 if (m_rImport
.getState().nDestinationState
== DESTINATION_SKIP
)
274 /*SAL_INFO("writefilter", OSL_THIS_FUNC << ": keyword '\\" << rKeyword.getStr() <<
275 "' with param? " << (bParam ? 1 : 0) <<" param val: '" << (bParam ? nParam : 0) << "'");*/
277 aSymbol
.sKeyword
= rKeyword
.getStr();
278 std::vector
<RTFSymbol
>::iterator low
= std::lower_bound(m_aRTFControlWords
.begin(), m_aRTFControlWords
.end(), aSymbol
);
279 int i
= low
- m_aRTFControlWords
.begin();
280 if (low
== m_aRTFControlWords
.end() || aSymbol
< *low
)
282 SAL_INFO("writerfilter", OSL_THIS_FUNC
<< ": unknown keyword '\\" << rKeyword
.getStr() << "'");
283 RTFSkipDestination
aSkip(m_rImport
);
284 aSkip
.setParsed(false);
289 switch (m_aRTFControlWords
[i
].nControlType
)
292 // flags ignore any parameter by definition
293 ret
= m_rImport
.dispatchFlag(m_aRTFControlWords
[i
].nIndex
);
297 case CONTROL_DESTINATION
:
298 // same for destinations
299 ret
= m_rImport
.dispatchDestination(m_aRTFControlWords
[i
].nIndex
);
305 ret
= m_rImport
.dispatchSymbol(m_aRTFControlWords
[i
].nIndex
);
310 ret
= m_rImport
.dispatchToggle(m_aRTFControlWords
[i
].nIndex
, bParam
, nParam
);
315 // values require a parameter by definition
317 ret
= m_rImport
.dispatchValue(m_aRTFControlWords
[i
].nIndex
, nParam
);
327 OUString
RTFTokenizer::getPosition()
330 aRet
.append(m_nLineNumber
+ 1);
332 aRet
.append(sal_Int32(Strm().Tell() - m_nLineStartPos
+ 1));
333 return aRet
.makeStringAndClear();
336 } // namespace rtftok
337 } // namespace writerfilter
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */