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 .
21 #include <ctype.h> // tolower
22 #include <stdio.h> // sscanf()
24 #include <sal/types.h>
25 #include <tools/solar.h>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/storagehelper.hxx>
28 #include <comphelper/string.hxx>
29 #include <sot/storinfo.hxx>
30 #include <com/sun/star/embed/XStorage.hpp>
31 #include <com/sun/star/embed/ElementModes.hpp>
32 #include <com/sun/star/embed/XTransactedObject.hpp>
33 #include <com/sun/star/io/XStream.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>
43 #include <com/sun/star/i18n/ScriptType.hpp>
44 #include <hintids.hxx>
45 #include <editeng/fontitem.hxx>
46 #include <editeng/fhgtitem.hxx>
47 #include <editeng/langitem.hxx>
49 #include <fmtanchr.hxx>
50 #include <pam.hxx> // fuer SwPam
52 #include <charatr.hxx> // class SwFmtFld
53 #include <flddat.hxx> // class SwDateTimeField
54 #include <docufld.hxx> // class SwPageNumberField
55 #include <reffld.hxx> // class SwGetRefField
57 #include <expfld.hxx> // class SwSetExpField
58 #include <dbfld.hxx> // class SwDBField
61 #include <section.hxx> // class SwSection
63 #include <fmtinfmt.hxx>
68 #include <shellres.hxx>
69 #include <fmtruby.hxx>
70 #include <charfmt.hxx>
72 #include <breakit.hxx>
73 #include <fmtclds.hxx>
74 #include <pagedesc.hxx>
75 #include <SwStyleNameMapper.hxx>
77 #include "ww8scan.hxx" // WW8FieldDesc
79 #include "ww8par2.hxx"
80 #include "writerhelper.hxx"
82 #include <unotools/fltrcfg.hxx>
83 #include <xmloff/odffields.hxx>
85 #include <algorithm> // #i24377#
87 #define MAX_FIELDLEN 64000
89 #define WW8_TOX_LEVEL_DELIM ':'
91 using namespace ::com::sun::star
;
92 using namespace sw::util
;
93 using namespace sw::mark
;
94 using namespace std
; // #i24377#
95 using namespace nsSwDocInfoSubType
;
98 class WW8ReadFieldParams
102 xub_StrLen nLen
, nFnd
, nNext
, nSavPtr
;
104 WW8ReadFieldParams( const String
& rData
);
105 ~WW8ReadFieldParams();
107 xub_StrLen
GoToTokenParam();
108 long SkipToNextToken();
109 xub_StrLen
GetTokenSttPtr() const { return nFnd
; }
111 xub_StrLen
FindNextStringPiece( xub_StrLen _nStart
= STRING_NOTFOUND
);
112 bool GetTokenSttFromTo(xub_StrLen
* _pFrom
, xub_StrLen
* _pTo
,
115 String
GetResult() const;
119 WW8ReadFieldParams::WW8ReadFieldParams( const String
& _rData
)
120 : aData( _rData
), nLen( _rData
.Len() ), nNext( 0 )
123 erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem
124 Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl
125 (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird
127 while( (nLen
> nNext
) && (aData
.GetChar( nNext
) == ' ') )
132 && (c
= aData
.GetChar( nNext
)) != ' '
144 WW8ReadFieldParams::~WW8ReadFieldParams()
150 String
WW8ReadFieldParams::GetResult() const
152 return (STRING_NOTFOUND
== nFnd
)
154 : aData
.Copy( nFnd
, (nSavPtr
- nFnd
) );
158 xub_StrLen
WW8ReadFieldParams::GoToTokenParam()
160 xub_StrLen nOld
= nNext
;
161 if( -2 == SkipToNextToken() )
162 return GetTokenSttPtr();
164 return STRING_NOTFOUND
;
167 // ret: -2: NOT a '\' parameter but normal Text
168 long WW8ReadFieldParams::SkipToNextToken()
170 long nRet
= -1; // Ende
172 (STRING_NOTFOUND
!= nNext
) && (nLen
> nNext
) &&
173 STRING_NOTFOUND
!= (nFnd
= FindNextStringPiece(nNext
))
178 if ('\\' == aData
.GetChar(nFnd
) && '\\' != aData
.GetChar(nFnd
+ 1))
180 nRet
= aData
.GetChar(++nFnd
);
181 nNext
= ++nFnd
; // und dahinter setzen
187 (STRING_NOTFOUND
!= nSavPtr
) &&
189 ('"' == aData
.GetChar(nSavPtr
- 1)) ||
190 (0x201d == aData
.GetChar(nSavPtr
- 1))
201 // FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette
202 // bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen
203 // oder zum String-Ende von pStr.
205 // Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0
207 // Returnwert: 0 falls String-Ende erreicht,
208 // ansonsten Anfang des Paramters bzw. der Zeichenkette
210 xub_StrLen
WW8ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart
)
212 xub_StrLen n
= ( STRING_NOTFOUND
== nStart
) ? nFnd
: nStart
; // Anfang
213 xub_StrLen n2
; // Ende
215 nNext
= STRING_NOTFOUND
; // Default fuer nicht gefunden
217 while( (nLen
> n
) && (aData
.GetChar( n
) == ' ') )
220 if ( aData
.GetChar( n
) == 0x13 )
222 // Skip the nested field code since it's not supported
223 while ( ( nLen
> n
) && ( aData
.GetChar( n
) != 0x14 ) )
228 return STRING_NOTFOUND
; // String End reached!
230 if( (aData
.GetChar( n
) == '"') // Anfuehrungszeichen vor Para?
231 || (aData
.GetChar( n
) == 0x201c)
232 || (aData
.GetChar( n
) == 132)
233 || (aData
.GetChar( n
) == 0x14) )
235 n
++; // Anfuehrungszeichen ueberlesen
236 n2
= n
; // ab hier nach Ende suchen
238 && (aData
.GetChar( n2
) != '"')
239 && (aData
.GetChar( n2
) != 0x201d)
240 && (aData
.GetChar( n2
) != 147)
241 && (aData
.GetChar( n2
) != 0x15) )
242 n2
++; // Ende d. Paras suchen
244 else // keine Anfuehrungszeichen
246 n2
= n
; // ab hier nach Ende suchen
247 while( (nLen
> n2
) && (aData
.GetChar( n2
) != ' ') ) // Ende d. Paras suchen
249 if( aData
.GetChar( n2
) == '\\' )
251 if( aData
.GetChar( n2
+1 ) == '\\' )
252 n2
+= 2; // Doppel-Backslash -> OK
257 break; // einfach-Backslash -> Ende
261 n2
++; // kein Backslash -> OK
266 if(aData
.GetChar( n2
) != ' ') n2
++;
274 // read parameters "1-3" or 1-3 with both values between 1 and nMax
275 bool WW8ReadFieldParams::GetTokenSttFromTo(sal_uInt16
* pFrom
, sal_uInt16
* pTo
, sal_uInt16 nMax
)
277 sal_uInt16 nStart
= 0;
279 xub_StrLen n
= GoToTokenParam();
280 if( STRING_NOTFOUND
!= n
)
283 String
sParams( GetResult() );
285 sal_Int32 nIndex
= 0;
286 String
sStart( sParams
.GetToken(0, '-', nIndex
) );
289 nStart
= static_cast<sal_uInt16
>(sStart
.ToInt32());
290 nEnd
= static_cast<sal_uInt16
>(sParams
.Copy(nIndex
).ToInt32());
293 if( pFrom
) *pFrom
= nStart
;
294 if( pTo
) *pTo
= nEnd
;
296 return nStart
&& nEnd
&& (nMax
>= nStart
) && (nMax
>= nEnd
);
299 //----------------------------------------
301 //----------------------------------------
303 long SwWW8ImplReader::Read_Book(WW8PLCFManResult
*)
305 // muesste auch ueber pRes.nCo2OrIdx gehen
306 WW8PLCFx_Book
* pB
= pPlcxMan
->GetBook();
309 OSL_ENSURE( pB
, "WW8PLCFx_Book - Pointer nicht da" );
313 eBookStatus eB
= pB
->GetStatus();
314 if (eB
& BOOK_IGNORE
)
315 return 0; // Bookmark zu ignorieren
319 pReffedStck
->SetAttr(*pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true,
320 pB
->GetHandle(), (eB
& BOOK_FIELD
)!=0);
324 //"_Toc*" and "_Hlt*" are unnecessary
325 const String
* pName
= pB
->GetName();
326 #if !defined(WW_NATIVE_TOC)
327 if( !pName
|| pName
->EqualsIgnoreCaseAscii( "_Toc", 0, 4 )
328 || pName
->EqualsIgnoreCaseAscii( "_Hlt", 0, 4 ) )
332 //ToUpper darf auf keinen Fall gemacht werden, weil der Bookmark- name ein Hyperlink-Ziel sein kann!
335 if( SwFltGetFlag( nFieldFlags
, SwFltControlStack::BOOK_TO_VAR_REF
) )
337 // Fuer UEbersetzung Bookmark -> Variable setzen
338 long nLen
= pB
->GetLen();
339 if( nLen
> MAX_FIELDLEN
)
342 long nOldPos
= pStrm
->Tell();
343 nLen
= pSBase
->WW8ReadString( *pStrm
, aVal
, pB
->GetStartPos(), nLen
,
345 pStrm
->Seek( nOldPos
);
347 // now here the implementation of the old "QuoteString" and
348 // I hope with a better performance as before. It's also only
349 // needed if the filterflags say we will convert bookmarks
350 // to SetExpFields! And this the exception!
352 OUString
sHex("\\x");
354 bool bAllowCr
= SwFltGetFlag(nFieldFlags
,
355 SwFltControlStack::ALLOW_FLD_CR
) ? true : false;
359 for( xub_StrLen nI
= 0;
360 nI
< aVal
.Len() && aVal
.Len() < (MAX_FIELDLEN
- 4); ++nI
)
362 switch( cChar
= aVal
.GetChar( nI
) )
368 aVal
.SetChar( nI
, '\n' ), bSetAsHex
= false;
379 bSetAsHex
= 0x20 > cChar
;
385 //all Hex-Numbers with \x before
389 sTmp
+= OUString::number( cChar
, 16 );
390 aVal
.Replace( nI
, 1 , sTmp
);
391 nI
+= sTmp
.Len() - 1;
395 if( aVal
.Len() > (MAX_FIELDLEN
- 4))
396 aVal
.Erase( MAX_FIELDLEN
- 4 );
399 //e.g. inserting bookmark around field result, so we need to put
400 //it around the entire writer field, as we don't have the separation
401 //of field and field result of word, see #i16941#
402 SwPosition
aStart(*pPaM
->GetPoint());
403 if (!maFieldStack
.empty())
405 const WW8FieldEntry
&rTest
= maFieldStack
.back();
406 aStart
= rTest
.maStartPos
;
409 pReffedStck
->NewAttr(aStart
, SwFltBookmark(BookmarkToWriter(*pName
), aVal
,
410 pB
->GetHandle(), 0));
414 //----------------------------------------------------------------------
415 // allgemeine Hilfsroutinen zum Auseinanderdroeseln der Parameter
416 //----------------------------------------------------------------------
418 // ConvertFFileName uebersetzt FeldParameter-Namen u. ae. in den
419 // System-Zeichensatz.
420 // Gleichzeitig werden doppelte Backslashes in einzelne uebersetzt.
421 void SwWW8ImplReader::ConvertFFileName( String
& rName
, const String
& rOrg
)
424 rName
.SearchAndReplaceAllAscii( "\\\\", OUString( '\\' ));
425 rName
.SearchAndReplaceAllAscii( "%20", OUString( ' ' ));
427 // ggfs. anhaengende Anfuehrungszeichen entfernen
428 if( rName
.Len() && '"' == rName
.GetChar( rName
.Len()-1 ))
429 rName
.Erase( rName
.Len()-1, 1);
431 // Need the more sophisticated url converter. cmc
433 rName
= URIHelper::SmartRel2Abs(
434 INetURLObject(sBaseURL
), rName
, Link(), false);
437 // ConvertUFNneme uebersetzt FeldParameter-Namen u. ae. in den
438 // System-Zeichensatz und Upcased sie ( z.B. fuer Ref-Felder )
441 void ConvertUFName( String
& rName
)
443 rName
= GetAppCharClass().uppercase( rName
);
447 static void lcl_ConvertSequenceName(String
& rSequenceName
)
449 ConvertUFName(rSequenceName
);
450 if ('0' <= rSequenceName
.GetChar(0) && '9' >= rSequenceName
.GetChar(0))
451 rSequenceName
.Insert('_', 0);
454 // FindParaStart() finds 1st Parameter that follows '\' and cToken
455 // and returns start of this parameter or STRING_NOT_FOUND.
456 xub_StrLen
FindParaStart( const String
& rStr
, sal_Unicode cToken
, sal_Unicode cToken2
)
458 bool bStr
= false; // innerhalb String ignorieren
460 for( xub_StrLen nBuf
=0; nBuf
+1 < rStr
.Len(); nBuf
++ )
462 if( rStr
.GetChar( nBuf
) == '"' )
466 && rStr
.GetChar( nBuf
) == '\\'
467 && ( rStr
.GetChar( nBuf
+ 1 ) == cToken
468 || rStr
.GetChar( nBuf
+ 1 ) == cToken2
) )
471 // skip spaces between cToken and it's parameters
472 while( nBuf
< rStr
.Len()
473 && rStr
.GetChar( nBuf
) == ' ' )
475 // return start of parameters
476 return nBuf
< rStr
.Len() ? nBuf
: STRING_NOTFOUND
;
479 return STRING_NOTFOUND
;
482 // FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
483 // ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
484 // und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
485 String
FindPara( const String
& rStr
, sal_Unicode cToken
, sal_Unicode cToken2
)
487 xub_StrLen n2
; // Ende
488 xub_StrLen n
= FindParaStart( rStr
, cToken
, cToken2
); // Anfang
489 if( STRING_NOTFOUND
== n
)
492 if( rStr
.GetChar( n
) == '"'
493 || rStr
.GetChar( n
) == 132 )
494 { // Anfuehrungszeichen vor Para
495 n
++; // Anfuehrungszeichen ueberlesen
496 n2
= n
; // ab hier nach Ende suchen
497 while( n2
< rStr
.Len()
498 && rStr
.GetChar( n2
) != 147
499 && rStr
.GetChar( n2
) != '"' )
500 n2
++; // Ende d. Paras suchen
503 { // keine Anfuehrungszeichen
504 n2
= n
; // ab hier nach Ende suchen
505 while( n2
< rStr
.Len()
506 && rStr
.GetChar( n2
) != ' ' )
507 n2
++; // Ende d. Paras suchen
509 return rStr
.Copy( n
, n2
-n
);
513 static SvxExtNumType
GetNumTypeFromName(const String
& rStr
,
514 bool bAllowPageDesc
= false)
516 SvxExtNumType eTyp
= bAllowPageDesc
? SVX_NUM_PAGEDESC
: SVX_NUM_ARABIC
;
517 if( rStr
.EqualsIgnoreCaseAscii( "Arabi", 0, 5 ) ) // Arabisch, Arabic
518 eTyp
= SVX_NUM_ARABIC
;
519 else if( rStr
.EqualsAscii( "misch", 2, 5 ) ) // r"omisch
520 eTyp
= SVX_NUM_ROMAN_LOWER
;
521 else if( rStr
.EqualsAscii( "MISCH", 2, 5 ) ) // R"OMISCH
522 eTyp
= SVX_NUM_ROMAN_UPPER
;
523 else if( rStr
.EqualsIgnoreCaseAscii( "alphabeti", 0, 9 ) )// alphabetisch, alphabetic
524 eTyp
= ( rStr
.GetChar( 0 ) == 'A' )
525 ? SVX_NUM_CHARS_UPPER_LETTER_N
526 : SVX_NUM_CHARS_LOWER_LETTER_N
;
527 else if( rStr
.EqualsIgnoreCaseAscii( "roman", 0, 5 ) ) // us
528 eTyp
= ( rStr
.GetChar( 0 ) == 'R' )
529 ? SVX_NUM_ROMAN_UPPER
530 : SVX_NUM_ROMAN_LOWER
;
534 static SvxExtNumType
GetNumberPara(String
& rStr
, bool bAllowPageDesc
= false)
536 String
s( FindPara( rStr
, '*', '*' ) ); // Ziffernart
537 SvxExtNumType aType
= GetNumTypeFromName( s
, bAllowPageDesc
);
544 bool SwWW8ImplReader::ForceFieldLanguage(SwField
&rFld
, sal_uInt16 nLang
)
548 const SvxLanguageItem
*pLang
=
549 (const SvxLanguageItem
*)GetFmtAttr(RES_CHRATR_LANGUAGE
);
550 OSL_ENSURE(pLang
, "impossible");
551 sal_uInt16 nDefault
= pLang
? pLang
->GetValue() : LANGUAGE_ENGLISH_US
;
553 if (nLang
!= nDefault
)
555 rFld
.SetAutomaticLanguage(false);
556 rFld
.SetLanguage(nLang
);
563 String
GetWordDefaultDateStringAsUS(SvNumberFormatter
* pFormatter
, sal_uInt16 nLang
)
565 //Get the system date in the correct final language layout, convert to
566 //a known language and modify the 2 digit year part to be 4 digit, and
567 //convert back to the correct language layout.
568 sal_uLong nIndex
= pFormatter
->GetFormatIndex(NF_DATE_SYSTEM_SHORT
, nLang
);
570 SvNumberformat aFormat
= const_cast<SvNumberformat
&>
571 (*(pFormatter
->GetEntry(nIndex
)));
572 aFormat
.ConvertLanguage(*pFormatter
, nLang
, LANGUAGE_ENGLISH_US
);
574 String
sParams(aFormat
.GetFormatstring());
576 // Fix provided by mloiseleur@openoffice.org.
577 // A default date can have already 4 year digits, in some case
578 const xub_StrLen pos
= sParams
.Search(OUString("YYYY"));
579 if ( pos
== STRING_NOTFOUND
)
581 sParams
.SearchAndReplace(OUString("YY"), OUString("YYYY"));
586 short SwWW8ImplReader::GetTimeDatePara(String
& rStr
, sal_uInt32
& rFormat
,
587 sal_uInt16
&rLang
, int nWhichDefault
, bool bHijri
)
590 if (pPlcxMan
&& !bVer67
)
592 const sal_uInt8
*pResult
= pPlcxMan
->HasCharSprm(0x85A);
593 if (pResult
&& *pResult
)
596 RES_CHRATR eLang
= bRTL
? RES_CHRATR_CTL_LANGUAGE
: RES_CHRATR_LANGUAGE
;
597 const SvxLanguageItem
*pLang
= (SvxLanguageItem
*)GetFmtAttr( static_cast< sal_uInt16
>(eLang
));
598 OSL_ENSURE(pLang
, "impossible");
599 rLang
= pLang
? pLang
->GetValue() : LANGUAGE_ENGLISH_US
;
601 SvNumberFormatter
* pFormatter
= rDoc
.GetNumberFormatter();
602 String
sParams( FindPara( rStr
, '@', '@' ) );// Date/Time
605 bool bHasTime
= false;
606 switch (nWhichDefault
)
610 sParams
= GetWordDefaultDateStringAsUS(pFormatter
, rLang
);
611 sParams
.AppendAscii(" HH:MM:SS AM/PM");
614 case ww::eCREATEDATE
:
615 sParams
.AssignAscii("DD/MM/YYYY HH:MM:SS");
620 sParams
= GetWordDefaultDateStringAsUS(pFormatter
, rLang
);
625 sParams
.Insert(OUString("[~hijri]"), 0);
627 sal_Int32 nCheckPos
= 0;
628 short nType
= NUMBERFORMAT_DEFINED
;
631 OUString
sTemp(sParams
);
632 pFormatter
->PutandConvertEntry(sTemp
, nCheckPos
, nType
, rFormat
,
633 LANGUAGE_ENGLISH_US
, rLang
);
636 return bHasTime
? NUMBERFORMAT_DATETIME
: NUMBERFORMAT_DATE
;
640 sw::ms::MSDateTimeFormatToSwFormat(sParams
, pFormatter
, rLang
, bHijri
,
642 short nNumFmtType
= NUMBERFORMAT_UNDEFINED
;
644 nNumFmtType
= pFormatter
->GetType(nFmtIdx
);
650 //-----------------------------------------
652 //-----------------------------------------
653 // Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
654 void SwWW8ImplReader::UpdateFields()
656 rDoc
.SetUpdateExpFldStat(true); // JP: neu fuer alles wichtige
657 rDoc
.SetInitDBFields(true); // Datenbank-Felder auch
660 sal_uInt16
SwWW8ImplReader::End_Field()
663 WW8PLCFx_FLD
* pF
= pPlcxMan
->GetFld();
664 OSL_ENSURE(pF
, "WW8PLCFx_FLD - Pointer nicht da");
665 if (!pF
|| !pF
->EndPosIsFieldEnd())
668 const SvtFilterOptions
&rOpt
= SvtFilterOptions::Get();
669 sal_Bool bUseEnhFields
= rOpt
.IsUseEnhancedFields();
671 OSL_ENSURE(!maFieldStack
.empty(), "Empty field stack\n");
672 if (!maFieldStack
.empty())
675 only hyperlinks currently need to be handled like this, for the other
676 cases we have inserted a field not an attribute with an unknown end
679 nRet
= maFieldStack
.back().mnFieldId
;
683 if (bUseEnhFields
&& pPaM
!=NULL
&& pPaM
->GetPoint()!=NULL
) {
684 SwPosition aEndPos
= *pPaM
->GetPoint();
685 SwPaM
aFldPam( maFieldStack
.back().GetPtNode(), maFieldStack
.back().GetPtCntnt(), aEndPos
.nNode
, aEndPos
.nContent
.GetIndex());
686 IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess( );
687 IFieldmark
*pFieldmark
= dynamic_cast<IFieldmark
*>( pMarksAccess
->makeFieldBookmark(
688 aFldPam
, maFieldStack
.back().GetBookmarkName(), ODF_FORMTEXT
) );
689 OSL_ENSURE(pFieldmark
!=NULL
, "hmmm; why was the bookmark not created?");
690 if (pFieldmark
!=NULL
) {
691 const IFieldmark::parameter_map_t
& pParametersToAdd
= maFieldStack
.back().getParameters();
692 pFieldmark
->GetParameters()->insert(pParametersToAdd
.begin(), pParametersToAdd
.end());
696 #if defined(WW_NATIVE_TOC)
698 case 13: // TOX_CONTENT
699 case 88: // HYPERLINK
701 if (pPaM
!=NULL
&& pPaM
->GetPoint()!=NULL
) {
703 SwPosition aEndPos
= *pPaM
->GetPoint();
704 SwPaM
aFldPam( maFieldStack
.back().GetPtNode(), maFieldStack
.back().GetPtCntnt(), aEndPos
.nNode
, aEndPos
.nContent
.GetIndex());
705 SwFieldBookmark
*pFieldmark
=(SwFieldBookmark
*)rDoc
.makeFieldBookmark(aFldPam
, maFieldStack
.back().GetBookmarkName(), maFieldStack
.back().GetBookmarkType());
706 OSL_ENSURE(pFieldmark
!=NULL
, "hmmm; why was the bookmark not created?");
707 if (pFieldmark
!=NULL
) {
708 const IFieldmark::parameter_map_t
& pParametersToAdd
= maFieldStack
.back().getParameters();
709 pFieldmark
->GetParameters()->insert(pParameters
.begin(), pParameters
.end());
715 pCtrlStck
->SetAttr(*pPaM
->GetPoint(),RES_TXTATR_INETFMT
);
720 //Move outside the section associated with this type of field
721 *pPaM
->GetPoint() = maFieldStack
.back().maStartPos
;
724 OUString aCode
= maFieldStack
.back().GetBookmarkCode();
725 if ( !aCode
.isEmpty() )
727 // Unhandled field with stored code
728 SwPosition aEndPos
= *pPaM
->GetPoint();
730 maFieldStack
.back().GetPtNode(), maFieldStack
.back().GetPtCntnt(),
731 aEndPos
.nNode
, aEndPos
.nContent
.GetIndex());
733 IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess( );
735 IFieldmark
* pFieldmark
= pMarksAccess
->makeFieldBookmark(
737 maFieldStack
.back().GetBookmarkName(),
741 const IFieldmark::parameter_map_t
& pParametersToAdd
= maFieldStack
.back().getParameters();
742 pFieldmark
->GetParameters()->insert(pParametersToAdd
.begin(), pParametersToAdd
.end());
743 OUString sFieldId
= OUString::valueOf( sal_Int32( maFieldStack
.back().mnFieldId
) );
744 pFieldmark
->GetParameters()->insert(
745 std::pair
< OUString
, uno::Any
> (
747 uno::makeAny( sFieldId
) ) );
748 pFieldmark
->GetParameters()->insert(
749 std::pair
< OUString
, uno::Any
> (
751 uno::makeAny( aCode
) ) );
753 if ( maFieldStack
.back().mnObjLocFc
> 0 )
755 // Store the OLE object as an internal link
756 String sOleId
= OUString('_');
757 sOleId
+= OUString::number( maFieldStack
.back().mnObjLocFc
);
759 SvStorageRef xSrc0
= pStg
->OpenSotStorage(OUString(SL::aObjectPool
));
760 SvStorageRef xSrc1
= xSrc0
->OpenSotStorage( sOleId
, STREAM_READ
);
763 uno::Reference
< embed::XStorage
> xDocStg
= GetDoc().GetDocStorage();
766 uno::Reference
< embed::XStorage
> xOleStg
= xDocStg
->openStorageElement(
767 "OLELinks", embed::ElementModes::WRITE
);
768 SotStorageRef xObjDst
= SotStorage::OpenOLEStorage( xOleStg
, sOleId
);
772 xSrc1
->CopyTo( xObjDst
);
774 if ( !xObjDst
->GetError() )
778 uno::Reference
< embed::XTransactedObject
> xTransact( xOleStg
, uno::UNO_QUERY
);
779 if ( xTransact
.is() )
783 // Store the OLE Id as a parameter
784 pFieldmark
->GetParameters()->insert(
785 std::pair
< OUString
, uno::Any
>(
786 ODF_OLE_PARAM
, uno::makeAny( OUString( sOleId
) ) ) );
794 maFieldStack
.pop_back();
799 bool AcceptableNestedField(sal_uInt16 nFieldCode
)
803 #if defined(WW_NATIVE_TOC)
804 case 8: // allow recursive field in TOC...
805 case 13: // allow recursive field in TOC...
811 // Accept AutoTextList field as nested field.
812 // Thus, the field result is imported as plain text.
820 WW8FieldEntry::WW8FieldEntry(SwPosition
&rPos
, sal_uInt16 nFieldId
) throw()
821 : maStartPos(rPos
), mnFieldId(nFieldId
), mnObjLocFc(0)
825 WW8FieldEntry::WW8FieldEntry(const WW8FieldEntry
&rOther
) throw()
826 : maStartPos(rOther
.maStartPos
), mnFieldId(rOther
.mnFieldId
), mnObjLocFc(rOther
.mnObjLocFc
)
830 void WW8FieldEntry::Swap(WW8FieldEntry
&rOther
) throw()
832 std::swap(maStartPos
, rOther
.maStartPos
);
833 std::swap(mnFieldId
, rOther
.mnFieldId
);
836 WW8FieldEntry
&WW8FieldEntry::operator=(const WW8FieldEntry
&rOther
) throw()
838 WW8FieldEntry
aTemp(rOther
);
843 OUString
WW8FieldEntry::GetBookmarkName()
845 return msBookmarkName
;
848 OUString
WW8FieldEntry::GetBookmarkCode()
853 void WW8FieldEntry::SetBookmarkName(OUString bookmarkName
)
855 msBookmarkName
=bookmarkName
;
858 void WW8FieldEntry::SetBookmarkType(OUString bookmarkType
)
860 msMarkType
=bookmarkType
;
863 void WW8FieldEntry::SetBookmarkCode(OUString bookmarkCode
)
865 msMarkCode
= bookmarkCode
;
869 ::sw::mark::IFieldmark::parameter_map_t
& WW8FieldEntry::getParameters() {
874 // Read_Field liest ein Feld ein oder, wenn es nicht gelesen werden kann,
875 // wird 0 zurueckgegeben, so dass das Feld vom Aufrufer textuell gelesen wird.
876 // Returnwert: Gesamtlaenge des Feldes ( zum UEberlesen )
877 long SwWW8ImplReader::Read_Field(WW8PLCFManResult
* pRes
)
879 typedef eF_ResT (SwWW8ImplReader:: *FNReadField
)( WW8FieldDesc
*, String
& );
880 enum Limits
{eMax
= 96};
881 static FNReadField aWW8FieldTab
[eMax
+1] =
884 &SwWW8ImplReader::Read_F_Input
,
886 &SwWW8ImplReader::Read_F_Ref
, // 3
889 &SwWW8ImplReader::Read_F_Set
, // 6
891 &SwWW8ImplReader::Read_F_Tox
, // 8
895 &SwWW8ImplReader::Read_F_Seq
, // 12
896 &SwWW8ImplReader::Read_F_Tox
, // 13
897 &SwWW8ImplReader::Read_F_DocInfo
, // 14
898 &SwWW8ImplReader::Read_F_DocInfo
, // 15
899 &SwWW8ImplReader::Read_F_DocInfo
, // 16
900 &SwWW8ImplReader::Read_F_Author
, // 17
901 &SwWW8ImplReader::Read_F_DocInfo
, // 18
902 &SwWW8ImplReader::Read_F_DocInfo
, // 19
903 &SwWW8ImplReader::Read_F_DocInfo
, // 20
904 &SwWW8ImplReader::Read_F_DocInfo
, // 21
905 &SwWW8ImplReader::Read_F_DocInfo
, // 22
906 &SwWW8ImplReader::Read_F_DocInfo
, // 23
907 &SwWW8ImplReader::Read_F_DocInfo
, // 24
908 &SwWW8ImplReader::Read_F_DocInfo
, // 25
909 &SwWW8ImplReader::Read_F_Anz
, // 26
910 &SwWW8ImplReader::Read_F_Anz
, // 27
911 &SwWW8ImplReader::Read_F_Anz
, // 28
912 &SwWW8ImplReader::Read_F_FileName
, // 29
913 &SwWW8ImplReader::Read_F_TemplName
, // 30
914 &SwWW8ImplReader::Read_F_DateTime
, // 31
915 &SwWW8ImplReader::Read_F_DateTime
, // 32
916 &SwWW8ImplReader::Read_F_CurPage
, // 33
919 &SwWW8ImplReader::Read_F_IncludeText
, // 36
920 &SwWW8ImplReader::Read_F_PgRef
, // 37
921 &SwWW8ImplReader::Read_F_InputVar
, // 38
922 &SwWW8ImplReader::Read_F_Input
, // 39
924 &SwWW8ImplReader::Read_F_DBNext
, // 41
927 &SwWW8ImplReader::Read_F_DBNum
, // 44
932 &SwWW8ImplReader::Read_F_Equation
, // 49
934 &SwWW8ImplReader::Read_F_Macro
, // 51
935 &SwWW8ImplReader::Read_F_ANumber
, // 52
936 &SwWW8ImplReader::Read_F_ANumber
, // 53
937 &SwWW8ImplReader::Read_F_ANumber
, // 54
944 &SwWW8ImplReader::Read_F_Symbol
, // 57
945 &SwWW8ImplReader::Read_F_Embedd
, // 58
946 &SwWW8ImplReader::Read_F_DBField
, // 59
951 &SwWW8ImplReader::Read_F_DocInfo
, // 64 - DOCVARIABLE
954 &SwWW8ImplReader::Read_F_IncludePicture
, // 67
955 &SwWW8ImplReader::Read_F_IncludeText
, // 68
957 &SwWW8ImplReader::Read_F_FormTextBox
, // 70
958 &SwWW8ImplReader::Read_F_FormCheckBox
, // 71
959 &SwWW8ImplReader::Read_F_NoteReference
, // 72
960 0, /*&SwWW8ImplReader::Read_F_Tox*/
970 &SwWW8ImplReader::Read_F_FormListBox
, // 83
972 &SwWW8ImplReader::Read_F_DocInfo
, // 85
974 &SwWW8ImplReader::Read_F_OCX
, // 87
975 &SwWW8ImplReader::Read_F_Hyperlink
, // 88
978 &SwWW8ImplReader::Read_F_HTMLControl
, // 91
982 &SwWW8ImplReader::Read_F_Shape
, // 95
983 0 // eMax - Dummy leer Methode
985 OSL_ENSURE( ( sizeof( aWW8FieldTab
) / sizeof( *aWW8FieldTab
) == eMax
+1 ),
986 "FeldFunc-Tabelle stimmt nicht" );
988 WW8PLCFx_FLD
* pF
= pPlcxMan
->GetFld();
989 OSL_ENSURE(pF
, "WW8PLCFx_FLD - Pointer nicht da");
991 if (!pF
|| !pF
->StartPosIsFieldStart())
994 bool bNested
= false;
995 if (!maFieldStack
.empty())
997 mycFieldIter aEnd
= maFieldStack
.end();
998 for(mycFieldIter aIter
= maFieldStack
.begin(); aIter
!= aEnd
; ++aIter
)
1000 bNested
= !AcceptableNestedField(aIter
->mnFieldId
);
1007 bool bOk
= pF
->GetPara(pRes
->nCp2OrIdx
, aF
);
1009 OSL_ENSURE(bOk
, "WW8: Bad Field!\n");
1010 if (aF
.nId
== 33) aF
.bCodeNest
=false; // do not recurse into nested page fields
1011 bool bCodeNest
= aF
.bCodeNest
;
1012 if ( aF
.nId
== 6 ) bCodeNest
= false; // We can handle them and loose the inner data
1014 maFieldStack
.push_back(WW8FieldEntry(*pPaM
->GetPoint(), aF
.nId
));
1019 sal_uInt16 n
= (aF
.nId
<= eMax
) ? aF
.nId
: static_cast<sal_uInt16
>(eMax
);
1020 sal_uInt16 nI
= n
/ 32; // # des sal_uInt32
1021 sal_uLong nMask
= 1 << ( n
% 32 ); // Maske fuer Bits
1023 if ((sizeof(nFieldTagAlways
)/sizeof(nFieldTagAlways
[0])) <= nI
)
1024 { // if indexes larger than 95 are needed, then a new configuration
1025 // item has to be added, and nFieldTagAlways/nFieldTagBad expanded!
1029 if( nFieldTagAlways
[nI
] & nMask
) // Flag: Tag it
1030 return Read_F_Tag( &aF
); // Resultat nicht als Text
1032 if( !bOk
|| !aF
.nId
) // Feld kaputt
1033 return aF
.nLen
; // -> ignorieren
1035 if( aF
.nId
> eMax
- 1) // WW: Nested Field
1037 if( nFieldTagBad
[nI
] & nMask
) // Flag: Tag it when bad
1038 return Read_F_Tag( &aF
); // Resultat nicht als Text
1043 //Only one type of field (hyperlink) in drawing textboxes exists
1044 if (aF
.nId
!= 88 && pPlcxMan
&& pPlcxMan
->GetDoingDrawTextBox())
1047 // keine Routine vorhanden
1048 if (bNested
|| !aWW8FieldTab
[aF
.nId
] || bCodeNest
)
1050 if( nFieldTagBad
[nI
] & nMask
) // Flag: Tag it when bad
1051 return Read_F_Tag( &aF
); // Resultat nicht als Text
1052 // Lese nur Resultat
1053 if (aF
.bResNest
&& !AcceptableNestedField(aF
.nId
))
1054 return aF
.nLen
; // Result nested -> nicht brauchbar
1056 long nOldPos
= pStrm
->Tell();
1058 aF
.nLCode
= pSBase
->WW8ReadString( *pStrm
, aStr
, pPlcxMan
->GetCpOfs()+
1059 aF
.nSCode
, aF
.nLCode
, eTextCharSet
);
1060 pStrm
->Seek( nOldPos
);
1062 // field codes which contain '/' or '.' are not displayed in WinWord
1063 // skip if it is formula field or found space before. see #i119446, #i119585.
1064 const xub_StrLen nDotPos
= aStr
.Search('.');
1065 const xub_StrLen nSlashPos
= aStr
.Search('/');
1066 xub_StrLen nSpacePos
= aStr
.Search( ' ', 1 );
1067 if ( nSpacePos
== STRING_NOTFOUND
)
1068 nSpacePos
= aStr
.Len();
1070 if ( !( aStr
.EqualsAscii( "=", 1, 1 ) ) &&
1071 ((( nDotPos
!= STRING_NOTFOUND
) && ( nDotPos
< nSpacePos
)) ||
1072 (( nSlashPos
!= STRING_NOTFOUND
) && ( nSlashPos
< nSpacePos
))))
1076 // Link fields aren't supported, but they are bound to an OLE object
1077 // that needs to be roundtripped
1080 // Field not supported: store the field code for later use
1081 maFieldStack
.back().SetBookmarkCode( aStr
);
1082 return aF
.nLen
- aF
.nLRes
- 1; // so viele ueberlesen, das Resultfeld
1083 // wird wie Haupttext eingelesen
1088 long nOldPos
= pStrm
->Tell();
1090 if ( aF
.nId
== 6 && aF
.bCodeNest
)
1092 // TODO Extract the whole code string using the nested codes
1093 aF
.nLCode
= pSBase
->WW8ReadString( *pStrm
, aStr
, pPlcxMan
->GetCpOfs() +
1094 aF
.nSCode
, aF
.nSRes
- aF
.nSCode
- 1, eTextCharSet
);
1098 aF
.nLCode
= pSBase
->WW8ReadString( *pStrm
, aStr
, pPlcxMan
->GetCpOfs()+
1099 aF
.nSCode
, aF
.nLCode
, eTextCharSet
);
1102 // #i51312# - graphics inside field code not supported by Writer.
1103 // Thus, delete character 0x01, which stands for such a graphic.
1104 if (aF
.nId
==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
1106 aStr
= comphelper::string::remove(aStr
, 0x01);
1109 eF_ResT eRes
= (this->*aWW8FieldTab
[aF
.nId
])( &aF
, aStr
);
1110 pStrm
->Seek( nOldPos
);
1115 return aF
.nLen
; // alles OK
1117 if ((nFieldTagBad
[nI
] & nMask
)) // Flag: Tag bad
1118 return Read_F_Tag(&aF
); // Taggen
1121 // so viele ueberlesen, das Resultfeld wird wie Haupttext
1123 // attributes can start at char 0x14 so skip one
1124 // char more back == "-2"
1126 return aF
.nLen
- aF
.nLRes
- 2;
1130 if( ( nFieldTagBad
[nI
] & nMask
) ) // Flag: Tag bad
1131 return Read_F_Tag( &aF
); // Taggen
1132 return aF
.nLen
; // oder ignorieren
1134 return aF
.nLen
- aF
.nLRes
- 2; // auf Char 1 positionieren
1136 return aF
.nLen
; // ignorieren
1141 //-----------------------------------------
1143 //-----------------------------------------
1145 // MakeTagString() gibt als Returnwert die Position des ersten
1146 // CR / Zeilenende / Seitenumbruch in pText und wandelt auch nur bis dort
1147 // Wenn keins dieser Sonderzeichen enthalten ist, wird 0 zurueckgeliefert.
1148 void SwWW8ImplReader::MakeTagString( String
& rStr
, const String
& rOrg
)
1150 OUString
sHex("\\x");
1151 bool bAllowCr
= SwFltGetFlag( nFieldFlags
, SwFltControlStack::TAGS_IN_TEXT
)
1152 || SwFltGetFlag( nFieldFlags
, SwFltControlStack::ALLOW_FLD_CR
);
1156 for( xub_StrLen nI
= 0;
1157 nI
< rStr
.Len() && rStr
.Len() < (MAX_FIELDLEN
- 4); ++nI
)
1159 bool bSetAsHex
= false;
1160 switch( cChar
= rStr
.GetChar( nI
) )
1162 case 132: // Typographische Anfuehrungszeichen
1163 case 148: // gegen normale tauschen
1165 rStr
.SetChar( nI
, '"' );
1168 rStr
.SetChar( nI
, '{' );
1169 break; // 19..21 zu {|}
1171 rStr
.SetChar( nI
, '|' );
1174 rStr
.SetChar( nI
, '}' );
1176 case '\\': // \{|} per \ Taggen
1180 rStr
.Insert( nI
, '\\' );
1187 rStr
.SetChar( nI
, '\n' );
1196 bSetAsHex
= 0x20 > cChar
;
1202 //all Hex-Numbers with \x before
1203 String
sTmp( sHex
);
1206 sTmp
+= OUString::number( cChar
, 16 );
1207 rStr
.Replace( nI
, 1 , sTmp
);
1208 nI
+= sTmp
.Len() - 1;
1212 if( rStr
.Len() > (MAX_FIELDLEN
- 4))
1213 rStr
.Erase( MAX_FIELDLEN
- 4 );
1216 void SwWW8ImplReader::InsertTagField( const sal_uInt16 nId
, const String
& rTagText
)
1218 String
aName(OUString("WwFieldTag"));
1219 if( SwFltGetFlag( nFieldFlags
, SwFltControlStack::TAGS_DO_ID
) ) // Nummer?
1220 aName
+= OUString::number( nId
); // ausgeben ?
1222 if( SwFltGetFlag(nFieldFlags
, SwFltControlStack::TAGS_IN_TEXT
))
1224 aName
+= rTagText
; // als Txt taggen
1225 rDoc
.InsertString(*pPaM
, aName
,
1226 IDocumentContentOperations::INS_NOHINTEXPAND
);
1231 SwFieldType
* pFT
= rDoc
.InsertFldType(
1232 SwSetExpFieldType( &rDoc
, aName
, nsSwGetSetExpType::GSE_STRING
) );
1233 SwSetExpField
aFld( (SwSetExpFieldType
*)pFT
, rTagText
); // SUB_INVISIBLE
1234 sal_uInt16 nSubType
= ( SwFltGetFlag( nFieldFlags
, SwFltControlStack::TAGS_VISIBLE
) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE
;
1235 aFld
.SetSubType(nSubType
| nsSwGetSetExpType::GSE_STRING
);
1237 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1241 long SwWW8ImplReader::Read_F_Tag( WW8FieldDesc
* pF
)
1243 long nOldPos
= pStrm
->Tell();
1245 WW8_CP nStart
= pF
->nSCode
- 1; // mit 0x19 am Anfang
1246 long nL
= pF
->nLen
; // Gesamtlaenge mit Resultat u. Nest
1247 if( nL
> MAX_FIELDLEN
)
1248 nL
= MAX_FIELDLEN
; // MaxLaenge, durch Quoten
1251 nL
= pSBase
->WW8ReadString( *pStrm
, sFTxt
,
1252 pPlcxMan
->GetCpOfs() + nStart
, nL
, eStructCharSet
);
1256 MakeTagString( aTagText
, sFTxt
);
1257 InsertTagField( pF
->nId
, aTagText
);
1259 pStrm
->Seek( nOldPos
);
1264 //-----------------------------------------
1266 //-----------------------------------------
1268 eF_ResT
SwWW8ImplReader::Read_F_Input( WW8FieldDesc
* pF
, String
& rStr
)
1273 WW8ReadFieldParams
aReadParam( rStr
);
1274 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1280 aQ
= aReadParam
.GetResult();
1285 xub_StrLen n
= aReadParam
.GoToTokenParam();
1286 if( STRING_NOTFOUND
!= n
)
1287 aDef
= aReadParam
.GetResult();
1293 aDef
= GetFieldResult( pF
);
1295 if ( pF
->nId
!= 0x01 ) // 0x01 fields have no result
1297 SwInputField
aFld( (SwInputFieldType
*)rDoc
.GetSysFldType( RES_INPUTFLD
),
1298 aDef
, aQ
, INP_TXT
, 0 ); // sichtbar ( geht z.Zt. nicht anders )
1299 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1305 // GetFieldResult alloziert einen String und liest das Feld-Resultat ein
1306 String
SwWW8ImplReader::GetFieldResult( WW8FieldDesc
* pF
)
1308 long nOldPos
= pStrm
->Tell();
1310 WW8_CP nStart
= pF
->nSRes
; // Start Resultat
1311 long nL
= pF
->nLRes
; // Laenge Resultat
1313 return aEmptyStr
; // kein Resultat
1315 if( nL
> MAX_FIELDLEN
)
1316 nL
= MAX_FIELDLEN
; // MaxLaenge, durch Quoten
1320 nL
= pSBase
->WW8ReadString( *pStrm
, sRes
, pPlcxMan
->GetCpOfs() + nStart
,
1321 nL
, eStructCharSet
);
1323 pStrm
->Seek( nOldPos
);
1325 //replace CR 0x0D with LF 0x0A
1326 sRes
.SearchAndReplaceAll(0x0D, 0x0A);
1327 //replace VT 0x0B with LF 0x0A
1328 sRes
.SearchAndReplaceAll(0x0B, 0x0A);
1333 Bookmarks can be set with fields SET and ASK, and they can be referenced with
1334 REF. When set, they behave like variables in writer, otherwise they behave
1335 like normal bookmarks. We can check whether we should use a show variable
1336 instead of a normal bookmark ref by converting to "show variable" at the end
1337 of the document those refs which look for the content of a bookmark but whose
1338 bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
1340 The other piece of the puzzle is that refs that point to the "location" of the
1341 bookmark will in word actually point to the last location where the bookmark
1342 was set with SET or ASK, not the actual bookmark. This is only noticable when
1343 a document sets the bookmark more than once. This is because word places the
1344 true bookmark at the location of the last set, but the refs will display the
1345 position of the first set before the ref.
1347 So what we will do is
1349 1) keep a list of all bookmarks that were set, any bookmark names mentioned
1350 here that are refed by content will be converted to show variables.
1352 2) create pseudo bookmarks for every position that a bookmark is set with SET
1353 or ASK but has no existing bookmark. We can then keep a map from the original
1354 bookmark name to the new one. As we parse the document new pseudo names will
1355 replace the older ones, so the map always contains the bookmark of the
1356 location that msword itself would use.
1358 3) word's bookmarks are case insensitive, writers are not. So we need to
1359 map case different versions together, regardless of whether they are
1362 4) when a reference is (first) SET or ASK, the bookmark associated with it
1363 is placed around the 0x14 0x15 result part of the field. We will fiddle
1364 the placement to be the writer equivalent of directly before and after
1365 the field, which gives the same effect and meaning, to do so we must
1366 get any bookmarks in the field range, and begin them immediately before
1367 the set/ask field, and end them directly afterwards. MapBookmarkVariables
1368 returns an identifier of the bookmark attribute to close after inserting
1369 the appropriate set/ask field.
1371 long SwWW8ImplReader::MapBookmarkVariables(const WW8FieldDesc
* pF
,
1372 String
&rOrigName
, const String
&rData
)
1374 OSL_ENSURE(pPlcxMan
,"No pPlcxMan");
1377 If there was no bookmark associated with this set field, then we create a
1378 pseudo one and insert it in the document.
1381 pPlcxMan
->GetBook()->MapName(rOrigName
);
1382 String sName
= pPlcxMan
->GetBook()->GetBookmark(
1383 pF
->nSCode
, pF
->nSCode
+ pF
->nLen
, nIndex
);
1386 pPlcxMan
->GetBook()->SetStatus(nIndex
, BOOK_IGNORE
);
1391 sName
= OUString("WWSetBkmk");
1392 nNo
= pReffingStck
->aFieldVarNames
.size()+1;
1393 sName
+= OUString::number(nNo
);
1394 nNo
+= pPlcxMan
->GetBook()->GetIMax();
1396 pReffedStck
->NewAttr(*pPaM
->GetPoint(),
1397 SwFltBookmark(BookmarkToWriter(sName
), rData
, nNo
, 0));
1398 pReffingStck
->aFieldVarNames
[rOrigName
] = sName
;
1403 Word can set a bookmark with set or with ask, such a bookmark is equivalent to
1404 our variables, but until the end of a document we cannot be sure if a bookmark
1405 is a variable or not, at the end we will have a list of reference names which
1406 were set or asked, all bookmarks using the content of those bookmarks are
1407 converted to show variables, those that reference the position of the field
1408 can be left as references, because a bookmark is also inserted at the position
1409 of a set or ask field, either by word, or in some special cases by the import
1412 SwFltStackEntry
*SwWW8FltRefStack::RefToVar(const SwField
* pFld
,
1413 SwFltStackEntry
&rEntry
)
1415 SwFltStackEntry
*pRet
=0;
1416 if (pFld
&& RES_GETREFFLD
== pFld
->Which())
1418 //Get the name of the ref field, and see if actually a variable
1419 const String
&rName
= pFld
->GetPar1();
1420 ::std::map
<String
,String
,SwWW8FltRefStack::ltstr
>::const_iterator
1421 aResult
= aFieldVarNames
.find(rName
);
1423 if (aResult
!= aFieldVarNames
.end())
1425 SwGetExpField
aFld( (SwGetExpFieldType
*)
1426 pDoc
->GetSysFldType(RES_GETEXPFLD
), rName
, nsSwGetSetExpType::GSE_STRING
, 0);
1427 delete rEntry
.pAttr
;
1428 SwFmtFld
aTmp(aFld
);
1429 rEntry
.pAttr
= aTmp
.Clone();
1436 String
SwWW8ImplReader::GetMappedBookmark(const String
&rOrigName
)
1438 String
sName(BookmarkToWriter(rOrigName
));
1439 OSL_ENSURE(pPlcxMan
,"no pPlcxMan");
1440 pPlcxMan
->GetBook()->MapName(sName
);
1442 //See if there has been a variable set with this name, if so get
1443 //the pseudo bookmark name that was set with it.
1444 ::std::map
<String
,String
,SwWW8FltRefStack::ltstr
>::const_iterator aResult
=
1445 pReffingStck
->aFieldVarNames
.find(sName
);
1447 const String
&rBkmName
= (aResult
== pReffingStck
->aFieldVarNames
.end())
1448 ? sName
: (*aResult
).second
;
1454 eF_ResT
SwWW8ImplReader::Read_F_InputVar( WW8FieldDesc
* pF
, String
& rStr
)
1460 WW8ReadFieldParams
aReadParam( rStr
);
1461 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1466 if (!sOrigName
.Len())
1467 sOrigName
= aReadParam
.GetResult();
1468 else if( !aQ
.Len() )
1469 aQ
= aReadParam
.GetResult();
1473 if (STRING_NOTFOUND
!= aReadParam
.GoToTokenParam())
1474 aDef
= aReadParam
.GetResult();
1479 if( !sOrigName
.Len() )
1480 return FLD_TAGIGN
; // macht ohne Textmarke keinen Sinn
1482 String
aResult(GetFieldResult(pF
));
1484 //#i24377#, munge Default Text into title as we have only one slot
1485 //available for aResult and aDef otherwise
1489 aQ
.AppendAscii(" - ");
1493 long nNo
= MapBookmarkVariables(pF
, sOrigName
, aResult
);
1495 SwSetExpFieldType
* pFT
= (SwSetExpFieldType
*)rDoc
.InsertFldType(
1496 SwSetExpFieldType(&rDoc
, sOrigName
, nsSwGetSetExpType::GSE_STRING
));
1497 SwSetExpField
aFld(pFT
, aResult
);
1498 aFld
.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE
| nsSwGetSetExpType::GSE_STRING
);
1499 aFld
.SetInputFlag(true);
1500 aFld
.SetPromptText( aQ
);
1502 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1504 pReffedStck
->SetAttr(*pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true, nNo
);
1509 eF_ResT
SwWW8ImplReader::Read_F_ANumber( WW8FieldDesc
*, String
& rStr
)
1511 if( !pNumFldType
){ // 1. Mal
1512 SwSetExpFieldType
aT( &rDoc
, OUString("AutoNr"), nsSwGetSetExpType::GSE_SEQ
);
1513 pNumFldType
= rDoc
.InsertFldType( aT
);
1515 SwSetExpField
aFld( (SwSetExpFieldType
*)pNumFldType
, aEmptyStr
,
1516 GetNumberPara( rStr
) );
1517 aFld
.SetValue( ++nFldNum
);
1518 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1523 eF_ResT
SwWW8ImplReader::Read_F_Seq( WW8FieldDesc
*, String
& rStr
)
1525 String aSequenceName
;
1527 bool bCountOn
= true;
1529 SvxExtNumType eNumFormat
= SVX_NUM_ARABIC
;
1531 WW8ReadFieldParams
aReadParam( rStr
);
1532 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1537 if( !aSequenceName
.Len() )
1538 aSequenceName
= aReadParam
.GetResult();
1539 else if( !aBook
.Len() )
1540 aBook
= aReadParam
.GetResult();
1547 nRet
= aReadParam
.SkipToNextToken();
1548 if( -2 == nRet
&& !( aReadParam
.GetResult().EqualsAscii("MERGEFORMAT") || aReadParam
.GetResult().EqualsAscii("CHARFORMAT") ))
1549 eNumFormat
= GetNumTypeFromName( aReadParam
.GetResult() );
1554 nRet
= aReadParam
.SkipToNextToken();
1556 sStart
= aReadParam
.GetResult();
1564 bCountOn
= true; // Nummer um eins erhoehen (default)
1567 case 's': // Outline Level
1568 //#i19682, what am I to do with this value
1572 if (!aSequenceName
.Len() && !aBook
.Len())
1575 SwSetExpFieldType
* pFT
= (SwSetExpFieldType
*)rDoc
.InsertFldType(
1576 SwSetExpFieldType( &rDoc
, aSequenceName
, nsSwGetSetExpType::GSE_SEQ
) );
1577 SwSetExpField
aFld( pFT
, aEmptyStr
, eNumFormat
);
1580 aFld
.SetFormula( ( aSequenceName
+= '=' ) += sStart
);
1582 aFld
.SetFormula(aSequenceName
);
1584 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
1588 eF_ResT
SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc
* pF
, String
& rStr
)
1591 // RegInfoFormat, DefaultFormat fuer DocInfoFelder
1592 sal_uInt16 nReg
= DI_SUB_AUTHOR
;
1593 bool bDateTime
= false;
1597 String aDocProperty
;
1598 WW8ReadFieldParams
aReadParam( rStr
);
1600 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1605 if( !aDocProperty
.Len() )
1606 aDocProperty
= aReadParam
.GetResult();
1609 //Skip over MERGEFORMAT
1610 aReadParam
.SkipToNextToken();
1615 aDocProperty
= comphelper::string::remove(aDocProperty
, '"');
1618 There are up to 26 fields that may be meant by 'DocumentProperty'.
1619 Which of them is to be inserted here ?
1620 This Problem can only be solved by implementing a name matching
1621 method that compares the given Parameter String with the four
1622 possible name sets (english, german, french, spanish)
1625 static const sal_Char
* aName10
= "\x0F"; // SW field code
1626 static const sal_Char
* aName11
// German
1628 static const sal_Char
* aName12
// French
1630 static const sal_Char
* aName13
// English
1632 static const sal_Char
* aName14
// Spanish
1634 static const sal_Char
* aName20
= "\x15"; // SW filed code
1635 static const sal_Char
* aName21
// German
1637 static const sal_Char
* aName22
// French
1639 static const sal_Char
* aName23
// English
1641 static const sal_Char
* aName24
// Spanish
1643 static const sal_Char
* aName30
= "\x16"; // SW filed code
1644 static const sal_Char
* aName31
// German
1645 = "ZULETZTGESPEICHERTZEIT";
1646 static const sal_Char
* aName32
// French
1647 = "DERNIERENREGISTREMENT";
1648 static const sal_Char
* aName33
// English
1650 static const sal_Char
* aName34
// Spanish
1652 static const sal_Char
* aName40
= "\x17"; // SW filed code
1653 static const sal_Char
* aName41
// German
1654 = "ZULETZTGEDRUCKT";
1655 static const sal_Char
* aName42
// French
1656 = "DERNI\xC8" "REIMPRESSION";
1657 static const sal_Char
* aName43
// English
1659 static const sal_Char
* aName44
// Spanish
1661 static const sal_Char
* aName50
= "\x18"; // SW filed code
1662 static const sal_Char
* aName51
// German
1663 = "\xDC" "BERARBEITUNGSNUMMER";
1664 static const sal_Char
* aName52
// French
1665 = "NUM\xC9" "RODEREVISION";
1666 static const sal_Char
* aName53
// English
1668 static const sal_Char
* aName54
// Spanish
1670 static const sal_uInt16 nFldCnt
= 5;
1672 // additional fields are to be coded soon! :-)
1674 static const sal_uInt16 nLangCnt
= 4;
1675 static const sal_Char
*aNameSet_26
[nFldCnt
][nLangCnt
+1] =
1677 {aName10
, aName11
, aName12
, aName13
, aName14
},
1678 {aName20
, aName21
, aName22
, aName23
, aName24
},
1679 {aName30
, aName31
, aName32
, aName33
, aName34
},
1680 {aName40
, aName41
, aName42
, aName43
, aName44
},
1681 {aName50
, aName51
, aName52
, aName53
, aName54
}
1684 bool bFldFound
= false;
1686 for(sal_uInt16 nLIdx
=1; !bFldFound
&& (nLangCnt
> nLIdx
); ++nLIdx
)
1688 for(nFIdx
= 0; !bFldFound
&& (nFldCnt
> nFIdx
); ++nFIdx
)
1690 if( aDocProperty
.Equals( String( aNameSet_26
[nFIdx
][nLIdx
],
1691 RTL_TEXTENCODING_MS_1252
) ) )
1694 pF
->nId
= aNameSet_26
[nFIdx
][0][0];
1701 SwDocInfoField
aFld( (SwDocInfoFieldType
*)
1702 rDoc
.GetSysFldType( RES_DOCINFOFLD
), DI_CUSTOM
|nReg
, aDocProperty
, GetFieldResult( pF
) );
1703 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
1712 /* kann alle INFO-Vars!! */
1729 nReg
= DI_SUB_AUTHOR
;
1754 case 64: // DOCVARIABLE
1759 sal_uInt32 nFormat
= 0;
1761 sal_uInt16
nLang(0);
1764 short nDT
= GetTimeDatePara(rStr
, nFormat
, nLang
, pF
->nId
);
1767 case NUMBERFORMAT_DATE
:
1770 case NUMBERFORMAT_TIME
:
1773 case NUMBERFORMAT_DATETIME
:
1783 // Extract DOCVARIABLE varname
1784 if ( 64 == pF
->nId
)
1786 WW8ReadFieldParams
aReadParam( rStr
);
1788 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1794 aData
= aReadParam
.GetResult();
1797 //Skip over MERGEFORMAT
1798 aReadParam
.SkipToNextToken();
1803 aData
= comphelper::string::remove(aData
, '"');
1806 SwDocInfoField
aFld( (SwDocInfoFieldType
*)
1807 rDoc
.GetSysFldType( RES_DOCINFOFLD
), nSub
|nReg
, aData
, nFormat
);
1809 ForceFieldLanguage(aFld
, nLang
);
1810 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
1815 eF_ResT
SwWW8ImplReader::Read_F_Author( WW8FieldDesc
*, String
& )
1817 // SH: Das SwAuthorField bezeichnet nicht den urspruenglichen
1818 // Autor, sondern den aktuellen Benutzer, also besser ueber DocInfo
1819 SwDocInfoField
aFld( (SwDocInfoFieldType
*)
1820 rDoc
.GetSysFldType( RES_DOCINFOFLD
),
1821 DI_CREATE
|DI_SUB_AUTHOR
, String() );
1822 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1826 eF_ResT
SwWW8ImplReader::Read_F_TemplName( WW8FieldDesc
*, String
& )
1828 SwTemplNameField
aFld( (SwTemplNameFieldType
*)
1829 rDoc
.GetSysFldType( RES_TEMPLNAMEFLD
), FF_NAME
);
1830 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1834 // Sowohl das Datum- wie auch das Uhrzeit-Feld kann fuer Datum, fuer Uhrzeit
1835 // oder fuer beides benutzt werden.
1836 eF_ResT
SwWW8ImplReader::Read_F_DateTime( WW8FieldDesc
*pF
, String
& rStr
)
1838 bool bHijri
= false;
1839 WW8ReadFieldParams
aReadParam(rStr
);
1841 while (-1 != (nTok
= aReadParam
.SkipToNextToken()))
1853 //Saka Calendar, should we do something with this ?
1858 sal_uInt32 nFormat
= 0;
1860 sal_uInt16
nLang(0);
1861 short nDT
= GetTimeDatePara(rStr
, nFormat
, nLang
, ww::eDATE
, bHijri
);
1863 if( NUMBERFORMAT_UNDEFINED
== nDT
) // no D/T-Formatstring
1867 nDT
= NUMBERFORMAT_TIME
;
1868 nFormat
= rDoc
.GetNumberFormatter()->GetFormatIndex(
1869 NF_TIME_START
, LANGUAGE_SYSTEM
);
1873 nDT
= NUMBERFORMAT_DATE
;
1874 nFormat
= rDoc
.GetNumberFormatter()->GetFormatIndex(
1875 NF_DATE_START
, LANGUAGE_SYSTEM
);
1879 if (nDT
& NUMBERFORMAT_DATE
)
1881 SwDateTimeField
aFld((SwDateTimeFieldType
*)
1882 rDoc
.GetSysFldType(RES_DATETIMEFLD
), DATEFLD
, nFormat
);
1883 ForceFieldLanguage(aFld
, nLang
);
1884 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1886 else if (nDT
== NUMBERFORMAT_TIME
)
1888 SwDateTimeField
aFld((SwDateTimeFieldType
*)
1889 rDoc
.GetSysFldType(RES_DATETIMEFLD
), TIMEFLD
, nFormat
);
1890 ForceFieldLanguage(aFld
, nLang
);
1891 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1897 eF_ResT
SwWW8ImplReader::Read_F_FileName(WW8FieldDesc
*, String
&rStr
)
1899 SwFileNameFormat eType
= FF_NAME
;
1901 WW8ReadFieldParams
aReadParam(rStr
);
1902 while (-1 != (nRet
= aReadParam
.SkipToNextToken()))
1907 eType
= FF_PATHNAME
;
1910 //Skip over MERGEFORMAT
1911 aReadParam
.SkipToNextToken();
1914 OSL_ENSURE(!this, "unknown option in FileName field");
1919 SwFileNameField
aFld(
1920 (SwFileNameFieldType
*)rDoc
.GetSysFldType(RES_FILENAMEFLD
), eType
);
1921 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
1925 eF_ResT
SwWW8ImplReader::Read_F_Anz( WW8FieldDesc
* pF
, String
& rStr
)
1926 { // SeitenZahl - Feld
1927 sal_uInt16 nSub
= DS_PAGE
;
1929 case 27: nSub
= DS_WORD
; break; // Wordzahl
1930 case 28: nSub
= DS_CHAR
; break; // Zeichenzahl
1932 SwDocStatField
aFld( (SwDocStatFieldType
*)
1933 rDoc
.GetSysFldType( RES_DOCSTATFLD
), nSub
,
1934 GetNumberPara( rStr
) );
1935 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1939 eF_ResT
SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc
*, String
& rStr
)
1942 SwPageNumberField
aFld( (SwPageNumberFieldType
*)
1943 rDoc
.GetSysFldType( RES_PAGENUMBERFLD
), PG_RANDOM
,
1944 GetNumberPara(rStr
, true));
1946 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
1950 eF_ResT
SwWW8ImplReader::Read_F_Symbol( WW8FieldDesc
*, String
& rStr
)
1955 sal_Int32 nSize
= 0;
1957 WW8ReadFieldParams
aReadParam( rStr
);
1958 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
1964 aQ
= aReadParam
.GetResult();
1969 xub_StrLen n
= aReadParam
.GoToTokenParam();
1970 if( STRING_NOTFOUND
!= n
)
1971 aName
= aReadParam
.GetResult();
1978 xub_StrLen n
= aReadParam
.GoToTokenParam();
1979 if (STRING_NOTFOUND
!= n
)
1980 aSiz
= aReadParam
.GetResult();
1982 nSize
= aSiz
.ToInt32() * 20; // pT -> twip
1988 return FLD_TAGIGN
; // -> kein 0-Zeichen in Text
1990 if (sal_Unicode cChar
= static_cast<sal_Unicode
>(aQ
.ToInt32()))
1992 if (aName
.Len()) // Font Name set ?
1994 SvxFontItem
aFont(FAMILY_DONTKNOW
, aName
, aEmptyStr
,
1995 PITCH_DONTKNOW
, RTL_TEXTENCODING_SYMBOL
, RES_CHRATR_FONT
);
1996 NewAttr(aFont
); // new Font
1999 if (nSize
> 0) //#i20118#
2001 SvxFontHeightItem
aSz(nSize
, 100, RES_CHRATR_FONTSIZE
);
2005 rDoc
.InsertString(*pPaM
, OUString(cChar
));
2008 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_CHRATR_FONTSIZE
);
2010 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_CHRATR_FONT
);
2014 rDoc
.InsertString(*pPaM
, OUString("###"));
2021 eF_ResT
SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc
*, String
& rStr
)
2026 WW8ReadFieldParams
aReadParam( rStr
);
2027 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2032 sHost
= aReadParam
.GetResult();
2041 if( bObj
&& nPicLocFc
)
2042 nObjLocFc
= nPicLocFc
;
2049 eF_ResT
SwWW8ImplReader::Read_F_Set( WW8FieldDesc
* pF
, String
& rStr
)
2054 WW8ReadFieldParams
aReadParam( rStr
);
2055 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2060 if( !sOrigName
.Len() )
2061 sOrigName
= aReadParam
.GetResult();
2062 else if( !sVal
.Len() )
2063 sVal
= aReadParam
.GetResult();
2068 long nNo
= MapBookmarkVariables(pF
,sOrigName
,sVal
);
2070 SwFieldType
* pFT
= rDoc
.InsertFldType( SwSetExpFieldType( &rDoc
, sOrigName
,
2071 nsSwGetSetExpType::GSE_STRING
) );
2072 SwSetExpField
aFld( (SwSetExpFieldType
*)pFT
, sVal
, ULONG_MAX
);
2073 aFld
.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE
| nsSwGetSetExpType::GSE_STRING
);
2075 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2077 pReffedStck
->SetAttr(*pPaM
->GetPoint(), RES_FLTR_BOOKMARK
, true, nNo
);
2083 eF_ResT
SwWW8ImplReader::Read_F_Ref( WW8FieldDesc
*, String
& rStr
)
2084 { // Reference - Field
2085 String sOrigBkmName
;
2086 REFERENCEMARK eFormat
= REF_CONTENT
;
2089 WW8ReadFieldParams
aReadParam( rStr
);
2090 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2095 if( !sOrigBkmName
.Len() ) // get name of bookmark
2096 sOrigBkmName
= aReadParam
.GetResult();
2099 /* References to numbers in Word could be either to a numbered
2100 paragraph or to a chapter number. However Word does not seem to
2101 have the capability we do, of refering to the chapter number some
2102 other bookmark is in. As a result, cross-references to chapter
2103 numbers in a word document will be cross-references to a numbered
2104 paragraph, being the chapter heading paragraph. As it happens, our
2105 cross-references to numbered paragraphs will do the right thing
2106 when the target is a numbered chapter heading, so there is no need
2107 for us to use the REF_CHAPTER bookmark format on import.
2110 eFormat
= REF_NUMBER_NO_CONTEXT
;
2113 eFormat
= REF_NUMBER
;
2116 eFormat
= REF_NUMBER_FULL_CONTEXT
;
2120 eFormat
= REF_UPDOWN
;
2125 // unimplemented switch: just do 'nix nought nothing' :-)
2130 String
sBkmName(GetMappedBookmark(sOrigBkmName
));
2133 (SwGetRefFieldType
*)rDoc
.GetSysFldType( RES_GETREFFLD
),
2134 sBkmName
,REF_BOOKMARK
,0,eFormat
);
2136 if (eFormat
== REF_CONTENT
)
2139 If we are just inserting the contents of the bookmark, then it
2140 is possible that the bookmark is actually a variable, so we
2141 must store it until the end of the document to see if it was,
2142 in which case we'll turn it into a show variable
2144 pReffingStck
->NewAttr( *pPaM
->GetPoint(), SwFmtFld(aFld
) );
2145 pReffingStck
->SetAttr( *pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2149 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
2154 // Note Reference - Field
2155 eF_ResT
SwWW8ImplReader::Read_F_NoteReference( WW8FieldDesc
*, String
& rStr
)
2158 bool bAboveBelow
= false;
2161 WW8ReadFieldParams
aReadParam( rStr
);
2162 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2167 if( !aBkmName
.Len() ) // get name of foot/endnote
2168 aBkmName
= aReadParam
.GetResult();
2171 // activate flag 'Chapter Number'
2179 // unimplemented switch: just do 'nix nought nothing' :-)
2184 // set Sequence No of corresponding Foot-/Endnote to Zero
2185 // (will be corrected in
2186 SwGetRefField
aFld( (SwGetRefFieldType
*)
2187 rDoc
.GetSysFldType( RES_GETREFFLD
), aBkmName
, REF_FOOTNOTE
, 0,
2189 pReffingStck
->NewAttr(*pPaM
->GetPoint(), SwFmtFld(aFld
));
2190 pReffingStck
->SetAttr(*pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2193 SwGetRefField
aFld2( (SwGetRefFieldType
*)
2194 rDoc
.GetSysFldType( RES_GETREFFLD
),aBkmName
, REF_FOOTNOTE
, 0,
2196 pReffingStck
->NewAttr(*pPaM
->GetPoint(), SwFmtFld(aFld2
));
2197 pReffingStck
->SetAttr(*pPaM
->GetPoint(), RES_TXTATR_FIELD
);
2203 eF_ResT
SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc
*, String
& rStr
)
2207 WW8ReadFieldParams
aReadParam( rStr
);
2208 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2213 if( !sOrigName
.Len() )
2214 sOrigName
= aReadParam
.GetResult();
2219 String
sName(GetMappedBookmark(sOrigName
));
2221 #if defined(WW_NATIVE_TOC)
2223 OUString
aBookmarkName("_REF");
2224 maFieldStack
.back().SetBookmarkName(aBookmarkName
);
2225 maFieldStack
.back().SetBookmarkType(ODF_PAGEREF
);
2226 maFieldStack
.back().AddParam(OUString(), sName
);
2233 (SwGetRefFieldType
*)rDoc
.GetSysFldType( RES_GETREFFLD
), sName
,
2234 REF_BOOKMARK
, 0, REF_PAGE
);
2236 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2240 //For MS MacroButton field, the symbol in plain text is always "(" (0x28),
2241 //which should be mapped according to the macro type
2242 bool ConvertMacroSymbol( const String
& rName
, String
& rReference
)
2244 bool bConverted
= false;
2245 if( rReference
.EqualsAscii( "(" ) )
2248 sal_Unicode cSymbol
= sal_Unicode(); // silence false warning
2249 if( rName
.EqualsAscii( "CheckIt" ) )
2251 else if( rName
.EqualsAscii( "UncheckIt" ) )
2253 else if( rName
.EqualsAscii( "ShowExample" ) )
2260 rReference
= cSymbol
;
2266 // "MACROSCHALTFL"ACHE"
2267 eF_ResT
SwWW8ImplReader::Read_F_Macro( WW8FieldDesc
*, String
& rStr
)
2272 bool bNewVText
= true;
2273 bool bBracket
= false;
2274 WW8ReadFieldParams
aReadParam( rStr
);
2276 xub_StrLen nOffset
= 0;
2278 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2284 aName
= aReadParam
.GetResult();
2285 else if( !aVText
.Len() || bBracket
)
2287 nOffset
= aReadParam
.GetTokenSttPtr() + 1;
2291 aVText
+= aReadParam
.GetResult();
2294 bBracket
= aVText
.EqualsIgnoreCaseAscii(OUString('['), 1, 0)
2298 else if( aVText
.GetChar( aVText
.Len()-1 ) == ']' )
2305 return FLD_TAGIGN
; // makes no sense without Makro-Name
2307 //try converting macro symbol according to macro name
2308 bool bApplyWingdings
= ConvertMacroSymbol( aName
, aVText
);
2309 aName
.InsertAscii( "StarOffice.Standard.Modul1.", 0 );
2311 SwMacroField
aFld( (SwMacroFieldType
*)
2312 rDoc
.GetSysFldType( RES_MACROFLD
), aName
, aVText
);
2314 if( !bApplyWingdings
)
2317 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2318 WW8_CP nOldCp
= pPlcxMan
->Where();
2319 WW8_CP nCp
= nOldCp
+ nOffset
;
2323 aPaM
.Move(fnMoveBackward
);
2326 mpPostProcessAttrsInfo
= new WW8PostProcessAttrsInfo(nCp
, nCp
, aPaM
);
2330 //set Wingdings font
2332 for ( ; i
< pFonts
->GetMax(); i
++ )
2337 CharSet eSrcCharSet
;
2338 if( GetFontParams( i
, eFamily
, aFontName
, ePitch
, eSrcCharSet
)
2339 && aFontName
.EqualsAscii("Wingdings") )
2345 if ( i
< pFonts
->GetMax() )
2348 SetNewFontAttr( i
, true, RES_CHRATR_FONT
);
2349 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2350 pCtrlStck
->SetAttr( *pPaM
->GetPoint(), RES_CHRATR_FONT
);
2358 WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart
, WW8_CP nCpEnd
,
2361 mnCpStart(nCpStart
),
2363 mPaM(*rPaM
.GetPoint(), *rPaM
.GetMark()),
2364 mItemSet(rPaM
.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN
, RES_PARATR_END
- 1)
2368 bool CanUseRemoteLink(const String
&rGrfName
)
2370 bool bUseRemote
= false;
2373 ::ucbhelper::Content
aCnt(rGrfName
,
2374 uno::Reference
< ucb::XCommandEnvironment
>(),
2375 comphelper::getProcessComponentContext() );
2378 aCnt
.getPropertyValue("Title") >>= aTitle
;
2379 bUseRemote
= !aTitle
.isEmpty();
2383 // this file did not exist, so we will not set this as graphiclink
2389 // "EINF"UGENGRAFIK"
2390 eF_ResT
SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc
*, String
& rStr
)
2393 bool bEmbedded
= true;
2396 WW8ReadFieldParams
aReadParam( rStr
);
2397 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2402 if (!aGrfName
.Len())
2403 ConvertFFileName(aGrfName
, aReadParam
.GetResult());
2407 bEmbedded
= false; // Embedded-Flag deaktivieren
2410 case 'c':// den Converter-Namen ueberlesen
2411 aReadParam
.FindNextStringPiece();
2417 bEmbedded
= !CanUseRemoteLink(aGrfName
);
2424 Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrmFmt.
2425 Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
2426 wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
2428 Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
2429 erkannt, dass wir soeben einen Grafik-Link inserted haben und
2430 das passende SwAttrSet wird ins Frame-Format eingesetzt.
2432 SfxItemSet
aFlySet( rDoc
.GetAttrPool(), RES_FRMATR_BEGIN
,
2434 aFlySet
.Put( SwFmtAnchor( FLY_AS_CHAR
) );
2435 aFlySet
.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP
, text::RelOrientation::FRAME
));
2436 pFlyFmtOfJustInsertedGraphic
= rDoc
.Insert( *pPaM
,
2442 maGrfNameGenerator
.SetUniqueGraphName(pFlyFmtOfJustInsertedGraphic
,
2443 INetURLObject(aGrfName
).GetBase());
2445 return FLD_READ_FSPA
;
2449 String
wwSectionNamer::UniqueName()
2451 String
aName(msFileLinkSeed
);
2452 aName
+= OUString::number(++mnFileSectionNo
);
2453 return mrDoc
.GetUniqueSectionName(&aName
);
2457 eF_ResT
SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc
* /*pF*/, String
& rStr
)
2462 WW8ReadFieldParams
aReadParam( rStr
);
2463 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2469 aPara
= aReadParam
.GetResult();
2470 else if( !aBook
.Len() )
2471 aBook
= aReadParam
.GetResult();
2474 //Skip over MERGEFORMAT
2475 aReadParam
.SkipToNextToken();
2479 ConvertFFileName(aPara
, aPara
);
2481 if (aBook
.Len() && aBook
.GetChar( 0 ) != '\\')
2483 // Bereich aus Quelle ( kein Switch ) ?
2484 ConvertUFName(aBook
);
2485 aPara
+= sfx2::cTokenSeparator
;
2486 aPara
+= sfx2::cTokenSeparator
;
2492 What we will do is insert a section to be linked to a file, but just in
2493 case the file is not available we will fill in the section with the stored
2494 content of this winword field as a fallback.
2496 SwPosition
aTmpPos(*pPaM
->GetPoint());
2498 SwSectionData
aSection(FILE_LINK_SECTION
,
2499 maSectionNameGenerator
.UniqueName());
2500 aSection
.SetLinkFileName( aPara
);
2501 aSection
.SetProtectFlag(true);
2503 SwSection
*const pSection
=
2504 rDoc
.InsertSwSection(*pPaM
, aSection
, 0, 0, false);
2505 OSL_ENSURE(pSection
, "no section inserted");
2508 const SwSectionNode
* pSectionNode
= pSection
->GetFmt()->GetSectionNode();
2509 OSL_ENSURE(pSectionNode
, "no section node!");
2513 pPaM
->GetPoint()->nNode
= pSectionNode
->GetIndex()+1;
2514 pPaM
->GetPoint()->nContent
.Assign(pPaM
->GetCntntNode(), 0 );
2516 //we have inserted a section before this point, so adjust pos
2517 //for future page/section segment insertion
2518 maSectionManager
.PrependedInlineNode(aTmpPos
, *pPaM
->GetNode());
2523 // "SERIENDRUCKFELD"
2524 eF_ResT
SwWW8ImplReader::Read_F_DBField( WW8FieldDesc
* pF
, String
& rStr
)
2528 WW8ReadFieldParams
aReadParam( rStr
);
2529 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
2535 aName
= aReadParam
.GetResult();
2539 SwDBFieldType
aD( &rDoc
, aName
, SwDBData() ); // Datenbank: Nichts
2541 SwFieldType
* pFT
= rDoc
.InsertFldType( aD
);
2542 SwDBField
aFld( (SwDBFieldType
*)pFT
);
2543 aFld
.SetFieldCode( rStr
);
2546 pSBase
->WW8ReadString( *pStrm
, aResult
, pPlcxMan
->GetCpOfs()+
2547 pF
->nSRes
, pF
->nLRes
, eTextCharSet
);
2549 aFld
.InitContent(aResult
);
2551 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld( aFld
), 0);
2557 eF_ResT
SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc
*, String
& )
2559 SwDBNextSetFieldType aN
;
2560 SwFieldType
* pFT
= rDoc
.InsertFldType( aN
);
2561 SwDBNextSetField
aFld( (SwDBNextSetFieldType
*)pFT
, aEmptyStr
, aEmptyStr
,
2562 SwDBData() ); // Datenbank: Nichts
2563 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2568 eF_ResT
SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc
*, String
& )
2570 SwDBSetNumberFieldType aN
;
2571 SwFieldType
* pFT
= rDoc
.InsertFldType( aN
);
2572 SwDBSetNumberField
aFld( (SwDBSetNumberFieldType
*)pFT
,
2573 SwDBData() ); // Datenbank: Nichts
2574 rDoc
.InsertPoolItem( *pPaM
, SwFmtFld( aFld
), 0 );
2579 EQ , only the usage for
2580 a. Combined Characters supported, must be exactly in the form that word
2581 only accepts as combined charactersm, i.e.
2582 eq \o(\s\up Y(XXX),\s\do Y(XXX))
2583 b. Ruby Text supported, must be in the form that word recognizes as being
2587 eF_ResT
SwWW8ImplReader::Read_F_Equation( WW8FieldDesc
*, String
& rStr
)
2589 WW8ReadFieldParams
aReadParam( rStr
);
2590 long cChar
= aReadParam
.SkipToNextToken();
2592 Read_SubF_Combined(aReadParam
);
2593 else if ('*' == cChar
)
2594 Read_SubF_Ruby(aReadParam
);
2598 void SwWW8ImplReader::Read_SubF_Combined( WW8ReadFieldParams
& rReadParam
)
2600 String sCombinedCharacters
;
2601 if ((-2 == rReadParam
.SkipToNextToken()) &&
2602 rReadParam
.GetResult().EqualsIgnoreCaseAscii(OUString('('), 1, 0))
2604 for (int i
=0;i
<2;i
++)
2606 if ('s' == rReadParam
.SkipToNextToken())
2608 long cChar
= rReadParam
.SkipToNextToken();
2609 if (-2 != rReadParam
.SkipToNextToken())
2611 String sF
= rReadParam
.GetResult();
2612 if ((('u' == cChar
) && sF
.EqualsIgnoreCaseAscii(OUString('p'), 1, 0))
2613 || (('d' == cChar
) && sF
.EqualsIgnoreCaseAscii(OUString('o'), 1, 0)))
2615 if (-2 == rReadParam
.SkipToNextToken())
2617 String sPart
= rReadParam
.GetResult();
2618 xub_StrLen nBegin
= sPart
.Search('(');
2620 //Word disallows brackets in this field, which
2621 //aids figuring out the case of an end of )) vs )
2622 xub_StrLen nEnd
= sPart
.Search(')');
2624 if ((nBegin
!= STRING_NOTFOUND
) &&
2625 (nEnd
!= STRING_NOTFOUND
))
2627 sCombinedCharacters
+=
2628 sPart
.Copy(nBegin
+1,nEnd
-nBegin
-1);
2635 if (sCombinedCharacters
.Len())
2637 SwCombinedCharField
aFld((SwCombinedCharFieldType
*)
2638 rDoc
.GetSysFldType(RES_COMBINED_CHARS
),sCombinedCharacters
);
2639 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
2643 void SwWW8ImplReader::Read_SubF_Ruby( WW8ReadFieldParams
& rReadParam
)
2645 sal_uInt16 nJustificationCode
=0;
2647 sal_uInt32 nFontSize
=0;
2651 while( -1 != ( nRet
= rReadParam
.SkipToNextToken() ))
2657 String sTemp
= rReadParam
.GetResult();
2658 if( sTemp
.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
2661 nJustificationCode
= static_cast<sal_uInt16
>(sTemp
.ToInt32());
2663 else if( sTemp
.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
2666 nFontSize
= static_cast<sal_uInt32
>(sTemp
.ToInt32());
2668 else if( sTemp
.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
2678 while( -1 != ( nRet
= rReadParam
.SkipToNextToken() ))
2682 if (-2 == rReadParam
.SkipToNextToken() &&
2683 (rReadParam
.GetResult().EqualsIgnoreCaseAscii(OUString('p'), 1, 0)))
2685 if (-2 == rReadParam
.SkipToNextToken())
2687 String sPart
= rReadParam
.GetResult();
2688 xub_StrLen nBegin
= sPart
.Search('(');
2690 //Word disallows brackets in this field,
2691 xub_StrLen nEnd
= sPart
.Search(')');
2693 if ((nBegin
!= STRING_NOTFOUND
) &&
2694 (nEnd
!= STRING_NOTFOUND
))
2696 sRuby
= sPart
.Copy(nBegin
+1,nEnd
-nBegin
-1);
2698 if (STRING_NOTFOUND
==
2699 (nBegin
= sPart
.Search(',',nEnd
)))
2701 nBegin
= sPart
.Search(';',nEnd
);
2703 nEnd
= sPart
.SearchBackward(')');
2704 if ((nBegin
!= STRING_NOTFOUND
) &&
2705 (nEnd
!= STRING_NOTFOUND
))
2707 sText
= sPart
.Copy(nBegin
+1,nEnd
-nBegin
-1);
2718 //Translate and apply
2719 if (sRuby
.Len() && sText
.Len() && sFontName
.Len() && nFontSize
)
2721 switch (nJustificationCode
)
2724 nJustificationCode
=1;
2727 nJustificationCode
=3;
2730 nJustificationCode
=4;
2734 nJustificationCode
=0;
2737 nJustificationCode
=2;
2741 SwFmtRuby
aRuby(sRuby
);
2742 const SwCharFmt
*pCharFmt
=0;
2743 //Make a guess at which of asian of western we should be setting
2745 if (g_pBreakIt
->GetBreakIter().is())
2746 nScript
= g_pBreakIt
->GetBreakIter()->getScriptType(sRuby
, 0);
2748 nScript
= i18n::ScriptType::ASIAN
;
2750 //Check to see if we already have a ruby charstyle that this fits
2751 std::vector
<const SwCharFmt
*>::const_iterator aEnd
=
2752 aRubyCharFmts
.end();
2753 for(std::vector
<const SwCharFmt
*>::const_iterator aIter
2754 = aRubyCharFmts
.begin(); aIter
!= aEnd
; ++aIter
)
2756 const SvxFontHeightItem
&rFH
=
2757 ItemGet
<SvxFontHeightItem
>(*(*aIter
),
2758 GetWhichOfScript(RES_CHRATR_FONTSIZE
,nScript
));
2759 if (rFH
.GetHeight() == nFontSize
*10)
2761 const SvxFontItem
&rF
= ItemGet
<SvxFontItem
>(*(*aIter
),
2762 GetWhichOfScript(RES_CHRATR_FONT
,nScript
));
2763 if (rF
.GetFamilyName().Equals(sFontName
))
2771 //Create a new char style if necessary
2776 //Take this as the base name
2777 SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT
,aNm
);
2778 aNm
+=OUString::number(aRubyCharFmts
.size()+1);
2779 pFmt
= rDoc
.MakeCharFmt(aNm
,(SwCharFmt
*)rDoc
.GetDfltCharFmt());
2780 SvxFontHeightItem
aHeightItem(nFontSize
*10, 100, RES_CHRATR_FONTSIZE
);
2781 SvxFontItem
aFontItem(FAMILY_DONTKNOW
,sFontName
,
2782 aEmptyStr
,PITCH_DONTKNOW
,RTL_TEXTENCODING_DONTKNOW
, RES_CHRATR_FONT
);
2783 aHeightItem
.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE
,nScript
));
2784 aFontItem
.SetWhich(GetWhichOfScript(RES_CHRATR_FONT
,nScript
));
2785 pFmt
->SetFmtAttr(aHeightItem
);
2786 pFmt
->SetFmtAttr(aFontItem
);
2787 aRubyCharFmts
.push_back(pFmt
);
2791 //Set the charstyle and justification
2792 aRuby
.SetCharFmtName(pCharFmt
->GetName());
2793 aRuby
.SetCharFmtId(pCharFmt
->GetPoolFmtId());
2794 aRuby
.SetAdjustment(nJustificationCode
);
2797 rDoc
.InsertString( *pPaM
, sText
);
2798 pCtrlStck
->SetAttr( *pPaM
->GetPoint(), RES_TXTATR_CJK_RUBY
);
2802 //-----------------------------------------
2803 // Verzeichnis-Felder
2804 //-----------------------------------------
2806 static void lcl_toxMatchACSwitch( SwWW8ImplReader
& /*rReader*/,
2809 WW8ReadFieldParams
& rParam
,
2810 SwCaptionDisplay eCaptionType
)
2812 xub_StrLen n
= rParam
.GoToTokenParam();
2813 if( STRING_NOTFOUND
!= n
)
2815 SwTOXType
* pType
= (SwTOXType
*)rDoc
.GetTOXType( TOX_ILLUSTRATIONS
, 0);
2816 rBase
.RegisterToTOXType( *pType
);
2817 rBase
.SetCaptionDisplay( eCaptionType
);
2818 // Read Sequence Name and store in TOXBase
2819 String
sSeqName( rParam
.GetResult() );
2820 lcl_ConvertSequenceName( sSeqName
);
2821 rBase
.SetSequenceName( sSeqName
);
2825 //For all outline styles that are not in the outline numbering add them here as
2826 //custom extra styles
2827 bool SwWW8ImplReader::AddExtraOutlinesAsExtraStyles(SwTOXBase
& rBase
)
2829 bool bExtras
= false;
2830 //This is the case if the winword outline numbering is set while the
2832 for (sal_uInt16 nI
= 0; nI
< vColl
.size(); ++nI
)
2834 SwWW8StyInf
& rSI
= vColl
[nI
];
2835 if (rSI
.IsOutline())
2837 const SwTxtFmtColl
*pFmt
= (const SwTxtFmtColl
*)(rSI
.pFmt
);
2838 sal_uInt16 nStyleLevel
= rSI
.nOutlineLevel
;
2839 sal_uInt16 nMaxLevel
= rBase
.GetLevel();
2841 nStyleLevel
!= (pFmt
->GetAttrOutlineLevel()-1) && //<-end,zhaojianwei
2842 nStyleLevel
< nMaxLevel
2845 String
sStyles(rBase
.GetStyleNames(rSI
.nOutlineLevel
));
2847 sStyles
+= TOX_STYLE_DELIMITER
;
2848 sStyles
+= pFmt
->GetName();
2849 rBase
.SetStyleNames(sStyles
, rSI
.nOutlineLevel
);
2857 static void EnsureMaxLevelForTemplates(SwTOXBase
& rBase
)
2859 //If the TOC contains Template entries at levels > the evaluation level
2860 //that was initially taken from the max normal outline level of the word TOC
2861 //then we cannot use that for the evaluation level because writer cuts off
2862 //all styles above that level, while word just cuts off the "standard"
2863 //outline styles, we have no option but to expand to the highest level
2865 if ((rBase
.GetLevel() != MAXLEVEL
) && (nsSwTOXElement::TOX_TEMPLATE
& rBase
.GetCreateType()))
2867 for (sal_uInt16 nI
= MAXLEVEL
; nI
> 0; --nI
)
2869 if (rBase
.GetStyleNames(nI
-1).Len())
2878 static void lcl_toxMatchTSwitch(SwWW8ImplReader
& rReader
, SwTOXBase
& rBase
,
2879 WW8ReadFieldParams
& rParam
)
2881 xub_StrLen n
= rParam
.GoToTokenParam();
2882 if( STRING_NOTFOUND
!= n
)
2884 String
sParams( rParam
.GetResult() );
2887 sal_Int32 nIndex
= 0;
2889 // Delimiters between styles and style levels appears to allow both ; and ,
2891 String
sTemplate( sParams
.GetToken(0, ';', nIndex
) );
2895 sTemplate
= sParams
.GetToken(0, ',', nIndex
);
2899 const SwFmt
* pStyle
= rReader
.GetStyleWithOrgWWName(sTemplate
);
2901 sTemplate
= pStyle
->GetName();
2902 // Store Style for Level 0 into TOXBase
2903 rBase
.SetStyleNames( sTemplate
, 0 );
2905 else while( -1 != nIndex
)
2907 sal_Int32 nOldIndex
=nIndex
;
2908 sal_uInt16 nLevel
= static_cast<sal_uInt16
>(
2909 sParams
.GetToken(0, ';', nIndex
).ToInt32());
2913 nLevel
= static_cast<sal_uInt16
>(
2914 sParams
.GetToken(0, ',', nIndex
).ToInt32());
2917 if( (0 < nLevel
) && (MAXLEVEL
>= nLevel
) )
2920 // Store Style and Level into TOXBase
2922 = rReader
.GetStyleWithOrgWWName( sTemplate
);
2925 sTemplate
= pStyle
->GetName();
2927 String
sStyles( rBase
.GetStyleNames( nLevel
) );
2929 sStyles
+= TOX_STYLE_DELIMITER
;
2930 sStyles
+= sTemplate
;
2931 rBase
.SetStyleNames( sStyles
, nLevel
);
2933 // read next style name...
2935 sTemplate
= sParams
.GetToken(0, ';', nIndex
);
2939 sTemplate
= sParams
.GetToken(0, ',', nIndex
);
2946 sal_uInt16
wwSectionManager::CurrentSectionColCount() const
2948 sal_uInt16 nIndexCols
= 1;
2949 if (!maSegments
.empty())
2950 nIndexCols
= maSegments
.back().maSep
.ccolM1
+ 1;
2954 //Will there be a new pagebreak at this position (don't know what type
2956 bool wwSectionManager::WillHavePageDescHere(SwNodeIndex aIdx
) const
2959 if (!maSegments
.empty())
2961 if (!maSegments
.back().IsContinous() &&
2962 maSegments
.back().maStart
== aIdx
)
2970 static sal_uInt16
lcl_GetMaxValidWordTOCLevel(const SwForm
&rForm
)
2972 // GetFormMax() returns level + 1, hence the -1
2973 sal_uInt16 nRet
= rForm
.GetFormMax()-1;
2975 // If the max of this type of TOC is greater than the max of a word
2976 // possible toc, then clip to the word max
2977 if (nRet
> WW8ListManager::nMaxLevel
)
2978 nRet
= WW8ListManager::nMaxLevel
;
2983 eF_ResT
SwWW8ImplReader::Read_F_Tox( WW8FieldDesc
* pF
, String
& rStr
)
2985 #if defined(WW_NATIVE_TOC)
2987 OUString
aBookmarkName("_TOC");
2988 maFieldStack
.back().SetBookmarkName(aBookmarkName
);
2989 maFieldStack
.back().SetBookmarkType(ODF_TOC
);
2995 return FLD_TEXT
; // ignore (#i25440#)
2997 TOXTypes eTox
; // Baue ToxBase zusammen
3011 sal_uInt16 nCreateOf
= (eTox
== TOX_CONTENT
) ? nsSwTOXElement::TOX_OUTLINELEVEL
: nsSwTOXElement::TOX_MARK
;
3013 sal_uInt16 nIndexCols
= 1;
3015 const SwTOXType
* pType
= rDoc
.GetTOXType( eTox
, 0 );
3016 SwForm
aOrigForm(eTox
);
3017 SwTOXBase
* pBase
= new SwTOXBase( pType
, aOrigForm
, nCreateOf
, aEmptyStr
);
3018 pBase
->SetProtected(maSectionManager
.CurrentSectionIsProtected());
3022 sal_uInt16 eOptions
= nsSwTOIOptions::TOI_SAME_ENTRY
| nsSwTOIOptions::TOI_CASE_SENSITIVE
;
3024 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
3025 // die Parameter \o in 1 bis 9 liegen
3026 // oder der Parameter \f existiert
3027 // oder GARKEINE Switches Parameter angegeben sind.
3029 WW8ReadFieldParams
aReadParam( rStr
);
3030 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
3036 xub_StrLen n
= aReadParam
.GoToTokenParam();
3037 if( STRING_NOTFOUND
!= n
)
3039 String
sParams( aReadParam
.GetResult() );
3040 // if NO String just ignore the \c
3044 static_cast<sal_uInt16
>(sParams
.ToInt32());
3051 xub_StrLen n
= aReadParam
.GoToTokenParam();
3052 if( STRING_NOTFOUND
!= n
) // if NO String just ignore the \e
3054 String
sDelimiter( aReadParam
.GetResult() );
3055 SwForm
aForm( pBase
->GetTOXForm() );
3057 // Attention: if TOX_CONTENT brave
3058 // GetFormMax() returns MAXLEVEL + 1 !!
3059 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3061 for(sal_uInt16 nLevel
= 1;
3065 // Levels count from 1
3066 // Level 0 is reserved for CAPTION
3068 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3069 // falls es eine Seitenzahl gibt:
3070 FormTokenType ePrevType
= TOKEN_END
;
3071 FormTokenType eType
;
3073 SwFormTokens aPattern
=
3074 aForm
.GetPattern(nLevel
);
3075 SwFormTokens::iterator aIt
= aPattern
.begin();
3078 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3080 if (eType
== TOKEN_PAGE_NUMS
)
3082 if (TOKEN_TAB_STOP
== ePrevType
)
3086 if(0x09 == sDelimiter
.GetChar(0))
3087 aIt
->eTabAlign
= SVX_TAB_ADJUST_END
;
3090 SwFormToken
aToken(TOKEN_TEXT
);
3091 aToken
.sText
= sDelimiter
;
3094 aForm
.SetPattern(nLevel
, aPattern
);
3102 while (TOKEN_END
!= eType
);
3105 pBase
->SetTOXForm( aForm
);
3111 eOptions
|= nsSwTOIOptions::TOI_ALPHA_DELIMITTER
;
3116 pBase
->SetOptions( eOptions
);
3122 bool bIsHyperlink
= false;
3123 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
3124 // die Parameter \o in 1 bis 9 liegen
3125 // oder der Parameter \f existiert
3126 // oder GARKEINE Switches Parameter angegeben sind.
3127 sal_uInt16 eCreateFrom
= 0;
3128 sal_uInt16 nMaxLevel
= 0;
3130 WW8ReadFieldParams
aReadParam( rStr
);
3131 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
3136 bIsHyperlink
= true;
3140 lcl_toxMatchACSwitch(*this, rDoc
, *pBase
, aReadParam
,
3148 if( !aReadParam
.GetTokenSttFromTo(0, &nVal
, WW8ListManager::nMaxLevel
) )
3149 nVal
= lcl_GetMaxValidWordTOCLevel(aOrigForm
);
3150 if( nMaxLevel
< nVal
)
3152 eCreateFrom
|= nsSwTOXElement::TOX_OUTLINELEVEL
;
3156 eCreateFrom
|= nsSwTOXElement::TOX_MARK
;
3161 if( aReadParam
.GetTokenSttFromTo(0, &nVal
, WW8ListManager::nMaxLevel
) )
3163 if( nMaxLevel
< nVal
)
3165 eCreateFrom
|= nsSwTOXElement::TOX_MARK
;
3169 case 't': // paragraphs using special styles shall
3170 // provide the TOX's content
3171 lcl_toxMatchTSwitch(*this, *pBase
, aReadParam
);
3172 eCreateFrom
|= nsSwTOXElement::TOX_TEMPLATE
;
3176 xub_StrLen n
= aReadParam
.GoToTokenParam();
3177 if( STRING_NOTFOUND
!= n
) // if NO String just ignore the \p
3179 String
sDelimiter( aReadParam
.GetResult() );
3180 SwForm
aForm( pBase
->GetTOXForm() );
3182 // Attention: if TOX_CONTENT brave
3183 // GetFormMax() returns MAXLEVEL + 1 !!
3184 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3186 for(sal_uInt16 nLevel
= 1;
3190 // Levels count from 1
3191 // Level 0 is reserved for CAPTION
3193 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3194 // falls es eine Seitenzahl gibt:
3195 FormTokenType ePrevType
= TOKEN_END
;
3196 FormTokenType eType
;
3199 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3200 SwFormTokens::iterator aIt
= aPattern
.begin();
3203 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3205 if (eType
== TOKEN_PAGE_NUMS
)
3207 if (TOKEN_TAB_STOP
== ePrevType
)
3211 SwFormToken
aToken(TOKEN_TEXT
);
3212 aToken
.sText
= sDelimiter
;
3215 aForm
.SetPattern(nLevel
,
3222 while( TOKEN_END
!= eType
);
3225 pBase
->SetTOXForm( aForm
);
3229 case 'n': // don't print page numbers
3231 // read START and END param
3232 sal_uInt16 nStart
, nEnd
;
3233 if( !aReadParam
.GetTokenSttFromTo( &nStart
, &nEnd
,
3234 WW8ListManager::nMaxLevel
) )
3237 nEnd
= aOrigForm
.GetFormMax()-1;
3239 // remove page numbers from this levels
3240 SwForm
aForm( pBase
->GetTOXForm() );
3241 if (aForm
.GetFormMax() <= nEnd
)
3242 nEnd
= aForm
.GetFormMax()-1;
3244 sal_uInt16 nLevel
= nStart
; nLevel
<= nEnd
;
3248 // Levels count from 1
3249 // Level 0 is reserved for CAPTION
3251 // Seitenzahl und ggfs. davorstehenden Tabstop
3253 FormTokenType eType
;
3255 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3256 SwFormTokens::iterator aIt
= aPattern
.begin();
3259 eType
= ++aIt
== aPattern
.end() ? TOKEN_END
: aIt
->eTokenType
;
3261 if (eType
== TOKEN_PAGE_NUMS
)
3263 aIt
= aPattern
.erase(aIt
);
3270 aPattern
.erase(aIt
);
3271 aForm
.SetPattern(nLevel
, aPattern
);
3276 while (TOKEN_END
!= eType
);
3279 pBase
->SetTOXForm( aForm
);
3284 // the following switches are not (yet) supported
3285 // by good old StarWriter:
3296 SwForm
aForm(pBase
->GetTOXForm());
3297 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3298 SwFormToken
aLinkStart(TOKEN_LINK_START
);
3299 SwFormToken
aLinkEnd(TOKEN_LINK_END
);
3302 for(sal_uInt16 nLevel
= 1; nLevel
<= nEnd
; ++nLevel
)
3304 SwFormTokens aPattern
= aForm
.GetPattern(nLevel
);
3306 aPattern
.insert(aPattern
.begin(), aLinkStart
);
3307 aPattern
.push_back(aLinkEnd
);
3309 aForm
.SetPattern(nLevel
, aPattern
);
3313 pBase
->SetTOXForm(aForm
);
3317 nMaxLevel
= WW8ListManager::nMaxLevel
;
3318 pBase
->SetLevel(nMaxLevel
);
3320 const TOXTypes eType
= pBase
->GetTOXType()->GetType();
3325 //If we would be created from outlines, either explictly or by default
3326 //then see if we need extra styles added to the outlines
3327 sal_uInt16 eEffectivelyFrom
= eCreateFrom
? eCreateFrom
: nsSwTOXElement::TOX_OUTLINELEVEL
;
3328 if (eEffectivelyFrom
& nsSwTOXElement::TOX_OUTLINELEVEL
)
3330 if (AddExtraOutlinesAsExtraStyles(*pBase
))
3331 eCreateFrom
|= (nsSwTOXElement::TOX_TEMPLATE
| nsSwTOXElement::TOX_OUTLINELEVEL
);
3333 // #i19683# Insert a text token " " between the number and entry token.
3334 // In an ideal world we could handle the tab stop between the number and
3335 // the entry correctly, but I currently have no clue how to obtain
3336 // the tab stop position. It is _not_ set at the paragraph style.
3338 for (sal_uInt16 nI
= 0; nI
< vColl
.size(); ++nI
)
3340 const SwWW8StyInf
& rSI
= vColl
[nI
];
3341 if (rSI
.IsOutlineNumbered())
3343 sal_uInt16 nStyleLevel
= rSI
.nOutlineLevel
;
3344 const SwNumFmt
& rFmt
= rSI
.GetOutlineNumrule()->Get( nStyleLevel
);
3345 if ( SVX_NUM_NUMBER_NONE
!= rFmt
.GetNumberingType() )
3350 pForm
= new SwForm( pBase
->GetTOXForm() );
3352 SwFormTokens aPattern
= pForm
->GetPattern(nStyleLevel
);
3353 SwFormTokens::iterator aIt
=
3354 find_if(aPattern
.begin(), aPattern
.end(),
3355 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO
));
3357 if ( aIt
!= aPattern
.end() )
3359 SwFormToken
aNumberEntrySeparator( TOKEN_TEXT
);
3360 aNumberEntrySeparator
.sText
= OUString(" ");
3361 aPattern
.insert( ++aIt
, aNumberEntrySeparator
);
3362 pForm
->SetPattern( nStyleLevel
, aPattern
);
3368 pBase
->SetTOXForm( *pForm
);
3372 pBase
->SetCreate(eCreateFrom
);
3373 EnsureMaxLevelForTemplates(*pBase
);
3376 case TOX_ILLUSTRATIONS
:
3379 eCreateFrom
= nsSwTOXElement::TOX_SEQUENCE
;
3380 pBase
->SetCreate( eCreateFrom
);
3383 We don't know until here if we are an illustration
3384 or not, and so have being used a TOX_CONTENT so far
3385 which has 10 levels, while TOX has only two, this
3386 level is set only in the constructor of SwForm, so
3387 create a new one and copy over anything that could
3388 be set in the old one, and remove entries from the
3389 pattern which do not apply to illustration indices
3391 SwForm
aOldForm( pBase
->GetTOXForm() );
3392 SwForm
aForm( eType
);
3393 sal_uInt16 nEnd
= aForm
.GetFormMax()-1;
3396 for(sal_uInt16 nLevel
= 1; nLevel
<= nEnd
; ++nLevel
)
3398 SwFormTokens aPattern
= aOldForm
.GetPattern(nLevel
);
3400 SwFormTokens::iterator new_end
=remove_if(aPattern
.begin(), aPattern
.end(),
3401 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO
));
3403 // table index imported with wrong page number format
3404 aPattern
.erase (new_end
, aPattern
.end() );
3406 aForm
.SetPattern(nLevel
, aPattern
);
3408 aForm
.SetTemplate( nLevel
,
3409 aOldForm
.GetTemplate(nLevel
));
3412 pBase
->SetTOXForm( aForm
);
3416 OSL_ENSURE(!this, "Unhandled toc options!");
3424 OSL_ENSURE(!this, "Unhandled toc options!");
3428 // Update fuer TOX anstossen
3429 rDoc
.SetUpdateTOX(true);
3431 // #i21237# - propagate tab stops from paragraph styles
3432 // used in TOX to patterns of the TOX
3434 pBase
->AdjustTabStops(rDoc
, sal_True
);
3436 // #i10028# - inserting a toc implicltly acts like a parabreak in word and writer
3437 if (pPaM
->GetPoint()->nContent
.GetIndex())
3438 AppendTxtNode(*pPaM
->GetPoint());
3440 const SwPosition
* pPos
= pPaM
->GetPoint();
3442 SwFltTOX
aFltTOX( pBase
, nIndexCols
);
3444 // test if there is already a break item on this node
3445 if(SwCntntNode
* pNd
= pPos
->nNode
.GetNode().GetCntntNode())
3447 const SfxItemSet
* pSet
= pNd
->GetpSwAttrSet();
3450 if (SFX_ITEM_SET
== pSet
->GetItemState(RES_BREAK
, false))
3451 aFltTOX
.SetHadBreakItem(true);
3452 if (SFX_ITEM_SET
== pSet
->GetItemState(RES_PAGEDESC
, false))
3453 aFltTOX
.SetHadPageDescItem(true);
3457 //Will there be a new pagebreak at this position (don't know what type
3459 if (maSectionManager
.WillHavePageDescHere(pPos
->nNode
))
3460 aFltTOX
.SetHadPageDescItem(true);
3462 // Setze Anfang in Stack
3463 pReffedStck
->NewAttr( *pPos
, aFltTOX
);
3465 rDoc
.InsertTableOf(*pPaM
->GetPoint(), *aFltTOX
.GetBase());
3467 //inserting a toc inserts a section before this point, so adjust pos
3468 //for future page/section segment insertion
3469 SwPaM
aRegion(*pPaM
);
3470 aRegion
.Move(fnMoveBackward
);
3471 OSL_ENSURE(rDoc
.GetCurTOX(*aRegion
.GetPoint()), "Misunderstood how toc works");
3472 if (SwTOXBase
* pBase2
= (SwTOXBase
*)rDoc
.GetCurTOX(*aRegion
.GetPoint()))
3476 // Set the column number for index
3477 SfxItemSet
aSet( rDoc
.GetAttrPool(), RES_COL
, RES_COL
);
3479 aCol
.Init( nIndexCols
, 708, USHRT_MAX
);
3481 pBase2
->SetAttrSet( aSet
);
3484 maSectionManager
.PrependedInlineNode(*pPaM
->GetPoint(),
3485 *aRegion
.GetNode());
3488 // Setze Ende in Stack
3489 pReffedStck
->SetAttr( *pPos
, RES_FLTR_TOX
);
3491 if (!maApos
.back()) //a para end in apo doesn't count
3496 eF_ResT
SwWW8ImplReader::Read_F_Shape(WW8FieldDesc
* /*pF*/, String
& /*rStr*/)
3499 #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3500 to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3501 the drawing that we are in the Shape field and respond accordingly
3506 eF_ResT
SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc
* /*pF*/, String
& rStr
)
3508 #if defined(WW_NATIVE_TOC)
3510 OUString
aBookmarkName("_HYPERLINK");
3511 maFieldStack
.back().SetBookmarkName(aBookmarkName
);
3512 maFieldStack
.back().SetBookmarkType(ODF_HYPERLINK
);
3517 String sURL
, sTarget
, sMark
;
3518 bool bDataImport
= false;
3519 //HYPERLINK "filename" [switches]
3521 rStr
= comphelper::string::stripEnd(rStr
, 1);
3525 bool bOptions
= false;
3527 WW8ReadFieldParams
aReadParam( rStr
);
3528 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
3533 if (!sURL
.Len() && !bOptions
)
3534 ConvertFFileName(sURL
, aReadParam
.GetResult());
3538 sTarget
.AssignAscii( "_blank" );
3543 nRet
= aReadParam
.SkipToNextToken();
3547 sMark
= aReadParam
.GetResult();
3548 if( sMark
.Len() && '"' == sMark
.GetChar( sMark
.Len()-1 ))
3549 sMark
.Erase( sMark
.Len() - 1 );
3554 nRet
= aReadParam
.SkipToNextToken();
3557 sTarget
= aReadParam
.GetResult();
3561 OSL_ENSURE( !this, "Auswertung fehlt noch - Daten unbekannt" );
3562 case 's': //worthless fake anchor option
3569 // das Resultat uebernehmen
3570 OSL_ENSURE((sURL
.Len() || sMark
.Len()), "WW8: Empty URL");
3573 ( sURL
+= INET_MARK_TOKEN
) += sMark
;
3575 SwFmtINetFmt
aURL( sURL
, sTarget
);
3577 //As an attribute this needs to be closed, and that'll happen from
3578 //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms
3579 //between the start and begin, their hyperlinks will be set at that time
3581 pCtrlStck
->NewAttr( *pPaM
->GetPoint(), aURL
);
3585 static void lcl_ImportTox(SwDoc
&rDoc
, SwPaM
&rPaM
, const String
&rStr
, bool bIdx
)
3587 TOXTypes eTox
= ( !bIdx
) ? TOX_CONTENT
: TOX_INDEX
; // Default
3589 sal_uInt16 nLevel
= 1;
3594 WW8ReadFieldParams
aReadParam(rStr
);
3595 while( -1 != ( nRet
= aReadParam
.SkipToNextToken() ))
3599 if( !sFldTxt
.Len() )
3601 // PrimaryKey ohne ":", 2nd dahinter
3602 sFldTxt
= aReadParam
.GetResult();
3607 n
= aReadParam
.GoToTokenParam();
3608 if( STRING_NOTFOUND
!= n
)
3610 String
sParams( aReadParam
.GetResult() );
3611 if( 'C' != sParams
.GetChar(0) && 'c' != sParams
.GetChar(0) )
3617 n
= aReadParam
.GoToTokenParam();
3618 if( STRING_NOTFOUND
!= n
)
3620 String
sParams( aReadParam
.GetResult() );
3621 if( sParams
.Len() // if NO String just ignore the \l
3622 && sParams
.GetChar( 0 ) > '0'
3623 && sParams
.GetChar( 0 ) <= '9' )
3625 nLevel
= (sal_uInt16
)sParams
.ToInt32();
3631 OSL_ENSURE( rDoc
.GetTOXTypeCount( eTox
), "Doc.GetTOXTypeCount() == 0 :-(" );
3633 const SwTOXType
* pT
= rDoc
.GetTOXType( eTox
, 0 );
3636 if( eTox
!= TOX_INDEX
)
3637 aM
.SetLevel( nLevel
);
3640 xub_StrLen nFnd
= sFldTxt
.Search( WW8_TOX_LEVEL_DELIM
);
3641 if( STRING_NOTFOUND
!= nFnd
) // it exist levels
3643 aM
.SetPrimaryKey( sFldTxt
.Copy( 0, nFnd
) );
3644 xub_StrLen nScndFnd
=
3645 sFldTxt
.Search( WW8_TOX_LEVEL_DELIM
, nFnd
+1 );
3646 if( STRING_NOTFOUND
!= nScndFnd
)
3648 aM
.SetSecondaryKey( sFldTxt
.Copy( nFnd
+1, nScndFnd
- nFnd
- 1 ));
3651 sFldTxt
.Erase( 0, nFnd
+1 );
3657 aM
.SetAlternativeText( sFldTxt
);
3658 rDoc
.InsertPoolItem( rPaM
, aM
, 0 );
3662 void sw::ms::ImportXE(SwDoc
&rDoc
, SwPaM
&rPaM
, const String
&rStr
)
3664 lcl_ImportTox(rDoc
, rPaM
, rStr
, true);
3667 void SwWW8ImplReader::ImportTox( int nFldId
, String aStr
)
3669 bool bIdx
= (nFldId
!= 9);
3670 lcl_ImportTox(rDoc
, *pPaM
, aStr
, bIdx
);
3673 void SwWW8ImplReader::Read_FldVanish( sal_uInt16
, const sal_uInt8
*, short nLen
)
3675 //Meaningless in a style
3676 if (pAktColl
|| !pPlcxMan
)
3679 const int nChunk
= 64; //number of characters to read at one time
3681 // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
3682 const static sal_Char
*aFldNames
[] = { "\x06""INHALT", "\x02""XE", // dt.
3684 const static sal_uInt8 aFldId
[] = { 9, 4, 9 };
3688 bIgnoreText
= false;
3692 // our methode was called from
3693 // ''Skip attributes of field contents'' loop within ReadTextAttr()
3698 long nOldPos
= pStrm
->Tell();
3700 WW8_CP nStartCp
= pPlcxMan
->Where() + pPlcxMan
->GetCpOfs();
3703 sal_uInt16 nFieldLen
= pSBase
->WW8ReadString( *pStrm
, sFieldName
, nStartCp
,
3704 nChunk
, eStructCharSet
);
3705 nStartCp
+=nFieldLen
;
3708 //If the first chunk did not start with a field start then
3709 //reset the stream position and give up
3710 if( !nFieldLen
|| (0x13 != sFieldName
.GetChar( nC
))) // Field Start Mark
3712 // If Field End Mark found
3713 if( nFieldLen
&& (0x15 == sFieldName
.GetChar( nC
)))
3714 bIgnoreText
= false;
3715 pStrm
->Seek( nOldPos
);
3716 return; // kein Feld zu finden
3720 //If this chunk does not contain a field end, keep reading chunks
3721 //until we find one, or we run out of text,
3722 while (STRING_NOTFOUND
== (nFnd
= sFieldName
.Search(0x15)))
3725 nFieldLen
= pSBase
->WW8ReadString( *pStrm
, sTemp
,
3726 nStartCp
, nChunk
, eStructCharSet
);
3728 nStartCp
+=nFieldLen
;
3733 pStrm
->Seek( nOldPos
);
3735 //if we have no 0x15 give up, otherwise erase everything from the 0x15
3737 if (STRING_NOTFOUND
== nFnd
)
3740 sFieldName
.Erase(nFnd
);
3743 while( ' ' == sFieldName
.GetChar( nC
))
3746 for( int i
= 0; i
< 3; i
++ )
3748 const sal_Char
* pName
= aFldNames
[i
];
3749 sal_uInt16 nNameLen
= *pName
++;
3750 if( sFieldName
.EqualsIgnoreCaseAscii( pName
, nC
, nNameLen
) )
3752 ImportTox( aFldId
[i
], sFieldName
.Copy( nC
+ nNameLen
) );
3753 break; // keine Mehrfachnennungen moeglich
3757 pStrm
->Seek( nOldPos
);
3760 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */