xref: /AOO41X/main/sw/source/filter/rtf/rtffld.cxx (revision 8e8ee8fefdac26d905672cc573c35fd0ae1f9356)
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_sw.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27 
28 #include <ctype.h>
29 #include <hintids.hxx>
30 
31 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
32 #include <com/sun/star/i18n/ScriptType.hdl>
33 #endif
34 #ifndef _GRAPH_HXX //autogen
35 #include <vcl/graph.hxx>
36 #endif
37 #include <svl/urihelper.hxx>
38 #include <svtools/rtftoken.h>
39 #include <svl/zforlist.hxx>
40 #include <editeng/fontitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/langitem.hxx>
43 #include <editeng/brkitem.hxx>
44 #include <fmtfld.hxx>
45 #include <fmtinfmt.hxx>
46 #include <swtypes.hxx>
47 #include <doc.hxx>
48 #include <pam.hxx>
49 #include <ndtxt.hxx>
50 #include <shellio.hxx>
51 #include <fldbas.hxx>
52 #include <swparrtf.hxx>
53 #include <txatbase.hxx>
54 #include <dbfld.hxx>
55 #include <usrfld.hxx>
56 #include <docufld.hxx>
57 #include <flddat.hxx>
58 #include <charfmt.hxx>
59 #ifndef _fmtruby_HXX
60 #include <fmtruby.hxx>
61 #endif
62 #include <breakit.hxx>
63 #include <reffld.hxx>
64 #include <SwStyleNameMapper.hxx>
65 #include <editeng/charhiddenitem.hxx>
66 
67 
68 // bestimme, ob es sich um ein IMPORT/TOC - Feld handelt.
69 // return:  0 - weder noch,
70 //          1 - TOC
71 //          2 - IMPORT
72 //          3 - INDEX
73 enum RTF_FLD_TYPES {
74     RTFFLD_UNKNOWN = 0,
75     RTFFLD_TOC,
76     RTFFLD_IMPORT,
77     RTFFLD_INDEX,
78     RTFFLD_SYMBOL,
79     RTFFLD_PAGE,
80     RTFFLD_NUMPAGES,
81     RTFFLD_DATE,
82     RTFFLD_TIME,
83     RTFFLD_DATA,
84     RTFFLD_MERGEFLD,
85     RTFFLD_HYPERLINK,
86     RTFFLD_REF,
87     RTFFLD_PAGEREF,
88     RTFFLD_EQ,
89     RTFFLD_INCLUDETEXT
90 };
91 
_WhichFld(String & rName,String & rNext)92 static RTF_FLD_TYPES _WhichFld( String& rName, String& rNext )
93 {
94     // Strings sind PascalStrings; Laenge steht an 1. Stellen, dadurch wird
95     // sich der Aufruf von strlen erspart!!!
96     sal_Char __READONLY_DATA sTOC[]=        "\x03""toc";
97     sal_Char __READONLY_DATA sIMPORT[]=     "\x06""import";
98     sal_Char __READONLY_DATA sINDEX[]=      "\x05""index";
99     sal_Char __READONLY_DATA sSYMBOL[]=     "\x06""symbol";
100     sal_Char __READONLY_DATA sPAGE[]=       "\x04""page";
101     sal_Char __READONLY_DATA sNUMPAGES[]=   "\x08""numpages";
102     sal_Char __READONLY_DATA sDATE[]=       "\x04""date";
103     sal_Char __READONLY_DATA sTIME[]=       "\x04""time";
104     sal_Char __READONLY_DATA sDATA[]=       "\x04""data";
105     sal_Char __READONLY_DATA sMERGEFLD[]=   "\x0A""mergefield";
106     sal_Char __READONLY_DATA sIMPORT2[]=    "\x0E""includepicture";
107     sal_Char __READONLY_DATA sHYPERLINK[]=  "\x09""hyperlink";
108     sal_Char __READONLY_DATA sREF[]=        "\x03""ref";
109     sal_Char __READONLY_DATA sPAGEREF[]=    "\x07""pageref";
110     sal_Char __READONLY_DATA sEQ[]=         "\x02""eq";
111     sal_Char __READONLY_DATA sINCLUDETEXT[]="\x0B""includetext";
112 
113     struct _Dummy_RTF_FLD_TYPES
114     {
115         RTF_FLD_TYPES eFldType;
116         const sal_Char* pFldNm;
117     };
118     __READONLY_DATA _Dummy_RTF_FLD_TYPES aFldNmArr[RTFFLD_INCLUDETEXT + 1] = {
119             {RTFFLD_TOC,         sTOC},
120             {RTFFLD_IMPORT,      sIMPORT},
121             {RTFFLD_INDEX,       sINDEX},
122             {RTFFLD_SYMBOL,      sSYMBOL},
123             {RTFFLD_PAGE,        sPAGE},
124             {RTFFLD_NUMPAGES,    sNUMPAGES},
125             {RTFFLD_DATE,        sDATE},
126             {RTFFLD_TIME,        sTIME},
127             {RTFFLD_DATA,        sDATA},
128             {RTFFLD_MERGEFLD,    sMERGEFLD},
129             {RTFFLD_IMPORT,      sIMPORT2},
130             {RTFFLD_HYPERLINK,   sHYPERLINK},
131             {RTFFLD_REF,         sREF},
132             {RTFFLD_PAGEREF,     sPAGEREF},
133             {RTFFLD_EQ,          sEQ},
134             {RTFFLD_INCLUDETEXT, sINCLUDETEXT}
135     };
136 
137 
138     if( !rName.Len() )
139         return RTFFLD_UNKNOWN;
140 
141     String sNm( rName );
142     sNm = sNm.EraseLeadingChars().GetToken(0, ' ');
143     ASSERT( sNm.Len(), "Feldname hat keine Laenge!" );
144     if( !sNm.Len() )
145         return RTFFLD_UNKNOWN;
146 
147     xub_StrLen nTokenStt = rName.Search( sNm );
148     sNm.ToLowerAscii();
149 
150     for (size_t n = 0; n < sizeof(aFldNmArr) / sizeof(aFldNmArr[0]); ++n)
151     {
152         const sal_Char* pCmp = aFldNmArr[n].pFldNm;
153         int nLen = *pCmp++;
154         xub_StrLen nFndPos = sNm.SearchAscii( pCmp );
155         if( STRING_NOTFOUND != nFndPos &&
156             ( !nFndPos || !isalpha(sNm.GetChar( static_cast< xub_StrLen >(nFndPos-1) )) ) &&
157             ( nFndPos+nLen == sNm.Len() || !isalpha(sNm.GetChar( static_cast< xub_StrLen >(nFndPos+nLen) ) ) ) )
158         {
159 //          rName = sNm.Copy( nFndPos, nLen );
160             rName = rName.Copy( nFndPos, static_cast< xub_StrLen >(nLen) );
161             nFndPos += nTokenStt + static_cast< xub_StrLen >(nLen);
162             while ((nFndPos < rNext.Len()) && (rNext.GetChar(nFndPos) == ' '))
163             {
164                 ++nFndPos;
165             }
166             rNext.Erase( 0, nFndPos );
167             rNext.EraseTrailingChars();
168             return aFldNmArr[n].eFldType;
169         }
170     }
171     return RTFFLD_UNKNOWN;      // nichts gefunden.
172 }
173 
CheckNumberFmtStr(const String & rNStr)174 static sal_uInt16 CheckNumberFmtStr( const String& rNStr )
175 {
176     const static sal_Char* aNumberTypeTab[] =
177     {
178         "\x0A""ALPHABETIC",       /* CHARS_UPPER_LETTER*/
179         "\x0A""alphabetic",       /* CHARS_LOWER_LETTER*/
180         "\x05""ROMAN",            /* ROMAN_UPPER       */
181         "\x05""roman",            /* ROMAN_LOWER       */
182         "\x06""ARABIC",           /* ARABIC            */
183         "\x04""NONE",             /* NUMBER_NONE       */
184         "\x04""CHAR",             /* CHAR_SPECIAL      */
185         "\x04""PAGE"              /* PAGEDESC          */
186     };
187 
188     ASSERT(sizeof(aNumberTypeTab) / sizeof(sal_Char *)
189            >= SVX_NUM_PAGEDESC - SVX_NUM_CHARS_UPPER_LETTER, "impossible");
190 
191     for (sal_uInt16 n = SVX_NUM_CHARS_UPPER_LETTER;  n <= SVX_NUM_PAGEDESC; ++n)
192     {
193         const sal_Char* pCmp = aNumberTypeTab[n - SVX_NUM_CHARS_UPPER_LETTER];
194         int nLen = *pCmp++;
195         if( rNStr.EqualsAscii( pCmp, 0, static_cast< xub_StrLen >(nLen) ))
196             return static_cast< sal_uInt16 >(2 <= n ? n : (n + SVX_NUM_CHARS_UPPER_LETTER_N));
197     }
198     return SVX_NUM_PAGEDESC;        // default-Wert
199 }
200 
201 class RtfFieldSwitch
202 {
203     String sParam;
204     xub_StrLen nCurPos;
205 public:
206     RtfFieldSwitch( const String& rParam );
207     sal_Unicode GetSwitch( String& rParam );
208 
IsAtEnd() const209     sal_Bool IsAtEnd() const                { return nCurPos >= sParam.Len(); }
GetCurPos() const210     xub_StrLen GetCurPos() const        { return nCurPos; }
Erase(xub_StrLen nEndPos)211     void Erase( xub_StrLen nEndPos )    { sParam.Erase( 0, nEndPos ); }
Insert(const String & rIns)212     void Insert( const String& rIns )   { sParam.Insert( rIns, 0 ); }
GetStr() const213     const String& GetStr() const        { return sParam; }
214 };
215 
RtfFieldSwitch(const String & rParam)216 RtfFieldSwitch::RtfFieldSwitch( const String& rParam )
217     : sParam( rParam ), nCurPos( 0  )
218 {
219     sParam.EraseTrailingChars().EraseLeadingChars();
220 }
221 
GetSwitch(String & rParam)222 sal_Unicode RtfFieldSwitch::GetSwitch( String& rParam )
223 {
224     // beginnt ein Schalter?
225     sal_Unicode c, cKey = 0;
226     if( '\\' == (c = sParam.GetChar( nCurPos )) )
227     {
228         if( '\\' == ( c = sParam.GetChar( ++nCurPos )) )
229             c = sParam.GetChar( ++nCurPos );
230 
231         cKey = c;
232 
233         while( ++nCurPos < sParam.Len() &&
234                 ' ' == ( c = sParam.GetChar( nCurPos )) )
235             ;
236     }
237 
238     // dann alles in Hochkommatas oder bis zum naechsten // als
239     // Param returnen
240     sal_uInt16 nOffset;
241     if( '"' != c && '\'' != c )
242         c = '\\', nOffset = 0;
243     else
244         nOffset = 1;
245 
246     sParam.Erase( 0, nCurPos + nOffset );
247     rParam = sParam.GetToken( 0, c );
248     sParam.Erase( 0, rParam.Len() + nOffset ).EraseLeadingChars();
249     if( '\\' == c )
250         rParam.EraseTrailingChars();
251     nCurPos = 0;
252 
253     return cKey;
254 }
255 
256 struct RTF_EquationData
257 {
258     String sFontName, sUp, sDown, sText;
259     sal_Int32 nJustificationCode, nFontSize, nUp, nDown, nStyleNo;
260 
RTF_EquationDataRTF_EquationData261     inline RTF_EquationData()
262         : nJustificationCode(0), nFontSize(0), nUp(0), nDown(0),
263         nStyleNo( -1 )
264     {}
265 };
266 
lcl_FindEndBracket(const String & rStr)267 xub_StrLen lcl_FindEndBracket( const String& rStr )
268 {
269     xub_StrLen nEnd = rStr.Len(), nRet = STRING_NOTFOUND, nPos = 0;
270     int nOpenCnt = 1;
271     sal_Unicode cCh;
272     for( ; nPos < nEnd; ++nPos )
273         if( ')' == (cCh = rStr.GetChar( nPos )) && !--nOpenCnt )
274         {
275             nRet = nPos;
276             break;
277         }
278         else if( '(' == cCh )
279             ++nOpenCnt;
280 
281     return nRet;
282 }
283 
lcl_ScanEquationField(const String & rStr,RTF_EquationData & rData,sal_Unicode nSttKey)284 void lcl_ScanEquationField( const String& rStr, RTF_EquationData& rData,
285                             sal_Unicode nSttKey )
286 {
287     int nSubSupFlag(0);
288     RtfFieldSwitch aRFS( rStr );
289     while( !aRFS.IsAtEnd() )
290     {
291         String sParam;
292         sal_Unicode cKey = aRFS.GetSwitch( sParam );
293         if( 1 == nSubSupFlag )
294             ++nSubSupFlag;
295         else if( 1 < nSubSupFlag )
296             nSubSupFlag = 0;
297 
298         sal_Bool bCheckBracket = sal_False;
299         switch( cKey )
300         {
301         case 0:
302             switch( nSttKey )
303             {
304             case 'u':   rData.sUp += sParam;    break;
305             case 'd':   rData.sDown += sParam;  break;
306             default:    rData.sText += sParam;  break;
307             }
308             break;
309 
310         case '*':
311             if( sParam.Len() )
312             {
313                 if( sParam.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
314                     rData.nJustificationCode = sParam.Copy( 2 ).ToInt32();
315                 else if( sParam.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
316                     rData.nFontSize= sParam.Copy( 3 ).ToInt32();
317                 else if( sParam.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
318                     rData.sFontName = sParam.Copy( 5 );
319                 else if( sParam.EqualsIgnoreCaseAscii( "cs", 0, 2 ) )
320                     rData.nStyleNo = sParam.Copy( 2 ).ToInt32();
321             }
322             break;
323         case 's' :
324             ++nSubSupFlag;
325             break;
326 
327         case 'u':
328             if( sParam.Len() && 'p' == sParam.GetChar( 0 ) &&
329                 2 == nSubSupFlag )
330             {
331                 rData.nUp = sParam.Copy( 1 ).ToInt32();
332                 bCheckBracket = sal_True;
333             }
334             break;
335 
336         case 'd':
337             if( sParam.Len() && 'o' == sParam.GetChar( 0 ) &&
338                 2 == nSubSupFlag )
339             {
340                 rData.nDown = sParam.Copy( 1 ).ToInt32();
341                 bCheckBracket = sal_True;
342             }
343             break;
344 
345         default:
346             bCheckBracket = sal_True;
347             cKey = 0;
348             break;
349         }
350 
351         if( bCheckBracket && sParam.Len() )
352         {
353             xub_StrLen nEnd, nStt = sParam.Search( '(' ),
354                         nLen = sParam.Len();
355             if( STRING_NOTFOUND != nStt )
356             {
357                 sParam.Erase( 0, nStt + 1 ) += aRFS.GetStr();
358                 if( STRING_NOTFOUND !=
359                         (nEnd = ::lcl_FindEndBracket( sParam )) )
360                 {
361                     // end in the added string?
362                     if( (nLen - nStt - 1 ) < nEnd )
363                         aRFS.Erase( nEnd + 1 - (nLen - nStt - 1));
364                     else
365                     {
366                         // not all handled here, so set new into the RFS
367                         aRFS.Insert( sParam.Copy( nEnd + 1,
368                                                 nLen - nStt - nEnd - 2 ));
369                         sal_Unicode cCh;
370                         if( aRFS.GetStr().Len() &&
371                             ( ',' == (cCh = aRFS.GetStr().GetChar(0)) ||
372                               ';' == cCh ))
373                             aRFS.Erase( 1 );
374                     }
375 
376                     ::lcl_ScanEquationField( sParam.Copy( 0, nEnd ),
377                                                 rData, cKey );
378                 }
379             }
380         }
381     }
382 }
383 
MakeFieldInst(String & rFieldStr)384 int SwRTFParser::MakeFieldInst( String& rFieldStr )
385 {
386     // sicher den Original-String fuer die FeldNamen (User/Datenbank)
387     String aSaveStr( rFieldStr );
388     SwFieldType * pFldType;
389     int nRet = _WhichFld(rFieldStr, aSaveStr);
390 
391     //Strip Mergeformat from fields
392     xub_StrLen nPos=0;
393     while (STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii("\\*", nPos)))
394     {
395         xub_StrLen nStartDel = nPos;
396         nPos += 2;
397         while ((nPos < aSaveStr.Len()) && (aSaveStr.GetChar(nPos) == ' '))
398         {
399             ++nPos;
400         }
401         if (aSaveStr.EqualsIgnoreCaseAscii("MERGEFORMAT", nPos, 11))
402         {
403             xub_StrLen nNoDel = (nPos + 11 ) - nStartDel;
404             aSaveStr.Erase(nStartDel, nNoDel);
405             nPos -= (nStartDel - nPos);
406         }
407     }
408 
409     nPos = 0;
410     switch (nRet)
411     {
412     case RTFFLD_INCLUDETEXT:
413         break;
414     case RTFFLD_IMPORT:
415         {
416 //JP 11.03.96: vertraegt sich nicht so ganz mit Internet!
417 //            if( STRING_NOTFOUND != ( nPos = aSaveStr.Search( '.' )))
418 //                aSaveStr.Erase( nPos+4 );
419 
420             aSaveStr.EraseLeadingAndTrailingChars();
421             if( aSaveStr.Len() )
422             {
423                 sal_Unicode c = aSaveStr.GetChar( 0 );
424                 if( '"' == c || '\'' == c )
425                 {
426                     aSaveStr.Erase( 0, 1 );
427                     aSaveStr = aSaveStr.GetToken( 0, c );
428                 }
429 
430                 rFieldStr = URIHelper::SmartRel2Abs(
431                     INetURLObject(GetBaseURL()), aSaveStr,
432                     URIHelper::GetMaybeFileHdl() );
433             }
434 //          SkipGroup();        // ueberlese den Rest
435         }
436         break;
437 
438     case RTFFLD_NUMPAGES:
439         {
440             SwDocStatField aFld( (SwDocStatFieldType*)pDoc->GetSysFldType( RES_DOCSTATFLD ),
441                                   DS_PAGE, SVX_NUM_ARABIC );
442             if( STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii( "\\*" )) )
443             {
444                 nPos += 2;
445                 while ((nPos < aSaveStr.Len()) &&
446                        (aSaveStr.GetChar(nPos) == ' '))
447                 { nPos++; }
448                 aSaveStr.Erase( 0, nPos );
449 
450                 // steht jetzt geanu auf dem Format-Namen
451                 aFld.ChangeFormat( CheckNumberFmtStr( aSaveStr ));
452             }
453             pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
454             SkipGroup();
455         }
456         break;
457 
458     case RTFFLD_PAGE:
459         {
460             pFldType = pDoc->GetSysFldType( RES_PAGENUMBERFLD );
461             SwPageNumberField aPF( (SwPageNumberFieldType*)pFldType,
462                                     PG_RANDOM, SVX_NUM_ARABIC);
463             if( STRING_NOTFOUND != ( nPos = aSaveStr.SearchAscii( "\\*" )) )
464             {
465                 nPos += 2;
466                 while ((nPos < aSaveStr.Len()) &&
467                        (aSaveStr.GetChar(nPos) == ' '))
468                 { nPos++; }
469                 aSaveStr.Erase( 0, nPos );
470 
471                 // steht jetzt geanu auf dem Format-Namen
472                 aPF.ChangeFormat( CheckNumberFmtStr( aSaveStr ));
473             }
474             pDoc->InsertPoolItem( *pPam, SwFmtFld( aPF ), 0 );
475             SkipGroup();        // ueberlese den Rest
476         }
477         break;
478     case RTFFLD_DATE:
479     case RTFFLD_TIME:
480         {
481             if( STRING_NOTFOUND == ( nPos = aSaveStr.SearchAscii( "\\@" )) )
482             {
483                 // es fehlt die Format - Angabe: defaulten auf Datum
484                 pFldType = pDoc->GetSysFldType( RES_DATETIMEFLD );
485                 pDoc->InsertPoolItem( *pPam, SwFmtFld( SwDateTimeField(
486                     static_cast<SwDateTimeFieldType*>(pFldType), DATEFLD)), 0);
487             }
488             else
489             {
490                 // versuche aus dem Formatstring zu erkennen, ob es ein
491                 // Datum oder Zeit oder Datum & Zeit Field ist
492                 // nur das Format interressiert
493                 aSaveStr.Erase( 0, aSaveStr.Search( '\"' )+1 );
494                 // alles hinter dem Format interressiert auch nicht mehr.
495                 aSaveStr.Erase( aSaveStr.Search( '\"' ) );
496                 aSaveStr.SearchAndReplaceAscii( "AM", aEmptyStr );
497                 aSaveStr.SearchAndReplaceAscii( "PM", aEmptyStr );
498 
499                 // #117892# M.M. Put the word date and time formatter stuff in a common area
500                 // and get the rtf filter to use it
501                 SwField *pFld = 0;
502                 short nNumFmtType = NUMBERFORMAT_UNDEFINED;
503                 sal_uLong nFmtIdx = NUMBERFORMAT_UNDEFINED;
504 
505                 sal_uInt16 rLang(0);
506                 RES_CHRATR eLang = maPageDefaults.mbRTLdoc ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
507                 const SvxLanguageItem *pLang = (SvxLanguageItem*)&pDoc->GetAttrPool().GetDefaultItem( static_cast< sal_uInt16 >(eLang) );
508                 rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
509 
510                 SvNumberFormatter* pFormatter = pDoc->GetNumberFormatter();
511                 bool bHijri = false;
512 
513                 if( pFormatter )
514                 {
515                     nFmtIdx = sw::ms::MSDateTimeFormatToSwFormat(aSaveStr, pFormatter, rLang, bHijri);
516                     if (nFmtIdx)
517                         nNumFmtType = pFormatter->GetType(nFmtIdx);
518                 }
519 
520                 pFldType = pDoc->GetSysFldType( RES_DATETIMEFLD );
521 
522                 if(nNumFmtType & NUMBERFORMAT_DATE)
523                     pFld = new SwDateTimeField( (SwDateTimeFieldType*)pFldType, DATEFLD, nFmtIdx );
524                 else if(nNumFmtType == NUMBERFORMAT_TIME)
525                     pFld = new SwDateTimeField( (SwDateTimeFieldType*)pFldType, TIMEFLD, nFmtIdx );
526 
527                 if( pFld )
528                 {
529                     pDoc->InsertPoolItem( *pPam, SwFmtFld( *pFld ), 0);
530                     delete pFld;
531                 }
532             }
533             SkipGroup();        // ueberlese den Rest
534         }
535         break;
536 
537     case RTFFLD_DATA:
538         {
539             // Datenbank-FileName: nur der Filename interressiert
540             // Zur Zeit werden nur SDF-Files verarbeitet, also suche nach
541             // der Extension
542 
543             // im SWG geben die DATA Felder den Namen der Datenbank
544             // an. Dieser kann als Field oder als DBInfo interpretiert
545             // werden:
546             //  \\data -> Datenbank-Name als Field
547             //  DATA -> Datenbank-Info
548             bool const bField = rFieldStr.Len() && rFieldStr.GetChar(0) != 'D';
549 
550             // nur der Name interressiert
551             if( STRING_NOTFOUND != (nPos = aSaveStr.Search( '.' )) )
552                 aSaveStr.Erase( nPos );
553             SwDBData aData;
554             aData.sDataSource = aSaveStr;
555             if( bField )
556             {
557                 pFldType = pDoc->GetSysFldType( RES_DBNAMEFLD );
558                 pDoc->InsertPoolItem( *pPam, SwFmtFld( SwDBNameField(
559                     static_cast<SwDBNameFieldType*>(pFldType), SwDBData())), 0);
560             }
561             else
562                 pDoc->ChgDBData( aData );       // MS: Keine DBInfo verwenden
563             SkipGroup();        // ueberlese den Rest
564         }
565         break;
566     case RTFFLD_MERGEFLD:
567         {
568             // ein Datenbank - Feld: nur der Name interressiert
569             // bis zum Ende vom String ist das der Feldname
570             SwDBFieldType aTmp( pDoc, aSaveStr, SwDBData() );   //
571             SwDBField aDBFld( (SwDBFieldType*)pDoc->InsertFldType( aTmp ));
572 
573             aDBFld.ChangeFormat( UF_STRING );
574             pDoc->InsertPoolItem(*pPam, SwFmtFld( aDBFld ), 0);
575             SkipGroup();        // ueberlese den Rest
576         }
577         break;
578 
579     case RTFFLD_SYMBOL:
580         {
581             // loesche fuehrende Blanks
582             if( IsNewGroup() )
583                 GetAttrSet();
584             SetNewGroup( sal_True );
585 
586             SfxItemSet& rSet = GetAttrSet();
587 
588             sal_Bool bCharIns = sal_False;
589             RtfFieldSwitch aRFS( aSaveStr );
590             while( !aRFS.IsAtEnd() )
591             {
592                 String sParam;
593                 sal_Unicode cKey = aRFS.GetSwitch( sParam );
594                 if( sParam.Len() )
595                     switch( cKey )
596                     {
597                     case 0:
598                         if( !bCharIns )
599                         {
600                             sal_Unicode nChar = (sal_Unicode)sParam.ToInt32();
601                             if( nChar )
602                             {
603                                 pDoc->InsertString( *pPam, nChar );
604                                 bCharIns = sal_True;
605                             }
606                         }
607                         break;
608 
609                     case 'f': case 'F':
610                         // Font setzen
611                         {
612                             SvxRTFFontTbl& rTbl = GetFontTbl();
613                             for( Font* pFont = rTbl.First(); pFont;
614                                     pFont = rTbl.Next() )
615                                 if( pFont->GetName() == sParam )
616                                 {
617                                     rSet.Put( SvxFontItem(
618                                             pFont->GetFamily(),
619                                             sParam,
620                                             pFont->GetStyleName(),
621                                             pFont->GetPitch(),
622                                             pFont->GetCharSet(),
623                                             RES_CHRATR_FONT ));
624                                     break;
625                                 }
626                         }
627                         break;
628                     case 'h': case 'H':
629                         //??
630                         break;
631                     case 's': case 'S':
632                         // Fontsize setzen
633                         {
634                             const sal_uInt16 nVal = (sal_uInt16)(sParam.ToInt32() * 20);
635                             rSet.Put( SvxFontHeightItem( nVal,
636                                                 100, RES_CHRATR_FONTSIZE ));
637                         }
638                         break;
639                     }
640             }
641 
642             if( !IsNewGroup() ) AttrGroupEnd();
643             SetNewGroup( sal_False );
644 
645             SkipGroup();        // ueberlese den Rest
646         }
647         break;
648 
649     case RTFFLD_HYPERLINK:
650         rFieldStr.Erase();
651         if( aSaveStr.Len() )
652         {
653             // return String ist URL, # Mark, \1 Frame
654             String sMark, sFrame;
655             RtfFieldSwitch aRFS( aSaveStr );
656             while( !aRFS.IsAtEnd() )
657             {
658                 String sParam;
659                 sal_Unicode cKey = aRFS.GetSwitch( sParam );
660                 if( sParam.Len() )
661                     switch( cKey )
662                     {
663                     case 0:
664                         if( !rFieldStr.Len() )
665                             rFieldStr = URIHelper::SmartRel2Abs(
666                                 INetURLObject(GetBaseURL()), sParam,
667                                 URIHelper::GetMaybeFileHdl() );
668                         break;
669 
670                     case 'l':   case 'L':   sMark = sParam;     break;
671                     case 't':   case 'T':   sFrame = sParam;    break;
672                     }
673             }
674 
675             if( sMark.Len() )
676                 ( rFieldStr += INET_MARK_TOKEN ) += sMark;
677             if( sFrame.Len() )
678                 ( rFieldStr += '\1' ) += sFrame;
679         }
680         break;
681 
682     case RTFFLD_EQ:
683         rFieldStr.Erase();
684         if( aSaveStr.Len() )
685         {
686             RTF_EquationData aData;
687             ::lcl_ScanEquationField( aSaveStr, aData, 0 );
688 
689             // is it a ruby attr?
690             if( aData.sText.Len() && aData.sFontName.Len() &&
691                 aData.nFontSize && aData.sUp.Len() && !aData.sDown.Len() )
692             {
693                 //Translate and apply
694                 switch( aData.nJustificationCode )
695                 {
696                 case 0:     aData.nJustificationCode = 1;   break;
697                 case 1:     aData.nJustificationCode = 3;   break;
698                 case 2:     aData.nJustificationCode = 4;   break;
699                 case 4:     aData.nJustificationCode = 2;   break;
700 //              case 3:
701                 default:    aData.nJustificationCode = 0;   break;
702                 }
703 
704                 SwFmtRuby aRuby( aData.sUp );
705                 SwCharFmt * pCharFmt = -1 != aData.nStyleNo
706                                           ? aCharFmtTbl.Get( aData.nStyleNo )
707                                           : 0;
708 
709                 if( !pCharFmt )
710                 {
711                     //Make a guess at which of asian of western we should be setting
712                     sal_uInt16 nScript;
713                     if (pBreakIt->GetBreakIter().is())
714                         nScript = pBreakIt->GetBreakIter()->getScriptType( aData.sUp, 0);
715                     else
716                         nScript = i18n::ScriptType::ASIAN;
717 
718                     sal_uInt16 nFntHWhich = GetWhichOfScript( RES_CHRATR_FONTSIZE, nScript ),
719                         nFntWhich = GetWhichOfScript( RES_CHRATR_FONT, nScript );
720 
721                     //Check to see if we already have a ruby charstyle that this fits
722                     for(sal_uInt16 i=0; i < aRubyCharFmts.Count(); ++i )
723                     {
724                         SwCharFmt *pFmt = (SwCharFmt *)aRubyCharFmts[i];
725                         const SvxFontHeightItem &rF = (const SvxFontHeightItem &)
726                                                     pFmt->GetFmtAttr( nFntHWhich );
727                         if( rF.GetHeight() == sal_uInt16(aData.nFontSize * 10 ))
728                         {
729                             const SvxFontItem &rFI = (const SvxFontItem &)
730                                                     pFmt->GetFmtAttr( nFntWhich );
731                             if( rFI.GetFamilyName().Equals( aData.sFontName ))
732                             {
733                                 pCharFmt = pFmt;
734                                 break;
735                             }
736                         }
737                     }
738 
739                     //Create a new char style if necessary
740                     if( !pCharFmt )
741                     {
742                         String sNm;
743                         //Take this as the base name
744                         SwStyleNameMapper::FillUIName( RES_POOLCHR_RUBYTEXT, sNm );
745                         sNm += String::CreateFromInt32( aRubyCharFmts.Count() + 1 );
746                         pCharFmt = pDoc->MakeCharFmt( sNm,
747                                             ( SwCharFmt*)pDoc->GetDfltCharFmt() );
748 
749                         SvxFontHeightItem aHeightItem( aData.nFontSize * 10, 100, RES_CHRATR_FONTSIZE );
750                         aHeightItem.SetWhich( nFntHWhich );
751 
752                         SvxFontItem aFontItem( FAMILY_DONTKNOW, aData.sFontName,
753                             aEmptyStr, PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, nFntWhich );
754 
755                         pCharFmt->SetFmtAttr( aHeightItem );
756                         pCharFmt->SetFmtAttr( aFontItem );
757                         void* p = pCharFmt;
758                         aRubyCharFmts.Insert( p, aRubyCharFmts.Count() );
759                     }
760                 }
761 
762                 //Set the charstyle and justification
763                 aRuby.SetCharFmtName( pCharFmt->GetName() );
764                 aRuby.SetCharFmtId( pCharFmt->GetPoolFmtId() );
765                 aRuby.SetAdjustment( (sal_uInt16)aData.nJustificationCode );
766 
767                 // im FieldStr steht der anzuzeigenden Text, im
768                 pDoc->InsertString( *pPam, aData.sText );
769                 pPam->SetMark();
770                 pPam->GetMark()->nContent -= aData.sText.Len();
771                 pDoc->InsertPoolItem( *pPam, aRuby,
772                     nsSetAttrMode::SETATTR_DONTEXPAND );
773                 pPam->DeleteMark();
774             }
775             // or a combined character field?
776             else if( aData.sUp.Len() && aData.sDown.Len() &&
777                     !aData.sText.Len() && !aData.sFontName.Len() &&
778                     !aData.nFontSize )
779             {
780                 String sFld( aData.sUp );
781                 sFld += aData.sDown;
782                 SwCombinedCharField aFld((SwCombinedCharFieldType*)pDoc->
783                                 GetSysFldType( RES_COMBINED_CHARS ), sFld );
784                 pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0);
785 
786             }
787             SkipGroup();        // ueberlese den Rest
788         }
789         break;
790 
791     case RTFFLD_PAGEREF:
792         {
793             String sOrigBkmName;
794             RtfFieldSwitch aRFS( aSaveStr );
795             while( !aRFS.IsAtEnd() )
796             {
797                 String sParam;
798                 sal_Unicode cKey = aRFS.GetSwitch( sParam );
799                 switch( cKey )
800                 {
801                     // In the case of pageref the only parameter we are
802                     // interested in, is the name of the bookmark
803                     case 0:
804                         if( !sOrigBkmName.Len() ) // get name of bookmark
805                             sOrigBkmName = sParam;
806                         break;
807                 }
808             }
809             SwGetRefField aFld(
810                     (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
811                     sOrigBkmName,REF_BOOKMARK,0,REF_PAGE);
812 
813             if(!bNestedField)
814             {
815                 pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
816             }
817             else
818                 bNestedField = false;
819         }
820         break;
821 
822     case RTFFLD_REF:
823         {
824             String sOrigBkmName;
825             bool bChapterNr = false;
826             bool bAboveBelow = false;
827 
828             RtfFieldSwitch aRFS( aSaveStr );
829             while( !aRFS.IsAtEnd() )
830             {
831                 String sParam;
832                 sal_Unicode cKey = aRFS.GetSwitch( sParam );
833                 switch( cKey )
834                 {
835                     case 0:
836                         if( !sOrigBkmName.Len() ) // get name of bookmark
837                             sOrigBkmName = sParam;
838                         break;
839 
840                     case 'n':
841                     case 'r':
842                     case 'w':
843                         bChapterNr = true; // activate flag 'Chapter Number'
844                         break;
845 
846                     case 'p':
847                         bAboveBelow = true;
848                         break;
849                 }
850             }
851             if (!bAboveBelow || bChapterNr)
852             {
853                 if (bChapterNr)
854                 {
855                     SwGetRefField aFld(
856                         (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
857                         sOrigBkmName,REF_BOOKMARK,0,REF_CHAPTER);
858                     pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
859                 }
860                 else
861                 {
862                     SwGetRefField aFld(
863                         (SwGetRefFieldType*)pDoc->GetSysFldType( RES_GETREFFLD ),
864                         sOrigBkmName,REF_BOOKMARK,0,REF_CONTENT);
865                     pDoc->InsertPoolItem( *pPam, SwFmtFld( aFld ), 0 );
866                 }
867             }
868 
869             if( bAboveBelow )
870             {
871                 SwGetRefField aFld( (SwGetRefFieldType*)
872                     pDoc->GetSysFldType( RES_GETREFFLD ), sOrigBkmName, REF_BOOKMARK, 0,
873                     REF_UPDOWN );
874                 pDoc->InsertPoolItem(*pPam, SwFmtFld(aFld), 0);
875             }
876         }
877         break;
878 
879     case RTFFLD_TOC:
880     case RTFFLD_INDEX:
881         break;
882 
883     default:
884         {
885             // keines von den bekannten Feldern, also eine neues UserField
886             aSaveStr.EraseLeadingChars().EraseTrailingChars();
887             SwUserFieldType aTmp( pDoc, aSaveStr );
888             SwUserField aUFld( (SwUserFieldType*)pDoc->InsertFldType( aTmp ));
889             aUFld.ChangeFormat( UF_STRING );
890             pDoc->InsertPoolItem( *pPam, SwFmtFld( aUFld ), 0);
891             nRet = RTFFLD_UNKNOWN;
892         }
893         break;
894     }
895     return nRet;
896 }
897 
898 
ReadXEField()899 void SwRTFParser::ReadXEField()
900 {
901     bReadSwFly = false; //#it may be that any uses of this need to be removed and replaced
902     int nNumOpenBrakets = 1;
903     String sFieldStr;
904     sal_uInt8 cCh;
905 
906     int nToken;
907     while (nNumOpenBrakets && IsParserWorking())
908     {
909         switch (nToken = GetNextToken())
910         {
911         case '}':
912             {
913                 --nNumOpenBrakets;
914 
915                 if( sFieldStr.Len())
916                 {
917                     String sXE(sFieldStr);
918                     sXE.Insert('\"', 0);
919                     sXE.Append('\"');
920 
921                     // we have to make sure the hidden text flag is not on
922                     // otherwise the index will not see this index mark
923                     SfxItemSet& rSet = GetAttrSet();
924                     const SfxPoolItem* pItem;
925                     if( SFX_ITEM_SET == rSet.GetItemState( RES_CHRATR_HIDDEN, sal_True, &pItem ) )
926                     {
927                         SvxCharHiddenItem aCharHidden(*(SvxCharHiddenItem*)pItem);
928                         aCharHidden.SetValue(sal_False);
929                         rSet.Put(aCharHidden);
930                     }
931 
932                     sw::ms::ImportXE(*pDoc, *pPam, sXE);
933 
934                     sFieldStr.Erase();
935                 }
936             }
937             break;
938 
939         case '{':
940             if( RTF_IGNOREFLAG != GetNextToken() )
941                 SkipToken( -1 );
942             // Unknown und alle bekannten nicht ausgewerteten Gruppen
943             // sofort ueberspringen
944             else if( RTF_UNKNOWNCONTROL != GetNextToken() )
945                 SkipToken( -2 );
946             else
947             {
948                 // gleich herausfiltern
949                 ReadUnknownData();
950                 if( '}' != GetNextToken() )
951                     eState = SVPAR_ERROR;
952                 break;
953             }
954             ++nNumOpenBrakets;
955             break;
956 
957         case RTF_U:
958             {
959                 if( nTokenValue )
960                     sFieldStr += (sal_Unicode)nTokenValue;
961                 else
962                     sFieldStr += aToken;
963             }
964             break;
965 
966         case RTF_LINE:          cCh = '\n'; goto INSINGLECHAR;
967         case RTF_TAB:           cCh = '\t'; goto INSINGLECHAR;
968         case RTF_SUBENTRYINDEX: cCh = ':';  goto INSINGLECHAR;
969         case RTF_EMDASH:        cCh = 151;  goto INSINGLECHAR;
970         case RTF_ENDASH:        cCh = 150;  goto INSINGLECHAR;
971         case RTF_BULLET:        cCh = 149;  goto INSINGLECHAR;
972         case RTF_LQUOTE:        cCh = 145;  goto INSINGLECHAR;
973         case RTF_RQUOTE:        cCh = 146;  goto INSINGLECHAR;
974         case RTF_LDBLQUOTE:     cCh = 147;  goto INSINGLECHAR;
975         case RTF_RDBLQUOTE:     cCh = 148;  goto INSINGLECHAR;
976 INSINGLECHAR:
977             sFieldStr += ByteString::ConvertToUnicode( cCh,
978                                             RTL_TEXTENCODING_MS_1252 );
979             break;
980 
981         // kein Break, aToken wird als Text gesetzt
982         case RTF_TEXTTOKEN:
983             sFieldStr += aToken;
984             break;
985 
986         case RTF_BKMK_KEY:
987         case RTF_TC:
988         case RTF_NEXTFILE:
989         case RTF_TEMPLATE:
990         case RTF_SHPRSLT:
991             SkipGroup();
992             break;
993 
994         case RTF_PAR:
995             sFieldStr.Append('\x0a');
996             break;
997         default:
998             SvxRTFParser::NextToken( nToken );
999             break;
1000         }
1001     }
1002 
1003     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
1004 }
1005 
1006 
ReadField()1007 void SwRTFParser::ReadField()
1008 {
1009     bReadSwFly = false; //#it may be that any uses of this need to be removed and replaced
1010     int nRet = 0;
1011     int nNumOpenBrakets = 1;        // die erste wurde schon vorher erkannt !!
1012     int bFldInst = sal_False, bFldRslt = sal_False;
1013     String sFieldStr, sFieldNm;
1014     sal_uInt8 cCh;
1015 
1016     int nToken;
1017     while (nNumOpenBrakets && IsParserWorking())
1018     {
1019         switch (nToken = GetNextToken())
1020         {
1021         case '}':
1022             {
1023                 --nNumOpenBrakets;
1024                 if( 1 != nNumOpenBrakets || !bFldInst )
1025                     break;
1026 
1027                 if( !bFldRslt )
1028                 {
1029                     // FieldInst vollstaendig eingelesen, was ist es denn?
1030                     nRet = MakeFieldInst( sFieldStr );
1031                     switch ( nRet )
1032                     {
1033                     case RTFFLD_INCLUDETEXT:
1034                     case RTFFLD_TOC:
1035                     case RTFFLD_INDEX:
1036                         // erstmal Index/Inhaltsverzeichniss ueberspringen
1037                         // und als normalen Text einfuegen. Spaeter mal auch dem
1038                         // SwPaM darum aufspannen.
1039                         return ;
1040 
1041                     case RTFFLD_IMPORT:
1042                     case RTFFLD_HYPERLINK:
1043                         sFieldNm = sFieldStr;
1044                         break;
1045                     }
1046                     sFieldStr.Erase();
1047                 }
1048                 else if (RTFFLD_UNKNOWN == nRet)
1049                 {
1050                     // FieldResult wurde eingelesen
1051                     if (SwTxtNode* pTxtNd = pPam->GetPoint()->nNode.GetNode().GetTxtNode())
1052                     {
1053                         SwTxtAttr* const pFldAttr =
1054                             pTxtNd->GetTxtAttrForCharAt(
1055                                 pPam->GetPoint()->nContent.GetIndex()-1 );
1056 
1057                         if (pFldAttr)
1058                         {
1059                             const SwField *pFld = pFldAttr->GetFmtFld().GetField();
1060                             SwFieldType *pTyp = pFld ? pFld->GetTyp() : 0;
1061                             ASSERT(pTyp->Which() == RES_USERFLD, "expected a user field");
1062                             if (pTyp->Which() == RES_USERFLD)
1063                             {
1064                                 SwUserFieldType *pUsrTyp = (SwUserFieldType*)pTyp;
1065                                 pUsrTyp->SetContent(sFieldStr);
1066                             }
1067                         }
1068                     }
1069                 }
1070                 else if( sFieldNm.Len() )
1071                 {
1072                     switch ( nRet )
1073                     {
1074                     case RTFFLD_IMPORT:
1075                         // Grafik einfuegen
1076                         InsPicture( sFieldNm );
1077                         nRet = INT_MAX;
1078                         break;
1079                     case RTFFLD_HYPERLINK:
1080                         if( sFieldStr.Len() )
1081                         {
1082                             if(sNestedFieldStr.Len())
1083                                 sFieldStr.Insert(sNestedFieldStr);
1084 
1085                             sNestedFieldStr.Erase();
1086                             // im FieldStr steht der anzuzeigenden Text, im
1087                             pDoc->InsertString( *pPam, sFieldStr );
1088 
1089                             String sTarget( sFieldNm.GetToken( 1, '\1' ));
1090                             if( sTarget.Len() )
1091                                 sFieldNm.Erase( sFieldNm.Len() - sTarget.Len() -1 );
1092 
1093                             // oder ueber den Stack setzen??
1094                             pPam->SetMark();
1095                             pPam->GetMark()->nContent -= sFieldStr.Len();
1096                             pDoc->InsertPoolItem( *pPam,
1097                                             SwFmtINetFmt( sFieldNm, sTarget ),
1098                                             nsSetAttrMode::SETATTR_DONTEXPAND );
1099                             pPam->DeleteMark();
1100                             // #i117947#: insert result only once in case
1101                             // field result is followed by invalid tokens
1102                             sFieldStr.Erase();
1103                         }
1104                         break;
1105                     }
1106                 }
1107                 else if(bNestedField)
1108                 {
1109                     if(nRet == RTFFLD_PAGEREF)
1110                     {
1111                         // #17371 Nasty hack to get a pageref within a hyperlink working
1112                         sNestedFieldStr = sFieldStr;
1113                     }
1114 
1115                 }
1116 
1117             }
1118             break;
1119 
1120         case '{':
1121             if( RTF_IGNOREFLAG != GetNextToken() )
1122                 SkipToken( -1 );
1123             // Unknown und alle bekannten nicht ausgewerteten Gruppen
1124             // sofort ueberspringen
1125             else if( RTF_UNKNOWNCONTROL != GetNextToken() )
1126                 SkipToken( -2 );
1127             else
1128             {
1129                 // gleich herausfiltern
1130                 ReadUnknownData();
1131                 if( '}' != GetNextToken() )
1132                     eState = SVPAR_ERROR;
1133                 break;
1134             }
1135             ++nNumOpenBrakets;
1136             break;
1137 
1138         case RTF_DATAFIELD:
1139             SkipGroup();
1140             break;
1141 
1142         case RTF_FIELD:
1143             bNestedField = true;
1144             ReadField();
1145             break;
1146 
1147         case RTF_FLDINST:
1148             bFldInst = sal_True;
1149             break;
1150 
1151         case RTF_FLDRSLT:
1152             bFldRslt = sal_True;
1153             break;
1154 
1155         case RTF_U:
1156             {
1157                 if( nTokenValue )
1158                     sFieldStr += (sal_Unicode)nTokenValue;
1159                 else
1160                     sFieldStr += aToken;
1161             }
1162             break;
1163 
1164         case RTF_LINE:          cCh = '\n'; goto INSINGLECHAR;
1165         case RTF_TAB:           cCh = '\t'; goto INSINGLECHAR;
1166         case RTF_SUBENTRYINDEX: cCh = ':';  goto INSINGLECHAR;
1167         case RTF_EMDASH:        cCh = 151;  goto INSINGLECHAR;
1168         case RTF_ENDASH:        cCh = 150;  goto INSINGLECHAR;
1169         case RTF_BULLET:        cCh = 149;  goto INSINGLECHAR;
1170         case RTF_LQUOTE:        cCh = 145;  goto INSINGLECHAR;
1171         case RTF_RQUOTE:        cCh = 146;  goto INSINGLECHAR;
1172         case RTF_LDBLQUOTE:     cCh = 147;  goto INSINGLECHAR;
1173         case RTF_RDBLQUOTE:     cCh = 148;  goto INSINGLECHAR;
1174 INSINGLECHAR:
1175             sFieldStr += ByteString::ConvertToUnicode( cCh,
1176                                             RTL_TEXTENCODING_MS_1252 );
1177             break;
1178 
1179         // kein Break, aToken wird als Text gesetzt
1180         case RTF_TEXTTOKEN:
1181             sFieldStr += aToken;
1182             break;
1183 
1184         case RTF_PICT:      // Pic-Daten einlesen!
1185             if( RTFFLD_IMPORT == nRet )
1186             {
1187                 Graphic aGrf;
1188                 SvxRTFPictureType aPicType;
1189                 if( ReadBmpData( aGrf, aPicType ) )
1190                 {
1191                     InsPicture( sFieldNm, &aGrf, &aPicType );
1192                     nRet = INT_MAX;
1193                 }
1194                 SkipGroup();
1195             }
1196             break;
1197 
1198         case RTF_BKMK_KEY:
1199         case RTF_XE:
1200         case RTF_TC:
1201         case RTF_NEXTFILE:
1202         case RTF_TEMPLATE:
1203         case RTF_SHPRSLT:
1204             SkipGroup();
1205             break;
1206 
1207         case RTF_CS:
1208             // we write every time "EQ "
1209             if( bFldInst && 0 == sFieldStr.SearchAscii( "EQ " ))
1210             {
1211                 // insert behind the EQ the "\*cs<NO> " string. This is utilize
1212                 // in the MakeFieldInst
1213                 String sTmp;
1214                 (sTmp.AssignAscii( "\\* cs" )
1215                     += String::CreateFromInt32( nTokenValue )) += ' ';
1216                 sFieldStr.Insert( sTmp, 3 );
1217             }
1218             break;
1219         case RTF_FFNAME:
1220         case RTF_FORMFIELD:
1221             break;
1222         case RTF_PAR:
1223             sFieldStr.Append('\x0a');
1224             break;
1225         default:
1226             SvxRTFParser::NextToken( nToken );
1227             break;
1228         }
1229     }
1230 
1231     // Grafik einfuegen
1232     if (RTFFLD_IMPORT == nRet && sFieldNm.Len())
1233         InsPicture( sFieldNm );
1234 
1235     SkipToken( -1 );        // die schliesende Klammer wird "oben" ausgewertet
1236 }
1237 
1238 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
1239