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