1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <sal/types.h>
23 #include <tools/solar.h>
24 #include <comphelper/processfactory.hxx>
25 #include <comphelper/storagehelper.hxx>
26 #include <comphelper/string.hxx>
27 #include <comphelper/simplefileaccessinteraction.hxx>
28 #include <sot/storinfo.hxx>
29 #include <com/sun/star/embed/XStorage.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <com/sun/star/embed/XTransactedObject.hpp>
32 #include <com/sun/star/io/XStream.hpp>
33 #include <com/sun/star/task/InteractionHandler.hpp>
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>
41 #include <ucbhelper/content.hxx>
42 #include <ucbhelper/commandenvironment.hxx>
44 #include <com/sun/star/i18n/ScriptType.hpp>
45 #include <hintids.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/fhgtitem.hxx>
48 #include <editeng/langitem.hxx>
50 #include <fmtanchr.hxx>
53 #include <IDocumentFieldsAccess.hxx>
54 #include <IDocumentState.hxx>
55 #include <charatr.hxx>
57 #include <docufld.hxx>
64 #include <section.hxx>
66 #include <fmtinfmt.hxx>
71 #include <shellres.hxx>
72 #include <fmtruby.hxx>
73 #include <charfmt.hxx>
75 #include <breakit.hxx>
76 #include <fmtclds.hxx>
77 #include <pagedesc.hxx>
78 #include <SwStyleNameMapper.hxx>
80 #include "ww8scan.hxx"
82 #include "ww8par2.hxx"
83 #include "writerhelper.hxx"
85 #include <unotools/fltrcfg.hxx>
86 #include <xmloff/odffields.hxx>
90 #define MAX_FIELDLEN 64000
92 #define WW8_TOX_LEVEL_DELIM ':'
94 using namespace ::com::sun::star
;
95 using namespace msfilter::util
;
96 using namespace sw::util
;
97 using namespace sw::mark
;
98 using namespace std
; // #i24377#
99 using namespace nsSwDocInfoSubType
;
104 // #120879# - helper method to identify a bookmark name to match the internal TOC bookmark naming convention
105 bool IsTOCBookmarkName(const OUString
& rName
)
107 return rName
.startsWith("_Toc") || rName
.startsWith(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()+"_Toc");
110 OUString
EnsureTOCBookmarkName(const OUString
& rName
)
112 OUString sTmp
= rName
;
113 if ( IsTOCBookmarkName ( rName
) )
115 if ( ! rName
.startsWith(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()) )
116 sTmp
= IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix() + rName
;
122 long SwWW8ImplReader::Read_Book(WW8PLCFManResult
*)
124 // should also work via pRes.nCo2OrIdx
125 WW8PLCFx_Book
* pB
= m_pPlcxMan
->GetBook();
128 OSL_ENSURE( pB
, "WW8PLCFx_Book - Pointer does not exist" );
132 eBookStatus eB
= pB
->GetStatus();
133 if (eB
& BOOK_IGNORE
)
134 return 0; // ignore bookmark
138 m_pReffedStck
->SetAttr(*m_pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true,
139 pB
->GetHandle(), (eB
& BOOK_FIELD
)!=0);
143 // "_Hlt*" are unnecessary
144 const OUString
* pName
= pB
->GetName();
145 // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available.
146 // So the hidden bookmarks inside for hyperlink jumping also should be kept.
148 pName
->startsWithIgnoreAsciiCase( "_Hlt" ) )
153 // do NOT call ToUpper as the bookmark name can also be a hyperlink target!
156 if( SwFltGetFlag( m_nFieldFlags
, SwFltControlStack::BOOK_TO_VAR_REF
) )
158 // set variable for translation bookmark
159 long nLen
= pB
->GetLen();
160 if( nLen
> MAX_FIELDLEN
)
163 long nOldPos
= m_pStrm
->Tell();
164 m_pSBase
->WW8ReadString( *m_pStrm
, aVal
, pB
->GetStartPos(), nLen
,
166 m_pStrm
->Seek( nOldPos
);
168 // now here the implementation of the old "QuoteString" and
169 // I hope with a better performance as before. It's also only
170 // needed if the filterflags say we will convert bookmarks
171 // to SetExpFields! And this the exception!
173 OUString
sHex("\\x");
175 bool bAllowCr
= SwFltGetFlag(m_nFieldFlags
,
176 SwFltControlStack::ALLOW_FLD_CR
);
178 for( sal_Int32 nI
= 0;
179 nI
< aVal
.getLength() && aVal
.getLength() < (MAX_FIELDLEN
- 4);
182 const sal_Unicode cChar
= aVal
[nI
];
190 aVal
= aVal
.replaceAt( nI
, 1, "\n" );
203 bSetAsHex
= 0x20 > cChar
;
209 //all Hex-Numbers with \x before
210 OUString
sTmp( sHex
);
213 sTmp
+= OUString::number( cChar
, 16 );
214 aVal
= aVal
.replaceAt( nI
, 1 , sTmp
);
215 nI
+= sTmp
.getLength() - 1;
219 if ( aVal
.getLength() > (MAX_FIELDLEN
- 4))
220 aVal
= aVal
.copy( 0, MAX_FIELDLEN
- 4 );
223 //e.g. inserting bookmark around field result, so we need to put
224 //it around the entire writer field, as we don't have the separation
225 //of field and field result of word, see #i16941#
226 SwPosition
aStart(*m_pPaM
->GetPoint());
227 if (!m_aFieldStack
.empty())
229 const WW8FieldEntry
&rTest
= m_aFieldStack
.back();
230 aStart
= rTest
.maStartPos
;
233 const OUString sOrigName
= BookmarkToWriter(*pName
);
234 m_pReffedStck
->NewAttr( aStart
,
235 SwFltBookmark( EnsureTOCBookmarkName( sOrigName
), aVal
, pB
->GetHandle(), IsTOCBookmarkName( sOrigName
) ));
239 long SwWW8ImplReader::Read_AtnBook(WW8PLCFManResult
*)
241 if (WW8PLCFx_AtnBook
* pAtnBook
= m_pPlcxMan
->GetAtnBook())
243 if (pAtnBook
->getIsEnd())
244 m_pReffedStck
->SetAttr(*m_pPaM
->GetPoint(), RES_FLTR_ANNOTATIONMARK
, true, pAtnBook
->getHandle());
246 m_pReffedStck
->NewAttr(*m_pPaM
->GetPoint(), CntUInt16Item(RES_FLTR_ANNOTATIONMARK
, pAtnBook
->getHandle()));
251 long SwWW8ImplReader::Read_FactoidBook(WW8PLCFManResult
*)
253 if (WW8PLCFx_FactoidBook
* pFactoidBook
= m_pPlcxMan
->GetFactoidBook())
255 if (pFactoidBook
->getIsEnd())
256 m_pReffedStck
->SetAttr(*m_pPaM
->GetPoint(), RES_FLTR_RDFMARK
, true, pFactoidBook
->getHandle());
260 aMark
.SetHandle(pFactoidBook
->getHandle());
261 GetSmartTagInfo(aMark
);
262 m_pReffedStck
->NewAttr(*m_pPaM
->GetPoint(), aMark
);
268 // general help methods to separate parameters
270 /// translate FieldParameter names into the system character set and
271 /// at the same time, double backslashes are converted into single ones
272 OUString
SwWW8ImplReader::ConvertFFileName(const OUString
& rOrg
)
274 OUString aName
= rOrg
;
275 aName
= aName
.replaceAll("\\\\", "\\");
276 aName
= aName
.replaceAll("%20", " ");
278 // remove attached quotation marks
279 if (aName
.endsWith("\""))
280 aName
= aName
.copy(0, aName
.getLength()-1);
282 // Need the more sophisticated url converter.
283 if (!aName
.isEmpty())
284 aName
= URIHelper::SmartRel2Abs(
285 INetURLObject(m_sBaseURL
), aName
, Link
<OUString
*, bool>(), false);
292 /// translate FieldParameter names into the
293 /// system character set and makes them uppercase
294 void ConvertUFName( OUString
& rName
)
296 rName
= GetAppCharClass().uppercase( rName
);
300 static void lcl_ConvertSequenceName(OUString
& rSequenceName
)
302 ConvertUFName(rSequenceName
);
303 if ('0' <= rSequenceName
[0] && '9' >= rSequenceName
[0])
304 rSequenceName
= "_" + rSequenceName
;
307 // FindParaStart() finds 1st Parameter that follows '\' and cToken
308 // and returns start of this parameter or -1
309 sal_Int32
FindParaStart( const OUString
& rStr
, sal_Unicode cToken
, sal_Unicode cToken2
)
311 bool bStr
= false; // ignore inside a string
313 for( sal_Int32 nBuf
= 0; nBuf
+1 < rStr
.getLength(); nBuf
++ )
315 if( rStr
[ nBuf
] == '"' )
319 && rStr
[ nBuf
] == '\\'
320 && ( rStr
[ nBuf
+ 1 ] == cToken
321 || rStr
[ nBuf
+ 1 ] == cToken2
) )
324 // skip spaces between cToken and its parameters
325 while( nBuf
< rStr
.getLength()
326 && rStr
[ nBuf
] == ' ' )
328 // return start of parameters
329 return nBuf
< rStr
.getLength() ? nBuf
: -1;
335 // FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
336 // ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
337 // und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
338 OUString
FindPara( const OUString
& rStr
, sal_Unicode cToken
, sal_Unicode cToken2
)
341 sal_Int32 n
= FindParaStart( rStr
, cToken
, cToken2
); // start
346 || rStr
[ n
] == 132 )
347 { // Anfuehrungszeichen vor Para
348 n
++; // Anfuehrungszeichen ueberlesen
349 n2
= n
; // ab hier nach Ende suchen
350 while( n2
< rStr
.getLength()
352 && rStr
[ n2
] != '"' )
353 n2
++; // Ende d. Paras suchen
356 { // keine Anfuehrungszeichen
357 n2
= n
; // ab hier nach Ende suchen
358 while( n2
< rStr
.getLength()
359 && rStr
[ n2
] != ' ' )
360 n2
++; // Ende d. Paras suchen
362 return rStr
.copy( n
, n2
-n
);
365 static SvxExtNumType
GetNumTypeFromName(const OUString
& rStr
,
366 bool bAllowPageDesc
= false)
368 SvxExtNumType eTyp
= bAllowPageDesc
? SVX_NUM_PAGEDESC
: SVX_NUM_ARABIC
;
369 if( rStr
.startsWithIgnoreAsciiCase( "Arabi" ) ) // Arabisch, Arabic
370 eTyp
= SVX_NUM_ARABIC
;
371 else if( rStr
.startsWith( "misch" ) ) // r"omisch
372 eTyp
= SVX_NUM_ROMAN_LOWER
;
373 else if( rStr
.startsWith( "MISCH" ) ) // R"OMISCH
374 eTyp
= SVX_NUM_ROMAN_UPPER
;
375 else if( rStr
.startsWithIgnoreAsciiCase( "alphabeti" ) )// alphabetisch, alphabetic
376 eTyp
= ( rStr
[0] == 'A' )
377 ? SVX_NUM_CHARS_UPPER_LETTER_N
378 : SVX_NUM_CHARS_LOWER_LETTER_N
;
379 else if( rStr
.startsWithIgnoreAsciiCase( "roman" ) ) // us
380 eTyp
= ( rStr
[0] == 'R' )
381 ? SVX_NUM_ROMAN_UPPER
382 : SVX_NUM_ROMAN_LOWER
;
386 static SvxExtNumType
GetNumberPara(const OUString
& rStr
, bool bAllowPageDesc
= false)
388 OUString
s( FindPara( rStr
, '*', '*' ) ); // Ziffernart
389 SvxExtNumType aType
= GetNumTypeFromName( s
, bAllowPageDesc
);
393 bool SwWW8ImplReader::ForceFieldLanguage(SwField
&rField
, sal_uInt16 nLang
)
397 const SvxLanguageItem
*pLang
=
398 static_cast<const SvxLanguageItem
*>(GetFormatAttr(RES_CHRATR_LANGUAGE
));
399 OSL_ENSURE(pLang
, "impossible");
400 sal_uInt16 nDefault
= pLang
? pLang
->GetValue() : LANGUAGE_ENGLISH_US
;
402 if (nLang
!= nDefault
)
404 rField
.SetAutomaticLanguage(false);
405 rField
.SetLanguage(nLang
);
412 OUString
GetWordDefaultDateStringAsUS(SvNumberFormatter
* pFormatter
, sal_uInt16 nLang
)
414 //Get the system date in the correct final language layout, convert to
415 //a known language and modify the 2 digit year part to be 4 digit, and
416 //convert back to the correct language layout.
417 const sal_uInt32 nIndex
= pFormatter
->GetFormatIndex(NF_DATE_SYSTEM_SHORT
, nLang
);
419 SvNumberformat aFormat
= const_cast<SvNumberformat
&>
420 (*(pFormatter
->GetEntry(nIndex
)));
421 aFormat
.ConvertLanguage(*pFormatter
, nLang
, LANGUAGE_ENGLISH_US
);
423 OUString
sParams(aFormat
.GetFormatstring());
425 // Fix provided by mloiseleur@openoffice.org.
426 // A default date can have already 4 year digits, in some case
427 const sal_Int32 pos
= sParams
.indexOf("YYYY");
430 sParams
= sParams
.replaceFirst("YY", "YYYY");
435 short SwWW8ImplReader::GetTimeDatePara(OUString
& rStr
, sal_uInt32
& rFormat
,
436 sal_uInt16
&rLang
, int nWhichDefault
, bool bHijri
)
439 if (m_pPlcxMan
&& !m_bVer67
)
441 const sal_uInt8
*pResult
= m_pPlcxMan
->HasCharSprm(0x85A);
442 if (pResult
&& *pResult
)
445 RES_CHRATR eLang
= bRTL
? RES_CHRATR_CTL_LANGUAGE
: RES_CHRATR_LANGUAGE
;
446 const SvxLanguageItem
*pLang
= static_cast<const SvxLanguageItem
*>(GetFormatAttr( static_cast< sal_uInt16
>(eLang
)));
447 OSL_ENSURE(pLang
, "impossible");
448 rLang
= pLang
? pLang
->GetValue() : LANGUAGE_ENGLISH_US
;
450 SvNumberFormatter
* pFormatter
= m_rDoc
.GetNumberFormatter();
451 OUString
sParams( FindPara( rStr
, '@', '@' ) );// Date/Time
452 if (sParams
.isEmpty())
454 bool bHasTime
= false;
455 switch (nWhichDefault
)
459 sParams
= GetWordDefaultDateStringAsUS(pFormatter
, rLang
);
460 sParams
+= " HH:MM:SS AM/PM";
463 case ww::eCREATEDATE
:
464 sParams
+= "DD/MM/YYYY HH:MM:SS";
469 sParams
= GetWordDefaultDateStringAsUS(pFormatter
, rLang
);
474 sParams
= "[~hijri]" + sParams
;
476 sal_Int32 nCheckPos
= 0;
477 short nType
= css::util::NumberFormat::DEFINED
;
480 OUString
sTemp(sParams
);
481 pFormatter
->PutandConvertEntry(sTemp
, nCheckPos
, nType
, rFormat
,
482 LANGUAGE_ENGLISH_US
, rLang
);
485 return bHasTime
? css::util::NumberFormat::DATETIME
: css::util::NumberFormat::DATE
;
488 sal_uLong nFormatIdx
=
489 sw::ms::MSDateTimeFormatToSwFormat(sParams
, pFormatter
, rLang
, bHijri
,
491 short nNumFormatType
= css::util::NumberFormat::UNDEFINED
;
493 nNumFormatType
= pFormatter
->GetType(nFormatIdx
);
494 rFormat
= nFormatIdx
;
496 return nNumFormatType
;
501 // Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
502 void SwWW8ImplReader::UpdateFields()
504 m_rDoc
.getIDocumentState().SetUpdateExpFieldStat(true); // JP: neu fuer alles wichtige
505 m_rDoc
.SetInitDBFields(true); // Datenbank-Felder auch
508 sal_uInt16
SwWW8ImplReader::End_Field()
511 WW8PLCFx_FLD
* pF
= m_pPlcxMan
->GetField();
512 OSL_ENSURE(pF
, "WW8PLCFx_FLD - Pointer nicht da");
514 if (!pF
|| !pF
->EndPosIsFieldEnd(nCP
))
517 const SvtFilterOptions
&rOpt
= SvtFilterOptions::Get();
518 bool bUseEnhFields
= rOpt
.IsUseEnhancedFields();
520 OSL_ENSURE(!m_aFieldStack
.empty(), "Empty field stack\n");
521 if (!m_aFieldStack
.empty())
524 only hyperlinks currently need to be handled like this, for the other
525 cases we have inserted a field not an attribute with an unknown end
528 nRet
= m_aFieldStack
.back().mnFieldId
;
532 if (bUseEnhFields
&& m_pPaM
!=nullptr && m_pPaM
->GetPoint()!=nullptr) {
533 SwPosition aEndPos
= *m_pPaM
->GetPoint();
534 SwPaM
aFieldPam( m_aFieldStack
.back().GetPtNode(), m_aFieldStack
.back().GetPtContent(), aEndPos
.nNode
, aEndPos
.nContent
.GetIndex());
535 IDocumentMarkAccess
* pMarksAccess
= m_rDoc
.getIDocumentMarkAccess( );
536 IFieldmark
*pFieldmark
= dynamic_cast<IFieldmark
*>( pMarksAccess
->makeFieldBookmark(
537 aFieldPam
, m_aFieldStack
.back().GetBookmarkName(), ODF_FORMTEXT
) );
538 OSL_ENSURE(pFieldmark
!=nullptr, "hmmm; why was the bookmark not created?");
539 if (pFieldmark
!=nullptr) {
540 const IFieldmark::parameter_map_t
& rParametersToAdd
= m_aFieldStack
.back().getParameters();
541 pFieldmark
->GetParameters()->insert(rParametersToAdd
.begin(), rParametersToAdd
.end());
545 // Doing corresponding status management for TOX field, index field, hyperlink field and page reference field
548 if (m_bLoadingTOXCache
)
550 if (m_nEmbeddedTOXLevel
> 0)
553 --m_nEmbeddedTOXLevel
;
557 m_aTOXEndCps
.insert(nCP
);
558 m_bLoadingTOXCache
= false;
559 if ( m_pPaM
->End() &&
560 m_pPaM
->End()->nNode
.GetNode().GetTextNode() &&
561 m_pPaM
->End()->nNode
.GetNode().GetTextNode()->Len() == 0 )
567 m_bCareLastParaEndInToc
= true;
572 *m_pPaM
= *m_pPosAfterTOC
;
573 m_pPosAfterTOC
.reset();
579 if (m_bLoadingTOXCache
&& !m_bLoadingTOXHyperlink
)
581 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(),RES_TXTATR_INETFMT
);
585 if (m_bLoadingTOXHyperlink
)
586 m_bLoadingTOXHyperlink
= false;
587 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), RES_TXTATR_INETFMT
);
591 //Move outside the section associated with this type of field
592 *m_pPaM
->GetPoint() = m_aFieldStack
.back().maStartPos
;
595 OUString aCode
= m_aFieldStack
.back().GetBookmarkCode();
596 if ( !aCode
.isEmpty() )
598 // Unhandled field with stored code
599 SwPosition aEndPos
= *m_pPaM
->GetPoint();
601 m_aFieldStack
.back().GetPtNode(), m_aFieldStack
.back().GetPtContent(),
602 aEndPos
.nNode
, aEndPos
.nContent
.GetIndex());
604 IDocumentMarkAccess
* pMarksAccess
= m_rDoc
.getIDocumentMarkAccess( );
606 IFieldmark
* pFieldmark
= pMarksAccess
->makeFieldBookmark(
608 m_aFieldStack
.back().GetBookmarkName(),
612 // adapt redline positions to inserted field mark start
613 // dummy char (assume not necessary for end dummy char)
614 m_pRedlineStack
->MoveAttrs(*aFieldPam
.Start());
615 const IFieldmark::parameter_map_t
& rParametersToAdd
= m_aFieldStack
.back().getParameters();
616 pFieldmark
->GetParameters()->insert(rParametersToAdd
.begin(), rParametersToAdd
.end());
617 OUString sFieldId
= OUString::number( m_aFieldStack
.back().mnFieldId
);
618 pFieldmark
->GetParameters()->insert(
619 std::pair
< OUString
, uno::Any
> (
621 uno::makeAny( sFieldId
) ) );
622 pFieldmark
->GetParameters()->insert(
623 std::pair
< OUString
, uno::Any
> (
625 uno::makeAny( aCode
) ) );
627 if ( m_aFieldStack
.back().mnObjLocFc
> 0 )
629 // Store the OLE object as an internal link
630 OUString
sOleId('_');
631 sOleId
+= OUString::number( m_aFieldStack
.back().mnObjLocFc
);
633 tools::SvRef
<SotStorage
> xSrc0
= m_pStg
->OpenSotStorage(OUString(SL::aObjectPool
));
634 tools::SvRef
<SotStorage
> xSrc1
= xSrc0
->OpenSotStorage( sOleId
, StreamMode::READ
);
637 uno::Reference
< embed::XStorage
> xDocStg
= GetDoc().GetDocStorage();
640 uno::Reference
< embed::XStorage
> xOleStg
= xDocStg
->openStorageElement(
641 "OLELinks", embed::ElementModes::WRITE
);
642 tools::SvRef
<SotStorage
> xObjDst
= SotStorage::OpenOLEStorage( xOleStg
, sOleId
);
646 xSrc1
->CopyTo( xObjDst
.get() );
648 if ( !xObjDst
->GetError() )
652 uno::Reference
< embed::XTransactedObject
> xTransact( xOleStg
, uno::UNO_QUERY
);
653 if ( xTransact
.is() )
657 // Store the OLE Id as a parameter
658 pFieldmark
->GetParameters()->insert(
659 std::pair
< OUString
, uno::Any
>(
660 ODF_OLE_PARAM
, uno::makeAny( OUString( sOleId
) ) ) );
667 m_aFieldStack
.pop_back();
672 bool AcceptableNestedField(sal_uInt16 nFieldCode
)
676 case 8: // allow recursive field in TOC...
677 case 13: // allow recursive field in TOC...
682 // Accept AutoTextList field as nested field.
683 // Thus, the field result is imported as plain text.
691 WW8FieldEntry::WW8FieldEntry(SwPosition
&rPos
, sal_uInt16 nFieldId
) throw()
692 : maStartPos(rPos
), mnFieldId(nFieldId
), mnObjLocFc(0)
696 WW8FieldEntry::WW8FieldEntry(const WW8FieldEntry
&rOther
) throw()
697 : maStartPos(rOther
.maStartPos
), mnFieldId(rOther
.mnFieldId
), mnObjLocFc(rOther
.mnObjLocFc
)
701 void WW8FieldEntry::Swap(WW8FieldEntry
&rOther
) throw()
703 std::swap(maStartPos
, rOther
.maStartPos
);
704 std::swap(mnFieldId
, rOther
.mnFieldId
);
707 WW8FieldEntry
&WW8FieldEntry::operator=(const WW8FieldEntry
&rOther
) throw()
709 WW8FieldEntry
aTemp(rOther
);
715 void WW8FieldEntry::SetBookmarkName(const OUString
& bookmarkName
)
717 msBookmarkName
=bookmarkName
;
720 void WW8FieldEntry::SetBookmarkType(const OUString
& bookmarkType
)
722 msMarkType
=bookmarkType
;
725 void WW8FieldEntry::SetBookmarkCode(const OUString
& bookmarkCode
)
727 msMarkCode
= bookmarkCode
;
731 // Read_Field liest ein Feld ein oder, wenn es nicht gelesen werden kann,
732 // wird 0 zurueckgegeben, so dass das Feld vom Aufrufer textuell gelesen wird.
733 // Returnwert: Gesamtlaenge des Feldes ( zum UEberlesen )
734 long SwWW8ImplReader::Read_Field(WW8PLCFManResult
* pRes
)
736 typedef eF_ResT (SwWW8ImplReader:: *FNReadField
)( WW8FieldDesc
*, OUString
& );
737 enum Limits
{eMax
= 96};
738 static const FNReadField aWW8FieldTab
[eMax
+1] =
741 &SwWW8ImplReader::Read_F_Input
,
743 &SwWW8ImplReader::Read_F_Ref
, // 3
746 &SwWW8ImplReader::Read_F_Set
, // 6
748 &SwWW8ImplReader::Read_F_Tox
, // 8
750 &SwWW8ImplReader::Read_F_Styleref
, // 10
752 &SwWW8ImplReader::Read_F_Seq
, // 12
753 &SwWW8ImplReader::Read_F_Tox
, // 13
754 &SwWW8ImplReader::Read_F_DocInfo
, // 14
755 &SwWW8ImplReader::Read_F_DocInfo
, // 15
756 &SwWW8ImplReader::Read_F_DocInfo
, // 16
757 &SwWW8ImplReader::Read_F_Author
, // 17
758 &SwWW8ImplReader::Read_F_DocInfo
, // 18
759 &SwWW8ImplReader::Read_F_DocInfo
, // 19
760 &SwWW8ImplReader::Read_F_DocInfo
, // 20
761 &SwWW8ImplReader::Read_F_DocInfo
, // 21
762 &SwWW8ImplReader::Read_F_DocInfo
, // 22
763 &SwWW8ImplReader::Read_F_DocInfo
, // 23
764 &SwWW8ImplReader::Read_F_DocInfo
, // 24
765 &SwWW8ImplReader::Read_F_DocInfo
, // 25
766 &SwWW8ImplReader::Read_F_Num
, // 26
767 &SwWW8ImplReader::Read_F_Num
, // 27
768 &SwWW8ImplReader::Read_F_Num
, // 28
769 &SwWW8ImplReader::Read_F_FileName
, // 29
770 &SwWW8ImplReader::Read_F_TemplName
, // 30
771 &SwWW8ImplReader::Read_F_DateTime
, // 31
772 &SwWW8ImplReader::Read_F_DateTime
, // 32
773 &SwWW8ImplReader::Read_F_CurPage
, // 33
776 &SwWW8ImplReader::Read_F_IncludeText
, // 36
777 &SwWW8ImplReader::Read_F_PgRef
, // 37
778 &SwWW8ImplReader::Read_F_InputVar
, // 38
779 &SwWW8ImplReader::Read_F_Input
, // 39
781 &SwWW8ImplReader::Read_F_DBNext
, // 41
784 &SwWW8ImplReader::Read_F_DBNum
, // 44
789 &SwWW8ImplReader::Read_F_Equation
, // 49
791 &SwWW8ImplReader::Read_F_Macro
, // 51
792 &SwWW8ImplReader::Read_F_ANumber
, // 52
793 &SwWW8ImplReader::Read_F_ANumber
, // 53
794 &SwWW8ImplReader::Read_F_ANumber
, // 54
799 &SwWW8ImplReader::Read_F_Symbol
, // 57
800 &SwWW8ImplReader::Read_F_Embedd
, // 58
801 &SwWW8ImplReader::Read_F_DBField
, // 59
806 &SwWW8ImplReader::Read_F_DocInfo
, // 64 - DOCVARIABLE
809 &SwWW8ImplReader::Read_F_IncludePicture
, // 67
810 &SwWW8ImplReader::Read_F_IncludeText
, // 68
812 &SwWW8ImplReader::Read_F_FormTextBox
, // 70
813 &SwWW8ImplReader::Read_F_FormCheckBox
, // 71
814 &SwWW8ImplReader::Read_F_NoteReference
, // 72
815 nullptr, /*&SwWW8ImplReader::Read_F_Tox*/
825 &SwWW8ImplReader::Read_F_FormListBox
, // 83
827 &SwWW8ImplReader::Read_F_DocInfo
, // 85
829 &SwWW8ImplReader::Read_F_OCX
, // 87
830 &SwWW8ImplReader::Read_F_Hyperlink
, // 88
833 &SwWW8ImplReader::Read_F_HTMLControl
, // 91
837 &SwWW8ImplReader::Read_F_Shape
, // 95
838 nullptr // eMax - Dummy leer Methode
840 OSL_ENSURE( ( sizeof( aWW8FieldTab
) / sizeof( *aWW8FieldTab
) == eMax
+1 ),
841 "FeldFunc-Tabelle stimmt nicht" );
843 WW8PLCFx_FLD
* pF
= m_pPlcxMan
->GetField();
844 OSL_ENSURE(pF
, "WW8PLCFx_FLD - Pointer nicht da");
846 if (!pF
|| !pF
->StartPosIsFieldStart())
849 bool bNested
= false;
850 if (!m_aFieldStack
.empty())
852 mycFieldIter aEnd
= m_aFieldStack
.end();
853 for(mycFieldIter aIter
= m_aFieldStack
.begin(); aIter
!= aEnd
; ++aIter
)
855 bNested
= !AcceptableNestedField(aIter
->mnFieldId
);
862 bool bOk
= pF
->GetPara(pRes
->nCp2OrIdx
, aF
);
864 OSL_ENSURE(bOk
, "WW8: Bad Field!\n");
865 if (aF
.nId
== 33) aF
.bCodeNest
=false; // do not recurse into nested page fields
866 bool bCodeNest
= aF
.bCodeNest
;
867 if ( aF
.nId
== 6 ) bCodeNest
= false; // We can handle them and lose the inner data
869 m_aFieldStack
.push_back(WW8FieldEntry(*m_pPaM
->GetPoint(), aF
.nId
));
874 sal_uInt16 n
= (aF
.nId
<= eMax
) ? aF
.nId
: static_cast<sal_uInt16
>(eMax
);
875 sal_uInt16 nI
= n
/ 32; // # des sal_uInt32
876 sal_uInt32 nMask
= 1 << ( n
% 32 ); // Maske fuer Bits
878 if (SAL_N_ELEMENTS(m_nFieldTagAlways
) <= nI
)
879 { // if indexes larger than 95 are needed, then a new configuration
880 // item has to be added, and nFieldTagAlways/nFieldTagBad expanded!
884 if( m_nFieldTagAlways
[nI
] & nMask
) // Flag: Tag it
885 return Read_F_Tag( &aF
); // Resultat nicht als Text
887 if( !bOk
|| !aF
.nId
) // Feld kaputt
888 return aF
.nLen
; // -> ignorieren
890 if( aF
.nId
> eMax
- 1) // WW: Nested Field
892 if( m_nFieldTagBad
[nI
] & nMask
) // Flag: Tag it when bad
893 return Read_F_Tag( &aF
); // Resultat nicht als Text
898 //Only one type of field (hyperlink) in drawing textboxes exists
899 if (aF
.nId
!= 88 && m_pPlcxMan
->GetDoingDrawTextBox())
902 bool bHasHandler
= aWW8FieldTab
[aF
.nId
] != nullptr;
903 if (aF
.nId
== 10) // STYLEREF
905 // STYLEREF, by default these are not handled.
907 sal_uInt64 nOldPos
= m_pStrm
->Tell();
909 aF
.nLCode
= m_pSBase
->WW8ReadString(*m_pStrm
, aStr
, m_pPlcxMan
->GetCpOfs() + aF
.nSCode
, aF
.nLCode
, m_eTextCharSet
);
910 m_pStrm
->Seek(nOldPos
);
912 WW8ReadFieldParams
aReadParam(aStr
);
913 sal_Int32 nRet
= aReadParam
.SkipToNextToken();
914 if (nRet
== -2 && !aReadParam
.GetResult().isEmpty())
915 // Single numeric argument: this can be handled by SwChapterField.
916 bHasHandler
= rtl::isAsciiDigit(aReadParam
.GetResult()[0]);
920 nRet
= aReadParam
.SkipToNextToken();
921 // Handle using SwChapterField only in case there is no \[a-z]
922 // switch after the field argument.
923 bHasHandler
= nRet
< 0 || nRet
== '*';
927 // keine Routine vorhanden
928 if (bNested
|| !bHasHandler
|| bCodeNest
)
930 if( m_nFieldTagBad
[nI
] & nMask
) // Flag: Tag it when bad
931 return Read_F_Tag( &aF
); // Resultat nicht als Text
933 if (aF
.bResNest
&& !AcceptableNestedField(aF
.nId
))
934 return aF
.nLen
; // Result nested -> nicht brauchbar
936 long nOldPos
= m_pStrm
->Tell();
938 aF
.nLCode
= m_pSBase
->WW8ReadString( *m_pStrm
, aStr
, m_pPlcxMan
->GetCpOfs()+
939 aF
.nSCode
, aF
.nLCode
, m_eTextCharSet
);
940 m_pStrm
->Seek( nOldPos
);
942 // field codes which contain '/' or '.' are not displayed in WinWord
943 // skip if it is formula field or found space before. see #i119446, #i119585.
944 const sal_Int32 nDotPos
= aStr
.indexOf('.');
945 const sal_Int32 nSlashPos
= aStr
.indexOf('/');
946 sal_Int32 nSpacePos
= aStr
.indexOf( ' ', 1 );
948 nSpacePos
= aStr
.getLength();
950 if ( !( aStr
.getLength()>1 && aStr
[1]=='=') &&
951 (( nDotPos
>=0 && nDotPos
< nSpacePos
) ||
952 ( nSlashPos
>=0 && nSlashPos
< nSpacePos
)))
956 // Link fields aren't supported, but they are bound to an OLE object
957 // that needs to be roundtripped
960 // Field not supported: store the field code for later use
961 m_aFieldStack
.back().SetBookmarkCode( aStr
);
962 return aF
.nLen
- aF
.nLRes
- 1; // so viele ueberlesen, das Resultfeld
963 // wird wie Haupttext eingelesen
968 long nOldPos
= m_pStrm
->Tell();
970 if ( aF
.nId
== 6 && aF
.bCodeNest
)
972 // TODO Extract the whole code string using the nested codes
973 aF
.nLCode
= m_pSBase
->WW8ReadString( *m_pStrm
, aStr
, m_pPlcxMan
->GetCpOfs() +
974 aF
.nSCode
, aF
.nSRes
- aF
.nSCode
- 1, m_eTextCharSet
);
978 aF
.nLCode
= m_pSBase
->WW8ReadString( *m_pStrm
, aStr
, m_pPlcxMan
->GetCpOfs()+
979 aF
.nSCode
, aF
.nLCode
, m_eTextCharSet
);
982 // #i51312# - graphics inside field code not supported by Writer.
983 // Thus, delete character 0x01, which stands for such a graphic.
984 if (aF
.nId
==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
986 aStr
= aStr
.replaceAll("\x01", "");
989 eF_ResT eRes
= (this->*aWW8FieldTab
[aF
.nId
])( &aF
, aStr
);
990 m_pStrm
->Seek( nOldPos
);
995 return aF
.nLen
; // alles OK
997 if ((m_nFieldTagBad
[nI
] & nMask
)) // Flag: Tag bad
998 return Read_F_Tag(&aF
); // Taggen
1001 // so viele ueberlesen, das Resultfeld wird wie Haupttext
1003 // attributes can start at char 0x14 so skip one
1004 // char more back == "-2"
1006 return aF
.nLen
- aF
.nLRes
- 2;
1010 if( ( m_nFieldTagBad
[nI
] & nMask
) ) // Flag: Tag bad
1011 return Read_F_Tag( &aF
); // Taggen
1012 return aF
.nLen
; // oder ignorieren
1014 return aF
.nLen
- aF
.nLRes
- 2; // auf Char 1 positionieren
1016 return aF
.nLen
; // ignorieren
1023 // MakeTagString() gibt als Returnwert die Position des ersten
1024 // CR / Zeilenende / Seitenumbruch in pText und wandelt auch nur bis dort
1025 // Wenn keins dieser Sonderzeichen enthalten ist, wird 0 zurueckgeliefert.
1026 void SwWW8ImplReader::MakeTagString( OUString
& rStr
, const OUString
& rOrg
)
1028 OUString
sHex("\\x");
1029 bool bAllowCr
= SwFltGetFlag( m_nFieldFlags
, SwFltControlStack::TAGS_IN_TEXT
)
1030 || SwFltGetFlag( m_nFieldFlags
, SwFltControlStack::ALLOW_FLD_CR
);
1034 for( sal_Int32 nI
= 0;
1035 nI
< rStr
.getLength() && rStr
.getLength() < (MAX_FIELDLEN
- 4); ++nI
)
1037 bool bSetAsHex
= false;
1038 switch( cChar
= rStr
[ nI
] )
1040 case 132: // Typographische Anfuehrungszeichen
1041 case 148: // gegen normale tauschen
1043 rStr
= rStr
.replaceAt( nI
, 1, "\"" );
1046 rStr
= rStr
.replaceAt( nI
, 1, "{" );
1047 break; // 19..21 zu {|}
1049 rStr
= rStr
.replaceAt( nI
, 1, "|" );
1052 rStr
= rStr
.replaceAt( nI
, 1, "}" );
1054 case '\\': // \{|} per \ Taggen
1058 rStr
= rStr
.replaceAt( nI
, 0, "\\" );
1065 rStr
= rStr
.replaceAt( nI
, 1, "\n" );
1074 bSetAsHex
= 0x20 > cChar
;
1080 //all Hex-Numbers with \x before
1081 OUString
sTmp( sHex
);
1084 sTmp
+= OUString::number( cChar
, 16 );
1085 rStr
= rStr
.replaceAt( nI
, 1 , sTmp
);
1086 nI
+= sTmp
.getLength() - 1;
1090 if( rStr
.getLength() > (MAX_FIELDLEN
- 4))
1091 rStr
= rStr
.copy( 0, MAX_FIELDLEN
- 4 );
1094 void SwWW8ImplReader::InsertTagField( const sal_uInt16 nId
, const OUString
& rTagText
)
1096 OUString
aName("WwFieldTag");
1097 if( SwFltGetFlag( m_nFieldFlags
, SwFltControlStack::TAGS_DO_ID
) ) // Nummer?
1098 aName
+= OUString::number( nId
); // ausgeben ?
1100 if( SwFltGetFlag(m_nFieldFlags
, SwFltControlStack::TAGS_IN_TEXT
))
1102 aName
+= rTagText
; // als Text taggen
1103 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, aName
,
1104 SwInsertFlags::NOHINTEXPAND
);
1109 SwFieldType
* pFT
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType(
1110 SwSetExpFieldType( &m_rDoc
, aName
, nsSwGetSetExpType::GSE_STRING
) );
1111 SwSetExpField
aField( static_cast<SwSetExpFieldType
*>(pFT
), rTagText
); // SUB_INVISIBLE
1112 sal_uInt16 nSubType
= ( SwFltGetFlag( m_nFieldFlags
, SwFltControlStack::TAGS_VISIBLE
) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE
;
1113 aField
.SetSubType(nSubType
| nsSwGetSetExpType::GSE_STRING
);
1115 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1119 long SwWW8ImplReader::Read_F_Tag( WW8FieldDesc
* pF
)
1121 long nOldPos
= m_pStrm
->Tell();
1123 WW8_CP nStart
= pF
->nSCode
- 1; // mit 0x19 am Anfang
1124 long nL
= pF
->nLen
; // Gesamtlaenge mit Resultat u. Nest
1125 if( nL
> MAX_FIELDLEN
)
1126 nL
= MAX_FIELDLEN
; // MaxLaenge, durch Quoten
1129 m_pSBase
->WW8ReadString( *m_pStrm
, sFText
,
1130 m_pPlcxMan
->GetCpOfs() + nStart
, nL
, m_eStructCharSet
);
1133 MakeTagString( aTagText
, sFText
);
1134 InsertTagField( pF
->nId
, aTagText
);
1136 m_pStrm
->Seek( nOldPos
);
1142 eF_ResT
SwWW8ImplReader::Read_F_Input( WW8FieldDesc
* pF
, OUString
& rStr
)
1146 WW8ReadFieldParams
aReadParam( rStr
);
1149 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1156 aQ
= aReadParam
.GetResult();
1160 if ( aReadParam
.GoToTokenParam() )
1161 aDef
= aReadParam
.GetResult();
1165 if( aDef
.isEmpty() )
1166 aDef
= GetFieldResult( pF
);
1168 if ( pF
->nId
!= 0x01 ) // 0x01 fields have no result
1170 SwInputField
aField( static_cast<SwInputFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_INPUTFLD
)),
1171 aDef
, aQ
, INP_TXT
, 0, false );
1172 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1178 // GetFieldResult alloziert einen String und liest das Feld-Resultat ein
1179 OUString
SwWW8ImplReader::GetFieldResult( WW8FieldDesc
* pF
)
1181 long nOldPos
= m_pStrm
->Tell();
1183 WW8_CP nStart
= pF
->nSRes
; // result start
1184 long nL
= pF
->nLRes
; // result length
1186 return OUString(); // no result
1188 if( nL
> MAX_FIELDLEN
)
1189 nL
= MAX_FIELDLEN
; // MaxLength, by quoting
1193 m_pSBase
->WW8ReadString( *m_pStrm
, sRes
, m_pPlcxMan
->GetCpOfs() + nStart
,
1194 nL
, m_eStructCharSet
);
1196 m_pStrm
->Seek( nOldPos
);
1198 //replace both CR 0x0D and VT 0x0B with LF 0x0A
1199 return sRes
.replace(0x0D, 0x0A).replace(0x0B, 0x0A);
1203 Bookmarks can be set with fields SET and ASK, and they can be referenced with
1204 REF. When set, they behave like variables in writer, otherwise they behave
1205 like normal bookmarks. We can check whether we should use a show variable
1206 instead of a normal bookmark ref by converting to "show variable" at the end
1207 of the document those refs which look for the content of a bookmark but whose
1208 bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
1210 The other piece of the puzzle is that refs that point to the "location" of the
1211 bookmark will in word actually point to the last location where the bookmark
1212 was set with SET or ASK, not the actual bookmark. This is only noticeable when
1213 a document sets the bookmark more than once. This is because word places the
1214 true bookmark at the location of the last set, but the refs will display the
1215 position of the first set before the ref.
1217 So what we will do is
1219 1) keep a list of all bookmarks that were set, any bookmark names mentioned
1220 here that are referred by content will be converted to show variables.
1222 2) create pseudo bookmarks for every position that a bookmark is set with SET
1223 or ASK but has no existing bookmark. We can then keep a map from the original
1224 bookmark name to the new one. As we parse the document new pseudo names will
1225 replace the older ones, so the map always contains the bookmark of the
1226 location that msword itself would use.
1228 3) word's bookmarks are case insensitive, writers are not. So we need to
1229 map case different versions together, regardless of whether they are
1232 4) when a reference is (first) SET or ASK, the bookmark associated with it
1233 is placed around the 0x14 0x15 result part of the field. We will fiddle
1234 the placement to be the writer equivalent of directly before and after
1235 the field, which gives the same effect and meaning, to do so we must
1236 get any bookmarks in the field range, and begin them immediately before
1237 the set/ask field, and end them directly afterwards. MapBookmarkVariables
1238 returns an identifier of the bookmark attribute to close after inserting
1239 the appropriate set/ask field.
1241 long SwWW8ImplReader::MapBookmarkVariables(const WW8FieldDesc
* pF
,
1242 OUString
&rOrigName
, const OUString
&rData
)
1244 OSL_ENSURE(m_pPlcxMan
,"No pPlcxMan");
1247 If there was no bookmark associated with this set field, then we create a
1248 pseudo one and insert it in the document.
1251 m_pPlcxMan
->GetBook()->MapName(rOrigName
);
1252 OUString sName
= m_pPlcxMan
->GetBook()->GetBookmark(
1253 pF
->nSCode
, pF
->nSCode
+ pF
->nLen
, nIndex
);
1254 if (!sName
.isEmpty())
1256 m_pPlcxMan
->GetBook()->SetStatus(nIndex
, BOOK_IGNORE
);
1261 nNo
= m_pReffingStck
->aFieldVarNames
.size()+1;
1262 sName
= "WWSetBkmk" + OUString::number(nNo
);
1263 nNo
+= m_pPlcxMan
->GetBook()->GetIMax();
1265 m_pReffedStck
->NewAttr(*m_pPaM
->GetPoint(),
1266 SwFltBookmark( BookmarkToWriter(sName
), rData
, nNo
));
1267 m_pReffingStck
->aFieldVarNames
[rOrigName
] = sName
;
1272 Word can set a bookmark with set or with ask, such a bookmark is equivalent to
1273 our variables, but until the end of a document we cannot be sure if a bookmark
1274 is a variable or not, at the end we will have a list of reference names which
1275 were set or asked, all bookmarks using the content of those bookmarks are
1276 converted to show variables, those that reference the position of the field
1277 can be left as references, because a bookmark is also inserted at the position
1278 of a set or ask field, either by word, or in some special cases by the import
1281 SwFltStackEntry
*SwWW8FltRefStack::RefToVar(const SwField
* pField
,
1282 SwFltStackEntry
&rEntry
)
1284 SwFltStackEntry
*pRet
=nullptr;
1285 if (pField
&& RES_GETREFFLD
== pField
->Which())
1287 //Get the name of the ref field, and see if actually a variable
1288 const OUString sName
= pField
->GetPar1();
1289 std::map
<OUString
, OUString
, SwWW8::ltstr
>::const_iterator
1290 aResult
= aFieldVarNames
.find(sName
);
1292 if (aResult
!= aFieldVarNames
.end())
1294 SwGetExpField
aField( static_cast<SwGetExpFieldType
*>(
1295 pDoc
->getIDocumentFieldsAccess().GetSysFieldType(RES_GETEXPFLD
)), sName
, nsSwGetSetExpType::GSE_STRING
, 0);
1296 delete rEntry
.pAttr
;
1297 SwFormatField
aTmp(aField
);
1298 rEntry
.pAttr
= aTmp
.Clone();
1305 OUString
SwWW8ImplReader::GetMappedBookmark(const OUString
&rOrigName
)
1307 OUString
sName(BookmarkToWriter(rOrigName
));
1308 OSL_ENSURE(m_pPlcxMan
,"no pPlcxMan");
1309 m_pPlcxMan
->GetBook()->MapName(sName
);
1311 //See if there has been a variable set with this name, if so get
1312 //the pseudo bookmark name that was set with it.
1313 std::map
<OUString
, OUString
, SwWW8::ltstr
>::const_iterator aResult
=
1314 m_pReffingStck
->aFieldVarNames
.find(sName
);
1316 return (aResult
== m_pReffingStck
->aFieldVarNames
.end())
1317 ? sName
: (*aResult
).second
;
1321 eF_ResT
SwWW8ImplReader::Read_F_InputVar( WW8FieldDesc
* pF
, OUString
& rStr
)
1323 OUString sOrigName
, aQ
;
1325 WW8ReadFieldParams
aReadParam( rStr
);
1328 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1334 if (sOrigName
.isEmpty())
1335 sOrigName
= aReadParam
.GetResult();
1336 else if (aQ
.isEmpty())
1337 aQ
= aReadParam
.GetResult();
1341 if ( aReadParam
.GoToTokenParam() )
1342 aDef
= aReadParam
.GetResult();
1347 if (sOrigName
.isEmpty())
1348 return FLD_TAGIGN
; // macht ohne Textmarke keinen Sinn
1350 const OUString
aResult(GetFieldResult(pF
));
1352 //#i24377#, munge Default Text into title as we have only one slot
1353 //available for aResult and aDef otherwise
1354 if (!aDef
.isEmpty())
1361 const long nNo
= MapBookmarkVariables(pF
, sOrigName
, aResult
);
1363 SwSetExpFieldType
* pFT
= static_cast<SwSetExpFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().InsertFieldType(
1364 SwSetExpFieldType(&m_rDoc
, sOrigName
, nsSwGetSetExpType::GSE_STRING
)));
1365 SwSetExpField
aField(pFT
, aResult
);
1366 aField
.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE
| nsSwGetSetExpType::GSE_STRING
);
1367 aField
.SetInputFlag(true);
1368 aField
.SetPromptText( aQ
);
1370 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1372 m_pReffedStck
->SetAttr(*m_pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true, nNo
);
1377 eF_ResT
SwWW8ImplReader::Read_F_ANumber( WW8FieldDesc
*, OUString
& rStr
)
1379 if( !m_pNumFieldType
){ // 1. Mal
1380 SwSetExpFieldType
aT( &m_rDoc
, OUString("AutoNr"), nsSwGetSetExpType::GSE_SEQ
);
1381 m_pNumFieldType
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType( aT
);
1383 SwSetExpField
aField( static_cast<SwSetExpFieldType
*>(m_pNumFieldType
), OUString(),
1384 GetNumberPara( rStr
) );
1385 aField
.SetValue( ++m_nFieldNum
);
1386 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1391 eF_ResT
SwWW8ImplReader::Read_F_Seq( WW8FieldDesc
*, OUString
& rStr
)
1393 OUString aSequenceName
;
1395 bool bHidden
= false;
1396 bool bFormat
= false;
1397 bool bCountOn
= true;
1399 SvxExtNumType eNumFormat
= SVX_NUM_ARABIC
;
1400 WW8ReadFieldParams
aReadParam( rStr
);
1403 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1409 if( aSequenceName
.isEmpty() )
1410 aSequenceName
= aReadParam
.GetResult();
1411 else if( aBook
.isEmpty() )
1412 aBook
= aReadParam
.GetResult();
1417 bHidden
= true; // Hidden-Flag aktivieren
1421 bFormat
= true; // Format-Flag aktivieren
1422 if ( aReadParam
.SkipToNextToken()!=-2 )
1424 if ( aReadParam
.GetResult()!="MERGEFORMAT" && aReadParam
.GetResult()!="CHARFORMAT" )
1425 eNumFormat
= GetNumTypeFromName( aReadParam
.GetResult() );
1430 if ( aReadParam
.SkipToNextToken()==-2 )
1431 sStart
= aReadParam
.GetResult();
1439 bCountOn
= true; // Nummer um eins erhoehen (default)
1442 case 's': // Outline Level
1443 //#i19682, what am I to do with this value
1447 if (aSequenceName
.isEmpty() && aBook
.isEmpty())
1450 SwSetExpFieldType
* pFT
= static_cast<SwSetExpFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().InsertFieldType(
1451 SwSetExpFieldType( &m_rDoc
, aSequenceName
, nsSwGetSetExpType::GSE_SEQ
) ) );
1452 SwSetExpField
aField( pFT
, OUString(), eNumFormat
);
1454 //#i120654# Add bHidden for /h flag (/h: Hide the field result.)
1456 aField
.SetSubType(aField
.GetSubType() | nsSwExtendedSubType::SUB_INVISIBLE
);
1458 if (!sStart
.isEmpty())
1459 aField
.SetFormula( ( aSequenceName
+= "=" ) += sStart
);
1461 aField
.SetFormula(aSequenceName
);
1463 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
1467 eF_ResT
SwWW8ImplReader::Read_F_Styleref(WW8FieldDesc
*, OUString
& rString
)
1469 WW8ReadFieldParams
aReadParam(rString
);
1470 sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1472 // \param was found, not normal text.
1475 OUString aResult
= aReadParam
.GetResult();
1476 sal_Int32 nResult
= aResult
.toInt32();
1480 SwFieldType
* pFieldType
= m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_CHAPTERFLD
);
1481 SwChapterField
aField(static_cast<SwChapterFieldType
*>(pFieldType
), CF_TITLE
);
1482 aField
.SetLevel(nResult
- 1);
1483 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
1488 eF_ResT
SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc
* pF
, OUString
& rStr
)
1491 // RegInfoFormat, DefaultFormat fuer DocInfoFelder
1492 sal_uInt16 nReg
= DI_SUB_AUTHOR
;
1493 bool bDateTime
= false;
1497 OUString aDocProperty
;
1498 WW8ReadFieldParams
aReadParam( rStr
);
1501 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1507 if( aDocProperty
.isEmpty() )
1508 aDocProperty
= aReadParam
.GetResult();
1511 //Skip over MERGEFORMAT
1512 (void)aReadParam
.SkipToNextToken();
1517 aDocProperty
= aDocProperty
.replaceAll("\"", "");
1520 There are up to 26 fields that may be meant by 'DocumentProperty'.
1521 Which of them is to be inserted here ?
1522 This Problem can only be solved by implementing a name matching
1523 method that compares the given Parameter String with the four
1524 possible name sets (english, german, french, spanish)
1527 static const sal_Char
* aName10
= "\x0F"; // SW field code
1528 static const sal_Char
* aName11
// German
1530 static const sal_Char
* aName12
// French
1532 static const sal_Char
* aName13
// English
1534 static const sal_Char
* aName14
// Spanish
1536 static const sal_Char
* aName20
= "\x15"; // SW filed code
1537 static const sal_Char
* aName21
// German
1539 static const sal_Char
* aName22
// French
1541 static const sal_Char
* aName23
// English
1543 static const sal_Char
* aName24
// Spanish
1545 static const sal_Char
* aName30
= "\x16"; // SW filed code
1546 static const sal_Char
* aName31
// German
1547 = "ZULETZTGESPEICHERTZEIT";
1548 static const sal_Char
* aName32
// French
1549 = "DERNIERENREGISTREMENT";
1550 static const sal_Char
* aName33
// English
1552 static const sal_Char
* aName34
// Spanish
1554 static const sal_Char
* aName40
= "\x17"; // SW filed code
1555 static const sal_Char
* aName41
// German
1556 = "ZULETZTGEDRUCKT";
1557 static const sal_Char
* aName42
// French
1558 = "DERNI\xC8" "REIMPRESSION";
1559 static const sal_Char
* aName43
// English
1561 static const sal_Char
* aName44
// Spanish
1563 static const sal_Char
* aName50
= "\x18"; // SW filed code
1564 static const sal_Char
* aName51
// German
1565 = "\xDC" "BERARBEITUNGSNUMMER";
1566 static const sal_Char
* aName52
// French
1567 = "NUM\xC9" "RODEREVISION";
1568 static const sal_Char
* aName53
// English
1570 static const sal_Char
* aName54
// Spanish
1572 static const sal_uInt16 nFieldCnt
= 5;
1574 // additional fields are to be coded soon! :-)
1576 static const sal_uInt16 nLangCnt
= 4;
1577 static const sal_Char
*aNameSet_26
[nFieldCnt
][nLangCnt
+1] =
1579 {aName10
, aName11
, aName12
, aName13
, aName14
},
1580 {aName20
, aName21
, aName22
, aName23
, aName24
},
1581 {aName30
, aName31
, aName32
, aName33
, aName34
},
1582 {aName40
, aName41
, aName42
, aName43
, aName44
},
1583 {aName50
, aName51
, aName52
, aName53
, aName54
}
1586 bool bFieldFound
= false;
1588 for(sal_uInt16 nLIdx
=1; !bFieldFound
&& (nLangCnt
> nLIdx
); ++nLIdx
)
1590 for(nFIdx
= 0; !bFieldFound
&& (nFieldCnt
> nFIdx
); ++nFIdx
)
1592 if( aDocProperty
== OUString( aNameSet_26
[nFIdx
][nLIdx
], strlen(aNameSet_26
[nFIdx
][nLIdx
]),
1593 RTL_TEXTENCODING_MS_1252
) )
1596 pF
->nId
= aNameSet_26
[nFIdx
][0][0];
1603 SwDocInfoField
aField( static_cast<SwDocInfoFieldType
*>(
1604 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_DOCINFOFLD
)), DI_CUSTOM
|nReg
, aDocProperty
, GetFieldResult( pF
) );
1605 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
1614 /* kann alle INFO-Vars!! */
1631 nReg
= DI_SUB_AUTHOR
;
1656 case 64: // DOCVARIABLE
1661 sal_uInt32 nFormat
= 0;
1663 sal_uInt16
nLang(0);
1666 short nDT
= GetTimeDatePara(rStr
, nFormat
, nLang
, pF
->nId
);
1669 case css::util::NumberFormat::DATE
:
1672 case css::util::NumberFormat::TIME
:
1675 case css::util::NumberFormat::DATETIME
:
1685 // Extract DOCVARIABLE varname
1686 if ( 64 == pF
->nId
)
1688 WW8ReadFieldParams
aReadParam( rStr
);
1691 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1697 if( aData
.isEmpty() )
1698 aData
= aReadParam
.GetResult();
1701 //Skip over MERGEFORMAT
1702 (void)aReadParam
.SkipToNextToken();
1707 aData
= aData
.replaceAll("\"", "");
1710 SwDocInfoField
aField( static_cast<SwDocInfoFieldType
*>(
1711 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_DOCINFOFLD
)), nSub
|nReg
, aData
, nFormat
);
1713 ForceFieldLanguage(aField
, nLang
);
1714 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
1719 eF_ResT
SwWW8ImplReader::Read_F_Author( WW8FieldDesc
*, OUString
& )
1721 // SH: Das SwAuthorField bezeichnet nicht den urspruenglichen
1722 // Autor, sondern den aktuellen Benutzer, also besser ueber DocInfo
1723 SwDocInfoField
aField( static_cast<SwDocInfoFieldType
*>(
1724 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_DOCINFOFLD
)),
1725 DI_CREATE
|DI_SUB_AUTHOR
, OUString() );
1726 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1730 eF_ResT
SwWW8ImplReader::Read_F_TemplName( WW8FieldDesc
*, OUString
& )
1732 SwTemplNameField
aField( static_cast<SwTemplNameFieldType
*>(
1733 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_TEMPLNAMEFLD
)), FF_NAME
);
1734 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1738 // Sowohl das Datum- wie auch das Uhrzeit-Feld kann fuer Datum, fuer Uhrzeit
1739 // oder fuer beides benutzt werden.
1740 eF_ResT
SwWW8ImplReader::Read_F_DateTime( WW8FieldDesc
*pF
, OUString
& rStr
)
1742 bool bHijri
= false;
1743 WW8ReadFieldParams
aReadParam(rStr
);
1746 const sal_Int32 nTok
= aReadParam
.SkipToNextToken();
1759 //Saka Calendar, should we do something with this ?
1764 sal_uInt32 nFormat
= 0;
1766 sal_uInt16
nLang(0);
1767 short nDT
= GetTimeDatePara(rStr
, nFormat
, nLang
, ww::eDATE
, bHijri
);
1769 if( css::util::NumberFormat::UNDEFINED
== nDT
) // no D/T-Formatstring
1773 nDT
= css::util::NumberFormat::TIME
;
1774 nFormat
= m_rDoc
.GetNumberFormatter()->GetFormatIndex(
1775 NF_TIME_START
, LANGUAGE_SYSTEM
);
1779 nDT
= css::util::NumberFormat::DATE
;
1780 nFormat
= m_rDoc
.GetNumberFormatter()->GetFormatIndex(
1781 NF_DATE_START
, LANGUAGE_SYSTEM
);
1785 if (nDT
& css::util::NumberFormat::DATE
)
1787 SwDateTimeField
aField(static_cast<SwDateTimeFieldType
*>(
1788 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_DATETIMEFLD
)), DATEFLD
, nFormat
);
1789 ForceFieldLanguage(aField
, nLang
);
1790 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1792 else if (nDT
== css::util::NumberFormat::TIME
)
1794 SwDateTimeField
aField(static_cast<SwDateTimeFieldType
*>(
1795 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_DATETIMEFLD
)), TIMEFLD
, nFormat
);
1796 ForceFieldLanguage(aField
, nLang
);
1797 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1803 eF_ResT
SwWW8ImplReader::Read_F_FileName(WW8FieldDesc
*, OUString
&rStr
)
1805 SwFileNameFormat eType
= FF_NAME
;
1806 WW8ReadFieldParams
aReadParam(rStr
);
1809 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1815 eType
= FF_PATHNAME
;
1818 //Skip over MERGEFORMAT
1819 (void)aReadParam
.SkipToNextToken();
1822 OSL_ENSURE(false, "unknown option in FileName field");
1827 SwFileNameField
aField(
1828 static_cast<SwFileNameFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_FILENAMEFLD
)), eType
);
1829 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
1833 eF_ResT
SwWW8ImplReader::Read_F_Num( WW8FieldDesc
* pF
, OUString
& rStr
)
1835 sal_uInt16 nSub
= DS_PAGE
; // page number
1837 case 27: nSub
= DS_WORD
; break; // number of words
1838 case 28: nSub
= DS_CHAR
; break; // number of characters
1840 SwDocStatField
aField( static_cast<SwDocStatFieldType
*>(
1841 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_DOCSTATFLD
)), nSub
,
1842 GetNumberPara( rStr
) );
1843 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1847 eF_ResT
SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc
*, OUString
& rStr
)
1850 SwPageNumberField
aField( static_cast<SwPageNumberFieldType
*>(
1851 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_PAGENUMBERFLD
)), PG_RANDOM
,
1852 GetNumberPara(rStr
, true));
1854 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1858 eF_ResT
SwWW8ImplReader::Read_F_Symbol( WW8FieldDesc
*, OUString
& rStr
)
1863 sal_Int32 nSize
= 0;
1864 WW8ReadFieldParams
aReadParam( rStr
);
1867 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1874 aQ
= aReadParam
.GetResult();
1878 if ( aReadParam
.GoToTokenParam() )
1879 aName
= aReadParam
.GetResult();
1883 if ( aReadParam
.GoToTokenParam() )
1885 const OUString aSiz
= aReadParam
.GetResult();
1886 if ( !aSiz
.isEmpty() )
1887 nSize
= aSiz
.toInt32() * 20; // pT -> twip
1893 return FLD_TAGIGN
; // -> no 0-char in text
1895 if (sal_Unicode cChar
= static_cast<sal_Unicode
>(aQ
.toInt32()))
1897 if (!aName
.isEmpty()) // Font Name set ?
1899 SvxFontItem
aFont(FAMILY_DONTKNOW
, aName
, OUString(),
1900 PITCH_DONTKNOW
, RTL_TEXTENCODING_SYMBOL
, RES_CHRATR_FONT
);
1901 NewAttr(aFont
); // new Font
1904 if (nSize
> 0) //#i20118#
1906 SvxFontHeightItem
aSz(nSize
, 100, RES_CHRATR_FONTSIZE
);
1910 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, OUString(cChar
));
1913 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), RES_CHRATR_FONTSIZE
);
1914 if (!aName
.isEmpty())
1915 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), RES_CHRATR_FONT
);
1919 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, "###");
1926 eF_ResT
SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc
*, OUString
& rStr
)
1930 WW8ReadFieldParams
aReadParam( rStr
);
1933 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1939 sHost
= aReadParam
.GetResult();
1948 if( m_bObj
&& m_nPicLocFc
)
1949 m_nObjLocFc
= m_nPicLocFc
;
1950 m_bEmbeddObj
= true;
1955 eF_ResT
SwWW8ImplReader::Read_F_Set( WW8FieldDesc
* pF
, OUString
& rStr
)
1959 WW8ReadFieldParams
aReadParam( rStr
);
1962 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
1968 if (sOrigName
.isEmpty())
1969 sOrigName
= aReadParam
.GetResult();
1970 else if (sVal
.isEmpty())
1971 sVal
= aReadParam
.GetResult();
1976 const long nNo
= MapBookmarkVariables(pF
, sOrigName
, sVal
);
1978 SwFieldType
* pFT
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType( SwSetExpFieldType( &m_rDoc
, sOrigName
,
1979 nsSwGetSetExpType::GSE_STRING
) );
1980 SwSetExpField
aField( static_cast<SwSetExpFieldType
*>(pFT
), sVal
, ULONG_MAX
);
1981 aField
.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE
| nsSwGetSetExpType::GSE_STRING
);
1983 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
1985 m_pReffedStck
->SetAttr(*m_pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true, nNo
);
1991 eF_ResT
SwWW8ImplReader::Read_F_Ref( WW8FieldDesc
*, OUString
& rStr
)
1992 { // Reference - Field
1993 OUString sOrigBkmName
;
1994 REFERENCEMARK eFormat
= REF_CONTENT
;
1996 WW8ReadFieldParams
aReadParam( rStr
);
1999 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2005 if( sOrigBkmName
.isEmpty() ) // get name of bookmark
2006 sOrigBkmName
= aReadParam
.GetResult();
2009 /* References to numbers in Word could be either to a numbered
2010 paragraph or to a chapter number. However Word does not seem to
2011 have the capability we do, of referring to the chapter number some
2012 other bookmark is in. As a result, cross-references to chapter
2013 numbers in a word document will be cross-references to a numbered
2014 paragraph, being the chapter heading paragraph. As it happens, our
2015 cross-references to numbered paragraphs will do the right thing
2016 when the target is a numbered chapter heading, so there is no need
2017 for us to use the REF_CHAPTER bookmark format on import.
2020 eFormat
= REF_NUMBER_NO_CONTEXT
;
2023 eFormat
= REF_NUMBER
;
2026 eFormat
= REF_NUMBER_FULL_CONTEXT
;
2030 eFormat
= REF_UPDOWN
;
2035 // unimplemented switch: just do 'nix nought nothing' :-)
2040 OUString
sBkmName(GetMappedBookmark(sOrigBkmName
));
2042 // #i120879# add cross reference bookmark name prefix, if it
2043 // matches internal TOC bookmark naming convention
2044 if ( IsTOCBookmarkName( sBkmName
) )
2046 sBkmName
= EnsureTOCBookmarkName(sBkmName
);
2047 // track <sBookmarkName> as referenced TOC bookmark.
2048 m_pReffedStck
->aReferencedTOCBookmarks
.insert( sBkmName
);
2051 SwGetRefField
aField(
2052 static_cast<SwGetRefFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_GETREFFLD
)),
2053 sBkmName
,REF_BOOKMARK
,0,eFormat
);
2055 if (eFormat
== REF_CONTENT
)
2058 If we are just inserting the contents of the bookmark, then it
2059 is possible that the bookmark is actually a variable, so we
2060 must store it until the end of the document to see if it was,
2061 in which case we'll turn it into a show variable
2063 m_pReffingStck
->NewAttr( *m_pPaM
->GetPoint(), SwFormatField(aField
) );
2064 m_pReffingStck
->SetAttr( *m_pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2068 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
2073 // Note Reference - Field
2074 eF_ResT
SwWW8ImplReader::Read_F_NoteReference( WW8FieldDesc
*, OUString
& rStr
)
2077 bool bAboveBelow
= false;
2079 WW8ReadFieldParams
aReadParam( rStr
);
2082 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2088 if( aBkmName
.isEmpty() ) // get name of foot/endnote
2089 aBkmName
= aReadParam
.GetResult();
2092 // activate flag 'Chapter Number'
2100 // unimplemented switch: just do 'nix nought nothing' :-)
2105 // set Sequence No of corresponding Foot-/Endnote to Zero
2106 // (will be corrected in
2107 SwGetRefField
aField( static_cast<SwGetRefFieldType
*>(
2108 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_GETREFFLD
)), aBkmName
, REF_FOOTNOTE
, 0,
2110 m_pReffingStck
->NewAttr(*m_pPaM
->GetPoint(), SwFormatField(aField
));
2111 m_pReffingStck
->SetAttr(*m_pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2114 SwGetRefField
aField2( static_cast<SwGetRefFieldType
*>(
2115 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_GETREFFLD
)),aBkmName
, REF_FOOTNOTE
, 0,
2117 m_pReffingStck
->NewAttr(*m_pPaM
->GetPoint(), SwFormatField(aField2
));
2118 m_pReffingStck
->SetAttr(*m_pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2124 eF_ResT
SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc
*, OUString
& rStr
)
2127 WW8ReadFieldParams
aReadParam( rStr
);
2130 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2133 else if ( nRet
== -2 && sOrigName
.isEmpty() )
2135 sOrigName
= aReadParam
.GetResult();
2139 const OUString
sName(GetMappedBookmark(sOrigName
));
2141 // loading page reference field in TOX
2142 if (m_bLoadingTOXCache
)
2144 // insert page ref representation as plain text --> return FLD_TEXT
2145 // if there is no hyperlink settings for current toc and referenced bookmark is available,
2146 // assign link to current ref area
2147 if (!m_bLoadingTOXHyperlink
&& !sName
.isEmpty())
2149 // #i120879# add cross reference bookmark name prefix, if it
2150 // matches internal TOC bookmark naming convention
2151 OUString sBookmarkName
;
2152 if ( IsTOCBookmarkName( sName
) )
2154 sBookmarkName
= EnsureTOCBookmarkName(sName
);
2155 // track <sBookmarkName> as referenced TOC bookmark.
2156 m_pReffedStck
->aReferencedTOCBookmarks
.insert( sBookmarkName
);
2160 sBookmarkName
= sName
;
2162 OUString sURL
= "#" + sBookmarkName
;
2163 const OUString sTarget
;
2164 SwFormatINetFormat
aURL( sURL
, sTarget
);
2165 const OUString
sLinkStyle("Index Link");
2166 const sal_uInt16 nPoolId
=
2167 SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle
, SwGetPoolIdFromName::ChrFmt
);
2168 aURL
.SetVisitedFormatAndId( sLinkStyle
, nPoolId
);
2169 aURL
.SetINetFormatAndId( sLinkStyle
, nPoolId
);
2170 m_pCtrlStck
->NewAttr( *m_pPaM
->GetPoint(), aURL
);
2175 // #i120879# add cross reference bookmark name prefix, if it matches
2176 // internal TOC bookmark naming convention
2177 OUString sPageRefBookmarkName
;
2178 if ( IsTOCBookmarkName( sName
) )
2180 sPageRefBookmarkName
= EnsureTOCBookmarkName(sName
);
2181 // track <sPageRefBookmarkName> as referenced TOC bookmark.
2182 m_pReffedStck
->aReferencedTOCBookmarks
.insert( sPageRefBookmarkName
);
2186 sPageRefBookmarkName
= sName
;
2188 SwGetRefField
aField( static_cast<SwGetRefFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_GETREFFLD
)),
2189 sPageRefBookmarkName
, REF_BOOKMARK
, 0, REF_PAGE
);
2190 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
2196 //For MS MacroButton field, the symbol in plain text is always "(" (0x28),
2197 //which should be mapped according to the macro type
2198 bool ConvertMacroSymbol( const OUString
& rName
, OUString
& rReference
)
2200 bool bConverted
= false;
2201 if( rReference
== "(" )
2204 sal_Unicode cSymbol
= sal_Unicode(); // silence false warning
2205 if (rName
== "CheckIt")
2207 else if (rName
== "UncheckIt")
2209 else if (rName
== "ShowExample")
2216 rReference
= OUString(cSymbol
);
2221 // "MACROSCHALTFL"ACHE"
2222 eF_ResT
SwWW8ImplReader::Read_F_Macro( WW8FieldDesc
*, OUString
& rStr
)
2226 bool bNewVText
= true;
2227 bool bBracket
= false;
2228 WW8ReadFieldParams
aReadParam( rStr
);
2230 sal_Int32 nOffset
= 0;
2234 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2240 if( aName
.isEmpty() )
2241 aName
= aReadParam
.GetResult();
2242 else if( aVText
.isEmpty() || bBracket
)
2244 nOffset
= aReadParam
.GetTokenSttPtr() + 1;
2248 aVText
+= aReadParam
.GetResult();
2251 bBracket
= (aVText
[0] == '[');
2254 else if( aVText
.endsWith("]") )
2260 if( aName
.isEmpty() )
2261 return FLD_TAGIGN
; // makes no sense without Makro-Name
2263 //try converting macro symbol according to macro name
2264 bool bApplyWingdings
= ConvertMacroSymbol( aName
, aVText
);
2265 aName
= "StarOffice.Standard.Modul1." + aName
;
2267 SwMacroField
aField( static_cast<SwMacroFieldType
*>(
2268 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_MACROFLD
)), aName
, aVText
);
2270 if( !bApplyWingdings
)
2273 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
2274 WW8_CP nOldCp
= m_pPlcxMan
->Where();
2275 WW8_CP nCp
= nOldCp
+ nOffset
;
2277 SwPaM
aPaM(*m_pPaM
, m_pPaM
);
2279 aPaM
.Move(fnMoveBackward
);
2282 m_pPostProcessAttrsInfo
= new WW8PostProcessAttrsInfo(nCp
, nCp
, aPaM
);
2286 //set Wingdings font
2288 for ( ; i
< m_pFonts
->GetMax(); i
++ )
2293 rtl_TextEncoding eSrcCharSet
;
2294 if( GetFontParams( i
, eFamily
, aFontName
, ePitch
, eSrcCharSet
)
2295 && aFontName
=="Wingdings" )
2301 if ( i
< m_pFonts
->GetMax() )
2304 SetNewFontAttr( i
, true, RES_CHRATR_FONT
);
2305 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
2306 m_pCtrlStck
->SetAttr( *m_pPaM
->GetPoint(), RES_CHRATR_FONT
);
2314 WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart
, WW8_CP nCpEnd
,
2317 , mnCpStart(nCpStart
)
2319 , mPaM(*rPaM
.GetMark(), *rPaM
.GetPoint())
2320 , mItemSet(rPaM
.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_END
- 1)
2324 bool CanUseRemoteLink(const OUString
&rGrfName
)
2326 bool bUseRemote
= false;
2329 // Related: tdf#102499, add a default css::ucb::XCommandEnvironment
2330 // in order to have https protocol manage certificates correctly
2331 uno::Reference
< task::XInteractionHandler
> xIH(
2332 task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr));
2334 uno::Reference
< ucb::XProgressHandler
> xProgress
;
2335 ::ucbhelper::CommandEnvironment
* pCommandEnv
=
2336 new ::ucbhelper::CommandEnvironment(new comphelper::SimpleFileAccessInteraction( xIH
), xProgress
);
2338 ::ucbhelper::Content
aCnt(rGrfName
,
2339 static_cast< ucb::XCommandEnvironment
* >(pCommandEnv
),
2340 comphelper::getProcessComponentContext());
2342 if ( !INetURLObject( rGrfName
).isAnyKnownWebDAVScheme() )
2345 aCnt
.getPropertyValue("Title") >>= aTitle
;
2346 bUseRemote
= !aTitle
.isEmpty();
2350 // is a link to a WebDAV resource
2351 // need to use MediaType to check for link usability
2352 OUString aMediaType
;
2353 aCnt
.getPropertyValue("MediaType") >>= aMediaType
;
2354 bUseRemote
= !aMediaType
.isEmpty();
2359 // this file did not exist, so we will not set this as graphiclink
2365 // "EINF"UGENGRAFIK"
2366 eF_ResT
SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc
*, OUString
& rStr
)
2369 bool bEmbedded
= true;
2371 WW8ReadFieldParams
aReadParam( rStr
);
2374 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2380 if (aGrfName
.isEmpty())
2381 aGrfName
= ConvertFFileName(aReadParam
.GetResult());
2388 case 'c':// den Converter-Namen ueberlesen
2389 aReadParam
.FindNextStringPiece();
2395 bEmbedded
= !CanUseRemoteLink(aGrfName
);
2402 Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrameFormat.
2403 Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
2404 wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
2406 Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
2407 erkannt, dass wir soeben einen Grafik-Link inserted haben und
2408 das passende SwAttrSet wird ins Frame-Format eingesetzt.
2410 SfxItemSet
aFlySet( m_rDoc
.GetAttrPool(), RES_FRMATR_BEGIN
,
2412 aFlySet
.Put( SwFormatAnchor( FLY_AS_CHAR
) );
2413 aFlySet
.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP
, text::RelOrientation::FRAME
));
2414 m_pFlyFormatOfJustInsertedGraphic
= m_rDoc
.getIDocumentContentOperations().Insert( *m_pPaM
,
2417 nullptr, // Graphic*
2419 nullptr, nullptr); // SwFrameFormat*
2420 m_aGrfNameGenerator
.SetUniqueGraphName(m_pFlyFormatOfJustInsertedGraphic
,
2421 INetURLObject(aGrfName
).GetBase());
2423 return FLD_READ_FSPA
;
2426 OUString
wwSectionNamer::UniqueName()
2428 const OUString
aName(msFileLinkSeed
+ OUString::number(++mnFileSectionNo
));
2429 return mrDoc
.GetUniqueSectionName(&aName
);
2433 eF_ResT
SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc
* /*pF*/, OUString
& rStr
)
2437 WW8ReadFieldParams
aReadParam( rStr
);
2440 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2446 if( aPara
.isEmpty() )
2447 aPara
= aReadParam
.GetResult();
2448 else if( aBook
.isEmpty() )
2449 aBook
= aReadParam
.GetResult();
2452 //Skip over MERGEFORMAT
2453 (void)aReadParam
.SkipToNextToken();
2457 aPara
= ConvertFFileName(aPara
);
2459 if (!aBook
.isEmpty() && aBook
[ 0 ] != '\\')
2461 // Bereich aus Quelle ( kein Switch ) ?
2462 ConvertUFName(aBook
);
2463 aPara
+= OUStringLiteral1(sfx2::cTokenSeparator
)
2464 + OUStringLiteral1(sfx2::cTokenSeparator
) + aBook
;
2469 What we will do is insert a section to be linked to a file, but just in
2470 case the file is not available we will fill in the section with the stored
2471 content of this winword field as a fallback.
2473 SwPosition
aTmpPos(*m_pPaM
->GetPoint());
2475 SwSectionData
aSection(FILE_LINK_SECTION
,
2476 m_aSectionNameGenerator
.UniqueName());
2477 aSection
.SetLinkFileName( aPara
);
2478 aSection
.SetProtectFlag(true);
2480 SwSection
*const pSection
=
2481 m_rDoc
.InsertSwSection(*m_pPaM
, aSection
, nullptr, nullptr, false);
2482 OSL_ENSURE(pSection
, "no section inserted");
2485 const SwSectionNode
* pSectionNode
= pSection
->GetFormat()->GetSectionNode();
2486 OSL_ENSURE(pSectionNode
, "no section node!");
2490 m_pPaM
->GetPoint()->nNode
= pSectionNode
->GetIndex()+1;
2491 m_pPaM
->GetPoint()->nContent
.Assign(m_pPaM
->GetContentNode(), 0 );
2493 //we have inserted a section before this point, so adjust pos
2494 //for future page/section segment insertion
2495 m_aSectionManager
.PrependedInlineNode(aTmpPos
, m_pPaM
->GetNode());
2500 // "SERIENDRUCKFELD"
2501 eF_ResT
SwWW8ImplReader::Read_F_DBField( WW8FieldDesc
* pF
, OUString
& rStr
)
2503 #if !HAVE_FEATURE_DBCONNECTIVITY
2508 WW8ReadFieldParams
aReadParam( rStr
);
2511 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2517 if( aName
.isEmpty() )
2518 aName
= aReadParam
.GetResult();
2522 SwDBFieldType
aD( &m_rDoc
, aName
, SwDBData() ); // Datenbank: Nichts
2524 SwFieldType
* pFT
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType( aD
);
2525 SwDBField
aField( static_cast<SwDBFieldType
*>(pFT
) );
2526 aField
.SetFieldCode( rStr
);
2529 m_pSBase
->WW8ReadString( *m_pStrm
, aResult
, m_pPlcxMan
->GetCpOfs()+
2530 pF
->nSRes
, pF
->nLRes
, m_eTextCharSet
);
2532 aResult
= aResult
.replace( '\xb', '\n' );
2534 aField
.InitContent(aResult
);
2536 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField( aField
));
2542 eF_ResT
SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc
*, OUString
& )
2544 #if HAVE_FEATURE_DBCONNECTIVITY
2545 SwDBNextSetFieldType aN
;
2546 SwFieldType
* pFT
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType( aN
);
2547 SwDBNextSetField
aField( static_cast<SwDBNextSetFieldType
*>(pFT
), OUString(), OUString(),
2548 SwDBData() ); // Datenbank: Nichts
2549 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
2555 eF_ResT
SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc
*, OUString
& )
2557 #if HAVE_FEATURE_DBCONNECTIVITY
2558 SwDBSetNumberFieldType aN
;
2559 SwFieldType
* pFT
= m_rDoc
.getIDocumentFieldsAccess().InsertFieldType( aN
);
2560 SwDBSetNumberField
aField( static_cast<SwDBSetNumberFieldType
*>(pFT
),
2561 SwDBData() ); // Datenbank: Nichts
2562 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) );
2568 EQ , only the usage for
2569 a. Combined Characters supported, must be exactly in the form that word
2570 only accepts as combined characters, 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
2576 eF_ResT
SwWW8ImplReader::Read_F_Equation( WW8FieldDesc
*, OUString
& rStr
)
2578 WW8ReadFieldParams
aReadParam( rStr
);
2579 const sal_Int32 cChar
= aReadParam
.SkipToNextToken();
2580 if ('o' == cChar
|| 'O' == cChar
)
2582 EquationResult
aResult(ParseCombinedChars(rStr
));
2584 if (aResult
.sType
== "Input")
2586 SwInputField
aField( static_cast<SwInputFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType( RES_INPUTFLD
)),
2587 aResult
.sResult
, aResult
.sResult
, INP_TXT
, 0 );
2588 m_rDoc
.getIDocumentContentOperations().InsertPoolItem( *m_pPaM
, SwFormatField( aField
) ); // insert input field
2590 else if (aResult
.sType
== "CombinedCharacters")
2592 SwCombinedCharField
aField(static_cast<SwCombinedCharFieldType
*>(
2593 m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_COMBINED_CHARS
)), aResult
.sType
);
2594 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
2597 else if ('*' == cChar
)
2598 Read_SubF_Ruby(aReadParam
);
2603 void SwWW8ImplReader::Read_SubF_Ruby( WW8ReadFieldParams
& rReadParam
)
2605 sal_uInt16 nJustificationCode
=0;
2607 sal_uInt32 nFontSize
=0;
2612 const sal_Int32 nRet
= rReadParam
.SkipToNextToken();
2619 OUString sTemp
= rReadParam
.GetResult();
2620 if( sTemp
.startsWithIgnoreAsciiCase( "jc" ) )
2622 sTemp
= sTemp
.copy(2);
2623 nJustificationCode
= static_cast<sal_uInt16
>(sTemp
.toInt32());
2625 else if( sTemp
.startsWithIgnoreAsciiCase( "hps" ) )
2627 sTemp
= sTemp
.copy(3);
2628 nFontSize
= static_cast<sal_uInt32
>(sTemp
.toInt32());
2630 else if( sTemp
.startsWithIgnoreAsciiCase( "Font:" ) )
2632 sTemp
= sTemp
.copy(5);
2642 const sal_Int32 nRes
= rReadParam
.SkipToNextToken();
2647 if (-2 == rReadParam
.SkipToNextToken() &&
2648 rReadParam
.GetResult().startsWithIgnoreAsciiCase("p"))
2650 if (-2 == rReadParam
.SkipToNextToken())
2652 OUString sPart
= rReadParam
.GetResult();
2653 sal_Int32 nBegin
= sPart
.indexOf('(');
2655 //Word disallows brackets in this field,
2656 sal_Int32 nEnd
= sPart
.indexOf(')');
2658 if ((nBegin
!= -1) &&
2659 (nEnd
!= -1) && (nBegin
< nEnd
))
2661 sRuby
= sPart
.copy(nBegin
+1,nEnd
-nBegin
-1);
2666 (nBegin
= sPart
.indexOf(',',nEnd
)))
2668 nBegin
= sPart
.indexOf(';',nEnd
);
2670 nEnd
= sPart
.lastIndexOf(')');
2672 if ((nBegin
!= -1) && (nEnd
!= -1) && (nBegin
< nEnd
))
2674 sText
= sPart
.copy(nBegin
+1,nEnd
-nBegin
-1);
2685 //Translate and apply
2686 if (!sRuby
.isEmpty() && !sText
.isEmpty() && !sFontName
.isEmpty() && nFontSize
)
2688 switch (nJustificationCode
)
2691 nJustificationCode
=1;
2694 nJustificationCode
=3;
2697 nJustificationCode
=4;
2701 nJustificationCode
=0;
2704 nJustificationCode
=2;
2708 SwFormatRuby
aRuby(sRuby
);
2709 const SwCharFormat
*pCharFormat
=nullptr;
2710 //Make a guess at which of asian of western we should be setting
2712 if (g_pBreakIt
->GetBreakIter().is())
2713 nScript
= g_pBreakIt
->GetBreakIter()->getScriptType(sRuby
, 0);
2715 nScript
= i18n::ScriptType::ASIAN
;
2717 //Check to see if we already have a ruby charstyle that this fits
2718 std::vector
<const SwCharFormat
*>::const_iterator aEnd
=
2719 m_aRubyCharFormats
.end();
2720 for(std::vector
<const SwCharFormat
*>::const_iterator aIter
2721 = m_aRubyCharFormats
.begin(); aIter
!= aEnd
; ++aIter
)
2723 const SvxFontHeightItem
&rFH
=
2724 ItemGet
<SvxFontHeightItem
>(*(*aIter
),
2725 GetWhichOfScript(RES_CHRATR_FONTSIZE
,nScript
));
2726 if (rFH
.GetHeight() == nFontSize
*10)
2728 const SvxFontItem
&rF
= ItemGet
<SvxFontItem
>(*(*aIter
),
2729 GetWhichOfScript(RES_CHRATR_FONT
,nScript
));
2730 if (rF
.GetFamilyName().equals(sFontName
))
2738 //Create a new char style if necessary
2741 SwCharFormat
*pFormat
=nullptr;
2743 //Take this as the base name
2744 SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT
,aNm
);
2745 aNm
+=OUString::number(m_aRubyCharFormats
.size()+1);
2746 pFormat
= m_rDoc
.MakeCharFormat(aNm
, m_rDoc
.GetDfltCharFormat());
2747 SvxFontHeightItem
aHeightItem(nFontSize
*10, 100, RES_CHRATR_FONTSIZE
);
2748 SvxFontItem
aFontItem(FAMILY_DONTKNOW
,sFontName
,
2749 OUString(), PITCH_DONTKNOW
, RTL_TEXTENCODING_DONTKNOW
, RES_CHRATR_FONT
);
2750 aHeightItem
.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE
,nScript
));
2751 aFontItem
.SetWhich(GetWhichOfScript(RES_CHRATR_FONT
,nScript
));
2752 pFormat
->SetFormatAttr(aHeightItem
);
2753 pFormat
->SetFormatAttr(aFontItem
);
2754 m_aRubyCharFormats
.push_back(pFormat
);
2755 pCharFormat
= pFormat
;
2758 //Set the charstyle and justification
2759 aRuby
.SetCharFormatName(pCharFormat
->GetName());
2760 aRuby
.SetCharFormatId(pCharFormat
->GetPoolFormatId());
2761 aRuby
.SetAdjustment(nJustificationCode
);
2764 m_rDoc
.getIDocumentContentOperations().InsertString( *m_pPaM
, sText
);
2765 m_pCtrlStck
->SetAttr( *m_pPaM
->GetPoint(), RES_TXTATR_CJK_RUBY
);
2769 // "table of ..." fields
2771 static void lcl_toxMatchACSwitch( SwWW8ImplReader
& /*rReader*/,
2774 WW8ReadFieldParams
& rParam
,
2775 SwCaptionDisplay eCaptionType
)
2777 if ( rParam
.GoToTokenParam() )
2779 SwTOXType
* pType
= const_cast<SwTOXType
*>(rDoc
.GetTOXType( TOX_ILLUSTRATIONS
, 0));
2780 rBase
.RegisterToTOXType( *pType
);
2781 rBase
.SetCaptionDisplay( eCaptionType
);
2782 // Read Sequence Name and store in TOXBase
2783 OUString
sSeqName( rParam
.GetResult() );
2784 lcl_ConvertSequenceName( sSeqName
);
2785 rBase
.SetSequenceName( sSeqName
);
2789 static void EnsureMaxLevelForTemplates(SwTOXBase
& rBase
)
2791 //If the TOC contains Template entries at levels > the evaluation level
2792 //that was initially taken from the max normal outline level of the word TOC
2793 //then we cannot use that for the evaluation level because writer cuts off
2794 //all styles above that level, while word just cuts off the "standard"
2795 //outline styles, we have no option but to expand to the highest level
2797 if ((rBase
.GetLevel() != MAXLEVEL
) && (nsSwTOXElement::TOX_TEMPLATE
& rBase
.GetCreateType()))
2799 for (sal_uInt16 nI
= MAXLEVEL
; nI
> 0; --nI
)
2801 if (!rBase
.GetStyleNames(nI
-1).isEmpty())
2810 static void lcl_toxMatchTSwitch(SwWW8ImplReader
& rReader
, SwTOXBase
& rBase
,
2811 WW8ReadFieldParams
& rParam
)
2813 if ( rParam
.GoToTokenParam() )
2815 OUString
sParams( rParam
.GetResult() );
2816 if( !sParams
.isEmpty() )
2818 sal_Int32 nIndex
= 0;
2820 // Delimiters between styles and style levels appears to allow both ; and ,
2822 OUString
sTemplate( sParams
.getToken(0, ';', nIndex
) );
2826 sTemplate
= sParams
.getToken(0, ',', nIndex
);
2830 const SwFormat
* pStyle
= rReader
.GetStyleWithOrgWWName(sTemplate
);
2832 sTemplate
= pStyle
->GetName();
2833 // Store Style for Level 0 into TOXBase
2834 rBase
.SetStyleNames( sTemplate
, 0 );
2836 else while( -1 != nIndex
)
2838 sal_Int32 nOldIndex
=nIndex
;
2839 sal_uInt16 nLevel
= static_cast<sal_uInt16
>(
2840 sParams
.getToken(0, ';', nIndex
).toInt32());
2844 nLevel
= static_cast<sal_uInt16
>(
2845 sParams
.getToken(0, ',', nIndex
).toInt32());
2848 if( (0 < nLevel
) && (MAXLEVEL
>= nLevel
) )
2851 // Store Style and Level into TOXBase
2852 const SwFormat
* pStyle
2853 = rReader
.GetStyleWithOrgWWName( sTemplate
);
2856 sTemplate
= pStyle
->GetName();
2858 OUString
sStyles( rBase
.GetStyleNames( nLevel
) );
2859 if( !sStyles
.isEmpty() )
2860 sStyles
+= OUStringLiteral1(TOX_STYLE_DELIMITER
);
2861 sStyles
+= sTemplate
;
2862 rBase
.SetStyleNames( sStyles
, nLevel
);
2864 // read next style name...
2866 sTemplate
= sParams
.getToken(0, ';', nIndex
);
2870 sTemplate
= sParams
.getToken(0, ',', nIndex
);
2877 sal_uInt16
wwSectionManager::CurrentSectionColCount() const
2879 sal_uInt16 nIndexCols
= 1;
2880 if (!maSegments
.empty())
2881 nIndexCols
= maSegments
.back().maSep
.ccolM1
+ 1;
2885 //Will there be a new pagebreak at this position (don't know what type
2887 bool wwSectionManager::WillHavePageDescHere(const SwNodeIndex
& rIdx
) const
2890 if (!maSegments
.empty())
2892 if (!maSegments
.back().IsContinuous() &&
2893 maSegments
.back().maStart
== rIdx
)
2901 static sal_uInt16
lcl_GetMaxValidWordTOCLevel(const SwForm
&rForm
)
2903 // GetFormMax() returns level + 1, hence the -1
2904 sal_uInt16 nRet
= rForm
.GetFormMax()-1;
2906 // If the max of this type of TOC is greater than the max of a word
2907 // possible toc, then clip to the word max
2908 if (nRet
> WW8ListManager::nMaxLevel
)
2909 nRet
= WW8ListManager::nMaxLevel
;
2914 eF_ResT
SwWW8ImplReader::Read_F_Tox( WW8FieldDesc
* pF
, OUString
& rStr
)
2916 if (!m_bLoadingTOXCache
)
2918 m_bLoadingTOXCache
= true;
2922 // Embedded TOX --> continue reading its content, but no further TOX
2924 ++m_nEmbeddedTOXLevel
;
2929 return FLD_TEXT
; // ignore (#i25440#)
2931 TOXTypes eTox
; // create a ToxBase
2945 sal_uInt16 nCreateOf
= (eTox
== TOX_CONTENT
) ? nsSwTOXElement::TOX_OUTLINELEVEL
: nsSwTOXElement::TOX_MARK
;
2947 sal_uInt16 nIndexCols
= 1;
2949 const SwTOXType
* pType
= m_rDoc
.GetTOXType( eTox
, 0 );
2950 SwForm
aOrigForm(eTox
);
2951 SwTOXBase
* pBase
= new SwTOXBase( pType
, aOrigForm
, nCreateOf
, OUString() );
2952 pBase
->SetProtected(m_aSectionManager
.CurrentSectionIsProtected());
2956 sal_uInt16 eOptions
= nsSwTOIOptions::TOI_SAME_ENTRY
| nsSwTOIOptions::TOI_CASE_SENSITIVE
;
2958 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
2959 // die Parameter \o in 1 bis 9 liegen
2960 // oder der Parameter \f existiert
2961 // oder GARKEINE Switches Parameter angegeben sind.
2962 WW8ReadFieldParams
aReadParam( rStr
);
2965 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
2971 if ( aReadParam
.GoToTokenParam() )
2973 const OUString
sParams( aReadParam
.GetResult() );
2974 // if NO OUString just ignore the \c
2975 if( !sParams
.isEmpty() )
2977 nIndexCols
= static_cast<sal_uInt16
>(sParams
.toInt32());
2983 if ( aReadParam
.GoToTokenParam() ) // if NO String just ignore the \e
2985 OUString
sDelimiter( aReadParam
.GetResult() );
2986 SwForm
aForm( pBase
->GetTOXForm() );
2988 // Attention: if TOX_CONTENT brave
2989 // GetFormMax() returns MAXLEVEL + 1 !!
2990 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
2992 for(sal_uInt16 nLevel
= 1;
2996 // Levels count from 1
2997 // Level 0 is reserved for CAPTION
2999 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3000 // falls es eine Seitenzahl gibt:
3001 FormTokenType ePrevType
= TOKEN_END
;
3002 FormTokenType eType
;
3004 SwFormTokens aPattern
=
3005 aForm
.GetPattern(nLevel
);
3006 SwFormTokens::iterator aIt
= aPattern
.begin();
3009 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3011 if (eType
== TOKEN_PAGE_NUMS
)
3013 if (TOKEN_TAB_STOP
== ePrevType
)
3017 if(0x09 == sDelimiter
[0])
3018 aIt
->eTabAlign
= SvxTabAdjust::End
;
3021 SwFormToken
aToken(TOKEN_TEXT
);
3022 aToken
.sText
= sDelimiter
;
3025 aForm
.SetPattern(nLevel
, aPattern
);
3033 while (TOKEN_END
!= eType
);
3036 pBase
->SetTOXForm( aForm
);
3042 eOptions
|= nsSwTOIOptions::TOI_ALPHA_DELIMITTER
;
3047 pBase
->SetOptions( eOptions
);
3053 bool bIsHyperlink
= false;
3054 bool bShowPage
= true;
3055 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
3056 // die Parameter \o in 1 bis 9 liegen
3057 // oder der Parameter \f existiert
3058 // oder GARKEINE Switches Parameter angegeben sind.
3059 sal_uInt16 eCreateFrom
= 0;
3060 sal_Int32 nMaxLevel
= 0;
3061 WW8ReadFieldParams
aReadParam( rStr
);
3064 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
3070 bIsHyperlink
= true;
3074 lcl_toxMatchACSwitch(*this, m_rDoc
, *pBase
, aReadParam
,
3082 if( !aReadParam
.GetTokenSttFromTo(nullptr, &nVal
, WW8ListManager::nMaxLevel
) )
3083 nVal
= lcl_GetMaxValidWordTOCLevel(aOrigForm
);
3084 if( nMaxLevel
< nVal
)
3086 eCreateFrom
|= nsSwTOXElement::TOX_OUTLINELEVEL
;
3090 eCreateFrom
|= nsSwTOXElement::TOX_MARK
;
3095 if( aReadParam
.GetTokenSttFromTo(nullptr, &nVal
, WW8ListManager::nMaxLevel
) )
3097 if( nMaxLevel
< nVal
)
3099 eCreateFrom
|= nsSwTOXElement::TOX_MARK
;
3103 case 't': // paragraphs using special styles shall
3104 // provide the TOX's content
3105 lcl_toxMatchTSwitch(*this, *pBase
, aReadParam
);
3106 eCreateFrom
|= nsSwTOXElement::TOX_TEMPLATE
;
3110 if ( aReadParam
.GoToTokenParam() ) // if NO String just ignore the \p
3112 OUString
sDelimiter( aReadParam
.GetResult() );
3113 SwForm
aForm( pBase
->GetTOXForm() );
3115 // Attention: if TOX_CONTENT brave
3116 // GetFormMax() returns MAXLEVEL + 1 !!
3117 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3119 for(sal_uInt16 nLevel
= 1;
3123 // Levels count from 1
3124 // Level 0 is reserved for CAPTION
3126 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3127 // falls es eine Seitenzahl gibt:
3128 FormTokenType ePrevType
= TOKEN_END
;
3129 FormTokenType eType
;
3132 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3133 SwFormTokens::iterator aIt
= aPattern
.begin();
3136 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3138 if (eType
== TOKEN_PAGE_NUMS
)
3140 if (TOKEN_TAB_STOP
== ePrevType
)
3144 SwFormToken
aToken(TOKEN_TEXT
);
3145 aToken
.sText
= sDelimiter
;
3148 aForm
.SetPattern(nLevel
,
3155 while( TOKEN_END
!= eType
);
3158 pBase
->SetTOXForm( aForm
);
3162 case 'n': // don't print page numbers
3164 // read START and END param
3165 sal_Int32
nStart(0);
3167 if( !aReadParam
.GetTokenSttFromTo( &nStart
, &nEnd
,
3168 WW8ListManager::nMaxLevel
) )
3171 nEnd
= aOrigForm
.GetFormMax()-1;
3173 // remove page numbers from this levels
3174 SwForm
aForm( pBase
->GetTOXForm() );
3175 if (aForm
.GetFormMax() <= nEnd
)
3176 nEnd
= aForm
.GetFormMax()-1;
3177 for ( sal_Int32 nLevel
= nStart
; nLevel
<=nEnd
; ++nLevel
)
3179 // Levels count from 1
3180 // Level 0 is reserved for CAPTION
3182 // Seitenzahl und ggfs. davorstehenden Tabstop
3184 FormTokenType eType
;
3186 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3187 SwFormTokens::iterator aIt
= aPattern
.begin();
3190 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3192 if (eType
== TOKEN_PAGE_NUMS
)
3194 aIt
= aPattern
.erase(aIt
);
3201 aPattern
.erase(aIt
);
3202 aForm
.SetPattern(nLevel
, aPattern
);
3207 while (TOKEN_END
!= eType
);
3210 pBase
->SetTOXForm( aForm
);
3215 // the following switches are not (yet) supported
3216 // by good old StarWriter:
3225 // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens
3226 // also include the hyperlinks and page references
3227 SwFormToken
aLinkStart(TOKEN_LINK_START
);
3228 SwFormToken
aLinkEnd(TOKEN_LINK_END
);
3229 aLinkStart
.sCharStyleName
= "Index Link";
3230 aLinkEnd
.sCharStyleName
= "Index Link";
3231 SwForm
aForm(pBase
->GetTOXForm());
3232 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3234 for(sal_uInt16 nLevel
= 1; nLevel
<= nEnd
; ++nLevel
)
3236 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3239 aPattern
.insert(aPattern
.begin(), aLinkStart
);
3241 else if ( bShowPage
)
3243 for (SwFormTokens::iterator aItr
= aPattern
.begin();aItr
!= aPattern
.end();++aItr
)
3245 if (aItr
->eTokenType
== TOKEN_PAGE_NUMS
)
3247 aPattern
.insert(aItr
,aLinkStart
);
3252 aPattern
.push_back(aLinkEnd
);
3253 aForm
.SetPattern(nLevel
, aPattern
);
3255 pBase
->SetTOXForm(aForm
);
3258 nMaxLevel
= WW8ListManager::nMaxLevel
;
3259 pBase
->SetLevel(nMaxLevel
);
3261 const TOXTypes eType
= pBase
->GetTOXType()->GetType();
3266 //If we would be created from outlines, either explicitly or by default
3267 //then see if we need extra styles added to the outlines
3268 sal_uInt16 eEffectivelyFrom
= eCreateFrom
? eCreateFrom
: nsSwTOXElement::TOX_OUTLINELEVEL
;
3269 if (eEffectivelyFrom
& nsSwTOXElement::TOX_OUTLINELEVEL
)
3271 // #i19683# Insert a text token " " between the number and entry token.
3272 // In an ideal world we could handle the tab stop between the number and
3273 // the entry correctly, but I currently have no clue how to obtain
3274 // the tab stop position. It is _not_ set at the paragraph style.
3275 SwForm
* pForm
= nullptr;
3276 for (SwWW8StyInf
& rSI
: m_vColl
)
3278 if (rSI
.IsOutlineNumbered())
3280 sal_uInt16 nStyleLevel
= rSI
.mnWW8OutlineLevel
;
3281 const SwNumFormat
& rFormat
= rSI
.GetOutlineNumrule()->Get( nStyleLevel
);
3282 if ( SVX_NUM_NUMBER_NONE
!= rFormat
.GetNumberingType() )
3287 pForm
= new SwForm( pBase
->GetTOXForm() );
3289 SwFormTokens aPattern
= pForm
->GetPattern(nStyleLevel
);
3290 SwFormTokens::iterator aIt
=
3291 find_if(aPattern
.begin(), aPattern
.end(),
3292 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO
));
3294 if ( aIt
!= aPattern
.end() )
3296 SwFormToken
aNumberEntrySeparator( TOKEN_TEXT
);
3297 aNumberEntrySeparator
.sText
= " ";
3298 aPattern
.insert( ++aIt
, aNumberEntrySeparator
);
3299 pForm
->SetPattern( nStyleLevel
, aPattern
);
3306 pBase
->SetTOXForm( *pForm
);
3312 pBase
->SetCreate(eCreateFrom
);
3313 EnsureMaxLevelForTemplates(*pBase
);
3316 case TOX_ILLUSTRATIONS
:
3319 eCreateFrom
= nsSwTOXElement::TOX_SEQUENCE
;
3320 pBase
->SetCreate( eCreateFrom
);
3323 We don't know until here if we are an illustration
3324 or not, and so have being used a TOX_CONTENT so far
3325 which has 10 levels, while TOX has only two, this
3326 level is set only in the constructor of SwForm, so
3327 create a new one and copy over anything that could
3328 be set in the old one, and remove entries from the
3329 pattern which do not apply to illustration indices
3331 SwForm
aOldForm( pBase
->GetTOXForm() );
3332 SwForm
aNewForm( eType
);
3333 sal_uInt16 nNewEnd
= aNewForm
.GetFormMax()-1;
3336 for(sal_uInt16 nLevel
= 1; nLevel
<= nNewEnd
; ++nLevel
)
3338 SwFormTokens aPattern
= aOldForm
.GetPattern(nLevel
);
3339 SwFormTokens::iterator new_end
=
3340 remove_if(aPattern
.begin(), aPattern
.end(), SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO
));
3341 aPattern
.erase(new_end
, aPattern
.end() ); // table index imported with wrong page number format
3342 aForm
.SetPattern( nLevel
, aPattern
);
3343 aForm
.SetTemplate( nLevel
, aOldForm
.GetTemplate(nLevel
) );
3346 pBase
->SetTOXForm( aNewForm
);
3350 OSL_ENSURE(false, "Unhandled toc options!");
3358 OSL_ENSURE(false, "Unhandled toc options!");
3362 // #i21237# - propagate tab stops from paragraph styles used in TOX to patterns of the TOX
3363 pBase
->AdjustTabStops( m_rDoc
);
3365 //#i10028# inserting a toc implicltly acts like a parabreak in word and writer
3366 if ( m_pPaM
->End() &&
3367 m_pPaM
->End()->nNode
.GetNode().GetTextNode() &&
3368 m_pPaM
->End()->nNode
.GetNode().GetTextNode()->Len() != 0 )
3370 m_bCareFirstParaEndInToc
= true;
3373 if (m_pPaM
->GetPoint()->nContent
.GetIndex())
3374 AppendTextNode(*m_pPaM
->GetPoint());
3376 const SwPosition
* pPos
= m_pPaM
->GetPoint();
3378 SwFltTOX
aFltTOX( pBase
);
3380 // test if there is already a break item on this node
3381 if(SwContentNode
* pNd
= pPos
->nNode
.GetNode().GetContentNode())
3383 const SfxItemSet
* pSet
= pNd
->GetpSwAttrSet();
3386 if (SfxItemState::SET
== pSet
->GetItemState(RES_BREAK
, false))
3387 aFltTOX
.SetHadBreakItem(true);
3388 if (SfxItemState::SET
== pSet
->GetItemState(RES_PAGEDESC
, false))
3389 aFltTOX
.SetHadPageDescItem(true);
3393 //Will there be a new pagebreak at this position (don't know what type
3395 if (m_aSectionManager
.WillHavePageDescHere(pPos
->nNode
))
3396 aFltTOX
.SetHadPageDescItem(true);
3398 // Setze Anfang in Stack
3399 m_pReffedStck
->NewAttr( *pPos
, aFltTOX
);
3401 m_rDoc
.InsertTableOf(*m_pPaM
->GetPoint(), *aFltTOX
.GetBase());
3403 //The TOC field representation contents should be inserted into TOC section, but not after TOC section.
3404 //So we need update the document position when loading TOC representation and after loading TOC;
3405 m_pPosAfterTOC
.reset(new SwPaM(*m_pPaM
, m_pPaM
));
3406 (*m_pPaM
).Move(fnMoveBackward
);
3407 SwPaM
aRegion(*m_pPaM
, m_pPaM
);
3409 OSL_ENSURE(SwDoc::GetCurTOX(*aRegion
.GetPoint()), "Misunderstood how toc works");
3410 if (SwTOXBase
* pBase2
= SwDoc::GetCurTOX(*aRegion
.GetPoint()))
3412 pBase2
->SetMSTOCExpression(rStr
);
3414 if ( nIndexCols
> 1 )
3416 // Set the column number for index
3417 SfxItemSet
aSet( m_rDoc
.GetAttrPool(), RES_COL
, RES_COL
);
3419 aCol
.Init( nIndexCols
, 708, USHRT_MAX
);
3421 pBase2
->SetAttrSet( aSet
);
3424 // inserting a toc inserts a section before this point, so adjust pos
3425 // for future page/section segment insertion
3426 m_aSectionManager
.PrependedInlineNode( *m_pPosAfterTOC
->GetPoint(), aRegion
.GetNode() );
3429 // Setze Ende in Stack
3430 m_pReffedStck
->SetAttr( *pPos
, RES_FLTR_TOX
);
3432 if (!m_aApos
.back()) //a para end in apo doesn't count
3433 m_bWasParaEnd
= true;
3435 //Return FLD_TEXT, instead of FLD_OK
3436 //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed
3437 //FLD_OK means the current field loading is finished. The rest part should be ignored.
3441 eF_ResT
SwWW8ImplReader::Read_F_Shape(WW8FieldDesc
* /*pF*/, OUString
& /*rStr*/)
3444 #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3445 to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3446 the drawing that we are in the Shape field and respond accordingly
3451 eF_ResT
SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc
* /*pF*/, OUString
& rStr
)
3453 OUString sURL
, sTarget
, sMark
;
3455 //HYPERLINK "filename" [switches]
3456 rStr
= comphelper::string::stripEnd(rStr
, 1);
3458 bool bOptions
= false;
3459 WW8ReadFieldParams
aReadParam( rStr
);
3462 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
3468 if (sURL
.isEmpty() && !bOptions
)
3469 sURL
= ConvertFFileName(aReadParam
.GetResult());
3479 if ( aReadParam
.SkipToNextToken()==-2 )
3481 sMark
= aReadParam
.GetResult();
3482 if( sMark
.endsWith("\""))
3484 sMark
= sMark
.copy( 0, sMark
.getLength() - 1 );
3486 // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
3487 if ( IsTOCBookmarkName( sMark
) )
3489 sMark
= EnsureTOCBookmarkName(sMark
);
3490 // track <sMark> as referenced TOC bookmark.
3491 m_pReffedStck
->aReferencedTOCBookmarks
.insert( sMark
);
3494 if (m_bLoadingTOXCache
)
3496 m_bLoadingTOXHyperlink
= true; //on loading a TOC field nested hyperlink field
3502 if ( aReadParam
.SkipToNextToken()==-2 )
3503 sTarget
= aReadParam
.GetResult();
3507 OSL_ENSURE( false, "Auswertung fehlt noch - Daten unbekannt" );
3509 case 's': //worthless fake anchor option
3515 // das Resultat uebernehmen
3516 OSL_ENSURE(!sURL
.isEmpty() || !sMark
.isEmpty(), "WW8: Empty URL");
3518 if( !sMark
.isEmpty() )
3519 ( sURL
+= "#" ) += sMark
;
3521 SwFormatINetFormat
aURL(sURL
, sTarget
);
3522 // If on loading TOC field, change the default style into the "index link"
3523 if (m_bLoadingTOXCache
)
3525 OUString
sLinkStyle("Index Link");
3526 sal_uInt16 nPoolId
=
3527 SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle
, SwGetPoolIdFromName::ChrFmt
);
3528 aURL
.SetVisitedFormatAndId( sLinkStyle
, nPoolId
);
3529 aURL
.SetINetFormatAndId( sLinkStyle
, nPoolId
);
3532 //As an attribute this needs to be closed, and that'll happen from
3533 //EndExtSprm in conjunction with the maFieldStack. If there are flyfrms
3534 //between the start and begin, their hyperlinks will be set at that time
3536 m_pCtrlStck
->NewAttr( *m_pPaM
->GetPoint(), aURL
);
3540 static void lcl_ImportTox(SwDoc
&rDoc
, SwPaM
&rPaM
, const OUString
&rStr
, bool bIdx
)
3542 TOXTypes eTox
= ( !bIdx
) ? TOX_CONTENT
: TOX_INDEX
; // Default
3544 sal_uInt16 nLevel
= 1;
3546 OUString sFieldText
;
3547 WW8ReadFieldParams
aReadParam(rStr
);
3550 const sal_Int32 nRet
= aReadParam
.SkipToNextToken();
3556 if( sFieldText
.isEmpty() )
3558 // PrimaryKey ohne ":", 2nd dahinter
3559 sFieldText
= aReadParam
.GetResult();
3564 if ( aReadParam
.GoToTokenParam() )
3566 const OUString
sParams( aReadParam
.GetResult() );
3567 if( sParams
[0]!='C' && sParams
[0]!='c' )
3573 if ( aReadParam
.GoToTokenParam() )
3575 const OUString
sParams( aReadParam
.GetResult() );
3576 // if NO String just ignore the \l
3577 if( !sParams
.isEmpty() && sParams
[0]>'0' && sParams
[0]<='9' )
3579 nLevel
= (sal_uInt16
)sParams
.toInt32();
3586 OSL_ENSURE( rDoc
.GetTOXTypeCount( eTox
), "Doc.GetTOXTypeCount() == 0 :-(" );
3588 const SwTOXType
* pT
= rDoc
.GetTOXType( eTox
, 0 );
3591 if( eTox
!= TOX_INDEX
)
3592 aM
.SetLevel( nLevel
);
3595 sal_Int32 nFnd
= sFieldText
.indexOf( WW8_TOX_LEVEL_DELIM
);
3596 if( -1 != nFnd
) // it exist levels
3598 aM
.SetPrimaryKey( sFieldText
.copy( 0, nFnd
) );
3599 sal_Int32 nScndFnd
= sFieldText
.indexOf( WW8_TOX_LEVEL_DELIM
, nFnd
+1 );
3600 if( -1 != nScndFnd
)
3602 aM
.SetSecondaryKey( sFieldText
.copy( nFnd
+1, nScndFnd
- nFnd
- 1 ));
3605 sFieldText
= sFieldText
.copy( nFnd
+1 );
3609 if (!sFieldText
.isEmpty())
3611 aM
.SetAlternativeText( sFieldText
);
3612 rDoc
.getIDocumentContentOperations().InsertPoolItem( rPaM
, aM
);
3616 void sw::ms::ImportXE(SwDoc
&rDoc
, SwPaM
&rPaM
, const OUString
&rStr
)
3618 lcl_ImportTox(rDoc
, rPaM
, rStr
, true);
3621 void SwWW8ImplReader::ImportTox( int nFieldId
, const OUString
& aStr
)
3623 bool bIdx
= (nFieldId
!= 9);
3624 lcl_ImportTox(m_rDoc
, *m_pPaM
, aStr
, bIdx
);
3627 void SwWW8ImplReader::Read_FieldVanish( sal_uInt16
, const sal_uInt8
*, short nLen
)
3629 //Meaningless in a style
3630 if (m_pAktColl
|| !m_pPlcxMan
)
3633 const int nChunk
= 64; //number of characters to read at one time
3635 // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
3636 const static sal_Char
*aFieldNames
[] = { "\x06""INHALT", "\x02""XE", // dt.
3638 const static sal_uInt8 aFieldId
[] = { 9, 4, 9 };
3642 m_bIgnoreText
= false;
3646 // our methode was called from
3647 // ''Skip attributes of field contents'' loop within ReadTextAttr()
3651 m_bIgnoreText
= true;
3652 long nOldPos
= m_pStrm
->Tell();
3654 WW8_CP nStartCp
= m_pPlcxMan
->Where() + m_pPlcxMan
->GetCpOfs();
3656 OUString sFieldName
;
3657 sal_Int32 nFieldLen
= m_pSBase
->WW8ReadString( *m_pStrm
, sFieldName
, nStartCp
,
3658 nChunk
, m_eStructCharSet
);
3659 nStartCp
+=nFieldLen
;
3662 //If the first chunk did not start with a field start then
3663 //reset the stream position and give up
3664 if( !nFieldLen
|| sFieldName
[nC
]!=0x13 ) // Field Start Mark
3666 // If Field End Mark found
3667 if( nFieldLen
&& sFieldName
[nC
]==0x15 )
3668 m_bIgnoreText
= false;
3669 m_pStrm
->Seek( nOldPos
);
3670 return; // kein Feld zu finden
3674 //If this chunk does not contain a field end, keep reading chunks
3675 //until we find one, or we run out of text,
3678 nFnd
= sFieldName
.indexOf(0x15);
3679 //found field end, we can stop now
3683 nFieldLen
= m_pSBase
->WW8ReadString( *m_pStrm
, sTemp
,
3684 nStartCp
, nChunk
, m_eStructCharSet
);
3686 nStartCp
+=nFieldLen
;
3691 m_pStrm
->Seek( nOldPos
);
3693 //if we have no 0x15 give up, otherwise erase everything from the 0x15
3698 sFieldName
= sFieldName
.copy(0, nFnd
);
3701 while ( sFieldName
[nC
]==' ' )
3704 for( int i
= 0; i
< 3; i
++ )
3706 const sal_Char
* pName
= aFieldNames
[i
];
3707 const sal_Int32 nNameLen
= static_cast<sal_Int32
>(*pName
++);
3708 if( sFieldName
.matchIgnoreAsciiCaseAsciiL( pName
, nNameLen
, nC
) )
3710 ImportTox( aFieldId
[i
], sFieldName
.copy( nC
+ nNameLen
) );
3711 break; // keine Mehrfachnennungen moeglich
3714 m_bIgnoreText
= true;
3715 m_pStrm
->Seek( nOldPos
);
3718 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */