xref: /AOO42X/main/sw/source/filter/ww8/ww8par5.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 
28 #include <ctype.h>              // tolower
29 #include <stdio.h>              // sscanf()
30 
31 #include <sal/types.h>
32 #include <tools/solar.h>
33 
34 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
35 #include <svl/urihelper.hxx>
36 #include <svl/zforlist.hxx>
37 #include <svl/zformat.hxx>
38 #include <sfx2/linkmgr.hxx>
39 
40 #include <ucbhelper/content.hxx>
41 #include <ucbhelper/contentbroker.hxx>
42 #include <ucbhelper/commandenvironment.hxx>
43 
44 #include <com/sun/star/i18n/ScriptType.hdl>
45 #include <hintids.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/fhgtitem.hxx>
48 #include <editeng/langitem.hxx>
49 #include <fmtfld.hxx>
50 #include <fmtanchr.hxx>
51 #include <pam.hxx>              // fuer SwPam
52 #include <doc.hxx>
53 #include <charatr.hxx>          // class SwFmtFld
54 #include <flddat.hxx>           // class SwDateTimeField
55 #include <docufld.hxx>          // class SwPageNumberField
56 #include <reffld.hxx>           // class SwGetRefField
57 #include <IMark.hxx>
58 #include <expfld.hxx>           // class SwSetExpField
59 #include <dbfld.hxx>            // class SwDBField
60 #include <usrfld.hxx>
61 #include <tox.hxx>
62 #include <section.hxx>          // class SwSection
63 #include <ndtxt.hxx>
64 #include <fmtinfmt.hxx>
65 #include <chpfld.hxx>
66 #include <ftnidx.hxx>
67 #include <txtftn.hxx>
68 #include <viewsh.hxx>
69 #include <shellres.hxx>
70 #include <fmtruby.hxx>
71 #include <charfmt.hxx>
72 #include <txtatr.hxx>
73 #include <breakit.hxx>
74 #include <fmtclds.hxx>
75 #include <pagedesc.hxx>
76 #include <SwStyleNameMapper.hxx>
77 #include <IMark.hxx>
78 
79 #include "ww8scan.hxx"          // WW8FieldDesc
80 #include "ww8par.hxx"
81 #include "ww8par2.hxx"
82 #include "writerhelper.hxx"
83 #include "fields.hxx"
84 #include <unotools/fltrcfg.hxx>
85 
86 #include <algorithm> // #i24377#
87 
88 #define MAX_FIELDLEN 64000
89 
90 #define WW8_TOX_LEVEL_DELIM     ':'
91 
92 using namespace ::com::sun::star;
93 using namespace sw::util;
94 using namespace sw::mark;
95 using namespace std; // #i24377#
96 using namespace nsSwDocInfoSubType;
97 
98 
99 class _ReadFieldParams
100 {
101 private:
102     String aData;
103     xub_StrLen nLen, nFnd, nNext, nSavPtr;
104 public:
105     _ReadFieldParams( const String& rData );
106     ~_ReadFieldParams();
107 
108     xub_StrLen GoToTokenParam();
109     long SkipToNextToken();
GetTokenSttPtr() const110     xub_StrLen GetTokenSttPtr() const   { return nFnd;  }
111 
112     xub_StrLen FindNextStringPiece( xub_StrLen _nStart = STRING_NOTFOUND );
113     bool GetTokenSttFromTo(xub_StrLen* _pFrom, xub_StrLen* _pTo,
114         xub_StrLen _nMax);
115 
116     String GetResult() const;
117 };
118 
119 
_ReadFieldParams(const String & _rData)120 _ReadFieldParams::_ReadFieldParams( const String& _rData )
121     : aData( _rData ), nLen( _rData.Len() ), nNext( 0 )
122 {
123     /*
124         erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem
125         Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl
126         (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird
127     */
128     while( (nLen > nNext) && (aData.GetChar( nNext ) == ' ') )
129         ++nNext;
130 
131     sal_Unicode c;
132     while(     nLen > nNext
133             && (c = aData.GetChar( nNext )) != ' '
134             && c != '"'
135             && c != '\\'
136             && c != 132
137             && c != 0x201c )
138         ++nNext;
139 
140     nFnd      = nNext;
141     nSavPtr   = nNext;
142 //  cLastChar = aData.GetChar( nSavPtr );
143 }
144 
145 
~_ReadFieldParams()146 _ReadFieldParams::~_ReadFieldParams()
147 {
148 //  aData.SetChar( nSavPtr, cLastChar );
149 }
150 
151 
GetResult() const152 String _ReadFieldParams::GetResult() const
153 {
154     return    (STRING_NOTFOUND == nFnd)
155             ? aEmptyStr
156             : aData.Copy( nFnd, (nSavPtr - nFnd) );
157 }
158 
159 
GoToTokenParam()160 xub_StrLen _ReadFieldParams::GoToTokenParam()
161 {
162     xub_StrLen nOld = nNext;
163     if( -2 == SkipToNextToken() )
164         return GetTokenSttPtr();
165     nNext = nOld;
166     return STRING_NOTFOUND;
167 }
168 
169 // ret: -2: NOT a '\' parameter but normal Text
SkipToNextToken()170 long _ReadFieldParams::SkipToNextToken()
171 {
172     long nRet = -1;     // Ende
173     if (
174          (STRING_NOTFOUND != nNext) && (nLen > nNext) &&
175          STRING_NOTFOUND != (nFnd = FindNextStringPiece(nNext))
176        )
177     {
178         nSavPtr = nNext;
179 
180         if ('\\' == aData.GetChar(nFnd) && '\\' != aData.GetChar(nFnd + 1))
181         {
182             nRet = aData.GetChar(++nFnd);
183             nNext = ++nFnd;             // und dahinter setzen
184         }
185         else
186         {
187             nRet = -2;
188             if (
189                  (STRING_NOTFOUND != nSavPtr ) &&
190                  (
191                    ('"' == aData.GetChar(nSavPtr - 1)) ||
192                    (0x201d == aData.GetChar(nSavPtr - 1))
193                  )
194                )
195             {
196                 --nSavPtr;
197             }
198         }
199     }
200     return nRet;
201 }
202 
203 // FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette
204 // bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen
205 // oder zum String-Ende von pStr.
206 //
207 // Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0
208 //
209 // Returnwert: 0 falls String-Ende erreicht,
210 //             ansonsten Anfang des Paramters bzw. der Zeichenkette
211 //
FindNextStringPiece(const xub_StrLen nStart)212 xub_StrLen _ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart)
213 {
214     xub_StrLen  n = ( STRING_NOTFOUND == nStart ) ? nFnd : nStart;  // Anfang
215     xub_StrLen n2;          // Ende
216 
217     nNext = STRING_NOTFOUND;        // Default fuer nicht gefunden
218 
219     while( (nLen > n) && (aData.GetChar( n ) == ' ') )
220         ++n;
221 
222     if( nLen == n )
223         return STRING_NOTFOUND;     // String End reached!
224 
225     if(     (aData.GetChar( n ) == '"')     // Anfuehrungszeichen vor Para?
226         ||  (aData.GetChar( n ) == 0x201c)
227         ||  (aData.GetChar( n ) == 132) )
228     {
229         n++;                        // Anfuehrungszeichen ueberlesen
230         n2 = n;                     // ab hier nach Ende suchen
231         while(     (nLen > n2)
232                 && (aData.GetChar( n2 ) != '"')
233                 && (aData.GetChar( n2 ) != 0x201d)
234                 && (aData.GetChar( n2 ) != 147) )
235             n2++;                   // Ende d. Paras suchen
236     }
237     else                        // keine Anfuehrungszeichen
238     {
239         n2 = n;                     // ab hier nach Ende suchen
240         while( (nLen > n2) && (aData.GetChar( n2 ) != ' ') ) // Ende d. Paras suchen
241         {
242             if( aData.GetChar( n2 ) == '\\' )
243             {
244                 if( aData.GetChar( n2+1 ) == '\\' )
245                     n2 += 2;        // Doppel-Backslash -> OK
246                 else
247                 {
248                     if( n2 > n )
249                         n2--;
250                     break;          // einfach-Backslash -> Ende
251                 }
252             }
253             else
254                 n2++;               // kein Backslash -> OK
255         }
256     }
257     if( nLen > n2 )
258     {
259         if(aData.GetChar( n2 ) != ' ') n2++;
260         nNext = n2;
261     }
262     return n;
263 }
264 
265 
266 
267 // read parameters "1-3" or 1-3 with both values between 1 and nMax
GetTokenSttFromTo(sal_uInt16 * pFrom,sal_uInt16 * pTo,sal_uInt16 nMax)268 bool _ReadFieldParams::GetTokenSttFromTo(sal_uInt16* pFrom, sal_uInt16* pTo, sal_uInt16 nMax)
269 {
270     sal_uInt16 nStart = 0;
271     sal_uInt16 nEnd   = 0;
272     xub_StrLen n = GoToTokenParam();
273     if( STRING_NOTFOUND != n )
274     {
275 
276         String sParams( GetResult() );
277 
278         xub_StrLen nIndex = 0;
279         String sStart( sParams.GetToken(0, '-', nIndex) );
280         if( STRING_NOTFOUND != nIndex )
281         {
282             nStart = static_cast<sal_uInt16>(sStart.ToInt32());
283             nEnd   = static_cast<sal_uInt16>(sParams.Copy(nIndex).ToInt32());
284         }
285     }
286     if( pFrom ) *pFrom = nStart;
287     if( pTo )   *pTo   = nEnd;
288 
289     return nStart && nEnd && (nMax >= nStart) && (nMax >= nEnd);
290 }
291 
292 //----------------------------------------
293 //              Bookmarks
294 //----------------------------------------
295 
296 namespace
297 {
298     // #120879# - helper method to identify a bookmark name to match the internal TOC bookmark naming convention
IsTOCBookmarkName(const::rtl::OUString & rName)299     bool IsTOCBookmarkName( const ::rtl::OUString& rName )
300     {
301         static const ::rtl::OUString cTOCBookmarkNamePrefix = ::rtl::OUString::createFromAscii("_Toc");
302 
303         return rName.match(cTOCBookmarkNamePrefix);
304     }
305 }
306 
Read_Book(WW8PLCFManResult *)307 long SwWW8ImplReader::Read_Book(WW8PLCFManResult*)
308 {
309     // muesste auch ueber pRes.nCo2OrIdx gehen
310     WW8PLCFx_Book* pB = pPlcxMan->GetBook();
311     if( !pB )
312     {
313         ASSERT( pB, "WW8PLCFx_Book - Pointer nicht da" );
314         return 0;
315     }
316 
317     eBookStatus eB = pB->GetStatus();
318     if (eB & BOOK_IGNORE)
319         return 0;                               // Bookmark zu ignorieren
320 
321     if (pB->GetIsEnd())
322     {
323         pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
324             pB->GetHandle(), (eB & BOOK_FIELD)!=0);
325         return 0;
326     }
327 
328     // "_Hlt*" are unnecessary
329     const String* pName = pB->GetName();
330     // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available.
331     // So the hidden bookmarks inside for hyperlink jumping also should be kept.
332     if ( !pName ||
333          pName->EqualsIgnoreCaseAscii( "_Hlt", 0, 4 ) )
334     {
335         return 0;
336     }
337 
338     //JP 16.11.98: ToUpper darf auf keinen Fall gemacht werden, weil der
339     //Bookmark- name ein Hyperlink-Ziel sein kann!
340 
341     String aVal;
342     if( SwFltGetFlag( nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
343     {
344         // Fuer UEbersetzung Bookmark -> Variable setzen
345         long nLen = pB->GetLen();
346         if( nLen > MAX_FIELDLEN )
347             nLen = MAX_FIELDLEN;
348 
349         long nOldPos = pStrm->Tell();
350         nLen = pSBase->WW8ReadString( *pStrm, aVal, pB->GetStartPos(), nLen,
351                                         eStructCharSet );
352         pStrm->Seek( nOldPos );
353 
354         // JP 19.03.2001 - now here the implementation of the old
355         //              "QuoteString" and I hope with a better performance
356         //              as before. It's also only needed if the filterflags
357         //              say we will convert bookmarks to SetExpFields! And
358         //              this the exception!
359 
360         String sHex(CREATE_CONST_ASC( "\\x" ));
361         bool bSetAsHex;
362         bool bAllowCr = SwFltGetFlag(nFieldFlags,
363             SwFltControlStack::ALLOW_FLD_CR) ? true : false;
364 
365         sal_Unicode cChar;
366 
367         for( xub_StrLen nI = 0;
368                 nI < aVal.Len() && aVal.Len() < (MAX_FIELDLEN - 4); ++nI )
369         {
370             switch( cChar = aVal.GetChar( nI ) )
371             {
372             case 0x0b:
373             case 0x0c:
374             case 0x0d:
375                 if( bAllowCr )
376                     aVal.SetChar( nI, '\n' ), bSetAsHex = false;
377                 else
378                     bSetAsHex = true;
379                 break;
380 
381             case 0xFE:
382             case 0xFF:
383                 bSetAsHex = true;
384                 break;
385 
386             default:
387                 bSetAsHex = 0x20 > cChar;
388                 break;
389             }
390 
391             if( bSetAsHex )
392             {
393                 //all Hex-Numbers with \x before
394                 String sTmp( sHex );
395                 if( cChar < 0x10 )
396                     sTmp += '0';
397                 sTmp += String::CreateFromInt32( cChar, 16 );
398                 aVal.Replace( nI, 1 , sTmp );
399                 nI += sTmp.Len() - 1;
400             }
401         }
402 
403         if( aVal.Len() > (MAX_FIELDLEN - 4))
404             aVal.Erase( MAX_FIELDLEN - 4 );
405     }
406 
407     //e.g. inserting bookmark around field result, so we need to put
408     //it around the entire writer field, as we don't have the separation
409     //of field and field result of word, see #i16941#
410     SwPosition aStart(*pPaM->GetPoint());
411     if (!maFieldStack.empty())
412     {
413         const FieldEntry &rTest = maFieldStack.back();
414         aStart = rTest.maStartPos;
415     }
416 
417     const String sOrigName = BookmarkToWriter(*pName);
418     pReffedStck->NewAttr( aStart,
419                           SwFltBookmark( sOrigName, aVal, pB->GetHandle(), IsTOCBookmarkName( sOrigName ) ));
420     return 0;
421 }
422 
423 //----------------------------------------------------------------------
424 //    allgemeine Hilfsroutinen zum Auseinanderdroeseln der Parameter
425 //----------------------------------------------------------------------
426 
427 // ConvertFFileName uebersetzt FeldParameter-Namen u. ae. in den
428 // System-Zeichensatz.
429 // Gleichzeitig werden doppelte Backslashes in einzelne uebersetzt.
ConvertFFileName(String & rName,const String & rOrg)430 void SwWW8ImplReader::ConvertFFileName( String& rName, const String& rOrg )
431 {
432     rName = rOrg;
433     rName.SearchAndReplaceAllAscii( "\\\\", String( '\\' ));
434     rName.SearchAndReplaceAllAscii( "%20", String( ' ' ));
435 
436     // ggfs. anhaengende Anfuehrungszeichen entfernen
437     if( rName.Len() &&  '"' == rName.GetChar( rName.Len()-1 ))
438         rName.Erase( rName.Len()-1, 1);
439 
440     //#82900# Need the more sophisticated url converter. cmc
441     if (rName.Len())
442         rName = URIHelper::SmartRel2Abs(
443             INetURLObject(sBaseURL), rName, Link(), false);
444 }
445 
446 // ConvertUFNneme uebersetzt FeldParameter-Namen u. ae. in den
447 // System-Zeichensatz und Upcased sie ( z.B. fuer Ref-Felder )
448 namespace
449 {
ConvertUFName(String & rName)450     void ConvertUFName( String& rName )
451     {
452         GetAppCharClass().toUpper( rName );
453     }
454 }
455 
lcl_ConvertSequenceName(String & rSequenceName)456 static void lcl_ConvertSequenceName(String& rSequenceName)
457 {
458     ConvertUFName(rSequenceName);
459     if ('0' <= rSequenceName.GetChar(0) && '9' >= rSequenceName.GetChar(0))
460         rSequenceName.Insert('_', 0);
461 }
462 
463 // FindParaStart() finds 1st Parameter that follows '\' and cToken
464 // and returns start of this parameter or STRING_NOT_FOUND.
FindParaStart(const String & rStr,sal_Unicode cToken,sal_Unicode cToken2)465 xub_StrLen FindParaStart( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
466 {
467     bool bStr = false;          // innerhalb String ignorieren
468 
469     for( xub_StrLen nBuf=0; nBuf+1 < rStr.Len(); nBuf++ )
470     {
471         if( rStr.GetChar( nBuf ) == '"' )
472             bStr = !bStr;
473 
474         if(    !bStr
475             && rStr.GetChar( nBuf ) == '\\'
476             && (    rStr.GetChar( nBuf + 1 ) == cToken
477                  || rStr.GetChar( nBuf + 1 ) == cToken2 ) )
478         {
479             nBuf += 2;
480             // skip spaces between cToken and it's parameters
481             while(    nBuf < rStr.Len()
482                    && rStr.GetChar( nBuf ) == ' ' )
483                 nBuf++;
484             // return start of parameters
485             return nBuf < rStr.Len() ? nBuf : STRING_NOTFOUND;
486         }
487     }
488     return STRING_NOTFOUND;
489 }
490 
491 // FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
492 // ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
493 // und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
FindPara(const String & rStr,sal_Unicode cToken,sal_Unicode cToken2)494 String FindPara( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
495 {
496     xub_StrLen n2;                                          // Ende
497     xub_StrLen n = FindParaStart( rStr, cToken, cToken2 );  // Anfang
498     if( STRING_NOTFOUND == n )
499         return aEmptyStr;
500 
501     if(    rStr.GetChar( n ) == '"'
502         || rStr.GetChar( n ) == 132 )
503     {                               // Anfuehrungszeichen vor Para
504         n++;                        // Anfuehrungszeichen ueberlesen
505         n2 = n;                     // ab hier nach Ende suchen
506         while(     n2 < rStr.Len()
507                 && rStr.GetChar( n2 ) != 147
508                 && rStr.GetChar( n2 ) != '"' )
509             n2++;                   // Ende d. Paras suchen
510     }
511     else
512     {                           // keine Anfuehrungszeichen
513         n2 = n;                     // ab hier nach Ende suchen
514         while(     n2 < rStr.Len()
515                 && rStr.GetChar( n2 ) != ' ' )
516             n2++;                   // Ende d. Paras suchen
517     }
518     return rStr.Copy( n, n2-n );
519 }
520 
521 
GetNumTypeFromName(const String & rStr,bool bAllowPageDesc=false)522 static SvxExtNumType GetNumTypeFromName(const String& rStr,
523     bool bAllowPageDesc = false)
524 {
525     SvxExtNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
526     if( rStr.EqualsIgnoreCaseAscii( "Arabi", 0, 5 ) )  // Arabisch, Arabic
527         eTyp = SVX_NUM_ARABIC;
528     else if( rStr.EqualsAscii( "misch", 2, 5 ) )    // r"omisch
529         eTyp = SVX_NUM_ROMAN_LOWER;
530     else if( rStr.EqualsAscii( "MISCH", 2, 5 ) )    // R"OMISCH
531         eTyp = SVX_NUM_ROMAN_UPPER;
532     else if( rStr.EqualsIgnoreCaseAscii( "alphabeti", 0, 9 ) )// alphabetisch, alphabetic
533         eTyp =  ( rStr.GetChar( 0 ) == 'A' )
534                 ? SVX_NUM_CHARS_UPPER_LETTER_N
535                 : SVX_NUM_CHARS_LOWER_LETTER_N;
536     else if( rStr.EqualsIgnoreCaseAscii( "roman", 0, 5 ) )  // us
537         eTyp =  ( rStr.GetChar( 0 ) == 'R' )
538                 ? SVX_NUM_ROMAN_UPPER
539                 : SVX_NUM_ROMAN_LOWER;
540     return eTyp;
541 }
542 
GetNumberPara(String & rStr,bool bAllowPageDesc=false)543 static SvxExtNumType GetNumberPara(String& rStr, bool bAllowPageDesc = false)
544 {
545     String s( FindPara( rStr, '*', '*' ) );     // Ziffernart
546     SvxExtNumType aType = GetNumTypeFromName( s, bAllowPageDesc );
547     return aType;
548 }
549 
550 
551 
552 
ForceFieldLanguage(SwField & rFld,sal_uInt16 nLang)553 bool SwWW8ImplReader::ForceFieldLanguage(SwField &rFld, sal_uInt16 nLang)
554 {
555     bool bRet(false);
556 
557     const SvxLanguageItem *pLang =
558         (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
559     ASSERT(pLang, "impossible");
560     sal_uInt16 nDefault =  pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
561 
562     if (nLang != nDefault)
563     {
564         rFld.SetAutomaticLanguage(false);
565         rFld.SetLanguage(nLang);
566         bRet = true;
567     }
568 
569     return bRet;
570 }
571 
GetWordDefaultDateStringAsUS(SvNumberFormatter * pFormatter,sal_uInt16 nLang)572 String GetWordDefaultDateStringAsUS(SvNumberFormatter* pFormatter, sal_uInt16 nLang)
573 {
574     //Get the system date in the correct final language layout, convert to
575     //a known language and modify the 2 digit year part to be 4 digit, and
576     //convert back to the correct language layout.
577     sal_uLong nIndex = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, nLang);
578 
579     SvNumberformat aFormat = const_cast<SvNumberformat &>
580         (*(pFormatter->GetEntry(nIndex)));
581     aFormat.ConvertLanguage(*pFormatter, nLang, LANGUAGE_ENGLISH_US);
582 
583     String sParams(aFormat.GetFormatstring());
584     // --> OD 2007-02-09 #i36594#
585     // Fix provided by mloiseleur@openoffice.org.
586     // A default date can have already 4 year digits, in some case
587     const xub_StrLen pos = sParams.Search( CREATE_CONST_ASC("YYYY") );
588     if ( pos == STRING_NOTFOUND )
589     {
590         sParams.SearchAndReplace(CREATE_CONST_ASC("YY"), CREATE_CONST_ASC("YYYY"));
591     }
592     // <--
593     return sParams;
594 }
595 
GetTimeDatePara(String & rStr,sal_uInt32 & rFormat,sal_uInt16 & rLang,int nWhichDefault,bool bHijri)596 short SwWW8ImplReader::GetTimeDatePara(String& rStr, sal_uInt32& rFormat,
597     sal_uInt16 &rLang, int nWhichDefault, bool bHijri)
598 {
599     bool bRTL = false;
600     if (pPlcxMan && !bVer67)
601     {
602         const sal_uInt8 *pResult = pPlcxMan->HasCharSprm(0x85A);
603         if (pResult && *pResult)
604             bRTL = true;
605     }
606     RES_CHRATR eLang = bRTL ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
607     const SvxLanguageItem *pLang = (SvxLanguageItem*)GetFmtAttr( static_cast< sal_uInt16 >(eLang));
608     ASSERT(pLang, "impossible");
609     rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
610 
611     SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
612     String sParams( FindPara( rStr, '@', '@' ) );// Date/Time
613     if (!sParams.Len())
614     {
615         bool bHasTime = false;
616         switch (nWhichDefault)
617         {
618             case ww::ePRINTDATE:
619             case ww::eSAVEDATE:
620                 sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
621                 sParams.APPEND_CONST_ASC(" HH:MM:SS AM/PM");
622                 bHasTime = true;
623                 break;
624             case ww::eCREATEDATE:
625                 sParams.ASSIGN_CONST_ASC("DD/MM/YYYY HH:MM:SS");
626                 bHasTime = true;
627                 break;
628             default:
629             case ww::eDATE:
630                 sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
631                 break;
632         }
633 
634         if (bHijri)
635             sParams.Insert(CREATE_CONST_ASC("[~hijri]"), 0);
636 
637         sal_uInt16 nCheckPos = 0;
638         sal_Int16 nType = NUMBERFORMAT_DEFINED;
639         rFormat = 0;
640 
641         pFormatter->PutandConvertEntry(sParams, nCheckPos, nType, rFormat,
642             LANGUAGE_ENGLISH_US, rLang);
643 
644         return bHasTime ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE;
645     }
646 
647     sal_uLong nFmtIdx =
648         sw::ms::MSDateTimeFormatToSwFormat(sParams, pFormatter, rLang, bHijri);
649     short nNumFmtType = NUMBERFORMAT_UNDEFINED;
650     if (nFmtIdx)
651         nNumFmtType = pFormatter->GetType(nFmtIdx);
652     rFormat = nFmtIdx;
653 
654     return nNumFmtType;
655 }
656 
657 //-----------------------------------------
658 //              Felder
659 //-----------------------------------------
660 // Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
UpdateFields()661 void SwWW8ImplReader::UpdateFields()
662 {
663 //  rDoc.GetSysFldType( RES_GETREFFLD )->UpdateFlds();  // Referenzen
664 //  rDoc.UpdateFlds();                                  // SetExp-Fields
665 //  rDoc.UpdateFlds();              // alles ???
666 //  rDoc.UpdateExpFlds();                               // SetExp-Fields
667     rDoc.SetUpdateExpFldStat(true);                 // JP: neu fuer alles wichtige
668     rDoc.SetInitDBFields(true);             // Datenbank-Felder auch
669 }
670 
End_Field()671 sal_uInt16 SwWW8ImplReader::End_Field()
672 {
673     sal_uInt16 nRet = 0;
674     WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
675     ASSERT(pF, "WW8PLCFx_FLD - Pointer nicht da");
676     WW8_CP nCP = 0;
677     if (!pF || !pF->EndPosIsFieldEnd(nCP))
678         return nRet;
679 
680     const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
681     sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
682 
683     ASSERT(!maFieldStack.empty(), "Empty field stack\n");
684     if (!maFieldStack.empty())
685     {
686         /*
687         only hyperlinks currently need to be handled like this, for the other
688         cases we have inserted a field not an attribute with an unknown end
689         point
690         */
691         nRet = maFieldStack.back().mnFieldId;
692         switch (nRet)
693         {
694         case 70:
695         if (bUseEnhFields && pPaM!=NULL && pPaM->GetPoint()!=NULL) {
696             SwPosition aEndPos = *pPaM->GetPoint();
697             SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
698             IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
699             IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeFieldBookmark(
700                         aFldPam, maFieldStack.back().GetBookmarkName(), ::rtl::OUString::createFromAscii(ODF_FORMTEXT ) ) );
701             ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
702             if (pFieldmark!=NULL) {
703                 const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
704                 pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
705             }
706         }
707         break;
708             // Doing corresponding status management for TOX field, index field, hyperlink field and page reference field
709             case 13://TOX
710             case 8://index
711                 if ( mbLoadingTOXCache )
712                 {
713                     if ( mnEmbeddedTOXLevel > 0 )
714                     {
715                         --mnEmbeddedTOXLevel;
716                     }
717                     else
718                     {
719                         maTOXEndCps.insert( nCP );
720                         mbLoadingTOXCache = false;
721                         if ( pPaM->End()
722                              && pPaM->End()->nNode.GetNode().GetTxtNode()
723                              && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0 )
724                         {
725                             JoinNode( *pPaM );
726                         }
727                         else
728                         {
729                             mbCareLastParaEndInToc = true;
730                         }
731 
732                         if ( mpPosAfterTOC )
733                         {
734                             *pPaM = *mpPosAfterTOC;
735                             delete mpPosAfterTOC;
736                             mpPosAfterTOC = 0;
737                         }
738                     }
739                 }
740                 break;
741             case 37://REF
742                 if (mbLoadingTOXCache && !mbLoadingTOXHyperlink)
743                 {
744                     pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
745                 }
746                 break;
747             case 88:
748                 if (mbLoadingTOXHyperlink)
749                     mbLoadingTOXHyperlink = false;
750                 pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
751                 break;
752             case 36:
753             case 68:
754                 //Move outside the section associated with this type of field
755                 *pPaM->GetPoint() = maFieldStack.back().maStartPos;
756                 break;
757             default:
758                 break;
759         }
760         maFieldStack.pop_back();
761     }
762     return nRet;
763 }
764 
AcceptableNestedField(sal_uInt16 nFieldCode)765 bool AcceptableNestedField(sal_uInt16 nFieldCode)
766 {
767     switch (nFieldCode)
768     {
769         case 8:  // allow recursive field in TOC...
770         case 13: // allow recursive field in TOC...
771         case 36:
772         case 68:
773         case 79:
774         case 88:
775         // Accept AutoTextList field as nested field.
776         // Thus, the field result is imported as plain text.
777         case 89:
778             return true;
779         default:
780             return false;
781     }
782 }
783 
FieldEntry(SwPosition & rPos,sal_uInt16 nFieldId)784 FieldEntry::FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw()
785     : maStartPos(rPos), mnFieldId(nFieldId)
786 {
787 }
788 
FieldEntry(const FieldEntry & rOther)789 FieldEntry::FieldEntry(const FieldEntry &rOther) throw()
790     : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId)
791 {
792 }
793 
Swap(FieldEntry & rOther)794 void FieldEntry::Swap(FieldEntry &rOther) throw()
795 {
796     std::swap(maStartPos, rOther.maStartPos);
797     std::swap(mnFieldId, rOther.mnFieldId);
798 }
799 
operator =(const FieldEntry & rOther)800 FieldEntry &FieldEntry::operator=(const FieldEntry &rOther) throw()
801 {
802     FieldEntry aTemp(rOther);
803     Swap(aTemp);
804     return *this;
805 }
806 
GetBookmarkName()807 ::rtl::OUString FieldEntry::GetBookmarkName()
808 {
809     return msBookmarkName;
810 }
811 
GetBookmarkType()812 ::rtl::OUString FieldEntry::GetBookmarkType()
813 {
814     return msMarkType;
815 }
816 
SetBookmarkName(::rtl::OUString bookmarkName)817 void FieldEntry::SetBookmarkName(::rtl::OUString bookmarkName)
818 {
819     msBookmarkName=bookmarkName;
820 }
821 
SetBookmarkType(::rtl::OUString bookmarkType)822 void FieldEntry::SetBookmarkType(::rtl::OUString bookmarkType)
823 {
824     msMarkType=bookmarkType;
825 }
826 
827 
getParameters()828 ::sw::mark::IFieldmark::parameter_map_t& FieldEntry::getParameters() {
829     return maParams;
830 }
831 
832 
833 // Read_Field liest ein Feld ein oder, wenn es nicht gelesen werden kann,
834 // wird 0 zurueckgegeben, so dass das Feld vom Aufrufer textuell gelesen wird.
835 // Returnwert: Gesamtlaenge des Feldes ( zum UEberlesen )
Read_Field(WW8PLCFManResult * pRes)836 long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
837 {
838     typedef eF_ResT (SwWW8ImplReader:: *FNReadField)( WW8FieldDesc*, String& );
839     enum Limits {eMax = 96};
840     static FNReadField aWW8FieldTab[eMax+1] =
841     {
842         0,
843         0,
844         0,
845         &SwWW8ImplReader::Read_F_Ref,               // 3
846         0,
847         0,
848         &SwWW8ImplReader::Read_F_Set,               // 6
849         0,
850         &SwWW8ImplReader::Read_F_Tox,               // 8
851         0,
852         0,
853         0,
854         &SwWW8ImplReader::Read_F_Seq,               // 12
855         &SwWW8ImplReader::Read_F_Tox,               // 13
856         &SwWW8ImplReader::Read_F_DocInfo,           // 14
857         &SwWW8ImplReader::Read_F_DocInfo,           // 15
858         &SwWW8ImplReader::Read_F_DocInfo,           // 16
859         &SwWW8ImplReader::Read_F_Author,            // 17
860         &SwWW8ImplReader::Read_F_DocInfo,           // 18
861         &SwWW8ImplReader::Read_F_DocInfo,           // 19
862         &SwWW8ImplReader::Read_F_DocInfo,           // 20
863         &SwWW8ImplReader::Read_F_DocInfo,           // 21
864         &SwWW8ImplReader::Read_F_DocInfo,           // 22
865         &SwWW8ImplReader::Read_F_DocInfo,           // 23
866         &SwWW8ImplReader::Read_F_DocInfo,           // 24
867         &SwWW8ImplReader::Read_F_DocInfo,           // 25
868         &SwWW8ImplReader::Read_F_Anz,               // 26
869         &SwWW8ImplReader::Read_F_Anz,               // 27
870         &SwWW8ImplReader::Read_F_Anz,               // 28
871         &SwWW8ImplReader::Read_F_FileName,          // 29
872         &SwWW8ImplReader::Read_F_TemplName,         // 30
873         &SwWW8ImplReader::Read_F_DateTime,          // 31
874         &SwWW8ImplReader::Read_F_DateTime,          // 32
875         &SwWW8ImplReader::Read_F_CurPage,           // 33
876         0,
877         0,
878         &SwWW8ImplReader::Read_F_IncludeText,       // 36
879         &SwWW8ImplReader::Read_F_PgRef,             // 37
880         &SwWW8ImplReader::Read_F_InputVar,          // 38
881         &SwWW8ImplReader::Read_F_Input,             // 39
882         0,
883         &SwWW8ImplReader::Read_F_DBNext,            // 41
884         0,
885         0,
886         &SwWW8ImplReader::Read_F_DBNum,             // 44
887         0,
888         0,
889         0,
890         0,
891         &SwWW8ImplReader::Read_F_Equation,          // 49
892         0,
893         &SwWW8ImplReader::Read_F_Macro,             // 51
894         &SwWW8ImplReader::Read_F_ANumber,           // 52
895         &SwWW8ImplReader::Read_F_ANumber,           // 53
896         &SwWW8ImplReader::Read_F_ANumber,           // 54
897         0,
898 
899 
900         0,      // 56: VERKNUePFUNG     // fehlt noch !!!!!!!!!!!!!!!!!!!!!!!
901 
902 
903         &SwWW8ImplReader::Read_F_Symbol,            // 57
904         &SwWW8ImplReader::Read_F_Embedd,            // 58
905         &SwWW8ImplReader::Read_F_DBField,           // 59
906         0,
907         0,
908         0,
909         0,
910         0,
911         0,
912         0,
913         &SwWW8ImplReader::Read_F_IncludePicture,    // 67
914         &SwWW8ImplReader::Read_F_IncludeText,       // 68
915         0,
916         &SwWW8ImplReader::Read_F_FormTextBox,       // 70
917         &SwWW8ImplReader::Read_F_FormCheckBox,      // 71
918         &SwWW8ImplReader::Read_F_NoteReference,     // 72
919         0, /*&SwWW8ImplReader::Read_F_Tox*/
920         0,
921         0,
922         0,
923         0,
924         0,
925         0,
926         0,
927         0,
928         0,
929         &SwWW8ImplReader::Read_F_FormListBox,       // 83
930         0,                                          // 84
931         &SwWW8ImplReader::Read_F_DocInfo,           // 85
932         0,                                          // 86
933         &SwWW8ImplReader::Read_F_OCX,               // 87
934         &SwWW8ImplReader::Read_F_Hyperlink,         // 88
935         0,                                          // 89
936         0,                                          // 90
937         0,                                          // 91
938         0,                                          // 92
939         0,                                          // 93
940         0,                                          // 94
941         &SwWW8ImplReader::Read_F_Shape,             // 95
942         0                                           // eMax - Dummy leer Methode
943     };
944     ASSERT( ( sizeof( aWW8FieldTab ) / sizeof( *aWW8FieldTab ) == eMax+1 ),
945             "FeldFunc-Tabelle stimmt nicht" );
946 
947     WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
948     ASSERT(pF, "WW8PLCFx_FLD - Pointer nicht da");
949 
950     if (!pF || !pF->StartPosIsFieldStart())
951         return 0;
952 
953     bool bNested = false;
954     if (!maFieldStack.empty())
955     {
956         mycFieldIter aEnd = maFieldStack.end();
957         for(mycFieldIter aIter = maFieldStack.begin(); aIter != aEnd; ++aIter)
958         {
959             bNested = !AcceptableNestedField(aIter->mnFieldId);
960             if (bNested)
961                 break;
962         }
963     }
964 
965     WW8FieldDesc aF;
966     bool bOk = pF->GetPara(pRes->nCp2OrIdx, aF);
967 
968     ASSERT(bOk, "WW8: Bad Field!\n");
969     if (aF.nId == 33) aF.bCodeNest=false; //#124716#: do not recurse into nested page fields
970 
971     maFieldStack.push_back(FieldEntry(*pPaM->GetPoint(), aF.nId));
972 
973     if (bNested)
974         return 0;
975 
976     sal_uInt16 n = (aF.nId <= eMax) ? aF.nId : static_cast<sal_uInt16>(eMax);
977     sal_uInt16 nI = n / 32;                     // # des sal_uInt32
978     sal_uLong nMask = 1 << ( n % 32 );          // Maske fuer Bits
979 
980     if ((sizeof(nFieldTagAlways)/sizeof(nFieldTagAlways[0])) <= nI)
981     {   // if indexes larger than 95 are needed, then a new configuration
982         // item has to be added, and nFieldTagAlways/nFieldTagBad expanded!
983         return aF.nLen;
984     }
985 
986     if( nFieldTagAlways[nI] & nMask )       // Flag: Tag it
987         return Read_F_Tag( &aF );           // Resultat nicht als Text
988 
989     if( !bOk || !aF.nId )                   // Feld kaputt
990         return aF.nLen;                     // -> ignorieren
991 
992     if( aF.nId > eMax - 1)                        // WW: Nested Field
993     {
994         if( nFieldTagBad[nI] & nMask )      // Flag: Tag it when bad
995             return Read_F_Tag( &aF );       // Resultat nicht als Text
996         else
997             return aF.nLen;
998     }
999 
1000     //Only one type of field (hyperlink) in drawing textboxes exists
1001     if (aF.nId != 88 && pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
1002         return aF.nLen;
1003 
1004     // keine Routine vorhanden
1005     if (bNested || !aWW8FieldTab[aF.nId] || aF.bCodeNest)
1006     {
1007         if( nFieldTagBad[nI] & nMask )      // Flag: Tag it when bad
1008             return Read_F_Tag( &aF );       // Resultat nicht als Text
1009                                             // Lese nur Resultat
1010         if (aF.bResNest && !AcceptableNestedField(aF.nId))
1011             return aF.nLen;                 // Result nested -> nicht brauchbar
1012 
1013         long nOldPos = pStrm->Tell();
1014         String aStr;
1015         aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
1016             aF.nSCode, aF.nLCode, eTextCharSet );
1017         pStrm->Seek( nOldPos );
1018 
1019         //#124725# field codes which contain '/' or '.' are not displayed in WinWord
1020         // skip if it is formula field or found space before. see #i119446, #i119585.
1021         const xub_StrLen nDotPos = aStr.Search('.');
1022         const xub_StrLen nSlashPos = aStr.Search('/');
1023         xub_StrLen nSpacePos = aStr.Search( ' ', 1 );
1024         if ( nSpacePos == STRING_NOTFOUND )
1025             nSpacePos = aStr.Len();
1026 
1027         if ( !( aStr.EqualsAscii( "=", 1, 1 ) ) &&
1028             ((( nDotPos != STRING_NOTFOUND ) && ( nDotPos < nSpacePos )) ||
1029             (( nSlashPos != STRING_NOTFOUND ) && ( nSlashPos < nSpacePos ))))
1030             return aF.nLen;
1031         else
1032             return aF.nLen - aF.nLRes - 1;  // so viele ueberlesen, das Resultfeld
1033                                             // wird wie Haupttext eingelesen
1034     }
1035     else
1036     {                                   // Lies Feld
1037         long nOldPos = pStrm->Tell();
1038         String aStr;
1039         aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
1040             aF.nSCode, aF.nLCode, eTextCharSet );
1041 
1042         // --> OD 2005-07-25 #i51312# - graphics inside field code not supported
1043         // by Writer. Thus, delete character 0x01, which stands for such a graphic.
1044         if (aF.nId==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
1045         {
1046             aStr.EraseAllChars( 0x01 );
1047         }
1048         // <--
1049 
1050         eF_ResT eRes = (this->*aWW8FieldTab[aF.nId])( &aF, aStr );
1051         pStrm->Seek( nOldPos );
1052 
1053         switch ( eRes )
1054         {
1055             case FLD_OK:
1056                 return aF.nLen;                     // alles OK
1057             case FLD_TAGTXT:
1058                 if ((nFieldTagBad[nI] & nMask)) // Flag: Tag bad
1059                     return Read_F_Tag(&aF);       // Taggen
1060                 //fall through...
1061             case FLD_TEXT:
1062                 // so viele ueberlesen, das Resultfeld wird wie Haupttext
1063                 // eingelesen
1064                 // JP 15.07.99: attributes can start at char 0x14 so skip one
1065                 // char more back == "-2"
1066                 if (aF.nLRes)
1067                     return aF.nLen - aF.nLRes - 2;
1068                 else
1069                     return aF.nLen;
1070             case FLD_TAGIGN:
1071                 if(  ( nFieldTagBad[nI] & nMask ) ) // Flag: Tag bad
1072                     return Read_F_Tag( &aF );       // Taggen
1073                 return aF.nLen;                 // oder ignorieren
1074             case FLD_READ_FSPA:
1075                 return aF.nLen - aF.nLRes - 2; // auf Char 1 positionieren
1076             default:
1077                 return aF.nLen;                     // ignorieren
1078         }
1079     }
1080 }
1081 
1082 //-----------------------------------------
1083 //        Felder Taggen
1084 //-----------------------------------------
1085 
1086 // MakeTagString() gibt als Returnwert die Position des ersten
1087 // CR / Zeilenende / Seitenumbruch in pText und wandelt auch nur bis dort
1088 // Wenn keins dieser Sonderzeichen enthalten ist, wird 0 zurueckgeliefert.
MakeTagString(String & rStr,const String & rOrg)1089 void SwWW8ImplReader::MakeTagString( String& rStr, const String& rOrg )
1090 {
1091     String sHex( CREATE_CONST_ASC( "\\x" ));
1092     bool bAllowCr = SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_IN_TEXT )
1093                 || SwFltGetFlag( nFieldFlags, SwFltControlStack::ALLOW_FLD_CR );
1094     sal_Unicode cChar;
1095     rStr = rOrg;
1096 
1097     for( xub_StrLen nI = 0;
1098             nI < rStr.Len() && rStr.Len() < (MAX_FIELDLEN - 4); ++nI )
1099     {
1100         bool bSetAsHex = false;
1101         switch( cChar = rStr.GetChar( nI ) )
1102         {
1103             case 132:                       // Typographische Anfuehrungszeichen
1104             case 148:                       // gegen normale tauschen
1105             case 147:
1106                 rStr.SetChar( nI, '"' );
1107                 break;
1108             case 19:
1109                 rStr.SetChar( nI, '{' );
1110                 break;  // 19..21 zu {|}
1111             case 20:
1112                 rStr.SetChar( nI, '|' );
1113                 break;
1114             case 21:
1115                 rStr.SetChar( nI, '}' );
1116                 break;
1117             case '\\':                      // \{|} per \ Taggen
1118             case '{':
1119             case '|':
1120             case '}':
1121                 rStr.Insert( nI, '\\' );
1122                 ++nI;
1123                 break;
1124             case 0x0b:
1125             case 0x0c:
1126             case 0x0d:
1127                 if( bAllowCr )
1128                     rStr.SetChar( nI, '\n' );
1129                 else
1130                     bSetAsHex = true;
1131                 break;
1132             case 0xFE:
1133             case 0xFF:
1134                 bSetAsHex = true;
1135                 break;
1136             default:
1137                 bSetAsHex = 0x20 > cChar;
1138                 break;
1139         }
1140 
1141         if( bSetAsHex )
1142         {
1143             //all Hex-Numbers with \x before
1144             String sTmp( sHex );
1145             if( cChar < 0x10 )
1146                 sTmp += '0';
1147             sTmp += String::CreateFromInt32( cChar, 16 );
1148             rStr.Replace( nI, 1 , sTmp );
1149             nI += sTmp.Len() - 1;
1150         }
1151     }
1152 
1153     if( rStr.Len() > (MAX_FIELDLEN - 4))
1154         rStr.Erase( MAX_FIELDLEN - 4 );
1155 }
1156 
InsertTagField(const sal_uInt16 nId,const String & rTagText)1157 void SwWW8ImplReader::InsertTagField( const sal_uInt16 nId, const String& rTagText )
1158 {
1159     String aName( CREATE_CONST_ASC( "WwFieldTag" ) );
1160     if( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_DO_ID ) ) // Nummer?
1161         aName += String::CreateFromInt32( nId );                    // ausgeben ?
1162 
1163     if( SwFltGetFlag(nFieldFlags, SwFltControlStack::TAGS_IN_TEXT))
1164     {
1165         aName += rTagText;      // als Txt taggen
1166         rDoc.InsertString(*pPaM, aName,
1167                 IDocumentContentOperations::INS_NOHINTEXPAND);
1168     }
1169     else
1170     {                                                   // normal tagggen
1171 
1172         SwFieldType* pFT = rDoc.InsertFldType(
1173                                 SwSetExpFieldType( &rDoc, aName, nsSwGetSetExpType::GSE_STRING ) );
1174         SwSetExpField aFld( (SwSetExpFieldType*)pFT, rTagText );                            // SUB_INVISIBLE
1175         sal_uInt16 nSubType = ( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_VISIBLE ) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE;
1176         aFld.SetSubType(nSubType | nsSwGetSetExpType::GSE_STRING);
1177 
1178         rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1179     }
1180 }
1181 
Read_F_Tag(WW8FieldDesc * pF)1182 long SwWW8ImplReader::Read_F_Tag( WW8FieldDesc* pF )
1183 {
1184     long nOldPos = pStrm->Tell();
1185 
1186     WW8_CP nStart = pF->nSCode - 1;         // mit 0x19 am Anfang
1187     long nL = pF->nLen;                     // Gesamtlaenge mit Resultat u. Nest
1188     if( nL > MAX_FIELDLEN )
1189         nL = MAX_FIELDLEN;                  // MaxLaenge, durch Quoten
1190                                             // max. 4* so gross
1191     String sFTxt;
1192     nL = pSBase->WW8ReadString( *pStrm, sFTxt,
1193                                 pPlcxMan->GetCpOfs() + nStart, nL, eStructCharSet);
1194 
1195 
1196     String aTagText;
1197     MakeTagString( aTagText, sFTxt );
1198     InsertTagField( pF->nId, aTagText );
1199 
1200     pStrm->Seek( nOldPos );
1201     return pF->nLen;
1202 }
1203 
1204 
1205 //-----------------------------------------
1206 //        normale Felder
1207 //-----------------------------------------
1208 
Read_F_Input(WW8FieldDesc * pF,String & rStr)1209 eF_ResT SwWW8ImplReader::Read_F_Input( WW8FieldDesc* pF, String& rStr )
1210 {
1211     String aDef;
1212     String aQ;
1213     long nRet;
1214     _ReadFieldParams aReadParam( rStr );
1215     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1216     {
1217         switch( nRet )
1218         {
1219         case -2:
1220             if( !aQ.Len() )
1221                 aQ = aReadParam.GetResult();
1222             break;
1223         case 'd':
1224         case 'D':
1225             {
1226                 xub_StrLen n = aReadParam.GoToTokenParam();
1227                 if( STRING_NOTFOUND != n )
1228                     aDef = aReadParam.GetResult();
1229             }
1230             break;
1231         }
1232     }
1233     if( !aDef.Len() )
1234         aDef = GetFieldResult( pF );
1235 
1236     SwInputField aFld( static_cast<SwInputFieldType*>(rDoc.GetSysFldType( RES_INPUTFLD )),
1237                         aDef, aQ, INP_TXT, 0, false );
1238     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1239 
1240     return FLD_OK;
1241 }
1242 
1243 // GetFieldResult alloziert einen String und liest das Feld-Resultat ein
GetFieldResult(WW8FieldDesc * pF)1244 String SwWW8ImplReader::GetFieldResult( WW8FieldDesc* pF )
1245 {
1246     long nOldPos = pStrm->Tell();
1247 
1248     WW8_CP nStart = pF->nSRes;              // Start Resultat
1249     long nL = pF->nLRes;                    // Laenge Resultat
1250     if( !nL )
1251         return aEmptyStr;                           // kein Resultat
1252 
1253     if( nL > MAX_FIELDLEN )
1254         nL = MAX_FIELDLEN;                  // MaxLaenge, durch Quoten
1255                                             // max. 4* so gross
1256 
1257     String sRes;
1258     nL = pSBase->WW8ReadString( *pStrm, sRes, pPlcxMan->GetCpOfs() + nStart,
1259                                 nL, eStructCharSet );
1260 
1261     pStrm->Seek( nOldPos );
1262 
1263     //replace CR 0x0D with LF 0x0A
1264     sRes.SearchAndReplaceAll(0x0D, 0x0A);
1265     //replace VT 0x0B with LF 0x0A
1266     sRes.SearchAndReplaceAll(0x0B, 0x0A);
1267     return sRes;
1268 }
1269 
1270 /*
1271 Bookmarks can be set with fields SET and ASK, and they can be referenced with
1272 REF. When set, they behave like variables in writer, otherwise they behave
1273 like normal bookmarks. We can check whether we should use a show variable
1274 instead of a normal bookmark ref by converting to "show variable" at the end
1275 of the document those refs which look for the content of a bookmark but whose
1276 bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
1277 
1278 The other piece of the puzzle is that refs that point to the "location" of the
1279 bookmark will in word actually point to the last location where the bookmark
1280 was set with SET or ASK, not the actual bookmark. This is only noticeable when
1281 a document sets the bookmark more than once. This is because word places the
1282 true bookmark at the location of the last set, but the refs will display the
1283 position of the first set before the ref.
1284 
1285 So what we will do is
1286 
1287 1) keep a list of all bookmarks that were set, any bookmark names mentioned
1288 here that are refed by content will be converted to show variables.
1289 
1290 2) create pseudo bookmarks for every position that a bookmark is set with SET
1291 or ASK but has no existing bookmark. We can then keep a map from the original
1292 bookmark name to the new one. As we parse the document new pseudo names will
1293 replace the older ones, so the map always contains the bookmark of the
1294 location that msword itself would use.
1295 
1296 3) word's bookmarks are case insensitive, writers are not. So we need to
1297 map case different versions together, regardless of whether they are
1298 variables or not.
1299 
1300 4) when a reference is (first) SET or ASK, the bookmark associated with it
1301 is placed around the 0x14 0x15 result part of the field. We will fiddle
1302 the placement to be the writer equivalent of directly before and after
1303 the field, which gives the same effect and meaning, to do so we must
1304 get any bookmarks in the field range, and begin them immediately before
1305 the set/ask field, and end them directly afterwards. MapBookmarkVariables
1306 returns an identifier of the bookmark attribute to close after inserting
1307 the appropriate set/ask field.
1308 */
MapBookmarkVariables(const WW8FieldDesc * pF,String & rOrigName,const String & rData)1309 long SwWW8ImplReader::MapBookmarkVariables(const WW8FieldDesc* pF,
1310     String &rOrigName, const String &rData)
1311 {
1312     ASSERT(pPlcxMan,"No pPlcxMan");
1313     long nNo;
1314     /*
1315     If there was no bookmark associated with this set field, then we create a
1316     pseudo one and insert it in the document.
1317     */
1318     sal_uInt16 nIndex;
1319     pPlcxMan->GetBook()->MapName(rOrigName);
1320     String sName = pPlcxMan->GetBook()->GetBookmark(
1321         pF->nSCode, pF->nSCode + pF->nLen, nIndex);
1322     if (sName.Len())
1323     {
1324         pPlcxMan->GetBook()->SetStatus(nIndex, BOOK_IGNORE);
1325         nNo = nIndex;
1326     }
1327     else
1328     {
1329         sName = CREATE_CONST_ASC("WWSetBkmk");
1330         nNo = pReffingStck->aFieldVarNames.size()+1;
1331         sName += String::CreateFromInt32(nNo);
1332         nNo += pPlcxMan->GetBook()->GetIMax();
1333     }
1334     pReffedStck->NewAttr(*pPaM->GetPoint(),
1335         SwFltBookmark( BookmarkToWriter(sName), rData, nNo ));
1336     pReffingStck->aFieldVarNames[rOrigName] = sName;
1337     return nNo;
1338 }
1339 
1340 /*
1341 Word can set a bookmark with set or with ask, such a bookmark is equivalent to
1342 our variables, but until the end of a document we cannot be sure if a bookmark
1343 is a variable or not, at the end we will have a list of reference names which
1344 were set or asked, all bookmarks using the content of those bookmarks are
1345 converted to show variables, those that reference the position of the field
1346 can be left as references, because a bookmark is also inserted at the position
1347 of a set or ask field, either by word, or in some special cases by the import
1348 filter itself.
1349 */
RefToVar(const SwField * pFld,SwFltStackEntry * pEntry)1350 SwFltStackEntry *SwWW8FltRefStack::RefToVar(const SwField* pFld,
1351     SwFltStackEntry *pEntry)
1352 {
1353     SwFltStackEntry *pRet=0;
1354     if (pFld && RES_GETREFFLD == pFld->Which())
1355     {
1356         //Get the name of the ref field, and see if actually a variable
1357         const String &rName = pFld->GetPar1();
1358         ::std::map<String,String,SwWW8::ltstr>::const_iterator
1359             aResult = aFieldVarNames.find(rName);
1360 
1361         if (aResult != aFieldVarNames.end())
1362         {
1363             SwGetExpField aFld( (SwGetExpFieldType*)
1364                 pDoc->GetSysFldType(RES_GETEXPFLD), rName, nsSwGetSetExpType::GSE_STRING, 0);
1365             delete pEntry->pAttr;
1366             SwFmtFld aTmp(aFld);
1367             pEntry->pAttr = aTmp.Clone();
1368             pRet = pEntry;
1369         }
1370     }
1371     return pRet;
1372 }
1373 
GetMappedBookmark(const String & rOrigName)1374 String SwWW8ImplReader::GetMappedBookmark(const String &rOrigName)
1375 {
1376     String sName(BookmarkToWriter(rOrigName));
1377     ASSERT(pPlcxMan,"no pPlcxMan");
1378     pPlcxMan->GetBook()->MapName(sName);
1379 
1380     //See if there has been a variable set with this name, if so get
1381     //the pseudo bookmark name that was set with it.
1382     ::std::map<String,String,SwWW8::ltstr>::const_iterator aResult =
1383             pReffingStck->aFieldVarNames.find(sName);
1384 
1385     const String &rBkmName = (aResult == pReffingStck->aFieldVarNames.end())
1386         ? sName : (*aResult).second;
1387 
1388     return rBkmName;
1389 }
1390 
1391 // "ASK"
Read_F_InputVar(WW8FieldDesc * pF,String & rStr)1392 eF_ResT SwWW8ImplReader::Read_F_InputVar( WW8FieldDesc* pF, String& rStr )
1393 {
1394     String sOrigName;
1395     String aQ;
1396     String aDef;
1397     long nRet;
1398     _ReadFieldParams aReadParam( rStr );
1399     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1400     {
1401         switch( nRet )
1402         {
1403         case -2:
1404             if (!sOrigName.Len())
1405                 sOrigName = aReadParam.GetResult();
1406             else if( !aQ.Len() )
1407                 aQ = aReadParam.GetResult();
1408             break;
1409         case 'd':
1410         case 'D':
1411             if (STRING_NOTFOUND != aReadParam.GoToTokenParam())
1412                 aDef = aReadParam.GetResult();
1413             break;
1414         }
1415     }
1416 
1417     if( !sOrigName.Len() )
1418         return FLD_TAGIGN;  // macht ohne Textmarke keinen Sinn
1419 
1420     String aResult(GetFieldResult(pF));
1421 
1422     //#i24377#, munge Default Text into title as we have only one slot
1423     //available for aResult and aDef otherwise
1424     if (aDef.Len())
1425     {
1426         if (aQ.Len())
1427             aQ.APPEND_CONST_ASC(" - ");
1428         aQ.Append(aDef);
1429     }
1430 
1431     long nNo = MapBookmarkVariables(pF, sOrigName, aResult);
1432 
1433     SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
1434         SwSetExpFieldType(&rDoc, sOrigName, nsSwGetSetExpType::GSE_STRING));
1435     SwSetExpField aFld(pFT, aResult);
1436     aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
1437     aFld.SetInputFlag(true);
1438     aFld.SetPromptText( aQ );
1439 
1440     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1441 
1442     pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
1443     return FLD_OK;
1444 }
1445 
1446 // "AUTONR"
Read_F_ANumber(WW8FieldDesc *,String & rStr)1447 eF_ResT SwWW8ImplReader::Read_F_ANumber( WW8FieldDesc*, String& rStr )
1448 {
1449     if( !pNumFldType ){     // 1. Mal
1450         SwSetExpFieldType aT( &rDoc, CREATE_CONST_ASC("AutoNr"), nsSwGetSetExpType::GSE_SEQ );
1451         pNumFldType = rDoc.InsertFldType( aT );
1452     }
1453     SwSetExpField aFld( (SwSetExpFieldType*)pNumFldType, aEmptyStr,
1454                         GetNumberPara( rStr ) );
1455     aFld.SetValue( ++nFldNum );
1456     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1457     return FLD_OK;
1458 }
1459 
1460 // "SEQ"
Read_F_Seq(WW8FieldDesc *,String & rStr)1461 eF_ResT SwWW8ImplReader::Read_F_Seq( WW8FieldDesc*, String& rStr )
1462 {
1463     String aSequenceName;
1464     String aBook;
1465     bool bHidden    = false;
1466     bool bFormat    = false;
1467     bool bShowLast  = false;
1468     bool bCountOn   = true;
1469     String sStart;
1470     SvxExtNumType eNumFormat = SVX_NUM_ARABIC;
1471     long nRet;
1472     _ReadFieldParams aReadParam( rStr );
1473     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1474     {
1475         switch( nRet )
1476         {
1477         case -2:
1478             if( !aSequenceName.Len() )
1479                 aSequenceName = aReadParam.GetResult();
1480             else if( !aBook.Len() )
1481                 aBook = aReadParam.GetResult();
1482             break;
1483 
1484         case 'h':
1485             if( !bFormat )
1486                 bHidden = true;             // Hidden-Flag aktivieren
1487             break;
1488 
1489         case '*':
1490             bFormat = true;                 // Format-Flag aktivieren
1491             bHidden = false;                // Hidden-Flag deaktivieren
1492             nRet = aReadParam.SkipToNextToken();
1493             if( -2 == nRet && !( aReadParam.GetResult().EqualsAscii("MERGEFORMAT") || aReadParam.GetResult().EqualsAscii("CHARFORMAT") ))
1494                 eNumFormat = GetNumTypeFromName( aReadParam.GetResult() );
1495             break;
1496 
1497         case 'r':
1498             bShowLast = false;              // Zaehler neu setzen
1499             bCountOn  = false;
1500             nRet = aReadParam.SkipToNextToken();
1501             if( -2 == nRet )
1502                 sStart = aReadParam.GetResult();
1503             break;
1504 
1505         case 'c':
1506             bShowLast = true;           // zuletzt verwendete Nummer anzeigen
1507             bCountOn  = false;
1508             break;
1509 
1510         case 'n':
1511             bCountOn  = true;               // Nummer um eins erhoehen (default)
1512             bShowLast = false;
1513             break;
1514 
1515         case 's':                       // Outline Level
1516             //#i19682, what am I to do with this value
1517             break;
1518         }
1519     }
1520     if (!aSequenceName.Len() && !aBook.Len())
1521         return FLD_TAGIGN;
1522 
1523     SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
1524                         SwSetExpFieldType( &rDoc, aSequenceName, nsSwGetSetExpType::GSE_SEQ ) );
1525     SwSetExpField aFld( pFT, aEmptyStr, eNumFormat );
1526 
1527     //Bug 120654: Add for /h flag(/h: Hiden the field result.)
1528     if (bHidden)
1529     aFld.SetSubType(aFld.GetSubType() | nsSwExtendedSubType::SUB_INVISIBLE);
1530     //Bug 120654(End)
1531 
1532 
1533     if (sStart.Len())
1534         aFld.SetFormula( ( aSequenceName += '=' ) += sStart );
1535     else if (!bCountOn)
1536         aFld.SetFormula(aSequenceName);
1537 
1538     rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1539     return FLD_OK;
1540 }
1541 
Read_F_DocInfo(WW8FieldDesc * pF,String & rStr)1542 eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, String& rStr )
1543 {
1544     sal_uInt16 nSub=0;
1545     // RegInfoFormat, DefaultFormat fuer DocInfoFelder
1546     sal_uInt16 nReg = DI_SUB_AUTHOR;
1547     bool bDateTime = false;
1548 
1549     if( 85 == pF->nId )
1550     {
1551         String aDocProperty;
1552         _ReadFieldParams aReadParam( rStr );
1553         long nRet;
1554         while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1555         {
1556             switch( nRet )
1557             {
1558                 case -2:
1559                     if( !aDocProperty.Len() )
1560                         aDocProperty = aReadParam.GetResult();
1561                     break;
1562                 case '*':
1563                     //Skip over MERGEFORMAT
1564                     aReadParam.SkipToNextToken();
1565                     break;
1566             }
1567         }
1568         aDocProperty.EraseAllChars('"');
1569 
1570         /*
1571         There are up to 26 fields that may be meant by 'DocumentProperty'.
1572         Which of them is to be inserted here ?
1573         This Problem can only be solved by implementing a name matching
1574         method that compares the given Parameter String with the four
1575         possible name sets (english, german, french, spanish)
1576         */
1577 
1578         static const sal_Char* aName10 = "\x0F"; // SW field code
1579         static const sal_Char* aName11 // German
1580             = "TITEL";
1581         static const sal_Char* aName12 // French
1582             = "TITRE";
1583         static const sal_Char* aName13 // English
1584             = "TITLE";
1585         static const sal_Char* aName14 // Spanish
1586             = "TITRO";
1587         static const sal_Char* aName20 = "\x15"; // SW filed code
1588         static const sal_Char* aName21 // German
1589             = "ERSTELLDATUM";
1590         static const sal_Char* aName22 // French
1591             = "CR\xC9\xC9";
1592         static const sal_Char* aName23 // English
1593             = "CREATED";
1594         static const sal_Char* aName24 // Spanish
1595             = "CREADO";
1596         static const sal_Char* aName30 = "\x16"; // SW filed code
1597         static const sal_Char* aName31 // German
1598             = "ZULETZTGESPEICHERTZEIT";
1599         static const sal_Char* aName32 // French
1600             = "DERNIERENREGISTREMENT";
1601         static const sal_Char* aName33 // English
1602             = "SAVED";
1603         static const sal_Char* aName34 // Spanish
1604             = "MODIFICADO";
1605         static const sal_Char* aName40 = "\x17"; // SW filed code
1606         static const sal_Char* aName41 // German
1607             = "ZULETZTGEDRUCKT";
1608         static const sal_Char* aName42 // French
1609             = "DERNI\xC8" "REIMPRESSION";
1610         static const sal_Char* aName43 // English
1611             = "LASTPRINTED";
1612         static const sal_Char* aName44 // Spanish
1613             = "HUPS PUPS";
1614         static const sal_Char* aName50 = "\x18"; // SW filed code
1615         static const sal_Char* aName51 // German
1616             = "\xDC" "BERARBEITUNGSNUMMER";
1617         static const sal_Char* aName52 // French
1618             = "NUM\xC9" "RODEREVISION";
1619         static const sal_Char* aName53 // English
1620             = "REVISIONNUMBER";
1621         static const sal_Char* aName54 // Spanish
1622             = "SNUBBEL BUBBEL";
1623         static const sal_uInt16 nFldCnt  = 5;
1624 
1625         // additional fields are to be coded soon!   :-)
1626 
1627         static const sal_uInt16 nLangCnt = 4;
1628         static const sal_Char *aNameSet_26[nFldCnt][nLangCnt+1] =
1629         {
1630             {aName10, aName11, aName12, aName13, aName14},
1631             {aName20, aName21, aName22, aName23, aName24},
1632             {aName30, aName31, aName32, aName33, aName34},
1633             {aName40, aName41, aName42, aName43, aName44},
1634             {aName50, aName51, aName52, aName53, aName54}
1635         };
1636 
1637         bool bFldFound= false;
1638         sal_uInt16 nFIdx;
1639         for(sal_uInt16 nLIdx=1; !bFldFound && (nLangCnt > nLIdx); ++nLIdx)
1640         {
1641             for(nFIdx = 0;  !bFldFound && (nFldCnt  > nFIdx); ++nFIdx)
1642             {
1643                 if( aDocProperty.Equals( String( aNameSet_26[nFIdx][nLIdx],
1644                     RTL_TEXTENCODING_MS_1252 ) ) )
1645                 {
1646                     bFldFound = true;
1647                     pF->nId   = aNameSet_26[nFIdx][0][0];
1648                 }
1649             }
1650         }
1651 
1652         if( !bFldFound )
1653         {
1654 /*
1655             SwUserFieldType aTmp( &rDoc, aDocProperty );
1656             aTmp.SetContent(GetFieldResult( pF ));
1657             SwUserField aUFld( (SwUserFieldType*)rDoc.InsertFldType( aTmp ));
1658             aUFld.ChangeFormat( UF_STRING );
1659             rDoc.Insert( *pPaM, SwFmtFld( aUFld ), 0);
1660 */
1661             SwDocInfoField aFld( (SwDocInfoFieldType*)
1662                 rDoc.GetSysFldType( RES_DOCINFOFLD ), DI_CUSTOM|nReg, aDocProperty, GetFieldResult( pF ) );
1663             rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1664 
1665             return FLD_OK;
1666         }
1667     }
1668 
1669     switch( pF->nId )
1670     {
1671         case 14:
1672             /* kann alle INFO-Vars!! */
1673             nSub = DI_KEYS;
1674             break;
1675         case 15:
1676             nSub = DI_TITEL;
1677             break;
1678         case 16:
1679             nSub = DI_THEMA;
1680             break;
1681         case 18:
1682             nSub = DI_KEYS;
1683             break;
1684         case 19:
1685             nSub = DI_COMMENT;
1686             break;
1687         case 20:
1688             nSub = DI_CHANGE;
1689             nReg = DI_SUB_AUTHOR;
1690             break;
1691         case 21:
1692             nSub = DI_CREATE;
1693             nReg = DI_SUB_DATE;
1694             bDateTime = true;
1695             break;
1696         case 23:
1697             nSub = DI_PRINT;
1698             nReg = DI_SUB_DATE;
1699             bDateTime = true;
1700             break;
1701         case 24:
1702             nSub = DI_DOCNO;
1703             break;
1704         case 22:
1705             nSub = DI_CHANGE;
1706             nReg = DI_SUB_DATE;
1707             bDateTime = true;
1708             break;
1709         case 25:
1710             nSub = DI_CHANGE;
1711             nReg = DI_SUB_TIME;
1712             bDateTime = true;
1713             break;
1714     }
1715 
1716     sal_uInt32 nFormat = 0;
1717 
1718     sal_uInt16 nLang(0);
1719     if (bDateTime)
1720     {
1721         short nDT = GetTimeDatePara(rStr, nFormat, nLang, pF->nId);
1722         switch (nDT)
1723         {
1724             case NUMBERFORMAT_DATE:
1725                 nReg = DI_SUB_DATE;
1726                 break;
1727             case NUMBERFORMAT_TIME:
1728                 nReg = DI_SUB_TIME;
1729                 break;
1730             case NUMBERFORMAT_DATETIME:
1731                 nReg = DI_SUB_DATE;
1732                 break;
1733             default:
1734                 nReg = DI_SUB_DATE;
1735                 break;
1736         }
1737     }
1738 
1739     SwDocInfoField aFld( (SwDocInfoFieldType*)
1740         rDoc.GetSysFldType( RES_DOCINFOFLD ), nSub|nReg, String(), nFormat );
1741     if (bDateTime)
1742         ForceFieldLanguage(aFld, nLang);
1743     rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1744 
1745     return FLD_OK;
1746 }
1747 
Read_F_Author(WW8FieldDesc *,String &)1748 eF_ResT SwWW8ImplReader::Read_F_Author( WW8FieldDesc*, String& )
1749 {
1750         // SH: Das SwAuthorField bezeichnet nicht den urspruenglichen
1751         // Autor, sondern den aktuellen Benutzer, also besser ueber DocInfo
1752         // (#56149)
1753     SwDocInfoField aFld( (SwDocInfoFieldType*)
1754                      rDoc.GetSysFldType( RES_DOCINFOFLD ),
1755                      DI_CREATE|DI_SUB_AUTHOR, String() );
1756     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1757     return FLD_OK;
1758 }
1759 
Read_F_TemplName(WW8FieldDesc *,String &)1760 eF_ResT SwWW8ImplReader::Read_F_TemplName( WW8FieldDesc*, String& )
1761 {
1762     SwTemplNameField aFld( (SwTemplNameFieldType*)
1763                      rDoc.GetSysFldType( RES_TEMPLNAMEFLD ), FF_NAME );
1764     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1765     return FLD_OK;
1766 }
1767 
1768 // Sowohl das Datum- wie auch das Uhrzeit-Feld kann fuer Datum, fuer Uhrzeit
1769 // oder fuer beides benutzt werden.
Read_F_DateTime(WW8FieldDesc * pF,String & rStr)1770 eF_ResT SwWW8ImplReader::Read_F_DateTime( WW8FieldDesc*pF, String& rStr )
1771 {
1772     bool bHijri = false;
1773     bool bSaka = false;
1774     _ReadFieldParams aReadParam(rStr);
1775     long nTok;
1776     while (-1 != (nTok = aReadParam.SkipToNextToken()))
1777     {
1778         switch (nTok)
1779         {
1780             default:
1781             case 'l':
1782             case -2:
1783                 break;
1784             case 'h':
1785                 bHijri = true;
1786                 break;
1787             case 's':
1788                 bSaka = true;
1789                 break;
1790         }
1791     }
1792 
1793     sal_uInt32 nFormat = 0;
1794 
1795     sal_uInt16 nLang(0);
1796     short nDT = GetTimeDatePara(rStr, nFormat, nLang, ww::eDATE, bHijri);
1797 
1798     if( NUMBERFORMAT_UNDEFINED == nDT )             // no D/T-Formatstring
1799     {
1800         if (32 == pF->nId)
1801         {
1802             nDT     = NUMBERFORMAT_TIME;
1803             nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
1804                         NF_TIME_START, LANGUAGE_SYSTEM );
1805         }
1806         else
1807         {
1808             nDT     = NUMBERFORMAT_DATE;
1809             nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
1810                         NF_DATE_START, LANGUAGE_SYSTEM );
1811         }
1812     }
1813 
1814     if (nDT & NUMBERFORMAT_DATE)
1815     {
1816         SwDateTimeField aFld((SwDateTimeFieldType*)
1817             rDoc.GetSysFldType(RES_DATETIMEFLD ), DATEFLD, nFormat);
1818         ForceFieldLanguage(aFld, nLang);
1819         rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1820     }
1821     else if (nDT == NUMBERFORMAT_TIME)
1822     {
1823         SwDateTimeField aFld((SwDateTimeFieldType*)
1824             rDoc.GetSysFldType(RES_DATETIMEFLD), TIMEFLD, nFormat);
1825         ForceFieldLanguage(aFld, nLang);
1826         rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1827     }
1828 
1829     return FLD_OK;
1830 }
1831 
Read_F_FileName(WW8FieldDesc *,String & rStr)1832 eF_ResT SwWW8ImplReader::Read_F_FileName(WW8FieldDesc*, String &rStr)
1833 {
1834     SwFileNameFormat eType = FF_NAME;
1835     long nRet;
1836     _ReadFieldParams aReadParam(rStr);
1837     while (-1 != (nRet = aReadParam.SkipToNextToken()))
1838     {
1839         switch (nRet)
1840         {
1841             case 'p':
1842                 eType = FF_PATHNAME;
1843                 break;
1844             case '*':
1845                 //Skip over MERGEFORMAT
1846                 aReadParam.SkipToNextToken();
1847                 break;
1848             default:
1849                 ASSERT(sal_False, "unknown option in FileName field");
1850                 break;
1851         }
1852     }
1853 
1854     SwFileNameField aFld(
1855         (SwFileNameFieldType*)rDoc.GetSysFldType(RES_FILENAMEFLD), eType);
1856     rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1857     return FLD_OK;
1858 }
1859 
Read_F_Anz(WW8FieldDesc * pF,String & rStr)1860 eF_ResT SwWW8ImplReader::Read_F_Anz( WW8FieldDesc* pF, String& rStr )
1861 {                                               // SeitenZahl - Feld
1862     sal_uInt16 nSub = DS_PAGE;
1863     switch ( pF->nId ){
1864     case 27: nSub = DS_WORD; break;             // Wordzahl
1865     case 28: nSub = DS_CHAR; break;             // Zeichenzahl
1866     }
1867     SwDocStatField aFld( (SwDocStatFieldType*)
1868                          rDoc.GetSysFldType( RES_DOCSTATFLD ), nSub,
1869                          GetNumberPara( rStr ) );
1870     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1871     return FLD_OK;
1872 }
1873 
Read_F_CurPage(WW8FieldDesc *,String & rStr)1874 eF_ResT SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc*, String& rStr )
1875 {
1876     // zusaetzlich mit Kapitelnummer?
1877     if( bPgChpLevel )
1878     {
1879         SwChapterField aFld( (SwChapterFieldType*)
1880                     rDoc.GetSysFldType( RES_CHAPTERFLD ), CF_NUMBER );
1881         aFld.SetLevel( nPgChpLevel );
1882         rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1883 
1884         static const sal_Char aDelim[] = "-.:\x97\x96";
1885         sal_uInt8 nDelim = nPgChpDelim;
1886         if( nDelim > 4 )
1887             nDelim = 0;
1888 
1889         sal_Unicode c = ByteString::ConvertToUnicode( aDelim[ nDelim ],
1890                                         RTL_TEXTENCODING_MS_1252 );
1891         if( '-' == c )
1892         {
1893             rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
1894         }
1895         else
1896         {
1897             rDoc.InsertString( *pPaM, c ); // maybe insert ZWNBSP?
1898         }
1899     }
1900 
1901     // Seitennummer
1902     SwPageNumberField aFld( (SwPageNumberFieldType*)
1903         rDoc.GetSysFldType( RES_PAGENUMBERFLD ), PG_RANDOM,
1904         GetNumberPara(rStr, true));
1905 
1906     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1907     return FLD_OK;
1908 }
1909 
Read_F_Symbol(WW8FieldDesc *,String & rStr)1910 eF_ResT SwWW8ImplReader::Read_F_Symbol( WW8FieldDesc*, String& rStr )
1911 {
1912     //e.g. #i20118#
1913     String aQ;
1914     String aName;
1915     sal_Int32 nSize = 0;
1916     long nRet;
1917     _ReadFieldParams aReadParam( rStr );
1918     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1919     {
1920         switch( nRet )
1921         {
1922         case -2:
1923             if( !aQ.Len() )
1924                 aQ = aReadParam.GetResult();
1925             break;
1926         case 'f':
1927         case 'F':
1928             {
1929                 xub_StrLen n = aReadParam.GoToTokenParam();
1930                 if( STRING_NOTFOUND != n )
1931                     aName = aReadParam.GetResult();
1932             }
1933             break;
1934         case 's':
1935         case 'S':
1936             {
1937                 String aSiz;
1938                 xub_StrLen n = aReadParam.GoToTokenParam();
1939                 if (STRING_NOTFOUND != n)
1940                     aSiz = aReadParam.GetResult();
1941                 if (aSiz.Len())
1942                     nSize = aSiz.ToInt32() * 20; // pT -> twip
1943             }
1944             break;
1945         }
1946     }
1947     if( !aQ.Len() )
1948         return FLD_TAGIGN;                      // -> kein 0-Zeichen in Text
1949 
1950     if (sal_Unicode cChar = static_cast<sal_Unicode>(aQ.ToInt32()))
1951     {
1952         if (aName.Len())                           // Font Name set ?
1953         {
1954             SvxFontItem aFont(FAMILY_DONTKNOW, aName, aEmptyStr,
1955                 PITCH_DONTKNOW, RTL_TEXTENCODING_SYMBOL, RES_CHRATR_FONT);
1956             NewAttr(aFont);                       // new Font
1957         }
1958 
1959         if (nSize > 0)  //#i20118#
1960         {
1961             SvxFontHeightItem aSz(nSize, 100, RES_CHRATR_FONTSIZE);
1962             NewAttr(aSz);
1963         }
1964 
1965         rDoc.InsertString(*pPaM, cChar);
1966 
1967         if (nSize > 0)
1968             pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONTSIZE);
1969         if (aName.Len())
1970             pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONT);
1971     }
1972     else
1973     {
1974         rDoc.InsertString(*pPaM, CREATE_CONST_ASC("###"));
1975     }
1976 
1977     return FLD_OK;
1978 }
1979 
1980 // "EINBETTEN"
Read_F_Embedd(WW8FieldDesc *,String & rStr)1981 eF_ResT SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc*, String& rStr )
1982 {
1983     String sHost;
1984 
1985     long nRet;
1986     _ReadFieldParams aReadParam( rStr );
1987     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1988     {
1989         switch( nRet )
1990         {
1991         case -2:
1992             sHost = aReadParam.GetResult();
1993             break;
1994 
1995         case 's':
1996             // use ObjectSize
1997             break;
1998         }
1999     }
2000 
2001     if( bObj && nPicLocFc )
2002         nObjLocFc = nPicLocFc;
2003     bEmbeddObj = true;
2004     return FLD_TEXT;
2005 }
2006 
2007 
2008 // "SET"
Read_F_Set(WW8FieldDesc * pF,String & rStr)2009 eF_ResT SwWW8ImplReader::Read_F_Set( WW8FieldDesc* pF, String& rStr )
2010 {
2011     String sOrigName;
2012     String sVal;
2013     long nRet;
2014     _ReadFieldParams aReadParam( rStr );
2015     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2016     {
2017         switch( nRet )
2018         {
2019         case -2:
2020             if( !sOrigName.Len() )
2021                 sOrigName = aReadParam.GetResult();
2022             else if( !sVal.Len() )
2023                 sVal = aReadParam.GetResult();
2024             break;
2025         }
2026     }
2027 
2028     long nNo = MapBookmarkVariables(pF,sOrigName,sVal);
2029 
2030     SwFieldType* pFT = rDoc.InsertFldType( SwSetExpFieldType( &rDoc, sOrigName,
2031         nsSwGetSetExpType::GSE_STRING ) );
2032     SwSetExpField aFld( (SwSetExpFieldType*)pFT, sVal, ULONG_MAX );
2033     aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
2034 
2035     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2036 
2037     pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
2038 
2039     return FLD_OK;
2040 }
2041 
2042 // "REF"
Read_F_Ref(WW8FieldDesc *,String & rStr)2043 eF_ResT SwWW8ImplReader::Read_F_Ref( WW8FieldDesc*, String& rStr )
2044 {                                                       // Reference - Field
2045     String sOrigBkmName;
2046     bool bChapterNr = false;
2047     bool bAboveBelow = false;
2048 
2049     long nRet;
2050     _ReadFieldParams aReadParam( rStr );
2051     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2052     {
2053         switch( nRet )
2054         {
2055         case -2:
2056             if( !sOrigBkmName.Len() ) // get name of bookmark
2057                 sOrigBkmName = aReadParam.GetResult();
2058             break;
2059         case 'n':
2060         case 'r':
2061         case 'w':
2062             bChapterNr = true; // activate flag 'Chapter Number'
2063             break;
2064 
2065         case 'p':
2066             bAboveBelow = true;
2067             break;
2068         case 'h':
2069             break;
2070         default:
2071             // unimplemented switch: just do 'nix nought nothing'  :-)
2072             break;
2073         }
2074     }
2075 
2076     String sBkmName(GetMappedBookmark(sOrigBkmName));
2077 
2078     if (!bAboveBelow || bChapterNr)
2079     {
2080         if (bChapterNr)
2081         {
2082             SwGetRefField aFld(
2083                 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2084                 sBkmName,REF_BOOKMARK,0,REF_CHAPTER);
2085             rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2086         }
2087         else
2088         {
2089             /*
2090             If we are just inserting the contents of the bookmark, then it
2091             is possible that the bookmark is actually a variable, so we
2092             must store it until the end of the document to see if it was,
2093             in which case we'll turn it into a show variable
2094             */
2095             SwGetRefField aFld(
2096                 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2097                 sOrigBkmName,REF_BOOKMARK,0,REF_CONTENT);
2098             pReffingStck->NewAttr( *pPaM->GetPoint(), SwFmtFld(aFld) );
2099             pReffingStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_FIELD);
2100         }
2101     }
2102 
2103     if( bAboveBelow )
2104     {
2105         SwGetRefField aFld( (SwGetRefFieldType*)
2106             rDoc.GetSysFldType( RES_GETREFFLD ), sBkmName, REF_BOOKMARK, 0,
2107             REF_UPDOWN );
2108         rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2109     }
2110     return FLD_OK;
2111 }
2112 
2113 // Note Reference - Field
Read_F_NoteReference(WW8FieldDesc *,String & rStr)2114 eF_ResT SwWW8ImplReader::Read_F_NoteReference( WW8FieldDesc*, String& rStr )
2115 {
2116     String aBkmName;
2117     bool bChapterNr = false;
2118     bool bAboveBelow = false;
2119 
2120     long nRet;
2121     _ReadFieldParams aReadParam( rStr );
2122     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2123     {
2124         switch( nRet )
2125         {
2126         case -2:
2127             if( !aBkmName.Len() ) // get name of foot/endnote
2128                 aBkmName = aReadParam.GetResult();
2129             break;
2130         case 'r':
2131             bChapterNr = true; // activate flag 'Chapter Number'
2132             break;
2133         case 'p':
2134             bAboveBelow = true;
2135             break;
2136         case 'h':
2137             break;
2138         default:
2139             // unimplemented switch: just do 'nix nought nothing'  :-)
2140             break;
2141         }
2142     }
2143 
2144     // set Sequence No of corresponding Foot-/Endnote to Zero
2145     // (will be corrected in
2146     SwGetRefField aFld( (SwGetRefFieldType*)
2147         rDoc.GetSysFldType( RES_GETREFFLD ), aBkmName, REF_FOOTNOTE, 0,
2148         REF_ONLYNUMBER );
2149     pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld));
2150     pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
2151     if (bAboveBelow)
2152     {
2153         SwGetRefField aFld2( (SwGetRefFieldType*)
2154             rDoc.GetSysFldType( RES_GETREFFLD ),aBkmName, REF_FOOTNOTE, 0,
2155             REF_UPDOWN );
2156         pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld2));
2157         pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
2158     }
2159     return FLD_OK;
2160 }
2161 
2162 // "SEITENREF"
Read_F_PgRef(WW8FieldDesc *,String & rStr)2163 eF_ResT SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc*, String& rStr )
2164 {
2165     String sOrigName;
2166     long nRet;
2167     _ReadFieldParams aReadParam( rStr );
2168     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2169     {
2170         if ( nRet == -2 &&
2171              !sOrigName.Len() )
2172         {
2173             sOrigName = aReadParam.GetResult();
2174         }
2175     }
2176 
2177     const String sName(GetMappedBookmark(sOrigName));
2178 
2179     // loading page reference field in TOX
2180     if (mbLoadingTOXCache )
2181     {
2182         // insert page ref representation as plain text --> return FLD_TEXT
2183         // if there is no hyperlink settings for current toc and referenced bookmark is available,
2184         // assign link to current ref area
2185         if ( !mbLoadingTOXHyperlink && sName.Len() > 0 )
2186         {
2187             // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
2188             String sBookmarkName;
2189             if ( IsTOCBookmarkName( sName ) )
2190             {
2191                 sBookmarkName = String( IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix() );
2192                 sBookmarkName += sName;
2193                 // track <sBookmarkName> as referenced TOC bookmark.
2194                 pReffedStck->aReferencedTOCBookmarks.insert( sBookmarkName );
2195             }
2196             else
2197             {
2198                 sBookmarkName = sName;
2199             }
2200             String sURL = INET_MARK_TOKEN;
2201             sURL += sBookmarkName;
2202             const String sTarget;
2203             SwFmtINetFmt aURL( sURL, sTarget );
2204             const String sLinkStyle = String::CreateFromAscii("Index Link");
2205             const sal_uInt16 nPoolId =
2206                 SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
2207             aURL.SetVisitedFmtAndId( sLinkStyle, nPoolId);
2208             aURL.SetINetFmtAndId( sLinkStyle, nPoolId );
2209             pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL );
2210         }
2211         return FLD_TEXT;
2212     }
2213 
2214     // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
2215     String sPageRefBookmarkName;
2216     if ( IsTOCBookmarkName( sName ) )
2217     {
2218         sPageRefBookmarkName = IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix();
2219         sPageRefBookmarkName += sName;
2220         // track <sPageRefBookmarkName> as referenced TOC bookmark.
2221         pReffedStck->aReferencedTOCBookmarks.insert( sPageRefBookmarkName );
2222     }
2223     else
2224     {
2225         sPageRefBookmarkName = sName;
2226     }
2227     SwGetRefField aFld( (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2228                         sPageRefBookmarkName, REF_BOOKMARK, 0, REF_PAGE );
2229     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2230 
2231     return FLD_OK;
2232 }
2233 //helper function
2234 //For MS MacroButton field, the symbol in plain text is always "(" (0x28),
2235 //which should be mapped according to the macro type
ConvertMacroSymbol(const String & rName,String & rReference)2236 bool ConvertMacroSymbol( const String& rName, String& rReference )
2237 {
2238     bool bConverted = false;
2239     if( rReference.EqualsAscii( "(" ) )
2240     {
2241         bConverted = true;
2242         sal_Unicode cSymbol = 0x0000;
2243         if( rName.EqualsAscii( "CheckIt" ) )
2244             cSymbol = 0xF06F;
2245         else if( rName.EqualsAscii( "UncheckIt" ) )
2246             cSymbol = 0xF0FE;
2247         else if( rName.EqualsAscii( "ShowExample" ) )
2248             cSymbol = 0xF02A;
2249         //else if... : todo
2250         else
2251             bConverted = false;
2252 
2253         if( bConverted )
2254             rReference = cSymbol;
2255     }
2256     return bConverted;
2257 }
2258 //end
2259 
2260 // "MACROSCHALTFL"ACHE"
Read_F_Macro(WW8FieldDesc *,String & rStr)2261 eF_ResT SwWW8ImplReader::Read_F_Macro( WW8FieldDesc*, String& rStr)
2262 {
2263     String aName;
2264     String aVText;
2265     long nRet;
2266     bool bNewVText = true;
2267     bool bBracket  = false;
2268     _ReadFieldParams aReadParam( rStr );
2269 
2270     xub_StrLen nOffset = 0;
2271 
2272     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2273     {
2274         switch( nRet )
2275         {
2276         case -2:
2277             if( !aName.Len() )
2278                 aName = aReadParam.GetResult();
2279             else if( !aVText.Len() || bBracket )
2280             {
2281                 nOffset = aReadParam.GetTokenSttPtr() + 1;
2282 
2283                 if( bBracket )
2284                     aVText += ' ';
2285                 aVText += aReadParam.GetResult();
2286                 if (bNewVText)
2287                 {
2288                     bBracket = aVText.EqualsIgnoreCaseAscii('[', 1, 0)
2289                         ? true : false;
2290                     bNewVText = false;
2291                 }
2292                 else if( aVText.GetChar( aVText.Len()-1 ) == ']' )
2293                     bBracket  = false;
2294             }
2295             break;
2296         }
2297     }
2298     if( !aName.Len() )
2299         return FLD_TAGIGN;  // makes no sense without Makro-Name
2300 
2301     //try converting macro symbol according to macro name
2302     bool bApplyWingdings = ConvertMacroSymbol( aName, aVText );
2303     aName.InsertAscii( "StarOffice.Standard.Modul1.", 0 );
2304 
2305     SwMacroField aFld( (SwMacroFieldType*)
2306                     rDoc.GetSysFldType( RES_MACROFLD ), aName, aVText );
2307 
2308     if( !bApplyWingdings )
2309     {
2310 
2311         rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2312         WW8_CP nOldCp = pPlcxMan->Where();
2313         WW8_CP nCp = nOldCp + nOffset;
2314 
2315         SwPaM aPaM(*pPaM);
2316         aPaM.SetMark();
2317         aPaM.Move(fnMoveBackward);
2318         aPaM.Exchange();
2319 
2320         mpPostProcessAttrsInfo = new WW8PostProcessAttrsInfo(nCp, nCp, aPaM);
2321     }
2322     else
2323     {
2324         //set Wingdings font
2325         sal_uInt16 i = 0;
2326         for ( ; i < pFonts->GetMax(); i++ )
2327         {
2328             FontFamily eFamily;
2329             String aFontName;
2330             FontPitch ePitch;
2331             CharSet eSrcCharSet;
2332             if( GetFontParams( i, eFamily, aFontName, ePitch, eSrcCharSet )
2333                 && aFontName.EqualsAscii("Wingdings") )
2334             {
2335                 break;
2336             }
2337         }
2338 
2339         if ( i < pFonts->GetMax() )
2340         {
2341 
2342             SetNewFontAttr( i, true, RES_CHRATR_FONT );
2343             rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2344             pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
2345             ResetCharSetVars();
2346         }
2347     }
2348 
2349     return FLD_OK;
2350 }
2351 
WW8PostProcessAttrsInfo(WW8_CP nCpStart,WW8_CP nCpEnd,SwPaM & rPaM)2352 WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd,
2353                                                  SwPaM & rPaM)
2354 : mbCopy(false),
2355   mnCpStart(nCpStart),
2356   mnCpEnd(nCpEnd),
2357   mPaM(*rPaM.GetPoint(), *rPaM.GetMark()),
2358   mItemSet(rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END - 1)
2359 {
2360 }
2361 
CanUseRemoteLink(const String & rGrfName)2362 bool CanUseRemoteLink(const String &rGrfName)
2363 {
2364     bool bUseRemote = false;
2365     try
2366     {
2367         ::ucbhelper::Content aCnt(rGrfName,
2368             uno::Reference<
2369             ucb::XCommandEnvironment >() );
2370         rtl::OUString   aTitle;
2371 
2372         aCnt.getPropertyValue(rtl::OUString::createFromAscii("Title" ))
2373             >>= aTitle;
2374         bUseRemote = (aTitle.getLength() > 0);
2375     }
2376     catch ( ... )
2377     {
2378         // this file did not exist, so we will not set this as graphiclink
2379         bUseRemote = false;
2380     }
2381     return bUseRemote;
2382 }
2383 
2384 // "EINF"UGENGRAFIK"
Read_F_IncludePicture(WW8FieldDesc *,String & rStr)2385 eF_ResT SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc*, String& rStr )
2386 {
2387     String aGrfName;
2388     bool bEmbedded = true;
2389 
2390     long nRet;
2391     _ReadFieldParams aReadParam( rStr );
2392     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2393     {
2394         switch( nRet )
2395         {
2396         case -2:
2397             if (!aGrfName.Len())
2398                 ConvertFFileName(aGrfName, aReadParam.GetResult());
2399             break;
2400 
2401         case 'd':
2402             bEmbedded = false;          // Embedded-Flag deaktivieren
2403             break;
2404 
2405         case 'c':// den Converter-Namen ueberlesen
2406             aReadParam.FindNextStringPiece();
2407             break;
2408         }
2409     }
2410 
2411     if (!bEmbedded)
2412         bEmbedded = !CanUseRemoteLink(aGrfName);
2413 
2414     if (!bEmbedded)
2415     {
2416         /*
2417             Besonderheit:
2418 
2419             Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrmFmt.
2420             Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
2421             wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
2422             wird.
2423             Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
2424             erkannt, dass wir soeben einen Grafik-Link inserted haben und
2425             das passende SwAttrSet wird ins Frame-Format eingesetzt.
2426         */
2427         SfxItemSet aFlySet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
2428             RES_FRMATR_END-1 );
2429         aFlySet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
2430         aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
2431         pFlyFmtOfJustInsertedGraphic = rDoc.Insert( *pPaM,
2432                                                     aGrfName,
2433                                                     aEmptyStr,
2434                                                     0,          // Graphic*
2435                                                     &aFlySet,
2436                                                     0, 0);         // SwFrmFmt*
2437         maGrfNameGenerator.SetUniqueGraphName(pFlyFmtOfJustInsertedGraphic,
2438             INetURLObject(aGrfName).GetBase());
2439     }
2440     return FLD_READ_FSPA;
2441 }
2442 
2443 
UniqueName()2444 String wwSectionNamer::UniqueName()
2445 {
2446     String aName(msFileLinkSeed);
2447     aName += String::CreateFromInt32(++mnFileSectionNo);
2448     return mrDoc.GetUniqueSectionName(&aName);
2449 }
2450 
2451 // "EINFUEGENTEXT"
Read_F_IncludeText(WW8FieldDesc *,String & rStr)2452 eF_ResT SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc* /*pF*/, String& rStr )
2453 {
2454     String aPara;
2455     String aBook;
2456     long nRet;
2457     _ReadFieldParams aReadParam( rStr );
2458     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2459     {
2460         switch( nRet )
2461         {
2462             case -2:
2463                 if( !aPara.Len() )
2464                     aPara = aReadParam.GetResult();
2465                 else if( !aBook.Len() )
2466                     aBook = aReadParam.GetResult();
2467                 break;
2468             case '*':
2469                 //Skip over MERGEFORMAT
2470                 aReadParam.SkipToNextToken();
2471                 break;
2472         }
2473     }
2474     ConvertFFileName(aPara, aPara);
2475 
2476     if (aBook.Len() && aBook.GetChar( 0 ) != '\\')
2477     {
2478         // Bereich aus Quelle ( kein Switch ) ?
2479         ConvertUFName(aBook);
2480         aPara += sfx2::cTokenSeperator;
2481         aPara += sfx2::cTokenSeperator;
2482         aPara += aBook;
2483     }
2484 
2485     /*
2486     ##509##
2487     What we will do is insert a section to be linked to a file, but just in
2488     case the file is not available we will fill in the section with the stored
2489     content of this winword field as a fallback.
2490     */
2491     SwPosition aTmpPos(*pPaM->GetPoint());
2492 
2493     SwSectionData aSection(FILE_LINK_SECTION,
2494             maSectionNameGenerator.UniqueName());
2495     aSection.SetLinkFileName( aPara );
2496     aSection.SetProtectFlag(true);
2497 
2498     SwSection *const pSection =
2499         rDoc.InsertSwSection(*pPaM, aSection, 0, 0, false);
2500     ASSERT(pSection, "no section inserted");
2501     if (!pSection)
2502         return FLD_TEXT;
2503     const SwSectionNode* pSectionNode = pSection->GetFmt()->GetSectionNode();
2504     ASSERT(pSectionNode, "no section node!");
2505     if (!pSectionNode)
2506         return FLD_TEXT;
2507 
2508     pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
2509     pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0 );
2510 
2511     //we have inserted a section before this point, so adjust pos
2512     //for future page/section segment insertion
2513     maSectionManager.PrependedInlineNode(aTmpPos, *pPaM->GetNode());
2514 
2515     return FLD_TEXT;
2516 }
2517 
2518 // "SERIENDRUCKFELD"
Read_F_DBField(WW8FieldDesc * pF,String & rStr)2519 eF_ResT SwWW8ImplReader::Read_F_DBField( WW8FieldDesc* pF, String& rStr )
2520 {
2521     String aName;
2522     long nRet;
2523     _ReadFieldParams aReadParam( rStr );
2524     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2525     {
2526         switch( nRet )
2527         {
2528         case -2:
2529             if( !aName.Len() )
2530                 aName = aReadParam.GetResult();
2531             break;
2532         }
2533     }
2534     SwDBFieldType aD( &rDoc, aName, SwDBData() );   // Datenbank: Nichts
2535 
2536     SwFieldType* pFT = rDoc.InsertFldType( aD );
2537     SwDBField aFld( (SwDBFieldType*)pFT );
2538     aFld.SetFieldCode( rStr );
2539 
2540     String aResult;
2541     pSBase->WW8ReadString( *pStrm, aResult, pPlcxMan->GetCpOfs()+
2542                            pF->nSRes, pF->nLRes, eTextCharSet );
2543 
2544     aFld.InitContent(aResult);
2545 
2546     rDoc.InsertPoolItem(*pPaM, SwFmtFld( aFld ), 0);
2547 
2548     return FLD_OK;
2549 }
2550 
2551 // "N"ACHSTER"
Read_F_DBNext(WW8FieldDesc *,String &)2552 eF_ResT SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc*, String& )
2553 {
2554     SwDBNextSetFieldType aN;
2555     SwFieldType* pFT = rDoc.InsertFldType( aN );
2556     SwDBNextSetField aFld( (SwDBNextSetFieldType*)pFT, aEmptyStr, aEmptyStr,
2557                             SwDBData() );       // Datenbank: Nichts
2558     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2559     return FLD_OK;
2560 }
2561 
2562 // "DATENSATZ"
Read_F_DBNum(WW8FieldDesc *,String &)2563 eF_ResT SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc*, String& )
2564 {
2565     SwDBSetNumberFieldType aN;
2566     SwFieldType* pFT = rDoc.InsertFldType( aN );
2567     SwDBSetNumberField aFld( (SwDBSetNumberFieldType*)pFT,
2568                            SwDBData() );            // Datenbank: Nichts
2569     rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2570     return FLD_OK;
2571 }
2572 
2573 /*
2574     EQ , only the usage for
2575     a. Combined Characters supported, must be exactly in the form that word
2576     only accepts as combined charactersm, i.e.
2577     eq \o(\s\up Y(XXX),\s\do Y(XXX))
2578     b. Ruby Text supported, must be in the form that word recognizes as being
2579     ruby text
2580     ...
2581 */
Read_F_Equation(WW8FieldDesc *,String & rStr)2582 eF_ResT SwWW8ImplReader::Read_F_Equation( WW8FieldDesc*, String& rStr )
2583 {
2584     _ReadFieldParams aReadParam( rStr );
2585     long cChar = aReadParam.SkipToNextToken();
2586     if ('o' == cChar || 'O' == cChar)
2587         Read_SubF_Combined(aReadParam);
2588     else if ('*' == cChar)
2589         Read_SubF_Ruby(aReadParam);
2590     return FLD_OK;
2591 }
2592 
Read_SubF_Combined(_ReadFieldParams & rReadParam)2593 void SwWW8ImplReader::Read_SubF_Combined( _ReadFieldParams& rReadParam)
2594 {
2595     String sCombinedCharacters;
2596     _ReadFieldParams aOriFldParam = rReadParam;
2597     long cGetChar = rReadParam.SkipToNextToken();
2598     switch( cGetChar )
2599     {
2600     case 'a':
2601     case 'A':
2602         {
2603             String sTemp = rReadParam.GetResult();
2604             if ( !sTemp.EqualsIgnoreCaseAscii("d", 1, 0) )
2605             {
2606                 break;
2607             }
2608             rReadParam.SkipToNextToken();
2609         }
2610     case -2:
2611         {
2612             if ( rReadParam.GetResult().EqualsIgnoreCaseAscii('(', 1, 0) )
2613             {
2614                 for (int i=0;i<2;i++)
2615                 {
2616                     if ('s' == rReadParam.SkipToNextToken())
2617                     {
2618                         long cChar = rReadParam.SkipToNextToken();
2619                         if (-2 != rReadParam.SkipToNextToken())
2620                             break;
2621                         String sF = rReadParam.GetResult();
2622                         if ((('u' == cChar) && sF.EqualsIgnoreCaseAscii('p', 1, 0))
2623                             || (('d' == cChar) && sF.EqualsIgnoreCaseAscii('o', 1, 0)))
2624                         {
2625                             if (-2 == rReadParam.SkipToNextToken())
2626                             {
2627                                 String sPart = rReadParam.GetResult();
2628                                 xub_StrLen nBegin = sPart.Search('(');
2629 
2630                                 //Word disallows brackets in this field, which
2631                                 //aids figuring out the case of an end of )) vs )
2632                                 xub_StrLen nEnd = sPart.Search(')');
2633 
2634                                 if ((nBegin != STRING_NOTFOUND) &&
2635                                     (nEnd != STRING_NOTFOUND))
2636                                 {
2637                                     sCombinedCharacters +=
2638                                         sPart.Copy(nBegin+1,nEnd-nBegin-1);
2639                                 }
2640                             }
2641                         }
2642                     }
2643                 }
2644                 if (sCombinedCharacters.Len())
2645                 {
2646                     SwCombinedCharField aFld((SwCombinedCharFieldType*)
2647                         rDoc.GetSysFldType(RES_COMBINED_CHARS),sCombinedCharacters);
2648                     rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2649                 }
2650                 else
2651                 {
2652                     const String sPart = aOriFldParam.GetResult();
2653                     xub_StrLen nBegin = sPart.Search('(');
2654                     xub_StrLen nEnd = sPart.Search(',');
2655                     if ( nEnd == STRING_NOTFOUND )
2656                     {
2657                         nEnd = sPart.Search(')');
2658                     }
2659                     if ( (nBegin != STRING_NOTFOUND) && (nEnd != STRING_NOTFOUND) )
2660                     {
2661                         // skip certain leading characters
2662                         for (int i = nBegin;i < nEnd-1;i++)
2663                         {
2664                             const sal_Unicode cC = sPart.GetChar(nBegin+1);
2665                             if ( cC < 32 )
2666                             {
2667                                 nBegin++;
2668                             }
2669                             else
2670                                 break;
2671                         }
2672                         sCombinedCharacters = sPart.Copy( nBegin+1, nEnd-nBegin-1 );
2673                         if ( sCombinedCharacters.Len() )
2674                         {
2675                             SwInputField aFld( static_cast<SwInputFieldType*>(rDoc.GetSysFldType( RES_INPUTFLD )),
2676                                 sCombinedCharacters, sCombinedCharacters, INP_TXT, 0, false );
2677                             rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 ); // insert input field
2678                         }
2679                     }
2680                 }
2681             }
2682         }
2683     default:
2684         break;
2685     }
2686 }
2687 
Read_SubF_Ruby(_ReadFieldParams & rReadParam)2688 void SwWW8ImplReader::Read_SubF_Ruby( _ReadFieldParams& rReadParam)
2689 {
2690     sal_uInt16 nJustificationCode=0;
2691     String sFontName;
2692     sal_uInt32 nFontSize=0;
2693     String sRuby;
2694     String sText;
2695     long nRet;
2696     while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
2697     {
2698         switch( nRet )
2699         {
2700         case -2:
2701             {
2702                 String sTemp = rReadParam.GetResult();
2703                 if( sTemp.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
2704                 {
2705                     sTemp.Erase(0,2);
2706                     nJustificationCode = static_cast<sal_uInt16>(sTemp.ToInt32());
2707                 }
2708                 else if( sTemp.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
2709                 {
2710                     sTemp.Erase(0,3);
2711                     nFontSize= static_cast<sal_uInt32>(sTemp.ToInt32());
2712                 }
2713                 else if( sTemp.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
2714                 {
2715                     sTemp.Erase(0,5);
2716                     sFontName = sTemp;
2717                 }
2718             }
2719             break;
2720         case '*':
2721             break;
2722         case 'o':
2723             while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
2724             {
2725                 if ('u' == nRet)
2726                 {
2727                     if (-2 == rReadParam.SkipToNextToken() &&
2728                       (rReadParam.GetResult().EqualsIgnoreCaseAscii('p', 1, 0)))
2729                     {
2730                         if (-2 == rReadParam.SkipToNextToken())
2731                         {
2732                             String sPart = rReadParam.GetResult();
2733                             xub_StrLen nBegin = sPart.Search('(');
2734 
2735                             //Word disallows brackets in this field,
2736                             xub_StrLen nEnd = sPart.Search(')');
2737 
2738                             if ((nBegin != STRING_NOTFOUND) &&
2739                                 (nEnd != STRING_NOTFOUND))
2740                             {
2741                                 sRuby = sPart.Copy(nBegin+1,nEnd-nBegin-1);
2742                             }
2743                             if (STRING_NOTFOUND ==
2744                                 (nBegin = sPart.Search(',',nEnd)))
2745                             {
2746                                 nBegin = sPart.Search(';',nEnd);
2747                             }
2748                             nEnd = sPart.SearchBackward(')');
2749                             if ((nBegin != STRING_NOTFOUND) &&
2750                                 (nEnd != STRING_NOTFOUND))
2751                             {
2752                                 sText = sPart.Copy(nBegin+1,nEnd-nBegin-1);
2753                             }
2754                         }
2755                     }
2756                 }
2757 
2758             }
2759             break;
2760         }
2761     }
2762 
2763     //Translate and apply
2764     if (sRuby.Len() && sText.Len() && sFontName.Len() && nFontSize)
2765     {
2766         switch (nJustificationCode)
2767         {
2768             case 0:
2769                 nJustificationCode=1;
2770                 break;
2771             case 1:
2772                 nJustificationCode=3;
2773                 break;
2774             case 2:
2775                 nJustificationCode=4;
2776                 break;
2777             default:
2778             case 3:
2779                 nJustificationCode=0;
2780                 break;
2781             case 4:
2782                 nJustificationCode=2;
2783                 break;
2784         }
2785 
2786         SwFmtRuby aRuby(sRuby);
2787         const SwCharFmt *pCharFmt=0;
2788         //Make a guess at which of asian of western we should be setting
2789         sal_uInt16 nScript;
2790         if (pBreakIt->GetBreakIter().is())
2791             nScript = pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
2792         else
2793             nScript = i18n::ScriptType::ASIAN;
2794 
2795         //Check to see if we already have a ruby charstyle that this fits
2796         std::vector<const SwCharFmt*>::const_iterator aEnd =
2797             aRubyCharFmts.end();
2798         for(std::vector<const SwCharFmt*>::const_iterator aIter
2799             = aRubyCharFmts.begin(); aIter != aEnd; ++aIter)
2800         {
2801             const SvxFontHeightItem &rFH =
2802                 ItemGet<SvxFontHeightItem>(*(*aIter),
2803                 GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2804             if (rFH.GetHeight() == nFontSize*10)
2805             {
2806                 const SvxFontItem &rF = ItemGet<SvxFontItem>(*(*aIter),
2807                     GetWhichOfScript(RES_CHRATR_FONT,nScript));
2808                 if (rF.GetFamilyName().Equals(sFontName))
2809                 {
2810                     pCharFmt=*aIter;
2811                     break;
2812                 }
2813             }
2814         }
2815 
2816         //Create a new char style if necessary
2817         if (!pCharFmt)
2818         {
2819             SwCharFmt *pFmt=0;
2820             String aNm;
2821             //Take this as the base name
2822             SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT,aNm);
2823             aNm+=String::CreateFromInt32(aRubyCharFmts.size()+1);
2824             pFmt = rDoc.MakeCharFmt(aNm,(SwCharFmt*)rDoc.GetDfltCharFmt());
2825             SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
2826             SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
2827                 aEmptyStr,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
2828             aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2829             aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
2830             pFmt->SetFmtAttr(aHeightItem);
2831             pFmt->SetFmtAttr(aFontItem);
2832             aRubyCharFmts.push_back(pFmt);
2833             pCharFmt = pFmt;
2834         }
2835 
2836         //Set the charstyle and justification
2837         aRuby.SetCharFmtName(pCharFmt->GetName());
2838         aRuby.SetCharFmtId(pCharFmt->GetPoolFmtId());
2839         aRuby.SetAdjustment(nJustificationCode);
2840 
2841         NewAttr(aRuby);
2842         rDoc.InsertString( *pPaM, sText );
2843         pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_CJK_RUBY );
2844     }
2845 }
2846 
2847 //-----------------------------------------
2848 //        Verzeichnis-Felder
2849 //-----------------------------------------
2850 
lcl_toxMatchACSwitch(SwWW8ImplReader &,SwDoc & rDoc,SwTOXBase & rBase,_ReadFieldParams & rParam,SwCaptionDisplay eCaptionType)2851 void lcl_toxMatchACSwitch(  SwWW8ImplReader& /*rReader*/,
2852                             SwDoc& rDoc,
2853                             SwTOXBase& rBase,
2854                             _ReadFieldParams& rParam,
2855                             SwCaptionDisplay eCaptionType)
2856 {
2857     xub_StrLen n = rParam.GoToTokenParam();
2858     if( STRING_NOTFOUND != n )
2859     {
2860         SwTOXType* pType = (SwTOXType*)rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0);
2861         rBase.RegisterToTOXType( *pType );
2862         rBase.SetCaptionDisplay( eCaptionType );
2863         // Read Sequence Name and store in TOXBase
2864         String sSeqName( rParam.GetResult() );
2865         lcl_ConvertSequenceName( sSeqName );
2866         rBase.SetSequenceName( sSeqName );
2867     }
2868 }
2869 
2870 
EnsureMaxLevelForTemplates(SwTOXBase & rBase)2871 static void EnsureMaxLevelForTemplates(SwTOXBase& rBase)
2872 {
2873     //If the TOC contains Template entries at levels > the evaluation level
2874     //that was initially taken from the max normal outline level of the word TOC
2875     //then we cannot use that for the evaluation level because writer cuts off
2876     //all styles above that level, while word just cuts off the "standard"
2877     //outline styles, we have no option but to expand to the highest level
2878     //Word included.
2879     if ((rBase.GetLevel() != MAXLEVEL) && (nsSwTOXElement::TOX_TEMPLATE & rBase.GetCreateType()))
2880     {
2881         for (sal_uInt16 nI = MAXLEVEL; nI > 0; --nI)
2882         {
2883             String sStyles(rBase.GetStyleNames(nI-1));
2884             if (rBase.GetStyleNames(nI-1).Len())
2885             {
2886                 rBase.SetLevel(nI);
2887                 break;
2888             }
2889         }
2890     }
2891 }
2892 
lcl_toxMatchTSwitch(SwWW8ImplReader & rReader,SwTOXBase & rBase,_ReadFieldParams & rParam)2893 void lcl_toxMatchTSwitch(SwWW8ImplReader& rReader, SwTOXBase& rBase,
2894     _ReadFieldParams& rParam)
2895 {
2896     xub_StrLen n = rParam.GoToTokenParam();
2897     if( STRING_NOTFOUND != n )
2898     {
2899         String sParams( rParam.GetResult() );
2900         if( sParams.Len() )
2901         {
2902             xub_StrLen nIndex = 0;
2903 
2904             //#92940# Delimiters between styles and style levels appears to
2905             //allow both ; and ,
2906 
2907             String sTemplate( sParams.GetToken(0, ';', nIndex) );
2908             if( STRING_NOTFOUND == nIndex )
2909             {
2910                 nIndex=0;
2911                 sTemplate = sParams.GetToken(0, ',', nIndex);
2912             }
2913             if( STRING_NOTFOUND == nIndex )
2914             {
2915                 const SwFmt* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
2916                 if( pStyle )
2917                     sTemplate = pStyle->GetName();
2918                 // Store Style for Level 0 into TOXBase
2919                 rBase.SetStyleNames( sTemplate, 0 );
2920             }
2921             else while( STRING_NOTFOUND != nIndex )
2922             {
2923                 xub_StrLen nOldIndex=nIndex;
2924                 sal_uInt16 nLevel = static_cast<sal_uInt16>(
2925                     sParams.GetToken(0, ';', nIndex).ToInt32());
2926                 if( STRING_NOTFOUND == nIndex )
2927                 {
2928                     nIndex = nOldIndex;
2929                     nLevel = static_cast<sal_uInt16>(
2930                         sParams.GetToken(0, ',', nIndex).ToInt32());
2931                 }
2932 
2933                 if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
2934                 {
2935                     nLevel--;
2936                     // Store Style and Level into TOXBase
2937                     const SwFmt* pStyle
2938                             = rReader.GetStyleWithOrgWWName( sTemplate );
2939 
2940                     if( pStyle )
2941                         sTemplate = pStyle->GetName();
2942 
2943                     String sStyles( rBase.GetStyleNames( nLevel ) );
2944                     if( sStyles.Len() )
2945                         sStyles += TOX_STYLE_DELIMITER;
2946                     sStyles += sTemplate;
2947                     rBase.SetStyleNames( sStyles, nLevel );
2948                 }
2949                 // read next style name...
2950                 nOldIndex = nIndex;
2951                 sTemplate = sParams.GetToken(0, ';', nIndex);
2952                 if( STRING_NOTFOUND == nIndex )
2953                 {
2954                     nIndex=nOldIndex;
2955                     sTemplate = sParams.GetToken(0, ',', nIndex);
2956                 }
2957             }
2958         }
2959     }
2960 }
2961 
CurrentSectionColCount() const2962 sal_uInt16 wwSectionManager::CurrentSectionColCount() const
2963 {
2964     sal_uInt16 nIndexCols = 1;
2965     if (!maSegments.empty())
2966         nIndexCols = maSegments.back().maSep.ccolM1 + 1;
2967     return nIndexCols;
2968 }
2969 
2970 //Will there be a new pagebreak at this position (don't know what type
2971 //until later)
WillHavePageDescHere(SwNodeIndex aIdx) const2972 bool wwSectionManager::WillHavePageDescHere(SwNodeIndex aIdx) const
2973 {
2974     bool bRet = false;
2975     if (!maSegments.empty())
2976     {
2977         if (!maSegments.back().IsContinous() &&
2978             maSegments.back().maStart == aIdx)
2979         {
2980             bRet = true;
2981         }
2982     }
2983     return bRet;
2984 }
2985 
lcl_GetMaxValidWordTOCLevel(const SwForm & rForm)2986 sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
2987 {
2988     // GetFormMax() returns level + 1, hence the -1
2989     sal_uInt16 nRet = rForm.GetFormMax()-1;
2990 
2991     // If the max of this type of TOC is greater than the max of a word
2992     // possible toc, then clip to the word max
2993     if (nRet > WW8ListManager::nMaxLevel)
2994         nRet = WW8ListManager::nMaxLevel;
2995 
2996     return nRet;
2997 }
2998 
Read_F_Tox(WW8FieldDesc * pF,String & rStr)2999 eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, String& rStr )
3000 {
3001     if ( !mbLoadingTOXCache )
3002     {
3003         mbLoadingTOXCache = true;
3004     }
3005     else
3006     {
3007         // Embedded TOX --> continue reading its content, but no further TOX field
3008         ++mnEmbeddedTOXLevel;
3009         return FLD_TEXT;
3010     }
3011 
3012     if (pF->nLRes < 3)
3013         return FLD_TEXT;      // ignore (#i25440#)
3014 
3015     TOXTypes eTox;                              // Baue ToxBase zusammen
3016     switch( pF->nId )
3017     {
3018         case  8:
3019             eTox = TOX_INDEX;
3020             break;
3021         case 13:
3022             eTox = TOX_CONTENT;
3023             break;
3024         default:
3025             eTox = TOX_USER;
3026             break;
3027     }
3028 
3029     sal_uInt16 nCreateOf = (eTox == TOX_CONTENT) ? nsSwTOXElement::TOX_OUTLINELEVEL : nsSwTOXElement::TOX_MARK;
3030 
3031     sal_uInt16 nIndexCols = 1;
3032 
3033     const SwTOXType* pType = rDoc.GetTOXType( eTox, 0 );
3034     SwForm aOrigForm(eTox);
3035     SwTOXBase* pBase = new SwTOXBase( pType, aOrigForm, nCreateOf, aEmptyStr );
3036     pBase->SetProtected(maSectionManager.CurrentSectionIsProtected());
3037     switch( eTox ){
3038     case TOX_INDEX:
3039         {
3040             sal_uInt16 eOptions = nsSwTOIOptions::TOI_SAME_ENTRY | nsSwTOIOptions::TOI_CASE_SENSITIVE;
3041 
3042             // TOX_OUTLINELEVEL setzen wir genau dann, wenn
3043             // die Parameter \o in 1 bis 9 liegen
3044             // oder der Parameter \f existiert
3045             // oder GARKEINE Switches Parameter angegeben sind.
3046             long nRet;
3047             _ReadFieldParams aReadParam( rStr );
3048             while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3049             {
3050                 switch( nRet )
3051                 {
3052                 case 'c':
3053                     {
3054                         xub_StrLen n = aReadParam.GoToTokenParam();
3055                         if( STRING_NOTFOUND != n )
3056                         {
3057                             String sParams( aReadParam.GetResult() );
3058                             // if NO String just ignore the \c
3059                             if( sParams.Len() )
3060                             {
3061                                 nIndexCols =
3062                                     static_cast<sal_uInt16>(sParams.ToInt32());
3063                             }
3064                         }
3065                     }
3066                     break;
3067                 case 'e':
3068                     {
3069                         xub_StrLen n = aReadParam.GoToTokenParam();
3070                         if( STRING_NOTFOUND != n )  // if NO String just ignore the \e
3071                         {
3072                             String sDelimiter( aReadParam.GetResult() );
3073                             SwForm aForm( pBase->GetTOXForm() );
3074 
3075                             // Attention: if TOX_CONTENT brave
3076                             //            GetFormMax() returns MAXLEVEL + 1  !!
3077                             sal_uInt16 nEnd = aForm.GetFormMax()-1;
3078 
3079                             for(sal_uInt16 nLevel = 1;
3080                                    nLevel <= nEnd;
3081                                    ++nLevel)
3082                             {
3083                                 // Levels count from 1
3084                                 // Level 0 is reserved for CAPTION
3085 
3086                                 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3087                                 // falls es eine Seitenzahl gibt:
3088                                 FormTokenType ePrevType = TOKEN_END;
3089                                 FormTokenType eType;
3090                                 // -> #i21237#
3091                                 SwFormTokens aPattern =
3092                                     aForm.GetPattern(nLevel);
3093                                 SwFormTokens::iterator aIt = aPattern.begin();
3094                                 do
3095                                 {
3096                                     eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3097 
3098                                     if (eType == TOKEN_PAGE_NUMS)
3099                                     {
3100                                         if (TOKEN_TAB_STOP == ePrevType)
3101                                         {
3102                                             aIt--;
3103 
3104                                             if(0x09 == sDelimiter.GetChar(0))
3105                                                 aIt->eTabAlign = SVX_TAB_ADJUST_END;
3106                                             else
3107                                             {
3108                                                 SwFormToken aToken(TOKEN_TEXT);
3109                                                 aToken.sText = sDelimiter;
3110                                                 *aIt = aToken;
3111                                             }
3112                                             aForm.SetPattern(nLevel, aPattern);
3113                                         }
3114 
3115                                         eType = TOKEN_END;
3116                                     }
3117 
3118                                     ePrevType = eType;
3119                                 }
3120                                 while (TOKEN_END != eType);
3121                                 // <- #i21237#
3122                             }
3123                             pBase->SetTOXForm( aForm );
3124                         }
3125                     }
3126                     break;
3127                 case 'h':
3128                     {
3129                         eOptions |= nsSwTOIOptions::TOI_ALPHA_DELIMITTER;
3130                     }
3131                     break;
3132                 }
3133             }
3134             pBase->SetOptions( eOptions );
3135         }
3136         break;
3137 
3138     case TOX_CONTENT:
3139         {
3140             bool bIsHyperlink = false;
3141             bool bShowPage = true;
3142             // TOX_OUTLINELEVEL setzen wir genau dann, wenn
3143             // die Parameter \o in 1 bis 9 liegen
3144             // oder der Parameter \f existiert
3145             // oder GARKEINE Switches Parameter angegeben sind.
3146             sal_uInt16 eCreateFrom = 0;
3147             sal_uInt16 nMaxLevel = 0;
3148             long nRet;
3149             _ReadFieldParams aReadParam( rStr );
3150             while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3151             {
3152                 switch( nRet )
3153                 {
3154                 case 'h':
3155                     bIsHyperlink = true;
3156                     break;
3157                 case 'a':
3158                 case 'c':
3159                     lcl_toxMatchACSwitch(*this, rDoc, *pBase, aReadParam,
3160                                            ('c' == nRet)
3161                                          ? CAPTION_COMPLETE
3162                                          : CAPTION_TEXT );
3163                     break;
3164                 case 'o':
3165                     {
3166                         sal_uInt16 nVal;
3167                         if( !aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
3168                             nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
3169                         if( nMaxLevel < nVal )
3170                             nMaxLevel = nVal;
3171                         eCreateFrom |= nsSwTOXElement::TOX_OUTLINELEVEL;
3172                     }
3173                     break;
3174                 case 'f':
3175                     eCreateFrom |= nsSwTOXElement::TOX_MARK;
3176                     break;
3177                 case 'l':
3178                     {
3179                         sal_uInt16 nVal;
3180                         if( aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
3181                         {
3182                             if( nMaxLevel < nVal )
3183                                 nMaxLevel = nVal;
3184                             eCreateFrom |= nsSwTOXElement::TOX_MARK;
3185                         }
3186                     }
3187                     break;
3188                 case 't': // paragraphs using special styles shall
3189                           // provide the TOX's content
3190                     lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
3191                     eCreateFrom |= nsSwTOXElement::TOX_TEMPLATE;
3192                     break;
3193                 case 'p':
3194                     {
3195                         xub_StrLen n = aReadParam.GoToTokenParam();
3196                         if( STRING_NOTFOUND != n )  // if NO String just ignore the \p
3197                         {
3198                             String sDelimiter( aReadParam.GetResult() );
3199                             SwForm aForm( pBase->GetTOXForm() );
3200 
3201                             // Attention: if TOX_CONTENT brave
3202                             //            GetFormMax() returns MAXLEVEL + 1  !!
3203                             sal_uInt16 nEnd = aForm.GetFormMax()-1;
3204 
3205                             for(sal_uInt16 nLevel = 1;
3206                                    nLevel <= nEnd;
3207                                    ++nLevel)
3208                             {
3209                                 // Levels count from 1
3210                                 // Level 0 is reserved for CAPTION
3211 
3212                                 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3213                                 // falls es eine Seitenzahl gibt:
3214                                 FormTokenType ePrevType = TOKEN_END;
3215                                 FormTokenType eType;
3216 
3217                                 // -> #i21237#
3218                                 SwFormTokens aPattern = aForm.GetPattern(nLevel);
3219                                 SwFormTokens::iterator aIt = aPattern.begin();
3220                                 do
3221                                 {
3222                                     eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3223 
3224                                     if (eType == TOKEN_PAGE_NUMS)
3225                                     {
3226                                         if (TOKEN_TAB_STOP == ePrevType)
3227                                         {
3228                                             aIt--;
3229 
3230                                             SwFormToken aToken(TOKEN_TEXT);
3231                                             aToken.sText = sDelimiter;
3232 
3233                                             *aIt = aToken;
3234                                             aForm.SetPattern(nLevel,
3235                                                              aPattern);
3236                                         }
3237                                         eType = TOKEN_END;
3238                                     }
3239                                     ePrevType = eType;
3240                                 }
3241                                 while( TOKEN_END != eType );
3242                                 // <- #i21237#
3243                             }
3244                             pBase->SetTOXForm( aForm );
3245                         }
3246                     }
3247                     break;
3248                 case 'n': // don't print page numbers
3249                     {
3250                         // read START and END param
3251                         bShowPage = false;
3252                         sal_uInt16 nStart, nEnd;
3253                         if( !aReadParam.GetTokenSttFromTo(  &nStart, &nEnd,
3254                             WW8ListManager::nMaxLevel ) )
3255                         {
3256                             nStart = 1;
3257                             nEnd = aOrigForm.GetFormMax()-1;
3258                         }
3259                         // remove page numbers from this levels
3260                         SwForm aForm( pBase->GetTOXForm() );
3261                         if (aForm.GetFormMax() <= nEnd)
3262                             nEnd = aForm.GetFormMax()-1;
3263                         for (
3264                               sal_uInt16 nLevel = nStart; nLevel <= nEnd;
3265                               ++nLevel
3266                             )
3267                         {
3268                             // Levels count from 1
3269                             // Level 0 is reserved for CAPTION
3270 
3271                             // Seitenzahl und ggfs. davorstehenden Tabstop
3272                             // entfernen:
3273                             FormTokenType eType;
3274                             // -> #i21237#
3275                             SwFormTokens aPattern = aForm.GetPattern(nLevel);
3276                             SwFormTokens::iterator aIt = aPattern.begin();
3277                             do
3278                             {
3279                                 eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3280 
3281                                 if (eType == TOKEN_PAGE_NUMS)
3282                                 {
3283                                     aIt = aPattern.erase(aIt);
3284                                     aIt--;
3285                                     if (
3286                                          TOKEN_TAB_STOP ==
3287                                          aIt->eTokenType
3288                                        )
3289                                     {
3290                                         aPattern.erase(aIt);
3291                                         aForm.SetPattern(nLevel, aPattern);
3292                                     }
3293                                     eType = TOKEN_END;
3294                                 }
3295                             }
3296                             while (TOKEN_END != eType);
3297                             // <- #i21237#
3298                         }
3299                         pBase->SetTOXForm( aForm );
3300                     }
3301                     break;
3302 
3303                 /*
3304                 // the following switches are not (yet) supported
3305                 // by good old StarWriter:
3306                 case 'b':
3307                 case 's':
3308                 case 'd':
3309                     break;
3310                 */
3311                 }
3312             }
3313 
3314             // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens
3315             // also include the hyperlinks and page references
3316             SwFormToken aLinkStart(TOKEN_LINK_START);
3317             SwFormToken aLinkEnd(TOKEN_LINK_END);
3318             aLinkStart.sCharStyleName = String::CreateFromAscii("Index Link");
3319             aLinkEnd.sCharStyleName = String::CreateFromAscii("Index Link");
3320             SwForm aForm(pBase->GetTOXForm());
3321             sal_uInt16 nEnd = aForm.GetFormMax()-1;
3322 
3323             for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
3324             {
3325                 SwFormTokens aPattern = aForm.GetPattern(nLevel);
3326                 if ( bIsHyperlink )
3327                 {
3328                     aPattern.insert(aPattern.begin(), aLinkStart);
3329                 }
3330                 else if ( bShowPage )
3331                 {
3332                     for (SwFormTokens::iterator aItr = aPattern.begin();aItr!= aPattern.end();aItr++)
3333                     {
3334                         if (aItr->eTokenType == TOKEN_PAGE_NUMS)
3335                         {
3336                             aPattern.insert(aItr,aLinkStart);
3337                             break;
3338                         }
3339                     }
3340                 }
3341                 aPattern.push_back(aLinkEnd);
3342                 aForm.SetPattern(nLevel, aPattern);
3343             }
3344             pBase->SetTOXForm(aForm);
3345 
3346             if (!nMaxLevel)
3347                 nMaxLevel = WW8ListManager::nMaxLevel;
3348             pBase->SetLevel(nMaxLevel);
3349 
3350             const TOXTypes eType = pBase->GetTOXType()->GetType();
3351             switch( eType )
3352             {
3353                 case TOX_CONTENT:
3354                     {
3355                         //If we would be created from outlines, either explicitly or by default
3356                         //then see if we need extra styles added to the outlines
3357                         sal_uInt16 eEffectivelyFrom = eCreateFrom ? eCreateFrom : nsSwTOXElement::TOX_OUTLINELEVEL;
3358                         if (eEffectivelyFrom & nsSwTOXElement::TOX_OUTLINELEVEL)
3359                         {
3360                             // #i19683# Insert a text token " " between the number and entry token.
3361                             // In an ideal world we could handle the tab stop between the number and
3362                             // the entry correctly, but I currently have no clue how to obtain the tab stop position.
3363                             // It is _not_ set at the paragraph style.
3364                             SwForm* pForm = 0;
3365                             for (sal_uInt16 nI = 0; nI < nColls; ++nI)
3366                             {
3367                                 const SwWW8StyInf& rSI = pCollA[nI];
3368                                 if (rSI.IsOutlineNumbered())
3369                                 {
3370                                     sal_uInt16 nStyleLevel = rSI.mnWW8OutlineLevel;
3371                                     const SwNumFmt& rFmt = rSI.GetOutlineNumrule()->Get( nStyleLevel );
3372                                     if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() )
3373                                     {
3374                                         ++nStyleLevel;
3375 
3376                                         if ( !pForm )
3377                                             pForm = new SwForm( pBase->GetTOXForm() );
3378 
3379                                         SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
3380                                         SwFormTokens::iterator aIt =
3381                                                 find_if(aPattern.begin(), aPattern.end(),
3382                                                 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3383 
3384                                         if ( aIt != aPattern.end() )
3385                                         {
3386                                             SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
3387                                             aNumberEntrySeparator.sText = String::CreateFromAscii(" ");
3388                                             aPattern.insert( ++aIt, aNumberEntrySeparator );
3389                                             pForm->SetPattern( nStyleLevel, aPattern );
3390                                         }
3391                                     }
3392                                 }
3393                             }
3394                             if ( pForm )
3395                             {
3396                                 pBase->SetTOXForm( *pForm );
3397                                 delete pForm;
3398                             }
3399                         }
3400 
3401                         if (eCreateFrom)
3402                             pBase->SetCreate(eCreateFrom);
3403                         EnsureMaxLevelForTemplates(*pBase);
3404                     }
3405                     break;
3406                 case TOX_ILLUSTRATIONS:
3407                     {
3408                         if( !eCreateFrom )
3409                             eCreateFrom = nsSwTOXElement::TOX_SEQUENCE;
3410                         pBase->SetCreate( eCreateFrom );
3411 
3412                         /*
3413                         #91214#
3414                         We don't know until here if we are an illustration
3415                         or not, and so have being used a TOX_CONTENT so far
3416                         which has 10 levels, while TOX has only two, this
3417                         level is set only in the constructor of SwForm, so
3418                         create a new one and copy over anything that could
3419                         be set in the old one, and remove entries from the
3420                         pattern which do not apply to illustration indices
3421                         */
3422                         SwForm aOldForm( pBase->GetTOXForm() );
3423                         SwForm aForm( eType );
3424                         sal_uInt16 nEnd = aForm.GetFormMax()-1;
3425 
3426                         // -> #i21237#
3427                         for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
3428                         {
3429                             SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
3430                             SwFormTokens::iterator new_end =
3431                                 remove_if(aPattern.begin(), aPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3432                             aPattern.erase(new_end, aPattern.end() ); // #124710#: table index imported with wrong page number format
3433                             aForm.SetPattern( nLevel, aPattern );
3434                             aForm.SetTemplate( nLevel, aOldForm.GetTemplate(nLevel) );
3435                         }
3436                         // <- #i21237#
3437 
3438                         pBase->SetTOXForm( aForm );
3439                     }
3440                     break;
3441                 default:
3442                     ASSERT(sal_False, "Unhandled toc options!");
3443                     break;
3444             }
3445         }
3446         break;
3447     case TOX_USER:
3448         break;
3449     default:
3450         ASSERT(sal_False, "Unhandled toc options!");
3451         break;
3452     } // ToxBase fertig
3453 
3454     // #i21237# - propagate tab stops from paragraph styles used in TOX to patterns of the TOX
3455     pBase->AdjustTabStops( rDoc );
3456 
3457     //#i10028# inserting a toc implicltly acts like a parabreak in word and writer
3458     if ( pPaM->End() &&
3459          pPaM->End()->nNode.GetNode().GetTxtNode() &&
3460          pPaM->End()->nNode.GetNode().GetTxtNode()->Len() != 0 )
3461     {
3462         mbCareFirstParaEndInToc = true;
3463     }
3464 
3465     if (pPaM->GetPoint()->nContent.GetIndex())
3466         AppendTxtNode(*pPaM->GetPoint());
3467 
3468     const SwPosition* pPos = pPaM->GetPoint();
3469 
3470     SwFltTOX aFltTOX( pBase, nIndexCols );
3471 
3472     // test if there is already a break item on this node
3473     if(SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode())
3474     {
3475         const SfxItemSet* pSet = pNd->GetpSwAttrSet();
3476         if( pSet )
3477         {
3478             if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false))
3479                 aFltTOX.SetHadBreakItem(true);
3480             if (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false))
3481                 aFltTOX.SetHadPageDescItem(true);
3482         }
3483     }
3484 
3485     //Will there be a new pagebreak at this position (don't know what type
3486     //until later)
3487     if (maSectionManager.WillHavePageDescHere(pPos->nNode))
3488         aFltTOX.SetHadPageDescItem(true);
3489 
3490     // Setze Anfang in Stack
3491     pReffedStck->NewAttr( *pPos, aFltTOX );
3492 
3493     rDoc.InsertTableOf(*pPaM->GetPoint(), *aFltTOX.GetBase());
3494 
3495     //The TOC field representation contents should be inserted into TOC section, but not after TOC section.
3496     //So we need update the document position when loading TOC representation and after loading TOC;
3497     if (mpPosAfterTOC)
3498     {
3499         delete mpPosAfterTOC;
3500     }
3501     mpPosAfterTOC = new SwPaM(*pPaM);
3502     (*pPaM).Move(fnMoveBackward);
3503     SwPaM aRegion(*pPaM);
3504 
3505     ASSERT(rDoc.GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
3506     if (SwTOXBase* pBase2 = (SwTOXBase*)rDoc.GetCurTOX(*aRegion.GetPoint()))
3507     {
3508         pBase2->SetMSTOCExpression(rStr);
3509 
3510         if ( nIndexCols > 1 )
3511         {
3512             // Set the column number for index
3513             SfxItemSet aSet( rDoc.GetAttrPool(), RES_COL, RES_COL );
3514             SwFmtCol aCol;
3515             aCol.Init( nIndexCols, 708, USHRT_MAX );
3516             aSet.Put( aCol );
3517             pBase2->SetAttrSet( aSet );
3518         }
3519 
3520         // inserting a toc inserts a section before this point, so adjust pos
3521         // for future page/section segment insertion
3522         maSectionManager.PrependedInlineNode( *mpPosAfterTOC->GetPoint(), *aRegion.GetNode() );
3523     }
3524 
3525     // Setze Ende in Stack
3526     pReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
3527 
3528     if (!maApos.back()) //a para end in apo doesn't count
3529         bWasParaEnd = true;
3530 
3531     //Return FLD_TEXT, instead of FLD_OK
3532     //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed
3533     //FLD_OK means the current field loading is finished. The rest part should be ignored.
3534     return FLD_TEXT;
3535 }
3536 
Read_F_Shape(WW8FieldDesc *,String &)3537 eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, String& /*rStr*/)
3538 {
3539     /*
3540     #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3541     to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3542     the drawing that we are in the Shape field and respond accordingly
3543     */
3544     return FLD_TEXT;
3545  }
3546 
Read_F_Hyperlink(WW8FieldDesc *,String & rStr)3547 eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, String& rStr )
3548 {
3549     String sURL, sTarget, sMark;
3550     bool bDataImport = false;
3551     //HYPERLINk "filename" [switches]
3552     bool bOptions=false;
3553 
3554     rStr.EraseTrailingChars( 1 );
3555 
3556     if (!bDataImport)
3557     {
3558         long nRet;
3559         _ReadFieldParams aReadParam( rStr );
3560         while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3561         {
3562             switch( nRet )
3563             {
3564                 case -2:
3565                     if (!sURL.Len() & !bOptions)
3566                         ConvertFFileName(sURL, aReadParam.GetResult());
3567                     break;
3568 
3569                 case 'n':
3570                     sTarget.ASSIGN_CONST_ASC( "_blank" );
3571                     bOptions = true;
3572                     break;
3573 
3574                 case 'l':
3575                     nRet = aReadParam.SkipToNextToken();
3576                     bOptions = true;
3577                     if( -2 == nRet )
3578                     {
3579                         sMark = aReadParam.GetResult();
3580                         if( sMark.Len() > 0 && '"' == sMark.GetChar( sMark.Len()-1 ) )
3581                         {
3582                             sMark.Erase( sMark.Len() - 1 );
3583                         }
3584                         // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
3585                         if ( IsTOCBookmarkName( sMark ) )
3586                         {
3587                             String sTmp = IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix();
3588                             sTmp += sMark;
3589                             sMark = sTmp;
3590                             // track <sMark> as referenced TOC bookmark.
3591                             pReffedStck->aReferencedTOCBookmarks.insert( sMark );
3592                         }
3593 
3594                         if (mbLoadingTOXCache)
3595                         {
3596                             mbLoadingTOXHyperlink = true;//on loading a TOX field nested hyperlink field
3597                         }
3598                     }
3599                     break;
3600                 case 't':
3601                     nRet = aReadParam.SkipToNextToken();
3602                     bOptions = true;
3603                     if (-2 == nRet)
3604                         sTarget = aReadParam.GetResult();
3605                     break;
3606                 case 'h':
3607                 case 'm':
3608                     ASSERT( sal_False, "Evaluation is still missing - data unknown" );
3609                 case 's':   //worthless fake anchor option
3610                     bOptions = true;
3611                     break;
3612             }
3613         }
3614     }
3615 
3616     // das Resultat uebernehmen
3617     ASSERT((sURL.Len() || sMark.Len()), "WW8: Empty URL")
3618 
3619     if( sMark.Len() )
3620         ( sURL += INET_MARK_TOKEN ) += sMark;
3621 
3622     SwFmtINetFmt aURL( sURL, sTarget );
3623     // If on loading TOX field, change the default style into the "index link"
3624     if (mbLoadingTOXCache)
3625     {
3626         String sLinkStyle = String::CreateFromAscii("Index Link");
3627         sal_uInt16 nPoolId =
3628             SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
3629         aURL.SetVisitedFmtAndId( sLinkStyle, nPoolId );
3630         aURL.SetINetFmtAndId( sLinkStyle, nPoolId );
3631     }
3632 
3633     //As an attribute this needs to be closed, and that'll happen from
3634     //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms
3635     //between the start and begin, their hyperlinks will be set at that time
3636     //as well.
3637     pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL );
3638     return FLD_TEXT;
3639 }
3640 
lcl_ImportTox(SwDoc & rDoc,SwPaM & rPaM,const String & rStr,bool bIdx)3641 void lcl_ImportTox(SwDoc &rDoc, SwPaM &rPaM, const String &rStr, bool bIdx)
3642 {
3643     TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX;    // Default
3644 
3645     sal_uInt16 nLevel = 1;
3646 
3647     xub_StrLen n;
3648     String sFldTxt;
3649     long nRet;
3650     _ReadFieldParams aReadParam(rStr);
3651     while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3652         switch( nRet )
3653         {
3654         case -2:
3655             if( !sFldTxt.Len() )
3656             {
3657                 // PrimaryKey ohne ":", 2nd dahinter
3658                 sFldTxt = aReadParam.GetResult();
3659             }
3660             break;
3661 
3662         case 'f':
3663             n = aReadParam.GoToTokenParam();
3664             if( STRING_NOTFOUND != n )
3665             {
3666                 String sParams( aReadParam.GetResult() );
3667                 if( 'C' != sParams.GetChar(0) && 'c' != sParams.GetChar(0) )
3668                     eTox = TOX_USER;
3669             }
3670             break;
3671 
3672         case 'l':
3673             n = aReadParam.GoToTokenParam();
3674             if( STRING_NOTFOUND != n )
3675             {
3676                 String sParams( aReadParam.GetResult() );
3677                 if(    sParams.Len() // if NO String just ignore the \l
3678                     && sParams.GetChar( 0 ) > '0'
3679                     && sParams.GetChar( 0 ) <= '9' )
3680                 {
3681                     nLevel = (sal_uInt16)sParams.ToInt32();
3682                 }
3683             }
3684             break;
3685         }
3686 
3687     ASSERT( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0  :-(" );
3688 
3689     const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
3690     SwTOXMark aM( pT );
3691 
3692     if( eTox != TOX_INDEX )
3693         aM.SetLevel( nLevel );
3694     else
3695     {
3696         xub_StrLen nFnd = sFldTxt.Search( WW8_TOX_LEVEL_DELIM );
3697         if( STRING_NOTFOUND != nFnd )  // it exist levels
3698         {
3699             aM.SetPrimaryKey( sFldTxt.Copy( 0, nFnd ) );
3700             xub_StrLen nScndFnd =
3701                 sFldTxt.Search( WW8_TOX_LEVEL_DELIM, nFnd+1 );
3702             if( STRING_NOTFOUND != nScndFnd )
3703             {
3704                 aM.SetSecondaryKey(  sFldTxt.Copy( nFnd+1, nScndFnd - nFnd - 1 ));
3705                 nFnd = nScndFnd;
3706             }
3707             sFldTxt.Erase( 0, nFnd+1 );
3708         }
3709     }
3710 
3711     if (sFldTxt.Len())
3712     {
3713         aM.SetAlternativeText( sFldTxt );
3714         rDoc.InsertPoolItem( rPaM, aM, 0 );
3715     }
3716 }
3717 
ImportXE(SwDoc & rDoc,SwPaM & rPaM,const String & rStr)3718 void sw::ms::ImportXE(SwDoc &rDoc, SwPaM &rPaM, const String &rStr)
3719 {
3720     lcl_ImportTox(rDoc, rPaM, rStr, true);
3721 }
3722 
ImportTox(int nFldId,String aStr)3723 void SwWW8ImplReader::ImportTox( int nFldId, String aStr )
3724 {
3725     bool bIdx = (nFldId != 9);
3726     lcl_ImportTox(rDoc, *pPaM, aStr, bIdx);
3727 }
3728 
Read_FldVanish(sal_uInt16,const sal_uInt8 *,short nLen)3729 void SwWW8ImplReader::Read_FldVanish( sal_uInt16, const sal_uInt8*, short nLen )
3730 {
3731     //Meaningless in a style
3732     if (pAktColl || !pPlcxMan)
3733         return;
3734 
3735     const int nChunk = 64;  //number of characters to read at one time
3736 
3737     // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
3738     const static sal_Char *aFldNames[] = {  "\x06""INHALT", "\x02""XE", // dt.
3739                                             "\x02""TC"  };              // us
3740     const static sal_uInt8  aFldId[] = { 9, 4, 9 };
3741 
3742     if( nLen < 0 )
3743     {
3744         bIgnoreText = false;
3745         return;
3746     }
3747 
3748     // our methode was called from
3749     // ''Skip attributes of field contents'' loop within ReadTextAttr()
3750     if( bIgnoreText )
3751         return;
3752 
3753     bIgnoreText = true;
3754     long nOldPos = pStrm->Tell();
3755 
3756     WW8_CP nStartCp = pPlcxMan->Where() + pPlcxMan->GetCpOfs();
3757 
3758     String sFieldName;
3759     sal_uInt16 nFieldLen = pSBase->WW8ReadString( *pStrm, sFieldName, nStartCp,
3760         nChunk, eStructCharSet );
3761     nStartCp+=nFieldLen;
3762 
3763     xub_StrLen nC = 0;
3764     //If the first chunk did not start with a field start then
3765     //reset the stream position and give up
3766     if( !nFieldLen || (0x13 != sFieldName.GetChar( nC ))) // Field Start Mark
3767     {
3768         // If Field End Mark found
3769         if( nFieldLen && (0x15 == sFieldName.GetChar( nC )))
3770             bIgnoreText = false;
3771         pStrm->Seek( nOldPos );
3772         return;                 // kein Feld zu finden
3773     }
3774 
3775     xub_StrLen nFnd;
3776     //If this chunk does not contain a field end, keep reading chunks
3777     //until we find one, or we run out of text,
3778     while (STRING_NOTFOUND == (nFnd = sFieldName.Search(0x15)))
3779     {
3780         String sTemp;
3781         nFieldLen = pSBase->WW8ReadString( *pStrm, sTemp,
3782         nStartCp, nChunk, eStructCharSet );
3783         sFieldName+=sTemp;
3784         nStartCp+=nFieldLen;
3785         if (!nFieldLen)
3786             break;
3787     }
3788 
3789     pStrm->Seek( nOldPos );
3790 
3791     //if we have no 0x15 give up, otherwise erase everything from the 0x15
3792     //onwards
3793     if (STRING_NOTFOUND == nFnd)
3794         return;
3795     else
3796         sFieldName.Erase(nFnd);
3797 
3798     nC++;
3799     while( ' '  == sFieldName.GetChar( nC ))
3800         nC++;
3801 
3802     for( int i = 0; i < 3; i++ )
3803     {
3804         const sal_Char* pName = aFldNames[i];
3805         sal_uInt16 nNameLen = *pName++;
3806         if( sFieldName.EqualsIgnoreCaseAscii( pName, nC, nNameLen ) )
3807         {
3808             ImportTox( aFldId[i], sFieldName.Copy( nC + nNameLen ) );
3809             break;                  // keine Mehrfachnennungen moeglich
3810         }
3811     }
3812     bIgnoreText = true;
3813     pStrm->Seek( nOldPos );
3814 }
3815 
3816 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
3817