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