xref: /AOO41X/main/editeng/source/rtf/svxrtf.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
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 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
28 
29 
30 #include <ctype.h>
31 #include <tools/datetime.hxx>
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 }
827 
828 void SvxRTFParser::ClearStyleTbl()
829 {
830     for( sal_uInt32 nCnt = aStyleTbl.Count(); nCnt; )
831         delete aStyleTbl.GetObject( --nCnt );
832 }
833 
834 void SvxRTFParser::ClearAttrStack()
835 {
836     SvxRTFItemStackType* pTmp;
837     for( size_t nCnt = aAttrStack.size(); nCnt; --nCnt )
838     {
839         pTmp = aAttrStack.back();
840         aAttrStack.pop_back();
841         delete pTmp;
842     }
843 }
844 
845 String& SvxRTFParser::DelCharAtEnd( String& rStr, const sal_Unicode cDel )
846 {
847     if( rStr.Len() && ' ' == rStr.GetChar( 0 ))
848         rStr.EraseLeadingChars();
849     if( rStr.Len() && ' ' == rStr.GetChar( rStr.Len()-1 ))
850         rStr.EraseTrailingChars();
851     if( rStr.Len() && cDel == rStr.GetChar( rStr.Len()-1 ))
852         rStr.Erase( rStr.Len()-1 );
853     return rStr;
854 }
855 
856 
857 const Font& SvxRTFParser::GetFont( sal_uInt16 nId )
858 {
859     const Font* pFont = aFontTbl.Get( nId );
860     if( !pFont )
861     {
862         const SvxFontItem& rDfltFont = (const SvxFontItem&)
863                         pAttrPool->GetDefaultItem(
864                     ((RTFPlainAttrMapIds*)aPlainMap.GetData())->nFont );
865         pDfltFont->SetName( rDfltFont.GetStyleName() );
866         pDfltFont->SetFamily( rDfltFont.GetFamily() );
867         pFont = pDfltFont;
868     }
869     return *pFont;
870 }
871 
872 SvxRTFItemStackType* SvxRTFParser::_GetAttrSet( int bCopyAttr )
873 {
874     SvxRTFItemStackType* pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
875     SvxRTFItemStackType* pNew;
876     if( pAkt )
877         pNew = new SvxRTFItemStackType( *pAkt, *pInsPos, bCopyAttr );
878     else
879         pNew = new SvxRTFItemStackType( *pAttrPool, aWhichMap.GetData(),
880                                         *pInsPos );
881     pNew->SetRTFDefaults( GetRTFDefaults() );
882 
883     aAttrStack.push_back( pNew );
884     bNewGroup = sal_False;
885     return pNew;
886 }
887 
888 
889 void SvxRTFParser::_ClearStyleAttr( SvxRTFItemStackType& rStkType )
890 {
891     // check attributes to the attributes of the stylesheet or to
892     // the default attrs of the document
893     SfxItemSet &rSet = rStkType.GetAttrSet();
894     const SfxItemPool& rPool = *rSet.GetPool();
895     const SfxPoolItem* pItem;
896     SfxWhichIter aIter( rSet );
897 
898     SvxRTFStyleType* pStyle;
899     if( !IsChkStyleAttr() ||
900         !rStkType.GetAttrSet().Count() ||
901         0 == ( pStyle = aStyleTbl.Get( rStkType.nStyleNo ) ))
902     {
903         for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() )
904         {
905             if( SFX_WHICH_MAX > nWhich &&
906                 SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem ) &&
907                      rPool.GetDefaultItem( nWhich ) == *pItem )
908                 rSet.ClearItem( nWhich );       // loeschen
909         }
910     }
911     else
912     {
913         // alle Attribute, die schon vom Style definiert sind, aus dem
914         // akt. AttrSet entfernen
915         SfxItemSet &rStyleSet = pStyle->aAttrSet;
916         const SfxPoolItem* pSItem;
917         for( sal_uInt16 nWhich = aIter.GetCurWhich(); nWhich; nWhich = aIter.NextWhich() )
918         {
919             if( SFX_ITEM_SET == rStyleSet.GetItemState( nWhich, sal_True, &pSItem ))
920             {
921                 // JP 22.06.99: im Style und im Set gleich gesetzt -> loeschen
922                 if( SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem )
923                     && *pItem == *pSItem )
924                     rSet.ClearItem( nWhich );       // loeschen
925             }
926                 // Bug 59571 - falls nicht im Style gesetzt und gleich mit
927                 //              dem PoolDefault -> auch dann loeschen
928             else if( SFX_WHICH_MAX > nWhich &&
929                     SFX_ITEM_SET == rSet.GetItemState( nWhich, sal_False, &pItem ) &&
930                      rPool.GetDefaultItem( nWhich ) == *pItem )
931                 rSet.ClearItem( nWhich );       // loeschen
932         }
933     }
934 }
935 
936 void SvxRTFParser::AttrGroupEnd()   // den akt. Bearbeiten, vom Stack loeschen
937 {
938     if( !aAttrStack.empty() )
939     {
940         SvxRTFItemStackType *pOld = aAttrStack.empty() ? 0 : aAttrStack.back();
941         aAttrStack.pop_back();
942         SvxRTFItemStackType *pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
943 
944         do {        // middle check loop
945             sal_uLong nOldSttNdIdx = pOld->pSttNd->GetIdx();
946             if( !pOld->pChildList &&
947                 ((!pOld->aAttrSet.Count() && !pOld->nStyleNo ) ||
948                 (nOldSttNdIdx == pInsPos->GetNodeIdx() &&
949                 pOld->nSttCnt == pInsPos->GetCntIdx() )))
950                 break;          // keine Attribute oder Bereich
951 
952             // setze nur die Attribute, die unterschiedlich zum Parent sind
953             if( pAkt && pOld->aAttrSet.Count() )
954             {
955                 SfxItemIter aIter( pOld->aAttrSet );
956                 const SfxPoolItem* pItem = aIter.GetCurItem(), *pGet;
957                 while( sal_True )
958                 {
959                     if( SFX_ITEM_SET == pAkt->aAttrSet.GetItemState(
960                         pItem->Which(), sal_False, &pGet ) &&
961                         *pItem == *pGet )
962                         pOld->aAttrSet.ClearItem( pItem->Which() );
963 
964                     if( aIter.IsAtEnd() )
965                         break;
966                     pItem = aIter.NextItem();
967                 }
968 
969                 if( !pOld->aAttrSet.Count() && !pOld->pChildList &&
970                     !pOld->nStyleNo )
971                     break;
972             }
973 
974             // setze alle Attribute, die von Start bis hier
975             // definiert sind.
976             int bCrsrBack = !pInsPos->GetCntIdx();
977             if( bCrsrBack )
978             {
979                 // am Absatzanfang ? eine Position zurueck
980                 sal_uLong nNd = pInsPos->GetNodeIdx();
981                 MovePos( sal_False );
982                 // if can not move backward then later dont move forward !
983                 bCrsrBack = nNd != pInsPos->GetNodeIdx();
984             }
985 
986             //Bug #46608#: ungueltige Bereiche ignorieren!
987             if( ( pOld->pSttNd->GetIdx() < pInsPos->GetNodeIdx() ||
988                 ( pOld->pSttNd->GetIdx() == pInsPos->GetNodeIdx() &&
989                 pOld->nSttCnt <= pInsPos->GetCntIdx() ))
990 #if 0
991 //BUG 68555 - dont test for empty paragraph or any range
992                 && ( nOldSttNdIdx != pInsPos->GetNodeIdx() ||
993                 pOld->nSttCnt != pInsPos->GetCntIdx() ||
994                 !pOld->nSttCnt )
995 #endif
996                 )
997             {
998                 if( !bCrsrBack )
999                 {
1000                     // alle pard-Attribute gelten nur bis zum vorherigen
1001                     // Absatz !!
1002                     if( nOldSttNdIdx == pInsPos->GetNodeIdx() )
1003                     {
1004 #if 0
1005 //BUG 68555 - dont reset pard attrs, if the group not begins not at start of
1006 //              paragraph
1007                         // Bereich innerhalb eines Absatzes:
1008                         // alle Absatz-Attribute und StyleNo loeschen
1009                         // aber nur wenn mitten drin angefangen wurde
1010                         if( pOld->nSttCnt )
1011                         {
1012                             pOld->nStyleNo = 0;
1013                             for( sal_uInt16 n = 0; n < aPardMap.Count() &&
1014                                                 pOld->aAttrSet.Count(); ++n )
1015                                 if( aPardMap[n] )
1016                                     pOld->aAttrSet.ClearItem( aPardMap[n] );
1017 
1018                             if( !pOld->aAttrSet.Count() && !pOld->pChildList &&
1019                                 !pOld->nStyleNo  )
1020                                 break;  // auch dieser verlaesst uns jetzt
1021                         }
1022 #endif
1023                     }
1024                     else
1025                     {
1026                         // jetzt wirds kompliziert:
1027                         // - alle Zeichen-Attribute behalten den Bereich,
1028                         // - alle Absatz-Attribute bekommen den Bereich
1029                         //          bis zum vorherigen Absatz
1030                         SvxRTFItemStackType* pNew = new SvxRTFItemStackType(
1031                                     *pOld, *pInsPos, sal_True );
1032                         pNew->aAttrSet.SetParent( pOld->aAttrSet.GetParent() );
1033 
1034                         // loesche aus pNew alle Absatz Attribute
1035                         for( sal_uInt16 n = 0; n < aPardMap.Count() &&
1036                                             pNew->aAttrSet.Count(); ++n )
1037                             if( aPardMap[n] )
1038                                 pNew->aAttrSet.ClearItem( aPardMap[n] );
1039                         pNew->SetRTFDefaults( GetRTFDefaults() );
1040 
1041                         // gab es ueberhaupt welche ?
1042                         if( pNew->aAttrSet.Count() == pOld->aAttrSet.Count() )
1043                             delete pNew;        // das wars dann
1044                         else
1045                         {
1046                             pNew->nStyleNo = 0;
1047 
1048                             // spanne jetzt den richtigen Bereich auf
1049                             // pNew von alter
1050                             SetEndPrevPara( pOld->pEndNd, pOld->nEndCnt );
1051                             pNew->nSttCnt = 0;
1052 
1053                             if( IsChkStyleAttr() )
1054                             {
1055                                 _ClearStyleAttr( *pOld );
1056                                 _ClearStyleAttr( *pNew );   //#i10381#, methinks.
1057                             }
1058 
1059                             if( pAkt )
1060                             {
1061                                 pAkt->Add( pOld );
1062                                 pAkt->Add( pNew );
1063                             }
1064                             else
1065                             {
1066                                 // letzter vom Stack, also zwischenspeichern, bis der
1067                                 // naechste Text eingelesen wurde. (keine Attribute
1068                                 // aufspannen!!)
1069                                 aAttrSetList.Insert( pOld, aAttrSetList.Count() );
1070                                 aAttrSetList.Insert( pNew, aAttrSetList.Count() );
1071                             }
1072                             pOld = 0;   // pOld nicht loeschen
1073                             break;      // das wars !!
1074                         }
1075                     }
1076                 }
1077 
1078                 pOld->pEndNd = pInsPos->MakeNodeIdx();
1079                 pOld->nEndCnt = pInsPos->GetCntIdx();
1080 
1081 #if 0
1082                 if( IsChkStyleAttr() )
1083                     _ClearStyleAttr( *pOld );
1084 #else
1085                 /*
1086                 #i21422#
1087                 If the parent (pAkt) sets something e.g. , and the child (pOld)
1088                 unsets it and the style both are based on has it unset then
1089                 clearing the pOld by looking at the style is clearly a disaster
1090                 as the text ends up with pAkts bold and not pOlds no bold, this
1091                 should be rethought out. For the moment its safest to just do
1092                 the clean if we have no parent, all we suffer is too many
1093                 redundant properties.
1094                 */
1095                 if (IsChkStyleAttr() && !pAkt)
1096                     _ClearStyleAttr( *pOld );
1097 #endif
1098 
1099                 if( pAkt )
1100                 {
1101                     pAkt->Add( pOld );
1102                     // split up and create new entry, because it make no sense
1103                     // to create a "so long" depend list. Bug 95010
1104                     if( bCrsrBack && 50 < pAkt->pChildList->Count() )
1105                     {
1106                         // am Absatzanfang ? eine Position zurueck
1107                         MovePos( sal_True );
1108                         bCrsrBack = sal_False;
1109 
1110                         // eine neue Gruppe aufmachen
1111                         SvxRTFItemStackType* pNew = new SvxRTFItemStackType(
1112                                                 *pAkt, *pInsPos, sal_True );
1113                         pNew->SetRTFDefaults( GetRTFDefaults() );
1114 
1115                         // alle bis hierher gueltigen Attribute "setzen"
1116                         AttrGroupEnd();
1117                         pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();  // can be changed after AttrGroupEnd!
1118                         pNew->aAttrSet.SetParent( pAkt ? &pAkt->aAttrSet : 0 );
1119                         aAttrStack.push_back( pNew );
1120                         pAkt = pNew;
1121                     }
1122                 }
1123                 else
1124                     // letzter vom Stack, also zwischenspeichern, bis der
1125                     // naechste Text eingelesen wurde. (keine Attribute
1126                     // aufspannen!!)
1127                     aAttrSetList.Insert( pOld, aAttrSetList.Count() );
1128 
1129                 pOld = 0;
1130             }
1131 
1132             if( bCrsrBack )
1133                 // am Absatzanfang ? eine Position zurueck
1134                 MovePos( sal_True );
1135 
1136         } while( sal_False );
1137 
1138         if( pOld )
1139             delete pOld;
1140 
1141         bNewGroup = sal_False;
1142     }
1143 }
1144 
1145 void SvxRTFParser::SetAllAttrOfStk()        // end all Attr. and set it into doc
1146 {
1147     // repeat until all attributes will be taken from stack
1148     while( !aAttrStack.empty() )
1149         AttrGroupEnd();
1150 
1151     for( sal_uInt16 n = aAttrSetList.Count(); n; )
1152     {
1153         SvxRTFItemStackType* pStkSet = aAttrSetList[--n];
1154         SetAttrSet( *pStkSet );
1155         aAttrSetList.DeleteAndDestroy( n );
1156     }
1157 }
1158 
1159 // setzt alle Attribute, die unterschiedlich zum aktuellen sind
1160 void SvxRTFParser::SetAttrSet( SvxRTFItemStackType &rSet )
1161 {
1162     // wurde DefTab nie eingelesen? dann setze auf default
1163     if( !bIsSetDfltTab )
1164         SetDefault( RTF_DEFTAB, 720 );
1165 
1166     if( rSet.pChildList )
1167         rSet.Compress( *this );
1168     if( rSet.aAttrSet.Count() || rSet.nStyleNo )
1169         SetAttrInDoc( rSet );
1170 
1171     // dann mal alle Childs abarbeiten
1172     if( rSet.pChildList )
1173         for( sal_uInt16 n = 0; n < rSet.pChildList->Count(); ++n )
1174             SetAttrSet( *(*rSet.pChildList)[ n ] );
1175 }
1176 
1177     // Is text wasn't inserted? (Get SttPos from the top of stack!)
1178 int SvxRTFParser::IsAttrSttPos()
1179 {
1180     SvxRTFItemStackType* pAkt = aAttrStack.empty() ? 0 : aAttrStack.back();
1181     return !pAkt || (pAkt->pSttNd->GetIdx() == pInsPos->GetNodeIdx() &&
1182         pAkt->nSttCnt == pInsPos->GetCntIdx());
1183 }
1184 
1185 
1186 void SvxRTFParser::SetAttrInDoc( SvxRTFItemStackType & )
1187 {
1188 }
1189 
1190 #ifdef USED
1191 void SvxRTFParser::SaveState( int nToken )
1192 {
1193     SvRTFParser::SaveState( nToken );
1194 }
1195 
1196 void SvxRTFParser::RestoreState()
1197 {
1198     SvRTFParser::RestoreState();
1199 }
1200 #endif
1201 
1202 void SvxRTFParser::BuildWhichTbl()
1203 {
1204     if( aWhichMap.Count() )
1205         aWhichMap.Remove( 0, aWhichMap.Count() );
1206     aWhichMap.Insert( (sal_uInt16)0, (sal_uInt16)0 );
1207 
1208     // Aufbau einer Which-Map 'rWhichMap' aus einem Array von
1209     // 'pWhichIds' von Which-Ids. Es hat die Lange 'nWhichIds'.
1210     // Die Which-Map wird nicht geloescht.
1211     SvParser::BuildWhichTbl( aWhichMap, (sal_uInt16*)aPardMap.GetData(), aPardMap.Count() );
1212     SvParser::BuildWhichTbl( aWhichMap, (sal_uInt16*)aPlainMap.GetData(), aPlainMap.Count() );
1213 }
1214 
1215 const SfxItemSet& SvxRTFParser::GetRTFDefaults()
1216 {
1217     if( !pRTFDefaults )
1218     {
1219         pRTFDefaults = new SfxItemSet( *pAttrPool, aWhichMap.GetData() );
1220         sal_uInt16 nId;
1221         if( 0 != ( nId = ((RTFPardAttrMapIds*)aPardMap.GetData())->nScriptSpace ))
1222         {
1223             SvxScriptSpaceItem aItem( sal_False, nId );
1224             if( bNewDoc )
1225                 pAttrPool->SetPoolDefaultItem( aItem );
1226             else
1227                 pRTFDefaults->Put( aItem );
1228         }
1229     }
1230     return *pRTFDefaults;
1231 }
1232 
1233 /**/
1234 
1235 SvxRTFStyleType::SvxRTFStyleType( SfxItemPool& rPool, const sal_uInt16* pWhichRange )
1236     : aAttrSet( rPool, pWhichRange )
1237 {
1238     nOutlineNo = sal_uInt8(-1);         // nicht gesetzt
1239     nBasedOn = 0;
1240     bBasedOnIsSet = sal_False;          //$flr #117411#
1241     nNext = 0;
1242     bIsCharFmt = sal_False;
1243 }
1244 
1245 
1246 SvxRTFItemStackType::SvxRTFItemStackType(
1247         SfxItemPool& rPool, const sal_uInt16* pWhichRange,
1248         const SvxPosition& rPos )
1249     : aAttrSet( rPool, pWhichRange ),
1250     pChildList( 0 ),
1251     nStyleNo( 0 )
1252 {
1253     pSttNd = rPos.MakeNodeIdx();
1254     nSttCnt = rPos.GetCntIdx();
1255     pEndNd = pSttNd;
1256     nEndCnt = nSttCnt;
1257 }
1258 
1259 SvxRTFItemStackType::SvxRTFItemStackType(
1260         const SvxRTFItemStackType& rCpy,
1261         const SvxPosition& rPos,
1262         int bCopyAttr )
1263     : aAttrSet( *rCpy.aAttrSet.GetPool(), rCpy.aAttrSet.GetRanges() ),
1264     pChildList( 0 ),
1265     nStyleNo( rCpy.nStyleNo )
1266 {
1267     pSttNd = rPos.MakeNodeIdx();
1268     nSttCnt = rPos.GetCntIdx();
1269     pEndNd = pSttNd;
1270     nEndCnt = nSttCnt;
1271 
1272     aAttrSet.SetParent( &rCpy.aAttrSet );
1273     if( bCopyAttr )
1274         aAttrSet.Put( rCpy.aAttrSet );
1275 }
1276 
1277 SvxRTFItemStackType::~SvxRTFItemStackType()
1278 {
1279     if( pChildList )
1280         delete pChildList;
1281     if( pSttNd != pEndNd )
1282         delete pEndNd;
1283     delete pSttNd;
1284 }
1285 
1286 void SvxRTFItemStackType::Add( SvxRTFItemStackType* pIns )
1287 {
1288     if( !pChildList )
1289          pChildList = new SvxRTFItemStackList( 4, 16 );
1290     pChildList->Insert( pIns, pChildList->Count() );
1291 }
1292 
1293 #if 0
1294 //cmc: This is the original. nEndCnt is redundantly assigned to itself, and
1295 //pEndNd can leak if not equal to pSttNd.
1296 void SvxRTFItemStackType::SetStartPos( const SvxPosition& rPos )
1297 {
1298     delete pSttNd;
1299     pSttNd = rPos.MakeNodeIdx();
1300     nSttCnt = rPos.GetCntIdx();
1301     pEndNd = pSttNd;
1302     nEndCnt = nEndCnt;
1303 }
1304 #else
1305 void SvxRTFItemStackType::SetStartPos( const SvxPosition& rPos )
1306 {
1307     if (pSttNd != pEndNd)
1308         delete pEndNd;
1309     delete pSttNd;
1310     pSttNd = rPos.MakeNodeIdx();
1311     pEndNd = pSttNd;
1312     nSttCnt = rPos.GetCntIdx();
1313 }
1314 #endif
1315 
1316 void SvxRTFItemStackType::MoveFullNode(const SvxNodeIdx &rOldNode,
1317     const SvxNodeIdx &rNewNode)
1318 {
1319     bool bSameEndAsStart = (pSttNd == pEndNd) ? true : false;
1320 
1321     if (GetSttNodeIdx() == rOldNode.GetIdx())
1322     {
1323         delete pSttNd;
1324         pSttNd = rNewNode.Clone();
1325         if (bSameEndAsStart)
1326             pEndNd = pSttNd;
1327     }
1328 
1329     if (!bSameEndAsStart && GetEndNodeIdx() == rOldNode.GetIdx())
1330     {
1331         delete pEndNd;
1332         pEndNd = rNewNode.Clone();
1333     }
1334 
1335     //And the same for all the children
1336     sal_uInt16 nCount = pChildList ? pChildList->Count() : 0;
1337     for (sal_uInt16 i = 0; i < nCount; ++i)
1338     {
1339         SvxRTFItemStackType* pStk = (*pChildList)[i];
1340         pStk->MoveFullNode(rOldNode, rNewNode);
1341     }
1342 }
1343 
1344 bool SvxRTFParser::UncompressableStackEntry(const SvxRTFItemStackType &) const
1345 {
1346     return false;
1347 }
1348 
1349 void SvxRTFItemStackType::Compress( const SvxRTFParser& rParser )
1350 {
1351     DBG_ASSERT( pChildList, "es gibt keine ChildListe" );
1352 
1353     sal_uInt16 n;
1354     SvxRTFItemStackType* pTmp = (*pChildList)[0];
1355 
1356     if( !pTmp->aAttrSet.Count() ||
1357         pSttNd->GetIdx() != pTmp->pSttNd->GetIdx() ||
1358         nSttCnt != pTmp->nSttCnt )
1359         return;
1360 
1361     SvxNodeIdx* pLastNd = pTmp->pEndNd;
1362     xub_StrLen nLastCnt = pTmp->nEndCnt;
1363 
1364     SfxItemSet aMrgSet( pTmp->aAttrSet );
1365     for( n = 1; n < pChildList->Count(); ++n )
1366     {
1367         pTmp = (*pChildList)[n];
1368         if( pTmp->pChildList )
1369             pTmp->Compress( rParser );
1370 
1371         if( !pTmp->nSttCnt
1372             ? (pLastNd->GetIdx()+1 != pTmp->pSttNd->GetIdx() ||
1373                !rParser.IsEndPara( pLastNd, nLastCnt ) )
1374             : ( pTmp->nSttCnt != nLastCnt ||
1375                 pLastNd->GetIdx() != pTmp->pSttNd->GetIdx() ))
1376         {
1377             while( ++n < pChildList->Count() )
1378                 if( (pTmp = (*pChildList)[n])->pChildList )
1379                     pTmp->Compress( rParser );
1380             return;
1381         }
1382 
1383         if (rParser.UncompressableStackEntry(*pTmp))
1384             return;
1385 
1386         if( n )
1387         {
1388             // suche alle, die ueber den gesamten Bereich gesetzt sind
1389             SfxItemIter aIter( aMrgSet );
1390             const SfxPoolItem* pItem;
1391             do {
1392                 sal_uInt16 nWhich = aIter.GetCurItem()->Which();
1393                 if( SFX_ITEM_SET != pTmp->aAttrSet.GetItemState( nWhich,
1394                       sal_False, &pItem ) || *pItem != *aIter.GetCurItem() )
1395                     aMrgSet.ClearItem( nWhich );
1396 
1397                 if( aIter.IsAtEnd() )
1398                     break;
1399                 aIter.NextItem();
1400             } while( sal_True );
1401 
1402             if( !aMrgSet.Count() )
1403                 return;
1404         }
1405 
1406         pLastNd = pTmp->pEndNd;
1407         nLastCnt = pTmp->nEndCnt;
1408     }
1409 
1410     if( pEndNd->GetIdx() != pLastNd->GetIdx() || nEndCnt != nLastCnt )
1411         return;
1412 
1413     // es kann zusammengefasst werden
1414     aAttrSet.Put( aMrgSet );
1415 
1416     for( n = 0; n < pChildList->Count(); ++n )
1417     {
1418         pTmp = (*pChildList)[n];
1419         pTmp->aAttrSet.Differentiate( aMrgSet );
1420 
1421         if( !pTmp->pChildList && !pTmp->aAttrSet.Count() && !pTmp->nStyleNo )
1422         {
1423             pChildList->Remove( n );
1424             delete pTmp;
1425             --n;
1426             continue;
1427         }
1428     }
1429     if( !pChildList->Count() )
1430     {
1431         delete pChildList;
1432         pChildList = 0;
1433     }
1434 }
1435 void SvxRTFItemStackType::SetRTFDefaults( const SfxItemSet& rDefaults )
1436 {
1437     if( rDefaults.Count() )
1438     {
1439         SfxItemIter aIter( rDefaults );
1440         do {
1441             sal_uInt16 nWhich = aIter.GetCurItem()->Which();
1442             if( SFX_ITEM_SET != aAttrSet.GetItemState( nWhich, sal_False ))
1443                 aAttrSet.Put( *aIter.GetCurItem() );
1444 
1445             if( aIter.IsAtEnd() )
1446                 break;
1447             aIter.NextItem();
1448         } while( sal_True );
1449     }
1450 }
1451 
1452 /**/
1453 
1454 RTFPlainAttrMapIds::RTFPlainAttrMapIds( const SfxItemPool& rPool )
1455 {
1456     nCaseMap = rPool.GetTrueWhich( SID_ATTR_CHAR_CASEMAP, sal_False );
1457     nBgColor = rPool.GetTrueWhich( SID_ATTR_BRUSH_CHAR, sal_False );
1458     nColor = rPool.GetTrueWhich( SID_ATTR_CHAR_COLOR, sal_False );
1459     nContour = rPool.GetTrueWhich( SID_ATTR_CHAR_CONTOUR, sal_False );
1460     nCrossedOut = rPool.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT, sal_False );
1461     nEscapement = rPool.GetTrueWhich( SID_ATTR_CHAR_ESCAPEMENT, sal_False );
1462     nFont = rPool.GetTrueWhich( SID_ATTR_CHAR_FONT, sal_False );
1463     nFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT, sal_False );
1464     nKering = rPool.GetTrueWhich( SID_ATTR_CHAR_KERNING, sal_False );
1465     nLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE, sal_False );
1466     nPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_POSTURE, sal_False );
1467     nShadowed = rPool.GetTrueWhich( SID_ATTR_CHAR_SHADOWED, sal_False );
1468     nUnderline = rPool.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE, sal_False );
1469     nOverline = rPool.GetTrueWhich( SID_ATTR_CHAR_OVERLINE, sal_False );
1470     nWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_WEIGHT, sal_False );
1471     nWordlineMode = rPool.GetTrueWhich( SID_ATTR_CHAR_WORDLINEMODE, sal_False );
1472     nAutoKerning = rPool.GetTrueWhich( SID_ATTR_CHAR_AUTOKERN, sal_False );
1473 
1474     nCJKFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT, sal_False );
1475     nCJKFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT, sal_False );
1476     nCJKLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE, sal_False );
1477     nCJKPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE, sal_False );
1478     nCJKWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT, sal_False );
1479     nCTLFont = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT, sal_False );
1480     nCTLFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT, sal_False );
1481     nCTLLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE, sal_False );
1482     nCTLPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE, sal_False );
1483     nCTLWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT, sal_False );
1484     nEmphasis = rPool.GetTrueWhich( SID_ATTR_CHAR_EMPHASISMARK, sal_False );
1485     nTwoLines = rPool.GetTrueWhich( SID_ATTR_CHAR_TWO_LINES, sal_False );
1486     nRuby = 0; //rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_RUBY, sal_False );
1487     nCharScaleX = rPool.GetTrueWhich( SID_ATTR_CHAR_SCALEWIDTH, sal_False );
1488     nHorzVert = rPool.GetTrueWhich( SID_ATTR_CHAR_ROTATED, sal_False );
1489     nRelief = rPool.GetTrueWhich( SID_ATTR_CHAR_RELIEF, sal_False );
1490     nHidden = rPool.GetTrueWhich( SID_ATTR_CHAR_HIDDEN, sal_False );
1491 }
1492 
1493 RTFPardAttrMapIds ::RTFPardAttrMapIds ( const SfxItemPool& rPool )
1494 {
1495     nLinespacing = rPool.GetTrueWhich( SID_ATTR_PARA_LINESPACE, sal_False );
1496     nAdjust = rPool.GetTrueWhich( SID_ATTR_PARA_ADJUST, sal_False );
1497     nTabStop = rPool.GetTrueWhich( SID_ATTR_TABSTOP, sal_False );
1498     nHyphenzone = rPool.GetTrueWhich( SID_ATTR_PARA_HYPHENZONE, sal_False );
1499     nLRSpace = rPool.GetTrueWhich( SID_ATTR_LRSPACE, sal_False );
1500     nULSpace = rPool.GetTrueWhich( SID_ATTR_ULSPACE, sal_False );
1501     nBrush = rPool.GetTrueWhich( SID_ATTR_BRUSH, sal_False );
1502     nBox = rPool.GetTrueWhich( SID_ATTR_BORDER_OUTER, sal_False );
1503     nShadow = rPool.GetTrueWhich( SID_ATTR_BORDER_SHADOW, sal_False );
1504     nOutlineLvl = rPool.GetTrueWhich( SID_ATTR_PARA_OUTLLEVEL, sal_False );
1505     nSplit = rPool.GetTrueWhich( SID_ATTR_PARA_SPLIT, sal_False );
1506     nKeep = rPool.GetTrueWhich( SID_ATTR_PARA_KEEP, sal_False );
1507     nFontAlign = rPool.GetTrueWhich( SID_PARA_VERTALIGN, sal_False );
1508     nScriptSpace = rPool.GetTrueWhich( SID_ATTR_PARA_SCRIPTSPACE, sal_False );
1509     nHangPunct = rPool.GetTrueWhich( SID_ATTR_PARA_HANGPUNCTUATION, sal_False );
1510     nForbRule = rPool.GetTrueWhich( SID_ATTR_PARA_FORBIDDEN_RULES, sal_False );
1511     nDirection = rPool.GetTrueWhich( SID_ATTR_FRAMEDIRECTION, sal_False );
1512 }
1513 
1514 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
1515