fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / svrtf / svparser.cxx
blob5f2bcba9750c63ab60f126a438f3e7c022b256f7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <stdio.h>
21 #include <svtools/svparser.hxx>
22 #include <tools/stream.hxx>
23 #include <tools/debug.hxx>
24 #include <rtl/textcvt.h>
25 #include <rtl/tencinfo.h>
27 // Struktur, um sich die akt. Daten zumerken
28 struct SvParser_Impl
30 String aToken; // gescanntes Token
31 sal_uLong nFilePos; // akt. Position im Stream
32 sal_uLong nlLineNr; // akt. Zeilen Nummer
33 sal_uLong nlLinePos; // akt. Spalten Nummer
34 long nTokenValue; // zusaetzlicher Wert (RTF)
35 sal_Bool bTokenHasValue; // indicates whether nTokenValue is valid
36 int nToken; // akt. Token
37 sal_Unicode nNextCh; // akt. Zeichen
39 int nSaveToken; // das Token vom Continue
41 rtl_TextToUnicodeConverter hConv;
42 rtl_TextToUnicodeContext hContext;
44 SvParser_Impl() :
45 nSaveToken(0), hConv( 0 ), hContext( (rtl_TextToUnicodeContext)1 )
53 // Konstruktor
54 SvParser::SvParser( SvStream& rIn, sal_uInt8 nStackSize )
55 : rInput( rIn )
56 , nlLineNr( 1 )
57 , nlLinePos( 1 )
58 , pImplData( 0 )
59 , nTokenValue( 0 )
60 , bTokenHasValue( false )
61 , eState( SVPAR_NOTSTARTED )
62 , eSrcEnc( RTL_TEXTENCODING_DONTKNOW )
63 , bDownloadingFile( sal_False )
64 , nTokenStackSize( nStackSize )
65 , nTokenStackPos( 0 )
67 bUCS2BSrcEnc = bSwitchToUCS2 = sal_False;
68 eState = SVPAR_NOTSTARTED;
69 if( nTokenStackSize < 3 )
70 nTokenStackSize = 3;
71 pTokenStack = new TokenStackType[ nTokenStackSize ];
72 pTokenStackPos = pTokenStack;
75 SvParser::~SvParser()
77 if( pImplData && pImplData->hConv )
79 rtl_destroyTextToUnicodeContext( pImplData->hConv,
80 pImplData->hContext );
81 rtl_destroyTextToUnicodeConverter( pImplData->hConv );
84 delete pImplData;
86 delete [] pTokenStack;
89 void SvParser::ClearTxtConvContext()
91 if( pImplData && pImplData->hConv )
92 rtl_resetTextToUnicodeContext( pImplData->hConv, pImplData->hContext );
95 void SvParser::SetSrcEncoding( rtl_TextEncoding eEnc )
98 if( eEnc != eSrcEnc )
100 if( pImplData && pImplData->hConv )
102 rtl_destroyTextToUnicodeContext( pImplData->hConv,
103 pImplData->hContext );
104 rtl_destroyTextToUnicodeConverter( pImplData->hConv );
105 pImplData->hConv = 0;
106 pImplData->hContext = (rtl_TextToUnicodeContext )1;
109 if( rtl_isOctetTextEncoding(eEnc) ||
110 RTL_TEXTENCODING_UCS2 == eEnc )
112 eSrcEnc = eEnc;
113 if( !pImplData )
114 pImplData = new SvParser_Impl;
115 pImplData->hConv = rtl_createTextToUnicodeConverter( eSrcEnc );
116 DBG_ASSERT( pImplData->hConv,
117 "SvParser::SetSrcEncoding: no converter for source encoding" );
118 if( !pImplData->hConv )
119 eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
120 else
121 pImplData->hContext =
122 rtl_createTextToUnicodeContext( pImplData->hConv );
124 else
126 DBG_ASSERT( !this,
127 "SvParser::SetSrcEncoding: invalid source encoding" );
128 eSrcEnc = RTL_TEXTENCODING_DONTKNOW;
133 void SvParser::RereadLookahead()
135 rInput.Seek(nNextChPos);
136 nNextCh = GetNextChar();
139 sal_Unicode SvParser::GetNextChar()
141 sal_Unicode c = 0U;
143 // When reading muliple bytes, we don't have to care about the file
144 // position when we run inti the pending state. The file position is
145 // maintained by SaveState/RestoreState.
146 sal_Bool bErr;
147 if( bSwitchToUCS2 && 0 == rInput.Tell() )
149 sal_uChar c1, c2;
150 sal_Bool bSeekBack = sal_True;
152 rInput >> c1;
153 bErr = rInput.IsEof() || rInput.GetError();
154 if( !bErr )
156 if( 0xff == c1 || 0xfe == c1 )
158 rInput >> c2;
159 bErr = rInput.IsEof() || rInput.GetError();
160 if( !bErr )
162 if( 0xfe == c1 && 0xff == c2 )
164 eSrcEnc = RTL_TEXTENCODING_UCS2;
165 bUCS2BSrcEnc = sal_True;
166 bSeekBack = sal_False;
168 else if( 0xff == c1 && 0xfe == c2 )
170 eSrcEnc = RTL_TEXTENCODING_UCS2;
171 bUCS2BSrcEnc = sal_False;
172 bSeekBack = sal_False;
177 if( bSeekBack )
178 rInput.Seek( 0 );
180 bSwitchToUCS2 = sal_False;
183 nNextChPos = rInput.Tell();
185 if( RTL_TEXTENCODING_UCS2 == eSrcEnc )
187 sal_Unicode cUC = USHRT_MAX;
188 sal_uChar c1, c2;
190 rInput >> c1 >> c2;
191 if( 2 == rInput.Tell() &&
192 !(rInput.IsEof() || rInput.GetError()) &&
193 ( (bUCS2BSrcEnc && 0xfe == c1 && 0xff == c2) ||
194 (!bUCS2BSrcEnc && 0xff == c1 && 0xfe == c2) ) )
195 rInput >> c1 >> c2;
197 bErr = rInput.IsEof() || rInput.GetError();
198 if( !bErr )
200 if( bUCS2BSrcEnc )
201 cUC = (sal_Unicode(c1) << 8) | c2;
202 else
203 cUC = (sal_Unicode(c2) << 8) | c1;
206 if( !bErr )
208 c = cUC;
211 else
213 sal_Size nChars = 0;
216 sal_Char c1; // signed, that's the text converter expects
217 rInput >> c1;
218 bErr = rInput.IsEof() || rInput.GetError();
219 if( !bErr )
221 if (
222 RTL_TEXTENCODING_DONTKNOW == eSrcEnc ||
223 RTL_TEXTENCODING_SYMBOL == eSrcEnc
226 // no convserion shall take place
227 c = (sal_Unicode)c1;
228 nChars = 1;
230 else
232 DBG_ASSERT( pImplData && pImplData->hConv,
233 "no text converter!" );
235 sal_Unicode cUC;
236 sal_uInt32 nInfo = 0;
237 sal_Size nCvtBytes;
238 nChars = rtl_convertTextToUnicode(
239 pImplData->hConv, pImplData->hContext,
240 &c1, 1, &cUC, 1,
241 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
242 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
243 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
244 &nInfo, &nCvtBytes);
245 if( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
247 // The conversion wasn't successful because we haven't
248 // read enough characters.
249 if( pImplData->hContext != (rtl_TextToUnicodeContext)1 )
251 while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 )
253 rInput >> c1;
254 bErr = rInput.IsEof() || rInput.GetError();
255 if( bErr )
256 break;
258 nChars = rtl_convertTextToUnicode(
259 pImplData->hConv, pImplData->hContext,
260 &c1, 1, &cUC, 1,
261 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
262 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
263 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
264 &nInfo, &nCvtBytes);
266 if( !bErr )
268 if( 1 == nChars && 0 == nInfo )
270 c = cUC;
272 else if( 0 != nChars || 0 != nInfo )
274 DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
275 "source buffer is to small" );
276 DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
277 "there is a conversion error" );
278 DBG_ASSERT( 0 == nChars,
279 "there is a converted character, but an error" );
280 // There are still errors, but nothing we can
281 // do
282 c = (sal_Unicode)'?';
283 nChars = 1;
287 else
289 sal_Char sBuffer[10];
290 sBuffer[0] = c1;
291 sal_uInt16 nLen = 1;
292 while( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) != 0 &&
293 nLen < 10 )
295 rInput >> c1;
296 bErr = rInput.IsEof() || rInput.GetError();
297 if( bErr )
298 break;
300 sBuffer[nLen++] = c1;
301 nChars = rtl_convertTextToUnicode(
302 pImplData->hConv, 0, sBuffer, nLen, &cUC, 1,
303 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR|
304 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR|
305 RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
306 &nInfo, &nCvtBytes);
308 if( !bErr )
310 if( 1 == nChars && 0 == nInfo )
312 DBG_ASSERT( nCvtBytes == nLen,
313 "no all bytes have been converted!" );
314 c = cUC;
316 else
318 DBG_ASSERT( (nInfo&RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL) == 0,
319 "source buffer is to small" );
320 DBG_ASSERT( (nInfo&~(RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL)) == 0,
321 "there is a conversion error" );
322 DBG_ASSERT( 0 == nChars,
323 "there is a converted character, but an error" );
325 // There are still errors, so we use the first
326 // character and restart after that.
327 c = (sal_Unicode)sBuffer[0];
328 rInput.SeekRel( -(nLen-1) );
329 nChars = 1;
334 else if( 1 == nChars && 0 == nInfo )
336 // The conversion was successful
337 DBG_ASSERT( nCvtBytes == 1,
338 "no all bytes have been converted!" );
339 c = cUC;
341 else if( 0 != nChars || 0 != nInfo )
343 DBG_ASSERT( 0 == nChars,
344 "there is a converted character, but an error" );
345 DBG_ASSERT( 0 != nInfo,
346 "there is no converted character and no error" );
347 // #73398#: If the character could not be converted,
348 // because a conversion is not available, do no conversion at all.
349 c = (sal_Unicode)c1;
350 nChars = 1;
356 while( 0 == nChars && !bErr );
358 if( bErr )
360 if( ERRCODE_IO_PENDING == rInput.GetError() )
362 eState = SVPAR_PENDING;
363 return c;
365 else
366 return sal_Unicode(EOF);
369 if( c == '\n' )
371 IncLineNr();
372 SetLinePos( 1L );
374 else
375 IncLinePos();
376 return c;
379 int SvParser::GetNextToken()
381 int nRet = 0;
383 if( !nTokenStackPos )
385 aToken.Erase(); // Token-Buffer loeschen
386 nTokenValue = -1; // Kennzeichen fuer kein Value gelesen
387 bTokenHasValue = false;
389 nRet = _GetNextToken();
390 if( SVPAR_PENDING == eState )
391 return nRet;
394 ++pTokenStackPos;
395 if( pTokenStackPos == pTokenStack + nTokenStackSize )
396 pTokenStackPos = pTokenStack;
398 // vom Stack holen ??
399 if( nTokenStackPos )
401 --nTokenStackPos;
402 nTokenValue = pTokenStackPos->nTokenValue;
403 bTokenHasValue = pTokenStackPos->bTokenHasValue;
404 aToken = pTokenStackPos->sToken;
405 nRet = pTokenStackPos->nTokenId;
407 // nein, dann das aktuelle auf den Stack
408 else if( SVPAR_WORKING == eState )
410 pTokenStackPos->sToken = aToken;
411 pTokenStackPos->nTokenValue = nTokenValue;
412 pTokenStackPos->bTokenHasValue = bTokenHasValue;
413 pTokenStackPos->nTokenId = nRet;
415 else if( SVPAR_ACCEPTED != eState && SVPAR_PENDING != eState )
416 eState = SVPAR_ERROR; // irgend ein Fehler
418 return nRet;
421 int SvParser::SkipToken( short nCnt ) // n Tokens zurueck "skippen"
423 pTokenStackPos = GetStackPtr( nCnt );
424 short nTmp = nTokenStackPos - nCnt;
425 if( nTmp < 0 )
426 nTmp = 0;
427 else if( nTmp > nTokenStackSize )
428 nTmp = nTokenStackSize;
429 nTokenStackPos = sal_uInt8(nTmp);
431 // und die Werte zurueck
432 aToken = pTokenStackPos->sToken;
433 nTokenValue = pTokenStackPos->nTokenValue;
434 bTokenHasValue = pTokenStackPos->bTokenHasValue;
436 return pTokenStackPos->nTokenId;
439 SvParser::TokenStackType* SvParser::GetStackPtr( short nCnt )
441 sal_uInt8 nAktPos = sal_uInt8(pTokenStackPos - pTokenStack );
442 if( nCnt > 0 )
444 if( nCnt >= nTokenStackSize )
445 nCnt = (nTokenStackSize-1);
446 if( nAktPos + nCnt < nTokenStackSize )
447 nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
448 else
449 nAktPos = sal::static_int_cast< sal_uInt8 >(
450 nAktPos + (nCnt - nTokenStackSize));
452 else if( nCnt < 0 )
454 if( -nCnt >= nTokenStackSize )
455 nCnt = -nTokenStackSize+1;
456 if( -nCnt <= nAktPos )
457 nAktPos = sal::static_int_cast< sal_uInt8 >(nAktPos + nCnt);
458 else
459 nAktPos = sal::static_int_cast< sal_uInt8 >(
460 nAktPos + (nCnt + nTokenStackSize));
462 return pTokenStack + nAktPos;
465 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
466 void SvParser::NextToken( int )
471 // fuers asynchrone lesen aus dem SvStream
473 int SvParser::GetSaveToken() const
475 return pImplData ? pImplData->nSaveToken : 0;
478 void SvParser::SaveState( int nToken )
480 // aktuellen Status merken
481 if( !pImplData )
483 pImplData = new SvParser_Impl;
484 pImplData->nSaveToken = 0;
487 pImplData->nFilePos = rInput.Tell();
488 pImplData->nToken = nToken;
490 pImplData->aToken = aToken;
491 pImplData->nlLineNr = nlLineNr;
492 pImplData->nlLinePos = nlLinePos;
493 pImplData->nTokenValue= nTokenValue;
494 pImplData->bTokenHasValue = bTokenHasValue;
495 pImplData->nNextCh = nNextCh;
498 void SvParser::RestoreState()
500 // alten Status wieder zurueck setzen
501 if( pImplData )
503 if( ERRCODE_IO_PENDING == rInput.GetError() )
504 rInput.ResetError();
505 aToken = pImplData->aToken;
506 nlLineNr = pImplData->nlLineNr;
507 nlLinePos = pImplData->nlLinePos;
508 nTokenValue= pImplData->nTokenValue;
509 bTokenHasValue=pImplData->bTokenHasValue;
510 nNextCh = pImplData->nNextCh;
512 pImplData->nSaveToken = pImplData->nToken;
514 rInput.Seek( pImplData->nFilePos );
518 void SvParser::Continue( int )
522 void SvParser::BuildWhichTbl( std::vector<sal_uInt16> &rWhichMap,
523 sal_uInt16 *pWhichIds,
524 sal_uInt16 nWhichIds )
526 sal_uInt16 aNewRange[2];
528 for( sal_uInt16 nCnt = 0; nCnt < nWhichIds; ++nCnt, ++pWhichIds )
529 if( *pWhichIds )
531 aNewRange[0] = aNewRange[1] = *pWhichIds;
532 sal_Bool bIns = sal_True;
534 // Position suchen
535 for ( sal_uInt16 nOfs = 0; rWhichMap[nOfs]; nOfs += 2 )
537 if( *pWhichIds < rWhichMap[nOfs] - 1 )
539 // neuen Range davor
540 rWhichMap.insert( rWhichMap.begin() + nOfs, aNewRange, aNewRange + 2 );
541 bIns = sal_False;
542 break;
544 else if( *pWhichIds == rWhichMap[nOfs] - 1 )
546 // diesen Range nach unten erweitern
547 rWhichMap[nOfs] = *pWhichIds;
548 bIns = sal_False;
549 break;
551 else if( *pWhichIds == rWhichMap[nOfs+1] + 1 )
553 if( rWhichMap[nOfs+2] != 0 && rWhichMap[nOfs+2] == *pWhichIds + 1 )
555 // mit dem naechsten Bereich mergen
556 rWhichMap[nOfs+1] = rWhichMap[nOfs+3];
557 rWhichMap.erase( rWhichMap.begin() + nOfs + 2,
558 rWhichMap.begin() + nOfs + 4 );
560 else
561 // diesen Range nach oben erweitern
562 rWhichMap[nOfs+1] = *pWhichIds;
563 bIns = sal_False;
564 break;
568 // einen Range hinten anhaengen
569 if( bIns )
571 rWhichMap.insert( rWhichMap.begin() + rWhichMap.size() - 1,
572 aNewRange, aNewRange + 2 );
578 IMPL_STATIC_LINK( SvParser, NewDataRead, void*, EMPTYARG )
580 switch( pThis->eState )
582 case SVPAR_PENDING:
583 // Wenn gerade ein File geladen wird duerfen wir nicht weiterlaufen,
584 // sondern muessen den Aufruf ignorieren.
585 if( pThis->IsDownloadingFile() )
586 break;
588 pThis->eState = SVPAR_WORKING;
589 pThis->RestoreState();
591 pThis->Continue( pThis->pImplData->nToken );
593 if( ERRCODE_IO_PENDING == pThis->rInput.GetError() )
594 pThis->rInput.ResetError();
596 if( SVPAR_PENDING != pThis->eState )
597 pThis->ReleaseRef(); // ansonsten sind wir fertig!
598 break;
600 case SVPAR_WAITFORDATA:
601 pThis->eState = SVPAR_WORKING;
602 break;
604 case SVPAR_NOTSTARTED:
605 case SVPAR_WORKING:
606 break;
608 default:
609 pThis->ReleaseRef(); // ansonsten sind wir fertig!
610 break;
613 return 0;
616 /*========================================================================
618 * SvKeyValueIterator.
620 *======================================================================*/
623 * SvKeyValueIterator.
625 SvKeyValueIterator::SvKeyValueIterator (void)
626 : m_pList (new SvKeyValueList_Impl),
627 m_nPos (0)
632 * ~SvKeyValueIterator.
634 SvKeyValueIterator::~SvKeyValueIterator (void)
636 delete m_pList;
640 * GetFirst.
642 sal_Bool SvKeyValueIterator::GetFirst (SvKeyValue &rKeyVal)
644 m_nPos = m_pList->size();
645 return GetNext (rKeyVal);
649 * GetNext.
651 sal_Bool SvKeyValueIterator::GetNext (SvKeyValue &rKeyVal)
653 if (m_nPos > 0)
655 rKeyVal = (*m_pList)[--m_nPos];
656 return sal_True;
658 else
660 // Nothing to do.
661 return sal_False;
666 * Append.
668 void SvKeyValueIterator::Append (const SvKeyValue &rKeyVal)
670 m_pList->push_back(new SvKeyValue(rKeyVal));
673 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */