xref: /trunk/main/editeng/source/rtf/svxrtf.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_editeng.hxx"
30 
31 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
32 
33 
34 #include <ctype.h>
35 #include <tools/datetime.hxx>
36 #include <rtl/tencinfo.h>
37 #include <svl/itemiter.hxx>
38 #include <svl/whiter.hxx>
39 #include <svtools/rtftoken.h>
40 #include <svl/itempool.hxx>
41 
42 #include <comphelper/string.hxx>
43 
44 #include <com/sun/star/lang/Locale.hpp>
45 #include <editeng/scriptspaceitem.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/colritem.hxx>
48 #include <editeng/svxrtf.hxx>
49 #include <editeng/editids.hrc>
50 #include <vcl/svapp.hxx>
51 
52 #include <com/sun/star/document/XDocumentProperties.hpp>
53 
54 
55 using namespace ::com::sun::star;
56 
57 
58 SV_IMPL_PTRARR( SvxRTFItemStackList, SvxRTFItemStackType* )
59 
60 CharSet lcl_GetDefaultTextEncodingForRTF()
61 {
62 
63     ::com::sun::star::lang::Locale aLocale;
64     ::rtl::OUString aLangString;
65 
66     aLocale = Application::GetSettings().GetLocale();
67     aLangString = aLocale.Language;
68 
69     if ( aLangString.equals( ::rtl::OUString::createFromAscii( "ru" ) )
70       || aLangString.equals( ::rtl::OUString::createFromAscii( "uk" ) ) )
71         return RTL_TEXTENCODING_MS_1251;
72     if ( aLangString.equals( ::rtl::OUString::createFromAscii( "tr" ) ) )
73         return RTL_TEXTENCODING_MS_1254;
74     else
75         return RTL_TEXTENCODING_MS_1252;
76 }
77 
78 // -------------- Methoden --------------------
79 
80 SvxRTFParser::SvxRTFParser( SfxItemPool& rPool, SvStream& rIn,
81             uno::Reference<document::XDocumentProperties> i_xDocProps,
82             int bReadNewDoc )
83     : SvRTFParser( rIn, 5 ),
84     rStrm(rIn),
85     aFontTbl( 16, 4 ),
86     pInsPos( 0 ),
87     pAttrPool( &rPool ),
88     m_xDocProps( i_xDocProps ),
89     pRTFDefaults( 0 ),
90     nVersionNo( 0 )
91 {
92     bNewDoc = bReadNewDoc;
93 
94     bChkStyleAttr = bCalcValue = bReadDocInfo = bIsInReadStyleTab = sal_False;
95     bIsLeftToRightDef = sal_True;
96 
97     {
98         RTFPlainAttrMapIds aTmp( rPool );
99         aPlainMap.Insert( (sal_uInt16*)&aTmp,
100                     sizeof( RTFPlainAttrMapIds ) / sizeof(sal_uInt16), 0 );
101     }
102     {
103         RTFPardAttrMapIds aTmp( rPool );
104         aPardMap.Insert( (sal_uInt16*)&aTmp,
105                     sizeof( RTFPardAttrMapIds ) / sizeof(sal_uInt16), 0 );
106     }
107     pDfltFont = new Font;
108     pDfltColor = new Color;
109 }
110 
111 void SvxRTFParser::EnterEnvironment()
112 {
113 }
114 
115 void SvxRTFParser::LeaveEnvironment()
116 {
117 }
118 
119 void SvxRTFParser::ResetPard()
120 {
121 }
122 
123 SvxRTFParser::~SvxRTFParser()
124 {
125     if( !aColorTbl.empty() )
126         ClearColorTbl();
127     if( aFontTbl.Count() )
128         ClearFontTbl();
129     if( aStyleTbl.Count() )
130         ClearStyleTbl();
131     if( !aAttrStack.empty() )
132         ClearAttrStack();
133 
134     delete pRTFDefaults;
135 
136     delete pInsPos;
137     delete pDfltFont;
138     delete pDfltColor;
139 }
140 
141 void SvxRTFParser::SetInsPos( const SvxPosition& rNew )
142 {
143     if( pInsPos )
144         delete pInsPos;
145     pInsPos = rNew.Clone();
146 }
147 
148 SvParserState SvxRTFParser::CallParser()
149 {
150     DBG_ASSERT( pInsPos, "no insertion" );
151 
152     if( !pInsPos )
153         return SVPAR_ERROR;
154 
155     if( !aColorTbl.empty() )
156         ClearColorTbl();
157     if( aFontTbl.Count() )
158         ClearFontTbl();
159     if( aStyleTbl.Count() )
160         ClearStyleTbl();
161     if( !aAttrStack.empty() )
162         ClearAttrStack();
163 
164     bIsSetDfltTab = sal_False;
165     bNewGroup = sal_False;
166     nDfltFont = 0;
167 
168     sBaseURL.Erase();
169 
170     // erzeuge aus den gesetzten WhichIds die richtige WhichId-Tabelle.
171     BuildWhichTbl();
172 
173     return SvRTFParser::CallParser();
174 }
175 
176 void SvxRTFParser::Continue( int nToken )
177 {
178     SvRTFParser::Continue( nToken );
179 
180     if( SVPAR_PENDING != GetStatus() )
181     {
182         SetAllAttrOfStk();
183 #if 0
184     //Regardless of what "color 0" is, word defaults to auto as the default colour.
185     //e.g. see #i7713#
186         if( bNewDoc && ((RTFPlainAttrMapIds*)aPlainMap.GetData())->nColor )
187             pAttrPool->SetPoolDefaultItem( SvxColorItem( GetColor( 0 ),
188                         ((RTFPlainAttrMapIds*)aPlainMap.GetData())->nColor ));
189 #endif
190      }
191 }
192 
193 
194 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
195 void SvxRTFParser::NextToken( int nToken )
196 {
197     sal_Unicode cCh;
198     switch( nToken )
199     {
200     case RTF_COLORTBL:      ReadColorTable();       break;
201     case RTF_FONTTBL:       ReadFontTable();        break;
202     case RTF_STYLESHEET:    ReadStyleTable();       break;
203 
204     case RTF_DEFF:
205             if( bNewDoc )
206             {
207                 if( aFontTbl.Count() )
208                     // koennen wir sofort setzen
209                     SetDefault( nToken, nTokenValue );
210                 else
211                     // wird nach einlesen der Fonttabelle gesetzt
212                     nDfltFont = int(nTokenValue);
213             }
214             break;
215 
216     case RTF_DEFTAB:
217     case RTF_DEFLANG:
218             if( bNewDoc )
219                 SetDefault( nToken, nTokenValue );
220             break;
221 
222 
223     case RTF_PICT:          ReadBitmapData();       break;
224 
225     case RTF_LINE:          cCh = '\n'; goto INSINGLECHAR;
226     case RTF_TAB:           cCh = '\t'; goto INSINGLECHAR;
227     case RTF_SUBENTRYINDEX: cCh = ':';  goto INSINGLECHAR;
228 
229     case RTF_EMDASH:        cCh = 151;  goto INSINGLECHAR;
230     case RTF_ENDASH:        cCh = 150;  goto INSINGLECHAR;
231     case RTF_BULLET:        cCh = 149;  goto INSINGLECHAR;
232     case RTF_LQUOTE:        cCh = 145;  goto INSINGLECHAR;
233     case RTF_RQUOTE:        cCh = 146;  goto INSINGLECHAR;
234     case RTF_LDBLQUOTE:     cCh = 147;  goto INSINGLECHAR;
235     case RTF_RDBLQUOTE:     cCh = 148;  goto INSINGLECHAR;
236 INSINGLECHAR:
237         aToken = ByteString::ConvertToUnicode( (sal_Char)cCh,
238                                             RTL_TEXTENCODING_MS_1252 );
239 
240         // kein Break, aToken wird als Text gesetzt
241     case RTF_TEXTTOKEN:
242         {
243             InsertText();
244             // alle angesammelten Attribute setzen
245             for( sal_uInt16 n = aAttrSetList.Count(); n; )
246             {
247                 SvxRTFItemStackType* pStkSet = aAttrSetList[--n];
248                 SetAttrSet( *pStkSet );
249                 aAttrSetList.DeleteAndDestroy( n );
250             }
251         }
252         break;
253 
254 
255     case RTF_PAR:
256         InsertPara();
257         break;
258     case '{':
259         if (bNewGroup)          // Verschachtelung !!
260             _GetAttrSet();
261         EnterEnvironment();
262         bNewGroup = true;
263         break;
264     case '}':
265         if( !bNewGroup )        // leere Gruppe ??
266             AttrGroupEnd();
267         LeaveEnvironment();
268         bNewGroup = false;
269         break;
270     case RTF_INFO:
271 #ifndef SVX_LIGHT
272         if (bReadDocInfo && bNewDoc && m_xDocProps.is())
273             ReadInfo();
274         else
275 #endif
276             SkipGroup();
277         break;
278 
279     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
280     // erstmal gesamt ueberlesen (muessen alle in einer Gruppe stehen !!)
281     // Koennen auch ohne dem IGNORE-Flag im RTF-File auftreten; alle Gruppen
282     // mit IGNORE-Flag werden im default-Zweig ueberlesen.
283 
284     case RTF_SWG_PRTDATA:
285     case RTF_FIELD:
286     case RTF_ATNID:
287     case RTF_ANNOTATION:
288 
289     case RTF_BKMKSTART:
290     case RTF_BKMKEND:
291     case RTF_BKMK_KEY:
292     case RTF_XE:
293     case RTF_TC:
294     case RTF_NEXTFILE:
295     case RTF_TEMPLATE:
296 #if 0
297     //disabled for #i19718#
298     case RTF_SHPRSLT:   // RTF_SHP fehlt noch !!
299 #endif
300                             SkipGroup();
301                             break;
302     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
303 
304     case RTF_PGDSCNO:
305     case RTF_PGBRK:
306     case RTF_SHADOW:
307             if( RTF_IGNOREFLAG != GetStackPtr( -1 )->nTokenId )
308                 break;
309             nToken = SkipToken( -1 );
310             if( '{' == GetStackPtr( -1 )->nTokenId )
311                 nToken = SkipToken( -1 );
312 
313             ReadAttr( nToken, &GetAttrSet() );
314             break;
315 
316     default:
317         switch( nToken & ~(0xff | RTF_SWGDEFS) )
318         {
319         case RTF_PARFMT:        // hier gibts keine Swg-Defines
320             ReadAttr( nToken, &GetAttrSet() );
321             break;
322 
323         case RTF_CHRFMT:
324         case RTF_BRDRDEF:
325         case RTF_TABSTOPDEF:
326 
327             if( RTF_SWGDEFS & nToken)
328             {
329                 if( RTF_IGNOREFLAG != GetStackPtr( -1 )->nTokenId )
330                     break;
331                 nToken = SkipToken( -1 );
332                 if( '{' == GetStackPtr( -1 )->nTokenId )
333                 {
334                     nToken = SkipToken( -1 );
335                 }
336             }
337             ReadAttr( nToken, &GetAttrSet() );
338             break;
339         default:
340             {
341                 if( /*( '{' == GetStackPtr( -1 )->nTokenId ) ||*/
342                     ( RTF_IGNOREFLAG == GetStackPtr( -1 )->nTokenId &&
343                       '{' == GetStackPtr( -2 )->nTokenId ) )
344                     SkipGroup();
345             }
346             break;
347         }
348         break;
349     }
350 }
351 
352 void SvxRTFParser::ReadStyleTable()
353 {
354     int nToken, bSaveChkStyleAttr = bChkStyleAttr;
355     short nStyleNo = 0;
356     int _nOpenBrakets = 1;      // die erste wurde schon vorher erkannt !!
357     SvxRTFStyleType* pStyle = new SvxRTFStyleType( *pAttrPool, aWhichMap.GetData() );
358     pStyle->aAttrSet.Put( GetRTFDefaults() );
359 
360     bIsInReadStyleTab = sal_True;
361     bChkStyleAttr = sal_False;      // Attribute nicht gegen die Styles checken
362 
363     while( _nOpenBrakets && IsParserWorking() )
364     {
365         switch( nToken = GetNextToken() )
366         {
367         case '}':       if( --_nOpenBrakets && IsParserWorking() )
368                             // Style konnte vollstaendig gelesen werden,
369                             // also ist das noch ein stabiler Status
370                             SaveState( RTF_STYLESHEET );
371                         break;
372         case '{':
373             {
374                 if( RTF_IGNOREFLAG != GetNextToken() )
375                     nToken = SkipToken( -1 );
376                 else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ) &&
377                             RTF_PN != nToken )
378                     nToken = SkipToken( -2 );
379                 else
380                 {
381                     // gleich herausfiltern
382                     ReadUnknownData();
383                     nToken = GetNextToken();
384                     if( '}' != nToken )
385                         eState = SVPAR_ERROR;
386                     break;
387                 }
388                 ++_nOpenBrakets;
389             }
390             break;
391 
392         case RTF_SBASEDON:  pStyle->nBasedOn = sal_uInt16(nTokenValue); pStyle->bBasedOnIsSet=sal_True; break;
393         case RTF_SNEXT:     pStyle->nNext = sal_uInt16(nTokenValue);    break;
394         case RTF_OUTLINELEVEL:
395         case RTF_SOUTLVL:   pStyle->nOutlineNo = sal_uInt8(nTokenValue);    break;
396         case RTF_S:         nStyleNo = (short)nTokenValue;          break;
397         case RTF_CS:        nStyleNo = (short)nTokenValue;
398                             pStyle->bIsCharFmt = sal_True;
399                             break;
400 
401         case RTF_TEXTTOKEN:
402             {
403                 pStyle->sName = DelCharAtEnd( aToken, ';' );
404 
405 /*
406 ??? soll man das umsetzen ???
407                 if( !pStyle->sName.Len() )
408                     pStyle->sName = "Standard";
409 */
410                 // sollte die Nummer doppelt vergeben werden ?
411                 if( aStyleTbl.Count() )
412                 {
413                     SvxRTFStyleType* pOldSt = aStyleTbl.Remove( nStyleNo );
414                     if( pOldSt )
415                         delete pOldSt;
416                 }
417                 // alle Daten vom Style vorhanden, also ab in die Tabelle
418                 aStyleTbl.Insert( nStyleNo, pStyle );
419                 pStyle = new SvxRTFStyleType( *pAttrPool, aWhichMap.GetData() );
420                 pStyle->aAttrSet.Put( GetRTFDefaults() );
421                 nStyleNo = 0;
422             }
423             break;
424         default:
425             switch( nToken & ~(0xff | RTF_SWGDEFS) )
426             {
427             case RTF_PARFMT:        // hier gibts keine Swg-Defines
428                 ReadAttr( nToken, &pStyle->aAttrSet );
429                 break;
430 
431             case RTF_CHRFMT:
432             case RTF_BRDRDEF:
433             case RTF_TABSTOPDEF:
434 
435                 if( RTF_SWGDEFS & nToken)
436                 {
437                     if( RTF_IGNOREFLAG != GetStackPtr( -1 )->nTokenId )
438                         break;
439                     nToken = SkipToken( -1 );
440                     if( '{' == GetStackPtr( -1 )->nTokenId )
441                     {
442                         nToken = SkipToken( -1 );
443 #if 0
444                         --_nOpenBrakets;        // korrigieren!!
445 #endif
446                     }
447                 }
448                 ReadAttr( nToken, &pStyle->aAttrSet );
449                 break;
450             }
451             break;
452         }
453     }
454     delete pStyle;          // loesche das letze Style
455     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
456 
457     // Flag wieder auf alten Zustand
458     bChkStyleAttr = bSaveChkStyleAttr;
459     bIsInReadStyleTab = sal_False;
460 }
461 
462 void SvxRTFParser::ReadColorTable()
463 {
464     int nToken;
465     sal_uInt8 nRed = 0xff, nGreen = 0xff, nBlue = 0xff;
466 
467     while( '}' != ( nToken = GetNextToken() ) && IsParserWorking() )
468     {
469         switch( nToken )
470         {
471         case RTF_RED:   nRed = sal_uInt8(nTokenValue);      break;
472         case RTF_GREEN: nGreen = sal_uInt8(nTokenValue);        break;
473         case RTF_BLUE:  nBlue = sal_uInt8(nTokenValue);     break;
474 
475         case RTF_TEXTTOKEN:     // oder sollte irgendein Unsin darumstehen?
476             if( 1 == aToken.Len()
477                     ? aToken.GetChar( 0 ) != ';'
478                     : STRING_NOTFOUND == aToken.Search( ';' ) )
479                 break;      // es muss zumindestens das ';' gefunden werden
480 
481             // else kein break !!
482 
483         case ';':
484             if( IsParserWorking() )
485             {
486                 // eine Farbe ist Fertig, in die Tabelle eintragen
487                 // versuche die Werte auf SV interne Namen zu mappen
488                 ColorPtr pColor = new Color( nRed, nGreen, nBlue );
489                 if( aColorTbl.empty() &&
490                     sal_uInt8(-1) == nRed && sal_uInt8(-1) == nGreen && sal_uInt8(-1) == nBlue )
491                     pColor->SetColor( COL_AUTO );
492                 aColorTbl.push_back( pColor );
493                 nRed = 0, nGreen = 0, nBlue = 0;
494 
495                 // Color konnte vollstaendig gelesen werden,
496                 // also ist das noch ein stabiler Status
497                 SaveState( RTF_COLORTBL );
498             }
499             break;
500         }
501     }
502     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
503 }
504 
505 void SvxRTFParser::ReadFontTable()
506 {
507     int nToken;
508     int _nOpenBrakets = 1;      // die erste wurde schon vorher erkannt !!
509     Font* pFont = new Font();
510     short nFontNo(0), nInsFontNo (0);
511     String sAltNm, sFntNm;
512     sal_Bool bIsAltFntNm = sal_False, bCheckNewFont;
513 
514     CharSet nSystemChar = lcl_GetDefaultTextEncodingForRTF();
515     pFont->SetCharSet( nSystemChar );
516     SetEncoding( nSystemChar );
517 
518     while( _nOpenBrakets && IsParserWorking() )
519     {
520         bCheckNewFont = sal_False;
521         switch( ( nToken = GetNextToken() ))
522         {
523             case '}':
524                 bIsAltFntNm = sal_False;
525                 // Style konnte vollstaendig gelesen werden,
526                 // also ist das noch ein stabiler Status
527                 if( --_nOpenBrakets <= 1 && IsParserWorking() )
528                     SaveState( RTF_FONTTBL );
529                 bCheckNewFont = sal_True;
530                 nInsFontNo = nFontNo;
531                 break;
532             case '{':
533                 if( RTF_IGNOREFLAG != GetNextToken() )
534                     nToken = SkipToken( -1 );
535                 // Unknown und alle bekannten nicht ausgewerteten Gruppen
536                 // sofort ueberspringen
537                 else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ) &&
538                         RTF_PANOSE != nToken && RTF_FNAME != nToken &&
539                         RTF_FONTEMB != nToken && RTF_FONTFILE != nToken )
540                     nToken = SkipToken( -2 );
541                 else
542                 {
543                     // gleich herausfiltern
544                     ReadUnknownData();
545                     nToken = GetNextToken();
546                     if( '}' != nToken )
547                         eState = SVPAR_ERROR;
548                     break;
549                 }
550                 ++_nOpenBrakets;
551                 break;
552             case RTF_FROMAN:
553                 pFont->SetFamily( FAMILY_ROMAN );
554                 break;
555             case RTF_FSWISS:
556                 pFont->SetFamily( FAMILY_SWISS );
557                 break;
558             case RTF_FMODERN:
559                 pFont->SetFamily( FAMILY_MODERN );
560                 break;
561             case RTF_FSCRIPT:
562                 pFont->SetFamily( FAMILY_SCRIPT );
563                 break;
564             case RTF_FDECOR:
565                 pFont->SetFamily( FAMILY_DECORATIVE );
566                 break;
567             // bei technischen/symbolischen Font wird der CharSet ungeschaltet!!
568             case RTF_FTECH:
569                 pFont->SetCharSet( RTL_TEXTENCODING_SYMBOL );
570                 // deliberate fall through
571             case RTF_FNIL:
572                 pFont->SetFamily( FAMILY_DONTKNOW );
573                 break;
574             case RTF_FCHARSET:
575                 if (-1 != nTokenValue)
576                 {
577                     CharSet nCharSet = rtl_getTextEncodingFromWindowsCharset(
578                         (sal_uInt8)nTokenValue);
579                     pFont->SetCharSet(nCharSet);
580                     //When we're in a font, the fontname is in the font
581                     //charset, except for symbol fonts I believe
582                     if (nCharSet == RTL_TEXTENCODING_SYMBOL)
583                         nCharSet = RTL_TEXTENCODING_DONTKNOW;
584                     SetEncoding(nCharSet);
585                 }
586                 break;
587             case RTF_FPRQ:
588                 switch( nTokenValue )
589                 {
590                     case 1:
591                         pFont->SetPitch( PITCH_FIXED );
592                         break;
593                     case 2:
594                         pFont->SetPitch( PITCH_VARIABLE );
595                         break;
596                 }
597                 break;
598             case RTF_F:
599                 bCheckNewFont = sal_True;
600                 nInsFontNo = nFontNo;
601                 nFontNo = (short)nTokenValue;
602                 break;
603             case RTF_FALT:
604                 bIsAltFntNm = sal_True;
605                 break;
606             case RTF_TEXTTOKEN:
607                 DelCharAtEnd( aToken, ';' );
608                 if ( aToken.Len() )
609                 {
610                     if( bIsAltFntNm )
611                         sAltNm = aToken;
612                     else
613                         sFntNm = aToken;
614                 }
615                 break;
616         }
617 
618         if( bCheckNewFont && 1 >= _nOpenBrakets && sFntNm.Len() )  // one font is ready
619         {
620             // alle Daten vom Font vorhanden, also ab in die Tabelle
621             if (sAltNm.Len())
622                 (sFntNm += ';' ) += sAltNm;
623 
624             pFont->SetName( sFntNm );
625             aFontTbl.Insert( nInsFontNo, pFont );
626             pFont = new Font();
627             pFont->SetCharSet( nSystemChar );
628             sAltNm.Erase();
629             sFntNm.Erase();
630         }
631     }
632     // den letzen muessen wir selbst loeschen
633     delete pFont;
634     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
635 
636     // setze den default Font am Doc
637     if( bNewDoc && IsParserWorking() )
638         SetDefault( RTF_DEFF, nDfltFont );
639 }
640 
641 void SvxRTFParser::ReadBitmapData()
642 {
643     SvRTFParser::ReadBitmapData();
644 }
645 
646 void SvxRTFParser::ReadOLEData()
647 {
648     SvRTFParser::ReadOLEData();
649 }
650 
651 String& SvxRTFParser::GetTextToEndGroup( String& rStr )
652 {
653     rStr.Erase( 0 );
654     int _nOpenBrakets = 1, nToken;      // die erste wurde schon vorher erkannt !!
655 
656     while( _nOpenBrakets && IsParserWorking() )
657     {
658         switch( nToken = GetNextToken() )
659         {
660         case '}':       --_nOpenBrakets;    break;
661         case '{':
662             {
663                 if( RTF_IGNOREFLAG != GetNextToken() )
664                     nToken = SkipToken( -1 );
665                 else if( RTF_UNKNOWNCONTROL != GetNextToken() )
666                     nToken = SkipToken( -2 );
667                 else
668                 {
669                     // gleich herausfiltern
670                     ReadUnknownData();
671                     nToken = GetNextToken();
672                     if( '}' != nToken )
673                         eState = SVPAR_ERROR;
674                     break;
675                 }
676                 ++_nOpenBrakets;
677             }
678             break;
679 
680         case RTF_TEXTTOKEN:
681             rStr += aToken;
682             break;
683         }
684     }
685     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
686     return rStr;
687 }
688 
689 util::DateTime SvxRTFParser::GetDateTimeStamp( )
690 {
691     util::DateTime aDT;
692     sal_Bool bWeiter = sal_True;
693     int nToken;
694     while( bWeiter && IsParserWorking() )
695     {
696         switch( nToken = GetNextToken() )
697         {
698         case RTF_YR:    aDT.Year = (sal_uInt16)nTokenValue;     break;
699         case RTF_MO:    aDT.Month = (sal_uInt16)nTokenValue;    break;
700         case RTF_DY:    aDT.Day = (sal_uInt16)nTokenValue;      break;
701         case RTF_HR:    aDT.Hours = (sal_uInt16)nTokenValue;    break;
702         case RTF_MIN:   aDT.Minutes = (sal_uInt16)nTokenValue;  break;
703         default:
704             bWeiter = sal_False;
705         }
706     }
707     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
708     return aDT;
709 }
710 
711 void SvxRTFParser::ReadInfo( const sal_Char* pChkForVerNo )
712 {
713 #ifndef SVX_LIGHT
714     int _nOpenBrakets = 1, nToken;      // die erste wurde schon vorher erkannt !!
715     DBG_ASSERT(m_xDocProps.is(),
716         "SvxRTFParser::ReadInfo: no DocumentProperties");
717     String sStr, sComment;
718     long nVersNo = 0;
719 
720     while( _nOpenBrakets && IsParserWorking() )
721     {
722         switch( nToken = GetNextToken() )
723         {
724         case '}':       --_nOpenBrakets;    break;
725         case '{':
726             {
727                 if( RTF_IGNOREFLAG != GetNextToken() )
728                     nToken = SkipToken( -1 );
729                 else if( RTF_UNKNOWNCONTROL != GetNextToken() )
730                     nToken = SkipToken( -2 );
731                 else
732                 {
733                     // gleich herausfiltern
734                     ReadUnknownData();
735                     nToken = GetNextToken();
736                     if( '}' != nToken )
737                         eState = SVPAR_ERROR;
738                     break;
739                 }
740                 ++_nOpenBrakets;
741             }
742             break;
743 
744         case RTF_TITLE:
745             m_xDocProps->setTitle( GetTextToEndGroup( sStr ) );
746             break;
747         case RTF_SUBJECT:
748             m_xDocProps->setSubject( GetTextToEndGroup( sStr ) );
749             break;
750         case RTF_AUTHOR:
751             m_xDocProps->setAuthor( GetTextToEndGroup( sStr ) );
752             break;
753         case RTF_OPERATOR:
754             m_xDocProps->setModifiedBy( GetTextToEndGroup( sStr ) );
755             break;
756         case RTF_KEYWORDS:
757             {
758                 ::rtl::OUString sTemp = GetTextToEndGroup( sStr );
759                 m_xDocProps->setKeywords(
760                     ::comphelper::string::convertCommaSeparated(sTemp) );
761                 break;
762             }
763         case RTF_DOCCOMM:
764             m_xDocProps->setDescription( GetTextToEndGroup( sStr ) );
765             break;
766 
767         case RTF_HLINKBASE:
768             sBaseURL = GetTextToEndGroup( sStr ) ;
769             break;
770 
771         case RTF_CREATIM:
772             m_xDocProps->setCreationDate( GetDateTimeStamp() );
773             break;
774 
775         case RTF_REVTIM:
776             m_xDocProps->setModificationDate( GetDateTimeStamp() );
777             break;
778 
779         case RTF_PRINTIM:
780             m_xDocProps->setPrintDate( GetDateTimeStamp() );
781             break;
782 
783         case RTF_COMMENT:
784             GetTextToEndGroup( sComment );
785             break;
786 
787         case RTF_BUPTIM:
788             SkipGroup();
789             break;
790 
791         case RTF_VERN:
792             nVersNo = nTokenValue;
793             break;
794 
795         case RTF_EDMINS:
796         case RTF_ID:
797         case RTF_VERSION:
798         case RTF_NOFPAGES:
799         case RTF_NOFWORDS:
800         case RTF_NOFCHARS:
801             NextToken( nToken );
802             break;
803 
804 //      default:
805         }
806     }
807 
808     if( pChkForVerNo &&
809         COMPARE_EQUAL == sComment.CompareToAscii( pChkForVerNo ))
810         nVersionNo = nVersNo;
811 
812     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
813 #endif
814 }
815 
816 
817 void SvxRTFParser::ClearColorTbl()
818 {
819     while ( !aColorTbl.empty() )
820     {
821         delete aColorTbl.back();
822         aColorTbl.pop_back();
823     }
824 }
825 
826 void SvxRTFParser::ClearFontTbl()
827 {
828     for( sal_uInt32 nCnt = aFontTbl.Count(); nCnt; )
829         delete aFontTbl.GetObject( --nCnt );
830 }
831 
832 void SvxRTFParser::ClearStyleTbl()
833 {
834     for( sal_uInt32 nCnt = aStyleTbl.Count(); nCnt; )
835         delete aStyleTbl.GetObject( --nCnt );
836 }
837 
838 void SvxRTFParser::ClearAttrStack()
839 {
840     SvxRTFItemStackType* pTmp;
841     for( size_t nCnt = aAttrStack.size(); nCnt; --nCnt )
842     {
843         pTmp = aAttrStack.back();
844         aAttrStack.pop_back();
845         delete pTmp;
846     }
847 }
848 
849 String& SvxRTFParser::DelCharAtEnd( String& rStr, const sal_Unicode cDel )
850 {
851     if( rStr.Len() && ' ' == rStr.GetChar( 0 ))
852         rStr.EraseLeadingChars();
853     if( rStr.Len() && ' ' == rStr.GetChar( rStr.Len()-1 ))
854         rStr.EraseTrailingChars();
855     if( rStr.Len() && cDel == rStr.GetChar( rStr.Len()-1 ))
856         rStr.Erase( rStr.Len()-1 );
857     return rStr;
858 }
859 
860 
861 const Font& SvxRTFParser::GetFont( sal_uInt16 nId )
862 {
863     const Font* pFont = aFontTbl.Get( nId );
864     if( !pFont )
865     {
866         const SvxFontItem& rDfltFont = (const SvxFontItem&)
867                         pAttrPool->GetDefaultItem(
868                     ((RTFPlainAttrMapIds*)aPlainMap.GetData())->nFont );
869         pDfltFont->SetName( rDfltFont.GetStyleName() );
870         pDfltFont->SetFamily( rDfltFont.GetFamily() );
871         pFont = pDfltFont;
872     }
873     return *pFont;
874 }
875 
876 SvxRTFItemStackType* SvxRTFParser::_GetAttrSet( int bCopyAttr )
877 {
878     SvxRTFItemStackType* pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
879     SvxRTFItemStackType* pNew;
880     if( pAkt )
881         pNew = new SvxRTFItemStackType( *pAkt, *pInsPos, bCopyAttr );
882     else
883         pNew = new SvxRTFItemStackType( *pAttrPool, aWhichMap.GetData(),
884                                         *pInsPos );
885     pNew->SetRTFDefaults( GetRTFDefaults() );
886 
887     aAttrStack.push_back( pNew );
888     bNewGroup = sal_False;
889     return pNew;
890 }
891 
892 
893 void SvxRTFParser::_ClearStyleAttr( SvxRTFItemStackType& rStkType )
894 {
895     // check attributes to the attributes of the stylesheet or to
896     // the default attrs of the document
897     SfxItemSet &rSet = rStkType.GetAttrSet();
898     const SfxItemPool& rPool = *rSet.GetPool();
899     const SfxPoolItem* pItem;
900     SfxWhichIter aIter( rSet );
901 
902     SvxRTFStyleType* pStyle;
903     if( !IsChkStyleAttr() ||
904         !rStkType.GetAttrSet().Count() ||
905         0 == ( pStyle = aStyleTbl.Get( rStkType.nStyleNo ) ))
906     {
907         for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() )
908         {
909             if( SFX_WHICH_MAX > nWhich &&
910                 SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem ) &&
911                      rPool.GetDefaultItem( nWhich ) == *pItem )
912                 rSet.ClearItem( nWhich );       // loeschen
913         }
914     }
915     else
916     {
917         // alle Attribute, die schon vom Style definiert sind, aus dem
918         // akt. AttrSet entfernen
919         SfxItemSet &rStyleSet = pStyle->aAttrSet;
920         const SfxPoolItem* pSItem;
921         for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() )
922         {
923             if( SFX_ITEM_SET == rStyleSet.GetItemState( nWhich, sal_True, &pSItem ))
924             {
925                 // JP 22.06.99: im Style und im Set gleich gesetzt -> loeschen
926                 if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem )
927                     && *pItem == *pSItem )
928                     rSet.ClearItem( nWhich );       // loeschen
929             }
930                 // Bug 59571 - falls nicht im Style gesetzt und gleich mit
931                 //              dem PoolDefault -> auch dann loeschen
932             else if( SFX_WHICH_MAX > nWhich &&
933                     SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem ) &&
934                      rPool.GetDefaultItem( nWhich ) == *pItem )
935                 rSet.ClearItem( nWhich );       // loeschen
936         }
937     }
938 }
939 
940 void SvxRTFParser::AttrGroupEnd()   // den akt. Bearbeiten, vom Stack loeschen
941 {
942     if( !aAttrStack.empty() )
943     {
944         SvxRTFItemStackType *pOld = aAttrStack.empty() ? 0 : aAttrStack.back();
945         aAttrStack.pop_back();
946         SvxRTFItemStackType *pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
947 
948         do {        // middle check loop
949             sal_uLong nOldSttNdIdx = pOld->pSttNd->GetIdx();
950             if( !pOld->pChildList &&
951                 ((!pOld->aAttrSet.Count() && !pOld->nStyleNo ) ||
952                 (nOldSttNdIdx == pInsPos->GetNodeIdx() &&
953                 pOld->nSttCnt == pInsPos->GetCntIdx() )))
954                 break;          // keine Attribute oder Bereich
955 
956             // setze nur die Attribute, die unterschiedlich zum Parent sind
957             if( pAkt && pOld->aAttrSet.Count() )
958             {
959                 SfxItemIter aIter( pOld->aAttrSet );
960                 const SfxPoolItem* pItem = aIter.GetCurItem(), *pGet;
961                 while( sal_True )
962                 {
963                     if( SFX_ITEM_SET == pAkt->aAttrSet.GetItemState(
964                         pItem->Which(), sal_False, &pGet ) &&
965                         *pItem == *pGet )
966                         pOld->aAttrSet.ClearItem( pItem->Which() );
967 
968                     if( aIter.IsAtEnd() )
969                         break;
970                     pItem = aIter.NextItem();
971                 }
972 
973                 if( !pOld->aAttrSet.Count() && !pOld->pChildList &&
974                     !pOld->nStyleNo )
975                     break;
976             }
977 
978             // setze alle Attribute, die von Start bis hier
979             // definiert sind.
980             int bCrsrBack = !pInsPos->GetCntIdx();
981             if( bCrsrBack )
982             {
983                 // am Absatzanfang ? eine Position zurueck
984                 sal_uLong nNd = pInsPos->GetNodeIdx();
985                 MovePos( sal_False );
986                 // if can not move backward then later dont move forward !
987                 bCrsrBack = nNd != pInsPos->GetNodeIdx();
988             }
989 
990             //Bug #46608#: ungueltige Bereiche ignorieren!
991             if( ( pOld->pSttNd->GetIdx() < pInsPos->GetNodeIdx() ||
992                 ( pOld->pSttNd->GetIdx() == pInsPos->GetNodeIdx() &&
993                 pOld->nSttCnt <= pInsPos->GetCntIdx() ))
994 #if 0
995 //BUG 68555 - dont test for empty paragraph or any range
996                 && ( nOldSttNdIdx != pInsPos->GetNodeIdx() ||
997                 pOld->nSttCnt != pInsPos->GetCntIdx() ||
998                 !pOld->nSttCnt )
999 #endif
1000                 )
1001             {
1002                 if( !bCrsrBack )
1003                 {
1004                     // alle pard-Attribute gelten nur bis zum vorherigen
1005                     // Absatz !!
1006                     if( nOldSttNdIdx == pInsPos->GetNodeIdx() )
1007                     {
1008 #if 0
1009 //BUG 68555 - dont reset pard attrs, if the group not begins not at start of
1010 //              paragraph
1011                         // Bereich innerhalb eines Absatzes:
1012                         // alle Absatz-Attribute und StyleNo loeschen
1013                         // aber nur wenn mitten drin angefangen wurde
1014                         if( pOld->nSttCnt )
1015                         {
1016                             pOld->nStyleNo = 0;
1017                             for( sal_uInt16 n = 0; n < aPardMap.Count() &&
1018                                                 pOld->aAttrSet.Count(); ++n )
1019                                 if( aPardMap[n] )
1020                                     pOld->aAttrSet.ClearItem( aPardMap[n] );
1021 
1022                             if( !pOld->aAttrSet.Count() && !pOld->pChildList &&
1023                                 !pOld->nStyleNo  )
1024                                 break;  // auch dieser verlaesst uns jetzt
1025                         }
1026 #endif
1027                     }
1028                     else
1029                     {
1030                         // jetzt wirds kompliziert:
1031                         // - alle Zeichen-Attribute behalten den Bereich,
1032                         // - alle Absatz-Attribute bekommen den Bereich
1033                         //          bis zum vorherigen Absatz
1034                         SvxRTFItemStackType* pNew = new SvxRTFItemStackType(
1035                                     *pOld, *pInsPos, sal_True );
1036                         pNew->aAttrSet.SetParent( pOld->aAttrSet.GetParent() );
1037 
1038                         // loesche aus pNew alle Absatz Attribute
1039                         for( sal_uInt16 n = 0; n < aPardMap.Count() &&
1040                                             pNew->aAttrSet.Count(); ++n )
1041                             if( aPardMap[n] )
1042                                 pNew->aAttrSet.ClearItem( aPardMap[n] );
1043                         pNew->SetRTFDefaults( GetRTFDefaults() );
1044 
1045                         // gab es ueberhaupt welche ?
1046                         if( pNew->aAttrSet.Count() == pOld->aAttrSet.Count() )
1047                             delete pNew;        // das wars dann
1048                         else
1049                         {
1050                             pNew->nStyleNo = 0;
1051 
1052                             // spanne jetzt den richtigen Bereich auf
1053                             // pNew von alter
1054                             SetEndPrevPara( pOld->pEndNd, pOld->nEndCnt );
1055                             pNew->nSttCnt = 0;
1056 
1057                             if( IsChkStyleAttr() )
1058                             {
1059                                 _ClearStyleAttr( *pOld );
1060                                 _ClearStyleAttr( *pNew );   //#i10381#, methinks.
1061                             }
1062 
1063                             if( pAkt )
1064                             {
1065                                 pAkt->Add( pOld );
1066                                 pAkt->Add( pNew );
1067                             }
1068                             else
1069                             {
1070                                 // letzter vom Stack, also zwischenspeichern, bis der
1071                                 // naechste Text eingelesen wurde. (keine Attribute
1072                                 // aufspannen!!)
1073                                 aAttrSetList.Insert( pOld, aAttrSetList.Count() );
1074                                 aAttrSetList.Insert( pNew, aAttrSetList.Count() );
1075                             }
1076                             pOld = 0;   // pOld nicht loeschen
1077                             break;      // das wars !!
1078                         }
1079                     }
1080                 }
1081 
1082                 pOld->pEndNd = pInsPos->MakeNodeIdx();
1083                 pOld->nEndCnt = pInsPos->GetCntIdx();
1084 
1085 #if 0
1086                 if( IsChkStyleAttr() )
1087                     _ClearStyleAttr( *pOld );
1088 #else
1089                 /*
1090                 #i21422#
1091                 If the parent (pAkt) sets something e.g. , and the child (pOld)
1092                 unsets it and the style both are based on has it unset then
1093                 clearing the pOld by looking at the style is clearly a disaster
1094                 as the text ends up with pAkts bold and not pOlds no bold, this
1095                 should be rethought out. For the moment its safest to just do
1096                 the clean if we have no parent, all we suffer is too many
1097                 redundant properties.
1098                 */
1099                 if (IsChkStyleAttr() && !pAkt)
1100                     _ClearStyleAttr( *pOld );
1101 #endif
1102 
1103                 if( pAkt )
1104                 {
1105                     pAkt->Add( pOld );
1106                     // split up and create new entry, because it make no sense
1107                     // to create a "so long" depend list. Bug 95010
1108                     if( bCrsrBack && 50 < pAkt->pChildList->Count() )
1109                     {
1110                         // am Absatzanfang ? eine Position zurueck
1111                         MovePos( sal_True );
1112                         bCrsrBack = sal_False;
1113 
1114                         // eine neue Gruppe aufmachen
1115                         SvxRTFItemStackType* pNew = new SvxRTFItemStackType(
1116                                                 *pAkt, *pInsPos, sal_True );
1117                         pNew->SetRTFDefaults( GetRTFDefaults() );
1118 
1119                         // alle bis hierher gueltigen Attribute "setzen"
1120                         AttrGroupEnd();
1121                         pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();  // can be changed after AttrGroupEnd!
1122                         pNew->aAttrSet.SetParent( pAkt ? &pAkt->aAttrSet : 0 );
1123                         aAttrStack.push_back( pNew );
1124                         pAkt = pNew;
1125                     }
1126                 }
1127                 else
1128                     // letzter vom Stack, also zwischenspeichern, bis der
1129                     // naechste Text eingelesen wurde. (keine Attribute
1130                     // aufspannen!!)
1131                     aAttrSetList.Insert( pOld, aAttrSetList.Count() );
1132 
1133                 pOld = 0;
1134             }
1135 
1136             if( bCrsrBack )
1137                 // am Absatzanfang ? eine Position zurueck
1138                 MovePos( sal_True );
1139 
1140         } while( sal_False );
1141 
1142         if( pOld )
1143             delete pOld;
1144 
1145         bNewGroup = sal_False;
1146     }
1147 }
1148 
1149 void SvxRTFParser::SetAllAttrOfStk()        // end all Attr. and set it into doc
1150 {
1151     // repeat until all attributes will be taken from stack
1152     while( !aAttrStack.empty() )
1153         AttrGroupEnd();
1154 
1155     for( sal_uInt16 n = aAttrSetList.Count(); n; )
1156     {
1157         SvxRTFItemStackType* pStkSet = aAttrSetList[--n];
1158         SetAttrSet( *pStkSet );
1159         aAttrSetList.DeleteAndDestroy( n );
1160     }
1161 }
1162 
1163 // setzt alle Attribute, die unterschiedlich zum aktuellen sind
1164 void SvxRTFParser::SetAttrSet( SvxRTFItemStackType &rSet )
1165 {
1166     // wurde DefTab nie eingelesen? dann setze auf default
1167     if( !bIsSetDfltTab )
1168         SetDefault( RTF_DEFTAB, 720 );
1169 
1170     if( rSet.pChildList )
1171         rSet.Compress( *this );
1172     if( rSet.aAttrSet.Count() || rSet.nStyleNo )
1173         SetAttrInDoc( rSet );
1174 
1175     // dann mal alle Childs abarbeiten
1176     if( rSet.pChildList )
1177         for( sal_uInt16 n = 0; n < rSet.pChildList->Count(); ++n )
1178             SetAttrSet( *(*rSet.pChildList)[ n ] );
1179 }
1180 
1181     // Is text wasn't inserted? (Get SttPos from the top of stack!)
1182 int SvxRTFParser::IsAttrSttPos()
1183 {
1184     SvxRTFItemStackType* pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
1185     return !pAkt || (pAkt->pSttNd->GetIdx() == pInsPos->GetNodeIdx() &&
1186         pAkt->nSttCnt == pInsPos->GetCntIdx());
1187 }
1188 
1189 
1190 void SvxRTFParser::SetAttrInDoc( SvxRTFItemStackType & )
1191 {
1192 }
1193 
1194 #ifdef USED
1195 void SvxRTFParser::SaveState( int nToken )
1196 {
1197     SvRTFParser::SaveState( nToken );
1198 }
1199 
1200 void SvxRTFParser::RestoreState()
1201 {
1202     SvRTFParser::RestoreState();
1203 }
1204 #endif
1205 
1206 void SvxRTFParser::BuildWhichTbl()
1207 {
1208     if( aWhichMap.Count() )
1209         aWhichMap.Remove( 0, aWhichMap.Count() );
1210     aWhichMap.Insert( (sal_uInt16)0, (sal_uInt16)0 );
1211 
1212     // Aufbau einer Which-Map 'rWhichMap' aus einem Array von
1213     // 'pWhichIds' von Which-Ids. Es hat die Lange 'nWhichIds'.
1214     // Die Which-Map wird nicht geloescht.
1215     SvParser::BuildWhichTbl( aWhichMap, (sal_uInt16*)aPardMap.GetData(), aPardMap.Count() );
1216     SvParser::BuildWhichTbl( aWhichMap, (sal_uInt16*)aPlainMap.GetData(), aPlainMap.Count() );
1217 }
1218 
1219 const SfxItemSet& SvxRTFParser::GetRTFDefaults()
1220 {
1221     if( !pRTFDefaults )
1222     {
1223         pRTFDefaults = new SfxItemSet( *pAttrPool, aWhichMap.GetData() );
1224         sal_uInt16 nId;
1225         if( 0 != ( nId = ((RTFPardAttrMapIds*)aPardMap.GetData())->nScriptSpace ))
1226         {
1227             SvxScriptSpaceItem aItem( sal_False, nId );
1228             if( bNewDoc )
1229                 pAttrPool->SetPoolDefaultItem( aItem );
1230             else
1231                 pRTFDefaults->Put( aItem );
1232         }
1233     }
1234     return *pRTFDefaults;
1235 }
1236 
1237 /**/
1238 
1239 SvxRTFStyleType::SvxRTFStyleType( SfxItemPool& rPool, const sal_uInt16* pWhichRange )
1240     : aAttrSet( rPool, pWhichRange )
1241 {
1242     nOutlineNo = sal_uInt8(-1);         // nicht gesetzt
1243     nBasedOn = 0;
1244     bBasedOnIsSet = sal_False;          //$flr #117411#
1245     nNext = 0;
1246     bIsCharFmt = sal_False;
1247 }
1248 
1249 
1250 SvxRTFItemStackType::SvxRTFItemStackType(
1251         SfxItemPool& rPool, const sal_uInt16* pWhichRange,
1252         const SvxPosition& rPos )
1253     : aAttrSet( rPool, pWhichRange ),
1254     pChildList( 0 ),
1255     nStyleNo( 0 )
1256 {
1257     pSttNd = rPos.MakeNodeIdx();
1258     nSttCnt = rPos.GetCntIdx();
1259     pEndNd = pSttNd;
1260     nEndCnt = nSttCnt;
1261 }
1262 
1263 SvxRTFItemStackType::SvxRTFItemStackType(
1264         const SvxRTFItemStackType& rCpy,
1265         const SvxPosition& rPos,
1266         int bCopyAttr )
1267     : aAttrSet( *rCpy.aAttrSet.GetPool(), rCpy.aAttrSet.GetRanges() ),
1268     pChildList( 0 ),
1269     nStyleNo( rCpy.nStyleNo )
1270 {
1271     pSttNd = rPos.MakeNodeIdx();
1272     nSttCnt = rPos.GetCntIdx();
1273     pEndNd = pSttNd;
1274     nEndCnt = nSttCnt;
1275 
1276     aAttrSet.SetParent( &rCpy.aAttrSet );
1277     if( bCopyAttr )
1278         aAttrSet.Put( rCpy.aAttrSet );
1279 }
1280 
1281 SvxRTFItemStackType::~SvxRTFItemStackType()
1282 {
1283     if( pChildList )
1284         delete pChildList;
1285     if( pSttNd != pEndNd )
1286         delete pEndNd;
1287     delete pSttNd;
1288 }
1289 
1290 void SvxRTFItemStackType::Add( SvxRTFItemStackType* pIns )
1291 {
1292     if( !pChildList )
1293          pChildList = new SvxRTFItemStackList( 4, 16 );
1294     pChildList->Insert( pIns, pChildList->Count() );
1295 }
1296 
1297 #if 0
1298 //cmc: This is the original. nEndCnt is redundantly assigned to itself, and
1299 //pEndNd can leak if not equal to pSttNd.
1300 void SvxRTFItemStackType::SetStartPos( const SvxPosition& rPos )
1301 {
1302     delete pSttNd;
1303     pSttNd = rPos.MakeNodeIdx();
1304     nSttCnt = rPos.GetCntIdx();
1305     pEndNd = pSttNd;
1306     nEndCnt = nEndCnt;
1307 }
1308 #else
1309 void SvxRTFItemStackType::SetStartPos( const SvxPosition& rPos )
1310 {
1311     if (pSttNd != pEndNd)
1312         delete pEndNd;
1313     delete pSttNd;
1314     pSttNd = rPos.MakeNodeIdx();
1315     pEndNd = pSttNd;
1316     nSttCnt = rPos.GetCntIdx();
1317 }
1318 #endif
1319 
1320 void SvxRTFItemStackType::MoveFullNode(const SvxNodeIdx &rOldNode,
1321     const SvxNodeIdx &rNewNode)
1322 {
1323     bool bSameEndAsStart = (pSttNd == pEndNd) ? true : false;
1324 
1325     if (GetSttNodeIdx() == rOldNode.GetIdx())
1326     {
1327         delete pSttNd;
1328         pSttNd = rNewNode.Clone();
1329         if (bSameEndAsStart)
1330             pEndNd = pSttNd;
1331     }
1332 
1333     if (!bSameEndAsStart && GetEndNodeIdx() == rOldNode.GetIdx())
1334     {
1335         delete pEndNd;
1336         pEndNd = rNewNode.Clone();
1337     }
1338 
1339     //And the same for all the children
1340     sal_uInt16 nCount = pChildList ? pChildList->Count() : 0;
1341     for (sal_uInt16 i = 0; i < nCount; ++i)
1342     {
1343         SvxRTFItemStackType* pStk = (*pChildList)[i];
1344         pStk->MoveFullNode(rOldNode, rNewNode);
1345     }
1346 }
1347 
1348 bool SvxRTFParser::UncompressableStackEntry(const SvxRTFItemStackType &) const
1349 {
1350     return false;
1351 }
1352 
1353 void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser )
1354 {
1355     DBG_ASSERT( pChildList, "es gibt keine ChildListe" );
1356 
1357     sal_uInt16 n;
1358     SvxRTFItemStackType* pTmp = (*pChildList)[0];
1359 
1360     if( !pTmp->aAttrSet.Count() ||
1361         pSttNd->GetIdx() != pTmp->pSttNd->GetIdx() ||
1362         nSttCnt != pTmp->nSttCnt )
1363         return;
1364 
1365     SvxNodeIdx* pLastNd = pTmp->pEndNd;
1366     xub_StrLen nLastCnt = pTmp->nEndCnt;
1367 
1368     SfxItemSet aMrgSet( pTmp->aAttrSet );
1369     for( n = 1; n < pChildList->Count(); ++n )
1370     {
1371         pTmp = (*pChildList)[n];
1372         if( pTmp->pChildList )
1373             pTmp->Compress( rParser );
1374 
1375         if( !pTmp->nSttCnt
1376             ? (pLastNd->GetIdx()+1 != pTmp->pSttNd->GetIdx() ||
1377                !rParser.IsEndPara( pLastNd, nLastCnt ) )
1378             : ( pTmp->nSttCnt != nLastCnt ||
1379                 pLastNd->GetIdx() != pTmp->pSttNd->GetIdx() ))
1380         {
1381             while( ++n < pChildList->Count() )
1382                 if( (pTmp = (*pChildList)[n])->pChildList )
1383                     pTmp->Compress( rParser );
1384             return;
1385         }
1386 
1387         if (rParser.UncompressableStackEntry(*pTmp))
1388             return;
1389 
1390         if( n )
1391         {
1392             // suche alle, die ueber den gesamten Bereich gesetzt sind
1393             SfxItemIter aIter( aMrgSet );
1394             const SfxPoolItem* pItem;
1395             do {
1396                 sal_uInt16 nWhich = aIter.GetCurItem()->Which();
1397                 if( SFX_ITEM_SET != pTmp->aAttrSet.GetItemState( nWhich,
1398                       sal_False, &pItem ) || *pItem != *aIter.GetCurItem() )
1399                     aMrgSet.ClearItem( nWhich );
1400 
1401                 if( aIter.IsAtEnd() )
1402                     break;
1403                 aIter.NextItem();
1404             } while( sal_True );
1405 
1406             if( !aMrgSet.Count() )
1407                 return;
1408         }
1409 
1410         pLastNd = pTmp->pEndNd;
1411         nLastCnt = pTmp->nEndCnt;
1412     }
1413 
1414     if( pEndNd->GetIdx() != pLastNd->GetIdx() || nEndCnt != nLastCnt )
1415         return;
1416 
1417     // es kann zusammengefasst werden
1418     aAttrSet.Put( aMrgSet );
1419 
1420     for( n = 0; n < pChildList->Count(); ++n )
1421     {
1422         pTmp = (*pChildList)[n];
1423         pTmp->aAttrSet.Differentiate( aMrgSet );
1424 
1425         if( !pTmp->pChildList && !pTmp->aAttrSet.Count() && !pTmp->nStyleNo )
1426         {
1427             pChildList->Remove( n );
1428             delete pTmp;
1429             --n;
1430             continue;
1431         }
1432     }
1433     if( !pChildList->Count() )
1434     {
1435         delete pChildList;
1436         pChildList = 0;
1437     }
1438 }
1439 void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet& rDefaults )
1440 {
1441     if( rDefaults.Count() )
1442     {
1443         SfxItemIter aIter( rDefaults );
1444         do {
1445             sal_uInt16 nWhich = aIter.GetCurItem()->Which();
1446             if( SFX_ITEM_SET != aAttrSet.GetItemState( nWhich, sal_False ))
1447                 aAttrSet.Put( *aIter.GetCurItem() );
1448 
1449             if( aIter.IsAtEnd() )
1450                 break;
1451             aIter.NextItem();
1452         } while( sal_True );
1453     }
1454 }
1455 
1456 /**/
1457 
1458 RTFPlainAttrMapIds::RTFPlainAttrMapIds( const SfxItemPool& rPool )
1459 {
1460     nCaseMap = rPool.GetTrueWhich( SID_ATTR_CHAR_CASEMAP, sal_False );
1461     nBgColor = rPool.GetTrueWhich( SID_ATTR_BRUSH_CHAR, sal_False );
1462     nColor = rPool.GetTrueWhich( SID_ATTR_CHAR_COLOR, sal_False );
1463     nContour = rPool.GetTrueWhich( SID_ATTR_CHAR_CONTOUR, sal_False );
1464     nCrossedOut = rPool.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT, sal_False );
1465     nEscapement = rPool.GetTrueWhich( SID_ATTR_CHAR_ESCAPEMENT, sal_False );
1466     nFont = rPool.GetTrueWhich( SID_ATTR_CHAR_FONT, sal_False );
1467     nFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT, sal_False );
1468     nKering = rPool.GetTrueWhich( SID_ATTR_CHAR_KERNING, sal_False );
1469     nLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE, sal_False );
1470     nPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_POSTURE, sal_False );
1471     nShadowed = rPool.GetTrueWhich( SID_ATTR_CHAR_SHADOWED, sal_False );
1472     nUnderline = rPool.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE, sal_False );
1473     nOverline = rPool.GetTrueWhich( SID_ATTR_CHAR_OVERLINE, sal_False );
1474     nWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_WEIGHT, sal_False );
1475     nWordlineMode = rPool.GetTrueWhich( SID_ATTR_CHAR_WORDLINEMODE, sal_False );
1476     nAutoKerning = rPool.GetTrueWhich( SID_ATTR_CHAR_AUTOKERN, sal_False );
1477 
1478     nCJKFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT, sal_False );
1479     nCJKFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT, sal_False );
1480     nCJKLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE, sal_False );
1481     nCJKPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE, sal_False );
1482     nCJKWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT, sal_False );
1483     nCTLFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT, sal_False );
1484     nCTLFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT, sal_False );
1485     nCTLLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE, sal_False );
1486     nCTLPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE, sal_False );
1487     nCTLWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT, sal_False );
1488     nEmphasis = rPool.GetTrueWhich( SID_ATTR_CHAR_EMPHASISMARK, sal_False );
1489     nTwoLines = rPool.GetTrueWhich( SID_ATTR_CHAR_TWO_LINES, sal_False );
1490     nRuby = 0; //rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_RUBY, sal_False );
1491     nCharScaleX = rPool.GetTrueWhich( SID_ATTR_CHAR_SCALEWIDTH, sal_False );
1492     nHorzVert = rPool.GetTrueWhich( SID_ATTR_CHAR_ROTATED, sal_False );
1493     nRelief = rPool.GetTrueWhich( SID_ATTR_CHAR_RELIEF, sal_False );
1494     nHidden = rPool.GetTrueWhich( SID_ATTR_CHAR_HIDDEN, sal_False );
1495 }
1496 
1497 RTFPardAttrMapIds ::RTFPardAttrMapIds ( const SfxItemPool& rPool )
1498 {
1499     nLinespacing = rPool.GetTrueWhich( SID_ATTR_PARA_LINESPACE, sal_False );
1500     nAdjust = rPool.GetTrueWhich( SID_ATTR_PARA_ADJUST, sal_False );
1501     nTabStop = rPool.GetTrueWhich( SID_ATTR_TABSTOP, sal_False );
1502     nHyphenzone = rPool.GetTrueWhich( SID_ATTR_PARA_HYPHENZONE, sal_False );
1503     nLRSpace = rPool.GetTrueWhich( SID_ATTR_LRSPACE, sal_False );
1504     nULSpace = rPool.GetTrueWhich( SID_ATTR_ULSPACE, sal_False );
1505     nBrush = rPool.GetTrueWhich( SID_ATTR_BRUSH, sal_False );
1506     nBox = rPool.GetTrueWhich( SID_ATTR_BORDER_OUTER, sal_False );
1507     nShadow = rPool.GetTrueWhich( SID_ATTR_BORDER_SHADOW, sal_False );
1508     nOutlineLvl = rPool.GetTrueWhich( SID_ATTR_PARA_OUTLLEVEL, sal_False );
1509     nSplit = rPool.GetTrueWhich( SID_ATTR_PARA_SPLIT, sal_False );
1510     nKeep = rPool.GetTrueWhich( SID_ATTR_PARA_KEEP, sal_False );
1511     nFontAlign = rPool.GetTrueWhich( SID_PARA_VERTALIGN, sal_False );
1512     nScriptSpace = rPool.GetTrueWhich( SID_ATTR_PARA_SCRIPTSPACE, sal_False );
1513     nHangPunct = rPool.GetTrueWhich( SID_ATTR_PARA_HANGPUNCTUATION, sal_False );
1514     nForbRule = rPool.GetTrueWhich( SID_ATTR_PARA_FORBIDDEN_RULES, sal_False );
1515     nDirection = rPool.GetTrueWhich( SID_ATTR_FRAMEDIRECTION, sal_False );
1516 }
1517 
1518 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
1519