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