Update ooo320-m1
[ooovba.git] / sw / source / filter / ww8 / ww8par5.cxx
blob56ba5c95c0917a3138e4c5e778b56d115c6ad56c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8par5.cxx,v $
10 * $Revision: 1.110.40.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 #include <ctype.h> // tolower
37 #include <stdio.h> // sscanf()
39 #include <sal/types.h>
40 #include <tools/solar.h>
42 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
43 #include <svtools/urihelper.hxx>
44 #include <svtools/zforlist.hxx>
45 #include <svtools/zformat.hxx>
46 #include <sfx2/linkmgr.hxx>
48 #ifndef _UCBHELPER_CONTENT_HXX_
49 #include <ucbhelper/content.hxx>
50 #endif
51 #ifndef _UCBHELPER_CONTENTBROKER_HXX_
52 #include <ucbhelper/contentbroker.hxx>
53 #endif
54 #include <ucbhelper/commandenvironment.hxx>
56 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
57 #include <com/sun/star/i18n/ScriptType.hdl>
58 #endif
59 #include <hintids.hxx>
60 #include <svx/fontitem.hxx>
61 #include <svx/fhgtitem.hxx>
62 #include <svx/langitem.hxx>
63 #include <fmtfld.hxx>
64 #include <fmtanchr.hxx>
65 #include <pam.hxx> // fuer SwPam
66 #include <doc.hxx>
67 #include <charatr.hxx> // class SwFmtFld
68 #include <flddat.hxx> // class SwDateTimeField
69 #include <docufld.hxx> // class SwPageNumberField
70 #include <reffld.hxx> // class SwGetRefField
71 #include <IMark.hxx>
72 #include <expfld.hxx> // class SwSetExpField
73 #include <dbfld.hxx> // class SwDBField
74 #include <usrfld.hxx>
75 #include <tox.hxx>
76 #include <section.hxx> // class SwSection
77 #include <ndtxt.hxx>
78 #include <fmtinfmt.hxx>
79 #include <chpfld.hxx>
80 #include <ftnidx.hxx>
81 #include <txtftn.hxx>
82 #include <viewsh.hxx>
83 #include <shellres.hxx>
84 #include <fmtruby.hxx>
85 #include <charfmt.hxx>
86 #include <txtatr.hxx>
87 #include <breakit.hxx>
88 #include <fmtclds.hxx>
89 #include <pagedesc.hxx>
90 #include <SwStyleNameMapper.hxx>
91 #include <IMark.hxx>
93 #include "ww8scan.hxx" // WW8FieldDesc
94 #include "ww8par.hxx"
95 #include "ww8par2.hxx"
96 #include "writerhelper.hxx"
97 #include "fields.hxx"
98 #include <svtools/fltrcfg.hxx>
100 #include <algorithm> // #i24377#
102 //#define WW_NATIVE_TOC 0
104 #define MAX_FIELDLEN 64000
106 #define WW8_TOX_LEVEL_DELIM ':'
108 using namespace ::com::sun::star;
109 using namespace sw::util;
110 using namespace sw::mark;
111 using namespace std; // #i24377#
112 using namespace nsSwDocInfoSubType;
115 class _ReadFieldParams
117 private:
118 String aData;
119 xub_StrLen nLen, nFnd, nNext, nSavPtr;
120 public:
121 _ReadFieldParams( const String& rData );
122 ~_ReadFieldParams();
124 xub_StrLen GoToTokenParam();
125 long SkipToNextToken();
126 xub_StrLen GetTokenSttPtr() const { return nFnd; }
128 xub_StrLen FindNextStringPiece( xub_StrLen _nStart = STRING_NOTFOUND );
129 bool GetTokenSttFromTo(xub_StrLen* _pFrom, xub_StrLen* _pTo,
130 xub_StrLen _nMax);
132 String GetResult() const;
136 _ReadFieldParams::_ReadFieldParams( const String& _rData )
137 : aData( _rData ), nLen( _rData.Len() ), nNext( 0 )
140 erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem
141 Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl
142 (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird
144 while( (nLen > nNext) && (aData.GetChar( nNext ) == ' ') )
145 ++nNext;
147 sal_Unicode c;
148 while( nLen > nNext
149 && (c = aData.GetChar( nNext )) != ' '
150 && c != '"'
151 && c != '\\'
152 && c != 132
153 && c != 0x201c )
154 ++nNext;
156 nFnd = nNext;
157 nSavPtr = nNext;
158 // cLastChar = aData.GetChar( nSavPtr );
162 _ReadFieldParams::~_ReadFieldParams()
164 // aData.SetChar( nSavPtr, cLastChar );
168 String _ReadFieldParams::GetResult() const
170 return (STRING_NOTFOUND == nFnd)
171 ? aEmptyStr
172 : aData.Copy( nFnd, (nSavPtr - nFnd) );
176 xub_StrLen _ReadFieldParams::GoToTokenParam()
178 xub_StrLen nOld = nNext;
179 if( -2 == SkipToNextToken() )
180 return GetTokenSttPtr();
181 nNext = nOld;
182 return STRING_NOTFOUND;
185 // ret: -2: NOT a '\' parameter but normal Text
186 long _ReadFieldParams::SkipToNextToken()
188 long nRet = -1; // Ende
189 if (
190 (STRING_NOTFOUND != nNext) && (nLen > nNext) &&
191 STRING_NOTFOUND != (nFnd = FindNextStringPiece(nNext))
194 nSavPtr = nNext;
196 if ('\\' == aData.GetChar(nFnd) && '\\' != aData.GetChar(nFnd + 1))
198 nRet = aData.GetChar(++nFnd);
199 nNext = ++nFnd; // und dahinter setzen
201 else
203 nRet = -2;
204 if (
205 (STRING_NOTFOUND != nSavPtr ) &&
207 ('"' == aData.GetChar(nSavPtr - 1)) ||
208 (0x201d == aData.GetChar(nSavPtr - 1))
212 --nSavPtr;
216 return nRet;
219 // FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette
220 // bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen
221 // oder zum String-Ende von pStr.
223 // Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0
225 // Returnwert: 0 falls String-Ende erreicht,
226 // ansonsten Anfang des Paramters bzw. der Zeichenkette
228 xub_StrLen _ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart)
230 xub_StrLen n = ( STRING_NOTFOUND == nStart ) ? nFnd : nStart; // Anfang
231 xub_StrLen n2; // Ende
233 nNext = STRING_NOTFOUND; // Default fuer nicht gefunden
235 while( (nLen > n) && (aData.GetChar( n ) == ' ') )
236 ++n;
238 if( nLen == n )
239 return STRING_NOTFOUND; // String End reached!
241 if( (aData.GetChar( n ) == '"') // Anfuehrungszeichen vor Para?
242 || (aData.GetChar( n ) == 0x201c)
243 || (aData.GetChar( n ) == 132) )
245 n++; // Anfuehrungszeichen ueberlesen
246 n2 = n; // ab hier nach Ende suchen
247 while( (nLen > n2)
248 && (aData.GetChar( n2 ) != '"')
249 && (aData.GetChar( n2 ) != 0x201d)
250 && (aData.GetChar( n2 ) != 147) )
251 n2++; // Ende d. Paras suchen
253 else // keine Anfuehrungszeichen
255 n2 = n; // ab hier nach Ende suchen
256 while( (nLen > n2) && (aData.GetChar( n2 ) != ' ') ) // Ende d. Paras suchen
258 if( aData.GetChar( n2 ) == '\\' )
260 if( aData.GetChar( n2+1 ) == '\\' )
261 n2 += 2; // Doppel-Backslash -> OK
262 else
264 if( n2 > n )
265 n2--;
266 break; // einfach-Backslash -> Ende
269 else
270 n2++; // kein Backslash -> OK
273 if( nLen > n2 )
275 if(aData.GetChar( n2 ) != ' ') n2++;
276 nNext = n2;
278 return n;
283 // read parameters "1-3" or 1-3 with both values between 1 and nMax
284 bool _ReadFieldParams::GetTokenSttFromTo(USHORT* pFrom, USHORT* pTo, USHORT nMax)
286 USHORT nStart = 0;
287 USHORT nEnd = 0;
288 xub_StrLen n = GoToTokenParam();
289 if( STRING_NOTFOUND != n )
292 String sParams( GetResult() );
294 xub_StrLen nIndex = 0;
295 String sStart( sParams.GetToken(0, '-', nIndex) );
296 if( STRING_NOTFOUND != nIndex )
298 nStart = static_cast<USHORT>(sStart.ToInt32());
299 nEnd = static_cast<USHORT>(sParams.Copy(nIndex).ToInt32());
302 if( pFrom ) *pFrom = nStart;
303 if( pTo ) *pTo = nEnd;
305 return nStart && nEnd && (nMax >= nStart) && (nMax >= nEnd);
308 //----------------------------------------
309 // Bookmarks
310 //----------------------------------------
312 long SwWW8ImplReader::Read_Book(WW8PLCFManResult*)
314 // muesste auch ueber pRes.nCo2OrIdx gehen
315 WW8PLCFx_Book* pB = pPlcxMan->GetBook();
316 if( !pB )
318 ASSERT( pB, "WW8PLCFx_Book - Pointer nicht da" );
319 return 0;
322 eBookStatus eB = pB->GetStatus();
323 if (eB & BOOK_IGNORE)
324 return 0; // Bookmark zu ignorieren
326 if (pB->GetIsEnd())
328 pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
329 pB->GetHandle(), (eB & BOOK_FIELD)!=0);
330 return 0;
333 //"_Toc*" and "_Hlt*" are unnecessary
334 const String* pName = pB->GetName();
335 #if !defined(WW_NATIVE_TOC)
336 if( !pName || pName->EqualsIgnoreCaseAscii( "_Toc", 0, 4 )
337 || pName->EqualsIgnoreCaseAscii( "_Hlt", 0, 4 ) )
338 return 0;
339 #endif
341 //JP 16.11.98: ToUpper darf auf keinen Fall gemacht werden, weil der
342 //Bookmark- name ein Hyperlink-Ziel sein kann!
344 String aVal;
345 if( SwFltGetFlag( nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
347 // Fuer UEbersetzung Bookmark -> Variable setzen
348 long nLen = pB->GetLen();
349 if( nLen > MAX_FIELDLEN )
350 nLen = MAX_FIELDLEN;
352 long nOldPos = pStrm->Tell();
353 nLen = pSBase->WW8ReadString( *pStrm, aVal, pB->GetStartPos(), nLen,
354 eStructCharSet );
355 pStrm->Seek( nOldPos );
357 // JP 19.03.2001 - now here the implementation of the old
358 // "QuoteString" and I hope with a better performance
359 // as before. It's also only needed if the filterflags
360 // say we will convert bookmarks to SetExpFields! And
361 // this the exception!
363 String sHex(CREATE_CONST_ASC( "\\x" ));
364 bool bSetAsHex;
365 bool bAllowCr = SwFltGetFlag(nFieldFlags,
366 SwFltControlStack::ALLOW_FLD_CR) ? true : false;
368 sal_Unicode cChar;
370 for( xub_StrLen nI = 0;
371 nI < aVal.Len() && aVal.Len() < (MAX_FIELDLEN - 4); ++nI )
373 switch( cChar = aVal.GetChar( nI ) )
375 case 0x0b:
376 case 0x0c:
377 case 0x0d:
378 if( bAllowCr )
379 aVal.SetChar( nI, '\n' ), bSetAsHex = false;
380 else
381 bSetAsHex = true;
382 break;
384 case 0xFE:
385 case 0xFF:
386 bSetAsHex = true;
387 break;
389 default:
390 bSetAsHex = 0x20 > cChar;
391 break;
394 if( bSetAsHex )
396 //all Hex-Numbers with \x before
397 String sTmp( sHex );
398 if( cChar < 0x10 )
399 sTmp += '0';
400 sTmp += String::CreateFromInt32( cChar, 16 );
401 aVal.Replace( nI, 1 , sTmp );
402 nI += sTmp.Len() - 1;
406 if( aVal.Len() > (MAX_FIELDLEN - 4))
407 aVal.Erase( MAX_FIELDLEN - 4 );
410 //e.g. inserting bookmark around field result, so we need to put
411 //it around the entire writer field, as we don't have the seperation
412 //of field and field result of word, see #i16941#
413 SwPosition aStart(*pPaM->GetPoint());
414 if (!maFieldStack.empty())
416 const FieldEntry &rTest = maFieldStack.back();
417 aStart = rTest.maStartPos;
420 pReffedStck->NewAttr(aStart, SwFltBookmark(BookmarkToWriter(*pName), aVal,
421 pB->GetHandle(), 0));
422 return 0;
425 //----------------------------------------------------------------------
426 // allgemeine Hilfsroutinen zum Auseinanderdroeseln der Parameter
427 //----------------------------------------------------------------------
429 // ConvertFFileName uebersetzt FeldParameter-Namen u. ae. in den
430 // System-Zeichensatz.
431 // Gleichzeitig werden doppelte Backslashes in einzelne uebersetzt.
432 void SwWW8ImplReader::ConvertFFileName( String& rName, const String& rOrg )
434 rName = rOrg;
435 rName.SearchAndReplaceAllAscii( "\\\\", String( '\\' ));
436 rName.SearchAndReplaceAllAscii( "%20", String( ' ' ));
438 // ggfs. anhaengende Anfuehrungszeichen entfernen
439 if( rName.Len() && '"' == rName.GetChar( rName.Len()-1 ))
440 rName.Erase( rName.Len()-1, 1);
442 //#82900# Need the more sophisticated url converter. cmc
443 if (rName.Len())
444 rName = URIHelper::SmartRel2Abs(
445 INetURLObject(sBaseURL), rName, Link(), false);
448 // ConvertUFNneme uebersetzt FeldParameter-Namen u. ae. in den
449 // System-Zeichensatz und Upcased sie ( z.B. fuer Ref-Felder )
450 namespace
452 void ConvertUFName( String& rName )
454 GetAppCharClass().toUpper( rName );
458 static void lcl_ConvertSequenceName(String& rSequenceName)
460 ConvertUFName(rSequenceName);
461 if ('0' <= rSequenceName.GetChar(0) && '9' >= rSequenceName.GetChar(0))
462 rSequenceName.Insert('_', 0);
465 // FindParaStart() finds 1st Parameter that follows '\' and cToken
466 // and returns start of this parameter or STRING_NOT_FOUND.
467 xub_StrLen FindParaStart( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
469 bool bStr = false; // innerhalb String ignorieren
471 for( xub_StrLen nBuf=0; nBuf+1 < rStr.Len(); nBuf++ )
473 if( rStr.GetChar( nBuf ) == '"' )
474 bStr = !bStr;
476 if( !bStr
477 && rStr.GetChar( nBuf ) == '\\'
478 && ( rStr.GetChar( nBuf + 1 ) == cToken
479 || rStr.GetChar( nBuf + 1 ) == cToken2 ) )
481 nBuf += 2;
482 // skip spaces between cToken and it's parameters
483 while( nBuf < rStr.Len()
484 && rStr.GetChar( nBuf ) == ' ' )
485 nBuf++;
486 // return start of parameters
487 return nBuf < rStr.Len() ? nBuf : STRING_NOTFOUND;
490 return STRING_NOTFOUND;
493 // FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
494 // ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
495 // und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
496 String FindPara( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
498 xub_StrLen n2; // Ende
499 xub_StrLen n = FindParaStart( rStr, cToken, cToken2 ); // Anfang
500 if( STRING_NOTFOUND == n )
501 return aEmptyStr;
503 if( rStr.GetChar( n ) == '"'
504 || rStr.GetChar( n ) == 132 )
505 { // Anfuehrungszeichen vor Para
506 n++; // Anfuehrungszeichen ueberlesen
507 n2 = n; // ab hier nach Ende suchen
508 while( n2 < rStr.Len()
509 && rStr.GetChar( n2 ) != 147
510 && rStr.GetChar( n2 ) != '"' )
511 n2++; // Ende d. Paras suchen
513 else
514 { // keine Anfuehrungszeichen
515 n2 = n; // ab hier nach Ende suchen
516 while( n2 < rStr.Len()
517 && rStr.GetChar( n2 ) != ' ' )
518 n2++; // Ende d. Paras suchen
520 return rStr.Copy( n, n2-n );
524 static SvxExtNumType GetNumTypeFromName(const String& rStr,
525 bool bAllowPageDesc = false)
527 SvxExtNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
528 if( rStr.EqualsIgnoreCaseAscii( "Arabi", 0, 5 ) ) // Arabisch, Arabic
529 eTyp = SVX_NUM_ARABIC;
530 else if( rStr.EqualsAscii( "misch", 2, 5 ) ) // r"omisch
531 eTyp = SVX_NUM_ROMAN_LOWER;
532 else if( rStr.EqualsAscii( "MISCH", 2, 5 ) ) // R"OMISCH
533 eTyp = SVX_NUM_ROMAN_UPPER;
534 else if( rStr.EqualsIgnoreCaseAscii( "alphabeti", 0, 9 ) )// alphabetisch, alphabetic
535 eTyp = ( rStr.GetChar( 0 ) == 'A' )
536 ? SVX_NUM_CHARS_UPPER_LETTER_N
537 : SVX_NUM_CHARS_LOWER_LETTER_N;
538 else if( rStr.EqualsIgnoreCaseAscii( "roman", 0, 5 ) ) // us
539 eTyp = ( rStr.GetChar( 0 ) == 'R' )
540 ? SVX_NUM_ROMAN_UPPER
541 : SVX_NUM_ROMAN_LOWER;
542 return eTyp;
545 static SvxExtNumType GetNumberPara(String& rStr, bool bAllowPageDesc = false)
547 String s( FindPara( rStr, '*', '*' ) ); // Ziffernart
548 SvxExtNumType aType = GetNumTypeFromName( s, bAllowPageDesc );
549 return aType;
555 bool SwWW8ImplReader::ForceFieldLanguage(SwField &rFld, USHORT nLang)
557 bool bRet(false);
559 const SvxLanguageItem *pLang =
560 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
561 ASSERT(pLang, "impossible");
562 USHORT nDefault = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
564 if (nLang != nDefault)
566 rFld.SetAutomaticLanguage(false);
567 rFld.SetLanguage(nLang);
568 bRet = true;
571 return bRet;
574 String GetWordDefaultDateStringAsUS(SvNumberFormatter* pFormatter, USHORT nLang)
576 //Get the system date in the correct final language layout, convert to
577 //a known language and modify the 2 digit year part to be 4 digit, and
578 //convert back to the correct language layout.
579 ULONG nIndex = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, nLang);
581 SvNumberformat aFormat = const_cast<SvNumberformat &>
582 (*(pFormatter->GetEntry(nIndex)));
583 aFormat.ConvertLanguage(*pFormatter, nLang, LANGUAGE_ENGLISH_US);
585 String sParams(aFormat.GetFormatstring());
586 // --> OD 2007-02-09 #i36594#
587 // Fix provided by mloiseleur@openoffice.org.
588 // A default date can have already 4 year digits, in some case
589 const xub_StrLen pos = sParams.Search( CREATE_CONST_ASC("YYYY") );
590 if ( pos == STRING_NOTFOUND )
592 sParams.SearchAndReplace(CREATE_CONST_ASC("YY"), CREATE_CONST_ASC("YYYY"));
594 // <--
595 return sParams;
598 short SwWW8ImplReader::GetTimeDatePara(String& rStr, sal_uInt32& rFormat,
599 USHORT &rLang, int nWhichDefault, bool bHijri)
601 bool bRTL = false;
602 if (pPlcxMan && !bVer67)
604 const BYTE *pResult = pPlcxMan->HasCharSprm(0x85A);
605 if (pResult && *pResult)
606 bRTL = true;
608 RES_CHRATR eLang = bRTL ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
609 const SvxLanguageItem *pLang = (SvxLanguageItem*)GetFmtAttr( static_cast< USHORT >(eLang));
610 ASSERT(pLang, "impossible");
611 rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
613 SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
614 String sParams( FindPara( rStr, '@', '@' ) );// Date/Time
615 if (!sParams.Len())
617 bool bHasTime = false;
618 switch (nWhichDefault)
620 case ww::ePRINTDATE:
621 case ww::eSAVEDATE:
622 sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
623 sParams.APPEND_CONST_ASC(" HH:MM:SS AM/PM");
624 bHasTime = true;
625 break;
626 case ww::eCREATEDATE:
627 sParams.ASSIGN_CONST_ASC("DD/MM/YYYY HH:MM:SS");
628 bHasTime = true;
629 break;
630 default:
631 case ww::eDATE:
632 sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
633 break;
636 if (bHijri)
637 sParams.Insert(CREATE_CONST_ASC("[~hijri]"), 0);
639 UINT16 nCheckPos = 0;
640 INT16 nType = NUMBERFORMAT_DEFINED;
641 rFormat = 0;
643 pFormatter->PutandConvertEntry(sParams, nCheckPos, nType, rFormat,
644 LANGUAGE_ENGLISH_US, rLang);
646 return bHasTime ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE;
649 ULONG nFmtIdx =
650 sw::ms::MSDateTimeFormatToSwFormat(sParams, pFormatter, rLang, bHijri);
651 short nNumFmtType = NUMBERFORMAT_UNDEFINED;
652 if (nFmtIdx)
653 nNumFmtType = pFormatter->GetType(nFmtIdx);
654 rFormat = nFmtIdx;
656 return nNumFmtType;
659 //-----------------------------------------
660 // Felder
661 //-----------------------------------------
662 // Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
663 void SwWW8ImplReader::UpdateFields()
665 // rDoc.GetSysFldType( RES_GETREFFLD )->UpdateFlds(); // Referenzen
666 // rDoc.UpdateFlds(); // SetExp-Fields
667 // rDoc.UpdateFlds(); // alles ???
668 // rDoc.UpdateExpFlds(); // SetExp-Fields
669 rDoc.SetUpdateExpFldStat(true); // JP: neu fuer alles wichtige
670 rDoc.SetInitDBFields(true); // Datenbank-Felder auch
673 sal_uInt16 SwWW8ImplReader::End_Field()
675 sal_uInt16 nRet = 0;
676 WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
677 ASSERT(pF, "WW8PLCFx_FLD - Pointer nicht da");
678 if (!pF || !pF->EndPosIsFieldEnd())
679 return nRet;
681 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
682 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
684 ASSERT(!maFieldStack.empty(), "Empty field stack\n");
685 if (!maFieldStack.empty())
688 only hyperlinks currently need to be handled like this, for the other
689 cases we have inserted a field not an attribute with an unknown end
690 point
692 nRet = maFieldStack.back().mnFieldId;
693 switch (nRet)
695 case 70:
696 if (bUseEnhFields && pPaM!=NULL && pPaM->GetPoint()!=NULL) {
697 SwPosition aEndPos = *pPaM->GetPoint();
698 SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
699 IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
700 IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeFieldBookmark(
701 aFldPam, maFieldStack.back().GetBookmarkName(), ::rtl::OUString::createFromAscii(ECMA_FORMTEXT ) ) );
702 ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
703 if (pFieldmark!=NULL) {
704 pFieldmark->addParams(maFieldStack.back().getParams());
707 break;
708 #if defined(WW_NATIVE_TOC)
709 case 8: // TOX_INDEX
710 case 13: // TOX_CONTENT
711 case 88: // HYPERLINK
712 case 37: // REF
713 if (pPaM!=NULL && pPaM->GetPoint()!=NULL) {
715 SwPosition aEndPos = *pPaM->GetPoint();
716 SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
717 SwFieldBookmark *pFieldmark=(SwFieldBookmark*)rDoc.makeFieldBookmark(aFldPam, maFieldStack.back().GetBookmarkName(), maFieldStack.back().GetBookmarkType());
718 ASSERT(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
719 if (pFieldmark!=NULL) {
720 pFieldmark->addParams(maFieldStack.back().getParams());
723 break;
724 #else
725 case 88:
726 pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
727 break;
728 #endif
729 case 36:
730 case 68:
731 //Move outside the section associated with this type of field
732 *pPaM->GetPoint() = maFieldStack.back().maStartPos;
733 break;
734 default:
735 break;
737 maFieldStack.pop_back();
739 return nRet;
742 bool AcceptableNestedField(sal_uInt16 nFieldCode)
744 switch (nFieldCode)
746 #if defined(WW_NATIVE_TOC)
747 case 8: // allow recursive field in TOC...
748 case 13: // allow recursive field in TOC...
749 #endif
750 case 36:
751 case 68:
752 case 79:
753 case 88:
754 // --> OD 2007-01-02 #b6504125#
755 // Accept AutoTextList field as nested field.
756 // Thus, the field result is imported as plain text.
757 case 89:
758 // <--
759 return true;
760 default:
761 return false;
765 FieldEntry::FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw()
766 : maStartPos(rPos), mnFieldId(nFieldId)
770 FieldEntry::FieldEntry(const FieldEntry &rOther) throw()
771 : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId)
775 void FieldEntry::Swap(FieldEntry &rOther) throw()
777 std::swap(maStartPos, rOther.maStartPos);
778 std::swap(mnFieldId, rOther.mnFieldId);
781 FieldEntry &FieldEntry::operator=(const FieldEntry &rOther) throw()
783 FieldEntry aTemp(rOther);
784 Swap(aTemp);
785 return *this;
788 ::rtl::OUString FieldEntry::GetBookmarkName()
790 return msBookmarkName;
793 ::rtl::OUString FieldEntry::GetBookmarkType()
795 return msMarkType;
798 void FieldEntry::SetBookmarkName(::rtl::OUString bookmarkName)
800 msBookmarkName=bookmarkName;
803 void FieldEntry::SetBookmarkType(::rtl::OUString bookmarkType)
805 msMarkType=bookmarkType;
808 void FieldEntry::AddParam(::rtl::OUString name, ::rtl::OUString value)
810 maParams.push_back( IFieldmark::ParamPair_t( name, value ) );
813 FieldEntry::Params_t &FieldEntry::getParams() {
814 return maParams;
818 // Read_Field liest ein Feld ein oder, wenn es nicht gelesen werden kann,
819 // wird 0 zurueckgegeben, so dass das Feld vom Aufrufer textuell gelesen wird.
820 // Returnwert: Gesamtlaenge des Feldes ( zum UEberlesen )
821 long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
823 typedef eF_ResT (SwWW8ImplReader:: *FNReadField)( WW8FieldDesc*, String& );
824 enum Limits {eMax = 96};
825 static FNReadField aWW8FieldTab[eMax+1] =
830 &SwWW8ImplReader::Read_F_Ref, // 3
833 &SwWW8ImplReader::Read_F_Set, // 6
835 &SwWW8ImplReader::Read_F_Tox, // 8
839 &SwWW8ImplReader::Read_F_Seq, // 12
840 &SwWW8ImplReader::Read_F_Tox, // 13
841 &SwWW8ImplReader::Read_F_DocInfo, // 14
842 &SwWW8ImplReader::Read_F_DocInfo, // 15
843 &SwWW8ImplReader::Read_F_DocInfo, // 16
844 &SwWW8ImplReader::Read_F_Author, // 17
845 &SwWW8ImplReader::Read_F_DocInfo, // 18
846 &SwWW8ImplReader::Read_F_DocInfo, // 19
847 &SwWW8ImplReader::Read_F_DocInfo, // 20
848 &SwWW8ImplReader::Read_F_DocInfo, // 21
849 &SwWW8ImplReader::Read_F_DocInfo, // 22
850 &SwWW8ImplReader::Read_F_DocInfo, // 23
851 &SwWW8ImplReader::Read_F_DocInfo, // 24
852 &SwWW8ImplReader::Read_F_DocInfo, // 25
853 &SwWW8ImplReader::Read_F_Anz, // 26
854 &SwWW8ImplReader::Read_F_Anz, // 27
855 &SwWW8ImplReader::Read_F_Anz, // 28
856 &SwWW8ImplReader::Read_F_FileName, // 29
857 &SwWW8ImplReader::Read_F_TemplName, // 30
858 &SwWW8ImplReader::Read_F_DateTime, // 31
859 &SwWW8ImplReader::Read_F_DateTime, // 32
860 &SwWW8ImplReader::Read_F_CurPage, // 33
863 &SwWW8ImplReader::Read_F_IncludeText, // 36
864 &SwWW8ImplReader::Read_F_PgRef, // 37
865 &SwWW8ImplReader::Read_F_InputVar, // 38
866 &SwWW8ImplReader::Read_F_Input, // 39
868 &SwWW8ImplReader::Read_F_DBNext, // 41
871 &SwWW8ImplReader::Read_F_DBNum, // 44
876 &SwWW8ImplReader::Read_F_Equation, // 49
878 &SwWW8ImplReader::Read_F_Macro, // 51
879 &SwWW8ImplReader::Read_F_ANumber, // 52
880 &SwWW8ImplReader::Read_F_ANumber, // 53
881 &SwWW8ImplReader::Read_F_ANumber, // 54
885 0, // 56: VERKNUePFUNG // fehlt noch !!!!!!!!!!!!!!!!!!!!!!!
888 &SwWW8ImplReader::Read_F_Symbol, // 57
889 &SwWW8ImplReader::Read_F_Embedd, // 58
890 &SwWW8ImplReader::Read_F_DBField, // 59
898 &SwWW8ImplReader::Read_F_IncludePicture, // 67
899 &SwWW8ImplReader::Read_F_IncludeText, // 68
901 &SwWW8ImplReader::Read_F_FormTextBox, // 70
902 &SwWW8ImplReader::Read_F_FormCheckBox, // 71
903 &SwWW8ImplReader::Read_F_NoteReference, // 72
904 0, /*&SwWW8ImplReader::Read_F_Tox*/
914 &SwWW8ImplReader::Read_F_FormListBox, // 83
915 0, // 84
916 &SwWW8ImplReader::Read_F_DocInfo, // 85
917 0, // 86
918 &SwWW8ImplReader::Read_F_OCX, // 87
919 &SwWW8ImplReader::Read_F_Hyperlink, // 88
920 0, // 89
921 0, // 90
922 &SwWW8ImplReader::Read_F_HTMLControl, // 91
923 0, // 92
924 0, // 93
925 0, // 94
926 &SwWW8ImplReader::Read_F_Shape, // 95
927 0 // eMax - Dummy leer Methode
929 ASSERT( ( sizeof( aWW8FieldTab ) / sizeof( *aWW8FieldTab ) == eMax+1 ),
930 "FeldFunc-Tabelle stimmt nicht" );
932 WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
933 ASSERT(pF, "WW8PLCFx_FLD - Pointer nicht da");
935 if (!pF || !pF->StartPosIsFieldStart())
936 return 0;
938 bool bNested = false;
939 if (!maFieldStack.empty())
941 mycFieldIter aEnd = maFieldStack.end();
942 for(mycFieldIter aIter = maFieldStack.begin(); aIter != aEnd; ++aIter)
944 bNested = !AcceptableNestedField(aIter->mnFieldId);
945 if (bNested)
946 break;
950 WW8FieldDesc aF;
951 bool bOk = pF->GetPara(pRes->nCp2OrIdx, aF);
953 ASSERT(bOk, "WW8: Bad Field!\n");
954 if (aF.nId == 33) aF.bCodeNest=false; //#124716#: do not recurse into nested page fields
956 maFieldStack.push_back(FieldEntry(*pPaM->GetPoint(), aF.nId));
958 if (bNested)
959 return 0;
961 USHORT n = ( aF.nId <= eMax ) ? aF.nId : static_cast< USHORT >(eMax); // alle > 91 werden 92
962 USHORT nI = n / 32; // # des UINT32
963 ULONG nMask = 1 << ( n % 32 ); // Maske fuer Bits
965 if( nFieldTagAlways[nI] & nMask ) // Flag: Tag it
966 return Read_F_Tag( &aF ); // Resultat nicht als Text
968 if( !bOk || !aF.nId ) // Feld kaputt
969 return aF.nLen; // -> ignorieren
971 if( aF.nId > eMax - 1) // WW: Nested Field
973 if( nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
974 return Read_F_Tag( &aF ); // Resultat nicht als Text
975 else
976 return aF.nLen;
979 //Only one type of field (hyperlink) in drawing textboxes exists
980 if (aF.nId != 88 && pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
981 return aF.nLen;
983 // keine Routine vorhanden
984 if (bNested || !aWW8FieldTab[aF.nId] || aF.bCodeNest)
986 if( nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
987 return Read_F_Tag( &aF ); // Resultat nicht als Text
988 // Lese nur Resultat
989 if (aF.bResNest && !AcceptableNestedField(aF.nId))
990 return aF.nLen; // Result nested -> nicht brauchbar
992 long nOldPos = pStrm->Tell();
993 String aStr;
994 aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
995 aF.nSCode, aF.nLCode, eTextCharSet );
996 pStrm->Seek( nOldPos );
998 //#124725# field codes which contain '/' or '.' are not displayed in WinWord
999 xub_StrLen nSpacePos = aStr.Search( ' ', 1 );
1000 if ( STRING_NOTFOUND == nSpacePos )
1001 nSpacePos = aStr.Len( );
1002 xub_StrLen nSearchPos = STRING_NOTFOUND;
1003 if ( ( ( nSearchPos = aStr.Search('.') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ||
1004 ( ( nSearchPos = aStr.Search('/') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) )
1005 return aF.nLen;
1006 else
1007 return aF.nLen - aF.nLRes - 1; // so viele ueberlesen, das Resultfeld
1008 // wird wie Haupttext eingelesen
1010 else
1011 { // Lies Feld
1012 long nOldPos = pStrm->Tell();
1013 String aStr;
1014 aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
1015 aF.nSCode, aF.nLCode, eTextCharSet );
1017 // --> OD 2005-07-25 #i51312# - graphics inside field code not supported
1018 // by Writer. Thus, delete character 0x01, which stands for such a graphic.
1019 if (aF.nId==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
1021 aStr.EraseAllChars( 0x01 );
1023 // <--
1025 eF_ResT eRes = (this->*aWW8FieldTab[aF.nId])( &aF, aStr );
1026 pStrm->Seek( nOldPos );
1028 switch ( eRes )
1030 case FLD_OK:
1031 return aF.nLen; // alles OK
1032 case FLD_TAGTXT:
1033 if ((nFieldTagBad[nI] & nMask)) // Flag: Tag bad
1034 return Read_F_Tag(&aF); // Taggen
1035 //fall through...
1036 case FLD_TEXT:
1037 // so viele ueberlesen, das Resultfeld wird wie Haupttext
1038 // eingelesen
1039 // JP 15.07.99: attributes can start at char 0x14 so skip one
1040 // char more back == "-2"
1041 if (aF.nLRes)
1042 return aF.nLen - aF.nLRes - 2;
1043 else
1044 return aF.nLen;
1045 case FLD_TAGIGN:
1046 if( ( nFieldTagBad[nI] & nMask ) ) // Flag: Tag bad
1047 return Read_F_Tag( &aF ); // Taggen
1048 return aF.nLen; // oder ignorieren
1049 case FLD_READ_FSPA:
1050 return aF.nLen - aF.nLRes - 2; // auf Char 1 positionieren
1051 default:
1052 return aF.nLen; // ignorieren
1057 //-----------------------------------------
1058 // Felder Taggen
1059 //-----------------------------------------
1061 // MakeTagString() gibt als Returnwert die Position des ersten
1062 // CR / Zeilenende / Seitenumbruch in pText und wandelt auch nur bis dort
1063 // Wenn keins dieser Sonderzeichen enthalten ist, wird 0 zurueckgeliefert.
1064 void SwWW8ImplReader::MakeTagString( String& rStr, const String& rOrg )
1066 String sHex( CREATE_CONST_ASC( "\\x" ));
1067 bool bAllowCr = SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_IN_TEXT )
1068 || SwFltGetFlag( nFieldFlags, SwFltControlStack::ALLOW_FLD_CR );
1069 sal_Unicode cChar;
1070 rStr = rOrg;
1072 for( xub_StrLen nI = 0;
1073 nI < rStr.Len() && rStr.Len() < (MAX_FIELDLEN - 4); ++nI )
1075 bool bSetAsHex = false;
1076 switch( cChar = rStr.GetChar( nI ) )
1078 case 132: // Typographische Anfuehrungszeichen
1079 case 148: // gegen normale tauschen
1080 case 147:
1081 rStr.SetChar( nI, '"' );
1082 break;
1083 case 19:
1084 rStr.SetChar( nI, '{' );
1085 break; // 19..21 zu {|}
1086 case 20:
1087 rStr.SetChar( nI, '|' );
1088 break;
1089 case 21:
1090 rStr.SetChar( nI, '}' );
1091 break;
1092 case '\\': // \{|} per \ Taggen
1093 case '{':
1094 case '|':
1095 case '}':
1096 rStr.Insert( nI, '\\' );
1097 ++nI;
1098 break;
1099 case 0x0b:
1100 case 0x0c:
1101 case 0x0d:
1102 if( bAllowCr )
1103 rStr.SetChar( nI, '\n' );
1104 else
1105 bSetAsHex = true;
1106 break;
1107 case 0xFE:
1108 case 0xFF:
1109 bSetAsHex = true;
1110 break;
1111 default:
1112 bSetAsHex = 0x20 > cChar;
1113 break;
1116 if( bSetAsHex )
1118 //all Hex-Numbers with \x before
1119 String sTmp( sHex );
1120 if( cChar < 0x10 )
1121 sTmp += '0';
1122 sTmp += String::CreateFromInt32( cChar, 16 );
1123 rStr.Replace( nI, 1 , sTmp );
1124 nI += sTmp.Len() - 1;
1128 if( rStr.Len() > (MAX_FIELDLEN - 4))
1129 rStr.Erase( MAX_FIELDLEN - 4 );
1132 void SwWW8ImplReader::InsertTagField( const USHORT nId, const String& rTagText )
1134 String aName( CREATE_CONST_ASC( "WwFieldTag" ) );
1135 if( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_DO_ID ) ) // Nummer?
1136 aName += String::CreateFromInt32( nId ); // ausgeben ?
1138 if( SwFltGetFlag(nFieldFlags, SwFltControlStack::TAGS_IN_TEXT))
1140 aName += rTagText; // als Txt taggen
1141 rDoc.InsertString(*pPaM, aName,
1142 IDocumentContentOperations::INS_NOHINTEXPAND);
1144 else
1145 { // normal tagggen
1147 SwFieldType* pFT = rDoc.InsertFldType(
1148 SwSetExpFieldType( &rDoc, aName, nsSwGetSetExpType::GSE_STRING ) );
1149 SwSetExpField aFld( (SwSetExpFieldType*)pFT, rTagText ); // SUB_INVISIBLE
1150 USHORT nSubType = ( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_VISIBLE ) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE;
1151 aFld.SetSubType(nSubType | nsSwGetSetExpType::GSE_STRING);
1153 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1157 long SwWW8ImplReader::Read_F_Tag( WW8FieldDesc* pF )
1159 long nOldPos = pStrm->Tell();
1161 WW8_CP nStart = pF->nSCode - 1; // mit 0x19 am Anfang
1162 long nL = pF->nLen; // Gesamtlaenge mit Resultat u. Nest
1163 if( nL > MAX_FIELDLEN )
1164 nL = MAX_FIELDLEN; // MaxLaenge, durch Quoten
1165 // max. 4* so gross
1166 String sFTxt;
1167 nL = pSBase->WW8ReadString( *pStrm, sFTxt,
1168 pPlcxMan->GetCpOfs() + nStart, nL, eStructCharSet);
1171 String aTagText;
1172 MakeTagString( aTagText, sFTxt );
1173 InsertTagField( pF->nId, aTagText );
1175 pStrm->Seek( nOldPos );
1176 return pF->nLen;
1180 //-----------------------------------------
1181 // normale Felder
1182 //-----------------------------------------
1184 eF_ResT SwWW8ImplReader::Read_F_Input( WW8FieldDesc* pF, String& rStr )
1186 String aDef;
1187 String aQ;
1188 long nRet;
1189 _ReadFieldParams aReadParam( rStr );
1190 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1192 switch( nRet )
1194 case -2:
1195 if( !aQ.Len() )
1196 aQ = aReadParam.GetResult();
1197 break;
1198 case 'd':
1199 case 'D':
1201 xub_StrLen n = aReadParam.GoToTokenParam();
1202 if( STRING_NOTFOUND != n )
1203 aDef = aReadParam.GetResult();
1205 break;
1208 if( !aDef.Len() )
1209 aDef = GetFieldResult( pF );
1211 SwInputField aFld( (SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
1212 aDef, aQ, INP_TXT, 0 ); // sichtbar ( geht z.Zt. nicht anders )
1213 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1215 return FLD_OK;
1218 // GetFieldResult alloziert einen String und liest das Feld-Resultat ein
1219 String SwWW8ImplReader::GetFieldResult( WW8FieldDesc* pF )
1221 long nOldPos = pStrm->Tell();
1223 WW8_CP nStart = pF->nSRes; // Start Resultat
1224 long nL = pF->nLRes; // Laenge Resultat
1225 if( !nL )
1226 return aEmptyStr; // kein Resultat
1228 if( nL > MAX_FIELDLEN )
1229 nL = MAX_FIELDLEN; // MaxLaenge, durch Quoten
1230 // max. 4* so gross
1232 String sRes;
1233 nL = pSBase->WW8ReadString( *pStrm, sRes, pPlcxMan->GetCpOfs() + nStart,
1234 nL, eStructCharSet );
1236 pStrm->Seek( nOldPos );
1238 //replace CR 0x0D with LF 0x0A
1239 sRes.SearchAndReplaceAll(0x0D, 0x0A);
1240 //replace VT 0x0B with LF 0x0A
1241 sRes.SearchAndReplaceAll(0x0B, 0x0A);
1242 return sRes;
1246 Bookmarks can be set with fields SET and ASK, and they can be referenced with
1247 REF. When set, they behave like variables in writer, otherwise they behave
1248 like normal bookmarks. We can check whether we should use a show variable
1249 instead of a normal bookmark ref by converting to "show variable" at the end
1250 of the document those refs which look for the content of a bookmark but whose
1251 bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
1253 The other piece of the puzzle is that refs that point to the "location" of the
1254 bookmark will in word actually point to the last location where the bookmark
1255 was set with SET or ASK, not the actual bookmark. This is only noticable when
1256 a document sets the bookmark more than once. This is because word places the
1257 true bookmark at the location of the last set, but the refs will display the
1258 position of the first set before the ref.
1260 So what we will do is
1262 1) keep a list of all bookmarks that were set, any bookmark names mentioned
1263 here that are refed by content will be converted to show variables.
1265 2) create pseudo bookmarks for every position that a bookmark is set with SET
1266 or ASK but has no existing bookmark. We can then keep a map from the original
1267 bookmark name to the new one. As we parse the document new pseudo names will
1268 replace the older ones, so the map always contains the bookmark of the
1269 location that msword itself would use.
1271 3) word's bookmarks are case insensitive, writers are not. So we need to
1272 map case different versions together, regardless of whether they are
1273 variables or not.
1275 4) when a reference is (first) SET or ASK, the bookmark associated with it
1276 is placed around the 0x14 0x15 result part of the field. We will fiddle
1277 the placement to be the writer equivalent of directly before and after
1278 the field, which gives the same effect and meaning, to do so we must
1279 get any bookmarks in the field range, and begin them immediately before
1280 the set/ask field, and end them directly afterwards. MapBookmarkVariables
1281 returns an identifier of the bookmark attribute to close after inserting
1282 the appropiate set/ask field.
1284 long SwWW8ImplReader::MapBookmarkVariables(const WW8FieldDesc* pF,
1285 String &rOrigName, const String &rData)
1287 ASSERT(pPlcxMan,"No pPlcxMan");
1288 long nNo;
1290 If there was no bookmark associated with this set field, then we create a
1291 pseudo one and insert it in the document.
1293 USHORT nIndex;
1294 pPlcxMan->GetBook()->MapName(rOrigName);
1295 String sName = pPlcxMan->GetBook()->GetBookmark(
1296 pF->nSCode, pF->nSCode + pF->nLen, nIndex);
1297 if (sName.Len())
1299 pPlcxMan->GetBook()->SetStatus(nIndex, BOOK_IGNORE);
1300 nNo = nIndex;
1302 else
1304 sName = CREATE_CONST_ASC("WWSetBkmk");
1305 nNo = pReffingStck->aFieldVarNames.size()+1;
1306 sName += String::CreateFromInt32(nNo);
1307 nNo += pPlcxMan->GetBook()->GetIMax();
1309 pReffedStck->NewAttr(*pPaM->GetPoint(),
1310 SwFltBookmark(BookmarkToWriter(sName), rData, nNo, 0));
1311 pReffingStck->aFieldVarNames[rOrigName] = sName;
1312 return nNo;
1316 Word can set a bookmark with set or with ask, such a bookmark is equivalent to
1317 our variables, but until the end of a document we cannot be sure if a bookmark
1318 is a variable or not, at the end we will have a list of reference names which
1319 were set or asked, all bookmarks using the content of those bookmarks are
1320 converted to show variables, those that reference the position of the field
1321 can be left as references, because a bookmark is also inserted at the position
1322 of a set or ask field, either by word, or in some special cases by the import
1323 filter itself.
1325 SwFltStackEntry *SwWW8FltRefStack::RefToVar(const SwField* pFld,
1326 SwFltStackEntry *pEntry)
1328 SwFltStackEntry *pRet=0;
1329 if (pFld && RES_GETREFFLD == pFld->Which())
1331 //Get the name of the ref field, and see if actually a variable
1332 const String &rName = pFld->GetPar1();
1333 ::std::map<String,String,SwWW8FltRefStack::ltstr>::const_iterator
1334 aResult = aFieldVarNames.find(rName);
1336 if (aResult != aFieldVarNames.end())
1338 SwGetExpField aFld( (SwGetExpFieldType*)
1339 pDoc->GetSysFldType(RES_GETEXPFLD), rName, nsSwGetSetExpType::GSE_STRING, 0);
1340 delete pEntry->pAttr;
1341 SwFmtFld aTmp(aFld);
1342 pEntry->pAttr = aTmp.Clone();
1343 pRet = pEntry;
1346 return pRet;
1349 String SwWW8ImplReader::GetMappedBookmark(const String &rOrigName)
1351 String sName(BookmarkToWriter(rOrigName));
1352 ASSERT(pPlcxMan,"no pPlcxMan");
1353 pPlcxMan->GetBook()->MapName(sName);
1355 //See if there has been a variable set with this name, if so get
1356 //the pseudo bookmark name that was set with it.
1357 ::std::map<String,String,SwWW8FltRefStack::ltstr>::const_iterator aResult =
1358 pReffingStck->aFieldVarNames.find(sName);
1360 const String &rBkmName = (aResult == pReffingStck->aFieldVarNames.end())
1361 ? sName : (*aResult).second;
1363 return rBkmName;
1366 // "ASK"
1367 eF_ResT SwWW8ImplReader::Read_F_InputVar( WW8FieldDesc* pF, String& rStr )
1369 String sOrigName;
1370 String aQ;
1371 String aDef;
1372 long nRet;
1373 _ReadFieldParams aReadParam( rStr );
1374 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1376 switch( nRet )
1378 case -2:
1379 if (!sOrigName.Len())
1380 sOrigName = aReadParam.GetResult();
1381 else if( !aQ.Len() )
1382 aQ = aReadParam.GetResult();
1383 break;
1384 case 'd':
1385 case 'D':
1386 if (STRING_NOTFOUND != aReadParam.GoToTokenParam())
1387 aDef = aReadParam.GetResult();
1388 break;
1392 if( !sOrigName.Len() )
1393 return FLD_TAGIGN; // macht ohne Textmarke keinen Sinn
1395 String aResult(GetFieldResult(pF));
1397 //#i24377#, munge Default Text into title as we have only one slot
1398 //available for aResult and aDef otherwise
1399 if (aDef.Len())
1401 if (aQ.Len())
1402 aQ.APPEND_CONST_ASC(" - ");
1403 aQ.Append(aDef);
1406 long nNo = MapBookmarkVariables(pF, sOrigName, aResult);
1408 SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
1409 SwSetExpFieldType(&rDoc, sOrigName, nsSwGetSetExpType::GSE_STRING));
1410 SwSetExpField aFld(pFT, aResult);
1411 aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
1412 aFld.SetInputFlag(true);
1413 aFld.SetPromptText( aQ );
1415 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1417 pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
1418 return FLD_OK;
1421 // "AUTONR"
1422 eF_ResT SwWW8ImplReader::Read_F_ANumber( WW8FieldDesc*, String& rStr )
1424 if( !pNumFldType ){ // 1. Mal
1425 SwSetExpFieldType aT( &rDoc, CREATE_CONST_ASC("AutoNr"), nsSwGetSetExpType::GSE_SEQ );
1426 pNumFldType = rDoc.InsertFldType( aT );
1428 SwSetExpField aFld( (SwSetExpFieldType*)pNumFldType, aEmptyStr,
1429 GetNumberPara( rStr ) );
1430 aFld.SetValue( ++nFldNum );
1431 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1432 return FLD_OK;
1435 // "SEQ"
1436 eF_ResT SwWW8ImplReader::Read_F_Seq( WW8FieldDesc*, String& rStr )
1438 String aSequenceName;
1439 String aBook;
1440 bool bHidden = false;
1441 bool bFormat = false;
1442 bool bShowLast = false;
1443 bool bCountOn = true;
1444 String sStart;
1445 SvxExtNumType eNumFormat = SVX_NUM_ARABIC;
1446 long nRet;
1447 _ReadFieldParams aReadParam( rStr );
1448 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1450 switch( nRet )
1452 case -2:
1453 if( !aSequenceName.Len() )
1454 aSequenceName = aReadParam.GetResult();
1455 else if( !aBook.Len() )
1456 aBook = aReadParam.GetResult();
1457 break;
1459 case 'h':
1460 if( !bFormat )
1461 bHidden = true; // Hidden-Flag aktivieren
1462 break;
1464 case '*':
1465 bFormat = true; // Format-Flag aktivieren
1466 bHidden = false; // Hidden-Flag deaktivieren
1467 nRet = aReadParam.SkipToNextToken();
1468 if( -2 == nRet )
1469 eNumFormat = GetNumTypeFromName( aReadParam.GetResult() );
1470 break;
1472 case 'r':
1473 bShowLast = false; // Zaehler neu setzen
1474 bCountOn = false;
1475 nRet = aReadParam.SkipToNextToken();
1476 if( -2 == nRet )
1477 sStart = aReadParam.GetResult();
1478 break;
1480 case 'c':
1481 bShowLast = true; // zuletzt verwendete Nummer anzeigen
1482 bCountOn = false;
1483 break;
1485 case 'n':
1486 bCountOn = true; // Nummer um eins erhoehen (default)
1487 bShowLast = false;
1488 break;
1490 case 's': // Outline Level
1491 //#i19682, what am I to do with this value
1492 break;
1495 if (!aSequenceName.Len() && !aBook.Len())
1496 return FLD_TAGIGN;
1498 SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
1499 SwSetExpFieldType( &rDoc, aSequenceName, nsSwGetSetExpType::GSE_SEQ ) );
1500 SwSetExpField aFld( pFT, aEmptyStr, eNumFormat );
1502 if (sStart.Len())
1503 aFld.SetFormula( ( aSequenceName += '=' ) += sStart );
1504 else if (!bCountOn)
1505 aFld.SetFormula(aSequenceName);
1507 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1508 return FLD_OK;
1511 eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, String& rStr )
1513 USHORT nSub=0;
1514 // RegInfoFormat, DefaultFormat fuer DocInfoFelder
1515 USHORT nReg = DI_SUB_AUTHOR;
1516 bool bDateTime = false;
1518 if( 85 == pF->nId )
1520 String aDocProperty;
1521 _ReadFieldParams aReadParam( rStr );
1522 long nRet;
1523 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1525 switch( nRet )
1527 case -2:
1528 if( !aDocProperty.Len() )
1529 aDocProperty = aReadParam.GetResult();
1530 break;
1531 case '*':
1532 //Skip over MERGEFORMAT
1533 aReadParam.SkipToNextToken();
1534 break;
1537 aDocProperty.EraseAllChars('"');
1540 There are up to 26 fields that may be meant by 'DocumentProperty'.
1541 Which of them is to be inserted here ?
1542 This Problem can only be solved by implementing a name matching
1543 method that compares the given Parameter String with the four
1544 possible name sets (english, german, french, spanish)
1547 static const sal_Char* aName10 = "\x0F"; // SW field code
1548 static const sal_Char* aName11 // German
1549 = "TITEL";
1550 static const sal_Char* aName12 // French
1551 = "TITRE";
1552 static const sal_Char* aName13 // English
1553 = "TITLE";
1554 static const sal_Char* aName14 // Spanish
1555 = "TITRO";
1556 static const sal_Char* aName20 = "\x15"; // SW filed code
1557 static const sal_Char* aName21 // German
1558 = "ERSTELLDATUM";
1559 static const sal_Char* aName22 // French
1560 = "CR\xC9\xC9";
1561 static const sal_Char* aName23 // English
1562 = "CREATED";
1563 static const sal_Char* aName24 // Spanish
1564 = "CREADO";
1565 static const sal_Char* aName30 = "\x16"; // SW filed code
1566 static const sal_Char* aName31 // German
1567 = "ZULETZTGESPEICHERTZEIT";
1568 static const sal_Char* aName32 // French
1569 = "DERNIERENREGISTREMENT";
1570 static const sal_Char* aName33 // English
1571 = "SAVED";
1572 static const sal_Char* aName34 // Spanish
1573 = "MODIFICADO";
1574 static const sal_Char* aName40 = "\x17"; // SW filed code
1575 static const sal_Char* aName41 // German
1576 = "ZULETZTGEDRUCKT";
1577 static const sal_Char* aName42 // French
1578 = "DERNI\xC8" "REIMPRESSION";
1579 static const sal_Char* aName43 // English
1580 = "LASTPRINTED";
1581 static const sal_Char* aName44 // Spanish
1582 = "HUPS PUPS";
1583 static const sal_Char* aName50 = "\x18"; // SW filed code
1584 static const sal_Char* aName51 // German
1585 = "\xDC" "BERARBEITUNGSNUMMER";
1586 static const sal_Char* aName52 // French
1587 = "NUM\xC9" "RODEREVISION";
1588 static const sal_Char* aName53 // English
1589 = "REVISIONNUMBER";
1590 static const sal_Char* aName54 // Spanish
1591 = "SNUBBEL BUBBEL";
1592 static const USHORT nFldCnt = 5;
1594 // additional fields are to be coded soon! :-)
1596 static const USHORT nLangCnt = 4;
1597 static const sal_Char *aNameSet_26[nFldCnt][nLangCnt+1] =
1599 {aName10, aName11, aName12, aName13, aName14},
1600 {aName20, aName21, aName22, aName23, aName24},
1601 {aName30, aName31, aName32, aName33, aName34},
1602 {aName40, aName41, aName42, aName43, aName44},
1603 {aName50, aName51, aName52, aName53, aName54}
1606 bool bFldFound= false;
1607 USHORT nFIdx;
1608 for(USHORT nLIdx=1; !bFldFound && (nLangCnt > nLIdx); ++nLIdx)
1610 for(nFIdx = 0; !bFldFound && (nFldCnt > nFIdx); ++nFIdx)
1612 if( aDocProperty.Equals( String( aNameSet_26[nFIdx][nLIdx],
1613 RTL_TEXTENCODING_MS_1252 ) ) )
1615 bFldFound = true;
1616 pF->nId = aNameSet_26[nFIdx][0][0];
1621 if( !bFldFound )
1624 SwUserFieldType aTmp( &rDoc, aDocProperty );
1625 aTmp.SetContent(GetFieldResult( pF ));
1626 SwUserField aUFld( (SwUserFieldType*)rDoc.InsertFldType( aTmp ));
1627 aUFld.ChangeFormat( UF_STRING );
1628 rDoc.Insert( *pPaM, SwFmtFld( aUFld ), 0);
1630 SwDocInfoField aFld( (SwDocInfoFieldType*)
1631 rDoc.GetSysFldType( RES_DOCINFOFLD ), DI_CUSTOM|nReg, aDocProperty, GetFieldResult( pF ) );
1632 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1634 return FLD_OK;
1638 switch( pF->nId )
1640 case 14:
1641 /* kann alle INFO-Vars!! */
1642 nSub = DI_KEYS;
1643 break;
1644 case 15:
1645 nSub = DI_TITEL;
1646 break;
1647 case 16:
1648 nSub = DI_THEMA;
1649 break;
1650 case 18:
1651 nSub = DI_KEYS;
1652 break;
1653 case 19:
1654 nSub = DI_COMMENT;
1655 break;
1656 case 20:
1657 nSub = DI_CHANGE;
1658 nReg = DI_SUB_AUTHOR;
1659 break;
1660 case 21:
1661 nSub = DI_CREATE;
1662 nReg = DI_SUB_DATE;
1663 bDateTime = true;
1664 break;
1665 case 23:
1666 nSub = DI_PRINT;
1667 nReg = DI_SUB_DATE;
1668 bDateTime = true;
1669 break;
1670 case 24:
1671 nSub = DI_DOCNO;
1672 break;
1673 case 22:
1674 nSub = DI_CHANGE;
1675 nReg = DI_SUB_DATE;
1676 bDateTime = true;
1677 break;
1678 case 25:
1679 nSub = DI_CHANGE;
1680 nReg = DI_SUB_TIME;
1681 bDateTime = true;
1682 break;
1685 sal_uInt32 nFormat = 0;
1687 USHORT nLang(0);
1688 if (bDateTime)
1690 short nDT = GetTimeDatePara(rStr, nFormat, nLang, pF->nId);
1691 switch (nDT)
1693 case NUMBERFORMAT_DATE:
1694 nReg = DI_SUB_DATE;
1695 break;
1696 case NUMBERFORMAT_TIME:
1697 nReg = DI_SUB_TIME;
1698 break;
1699 case NUMBERFORMAT_DATETIME:
1700 nReg = DI_SUB_DATE;
1701 break;
1702 default:
1703 nReg = DI_SUB_DATE;
1704 break;
1708 SwDocInfoField aFld( (SwDocInfoFieldType*)
1709 rDoc.GetSysFldType( RES_DOCINFOFLD ), nSub|nReg, String(), nFormat );
1710 if (bDateTime)
1711 ForceFieldLanguage(aFld, nLang);
1712 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1714 return FLD_OK;
1717 eF_ResT SwWW8ImplReader::Read_F_Author( WW8FieldDesc*, String& )
1719 // SH: Das SwAuthorField bezeichnet nicht den urspruenglichen
1720 // Autor, sondern den aktuellen Benutzer, also besser ueber DocInfo
1721 // (#56149)
1722 SwDocInfoField aFld( (SwDocInfoFieldType*)
1723 rDoc.GetSysFldType( RES_DOCINFOFLD ),
1724 DI_CREATE|DI_SUB_AUTHOR, String() );
1725 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1726 return FLD_OK;
1729 eF_ResT SwWW8ImplReader::Read_F_TemplName( WW8FieldDesc*, String& )
1731 SwTemplNameField aFld( (SwTemplNameFieldType*)
1732 rDoc.GetSysFldType( RES_TEMPLNAMEFLD ), FF_NAME );
1733 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1734 return FLD_OK;
1737 // Sowohl das Datum- wie auch das Uhrzeit-Feld kann fuer Datum, fuer Uhrzeit
1738 // oder fuer beides benutzt werden.
1739 eF_ResT SwWW8ImplReader::Read_F_DateTime( WW8FieldDesc*pF, String& rStr )
1741 bool bHijri = false;
1742 bool bSaka = false;
1743 _ReadFieldParams aReadParam(rStr);
1744 long nTok;
1745 while (-1 != (nTok = aReadParam.SkipToNextToken()))
1747 switch (nTok)
1749 default:
1750 case 'l':
1751 case -2:
1752 break;
1753 case 'h':
1754 bHijri = true;
1755 break;
1756 case 's':
1757 bSaka = true;
1758 break;
1762 sal_uInt32 nFormat = 0;
1764 USHORT nLang(0);
1765 short nDT = GetTimeDatePara(rStr, nFormat, nLang, ww::eDATE, bHijri);
1767 if( NUMBERFORMAT_UNDEFINED == nDT ) // no D/T-Formatstring
1769 if (32 == pF->nId)
1771 nDT = NUMBERFORMAT_TIME;
1772 nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
1773 NF_TIME_START, LANGUAGE_SYSTEM );
1775 else
1777 nDT = NUMBERFORMAT_DATE;
1778 nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
1779 NF_DATE_START, LANGUAGE_SYSTEM );
1783 if (nDT & NUMBERFORMAT_DATE)
1785 SwDateTimeField aFld((SwDateTimeFieldType*)
1786 rDoc.GetSysFldType(RES_DATETIMEFLD ), DATEFLD, nFormat);
1787 ForceFieldLanguage(aFld, nLang);
1788 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1790 else if (nDT == NUMBERFORMAT_TIME)
1792 SwDateTimeField aFld((SwDateTimeFieldType*)
1793 rDoc.GetSysFldType(RES_DATETIMEFLD), TIMEFLD, nFormat);
1794 ForceFieldLanguage(aFld, nLang);
1795 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1798 return FLD_OK;
1801 eF_ResT SwWW8ImplReader::Read_F_FileName(WW8FieldDesc*, String &rStr)
1803 SwFileNameFormat eType = FF_NAME;
1804 long nRet;
1805 _ReadFieldParams aReadParam(rStr);
1806 while (-1 != (nRet = aReadParam.SkipToNextToken()))
1808 switch (nRet)
1810 case 'p':
1811 eType = FF_PATHNAME;
1812 break;
1813 case '*':
1814 //Skip over MERGEFORMAT
1815 aReadParam.SkipToNextToken();
1816 break;
1817 default:
1818 ASSERT(!this, "unknown option in FileName field");
1819 break;
1823 SwFileNameField aFld(
1824 (SwFileNameFieldType*)rDoc.GetSysFldType(RES_FILENAMEFLD), eType);
1825 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1826 return FLD_OK;
1829 eF_ResT SwWW8ImplReader::Read_F_Anz( WW8FieldDesc* pF, String& rStr )
1830 { // SeitenZahl - Feld
1831 USHORT nSub = DS_PAGE;
1832 switch ( pF->nId ){
1833 case 27: nSub = DS_WORD; break; // Wordzahl
1834 case 28: nSub = DS_CHAR; break; // Zeichenzahl
1836 SwDocStatField aFld( (SwDocStatFieldType*)
1837 rDoc.GetSysFldType( RES_DOCSTATFLD ), nSub,
1838 GetNumberPara( rStr ) );
1839 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1840 return FLD_OK;
1843 eF_ResT SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc*, String& rStr )
1845 // zusaetzlich mit Kapitelnummer?
1846 if( bPgChpLevel )
1848 SwChapterField aFld( (SwChapterFieldType*)
1849 rDoc.GetSysFldType( RES_CHAPTERFLD ), CF_NUMBER );
1850 aFld.SetLevel( nPgChpLevel );
1851 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1853 static const sal_Char aDelim[] = "-.:\x97\x96";
1854 BYTE nDelim = nPgChpDelim;
1855 if( nDelim > 4 )
1856 nDelim = 0;
1858 sal_Unicode c = ByteString::ConvertToUnicode( aDelim[ nDelim ],
1859 RTL_TEXTENCODING_MS_1252 );
1860 if( '-' == c )
1862 rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
1864 else
1866 rDoc.InsertString( *pPaM, c ); // maybe insert ZWNBSP?
1870 // Seitennummer
1871 SwPageNumberField aFld( (SwPageNumberFieldType*)
1872 rDoc.GetSysFldType( RES_PAGENUMBERFLD ), PG_RANDOM,
1873 GetNumberPara(rStr, true));
1875 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1876 return FLD_OK;
1879 eF_ResT SwWW8ImplReader::Read_F_Symbol( WW8FieldDesc*, String& rStr )
1881 //e.g. #i20118#
1882 String aQ;
1883 String aName;
1884 sal_Int32 nSize = 0;
1885 long nRet;
1886 _ReadFieldParams aReadParam( rStr );
1887 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1889 switch( nRet )
1891 case -2:
1892 if( !aQ.Len() )
1893 aQ = aReadParam.GetResult();
1894 break;
1895 case 'f':
1896 case 'F':
1898 xub_StrLen n = aReadParam.GoToTokenParam();
1899 if( STRING_NOTFOUND != n )
1900 aName = aReadParam.GetResult();
1902 break;
1903 case 's':
1904 case 'S':
1906 String aSiz;
1907 xub_StrLen n = aReadParam.GoToTokenParam();
1908 if (STRING_NOTFOUND != n)
1909 aSiz = aReadParam.GetResult();
1910 if (aSiz.Len())
1911 nSize = aSiz.ToInt32() * 20; // pT -> twip
1913 break;
1916 if( !aQ.Len() )
1917 return FLD_TAGIGN; // -> kein 0-Zeichen in Text
1919 if (sal_Unicode cChar = static_cast<sal_Unicode>(aQ.ToInt32()))
1921 if (aName.Len()) // Font Name set ?
1923 SvxFontItem aFont(FAMILY_DONTKNOW, aName, aEmptyStr,
1924 PITCH_DONTKNOW, RTL_TEXTENCODING_SYMBOL, RES_CHRATR_FONT);
1925 NewAttr(aFont); // new Font
1928 if (nSize > 0) //#i20118#
1930 SvxFontHeightItem aSz(nSize, 100, RES_CHRATR_FONTSIZE);
1931 NewAttr(aSz);
1934 rDoc.InsertString(*pPaM, cChar);
1936 if (nSize > 0)
1937 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONTSIZE);
1938 if (aName.Len())
1939 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONT);
1941 else
1943 rDoc.InsertString(*pPaM, CREATE_CONST_ASC("###"));
1946 return FLD_OK;
1949 // "EINBETTEN"
1950 eF_ResT SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc*, String& rStr )
1952 String sHost;
1954 long nRet;
1955 _ReadFieldParams aReadParam( rStr );
1956 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1958 switch( nRet )
1960 case -2:
1961 sHost = aReadParam.GetResult();
1962 break;
1964 case 's':
1965 // use ObjectSize
1966 break;
1970 if( bObj && nPicLocFc )
1971 nObjLocFc = nPicLocFc;
1972 bEmbeddObj = true;
1973 return FLD_TEXT;
1977 // "SET"
1978 eF_ResT SwWW8ImplReader::Read_F_Set( WW8FieldDesc* pF, String& rStr )
1980 String sOrigName;
1981 String sVal;
1982 long nRet;
1983 _ReadFieldParams aReadParam( rStr );
1984 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
1986 switch( nRet )
1988 case -2:
1989 if( !sOrigName.Len() )
1990 sOrigName = aReadParam.GetResult();
1991 else if( !sVal.Len() )
1992 sVal = aReadParam.GetResult();
1993 break;
1997 long nNo = MapBookmarkVariables(pF,sOrigName,sVal);
1999 SwFieldType* pFT = rDoc.InsertFldType( SwSetExpFieldType( &rDoc, sOrigName,
2000 nsSwGetSetExpType::GSE_STRING ) );
2001 SwSetExpField aFld( (SwSetExpFieldType*)pFT, sVal, ULONG_MAX );
2002 aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
2004 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2006 pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
2008 return FLD_OK;
2011 // "REF"
2012 eF_ResT SwWW8ImplReader::Read_F_Ref( WW8FieldDesc*, String& rStr )
2013 { // Reference - Field
2014 String sOrigBkmName;
2015 bool bChapterNr = false;
2016 bool bAboveBelow = false;
2018 long nRet;
2019 _ReadFieldParams aReadParam( rStr );
2020 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2022 switch( nRet )
2024 case -2:
2025 if( !sOrigBkmName.Len() ) // get name of bookmark
2026 sOrigBkmName = aReadParam.GetResult();
2027 break;
2028 case 'n':
2029 case 'r':
2030 case 'w':
2031 bChapterNr = true; // activate flag 'Chapter Number'
2032 break;
2034 case 'p':
2035 bAboveBelow = true;
2036 break;
2037 case 'h':
2038 break;
2039 default:
2040 // unimplemented switch: just do 'nix nought nothing' :-)
2041 break;
2045 String sBkmName(GetMappedBookmark(sOrigBkmName));
2047 if (!bAboveBelow || bChapterNr)
2049 if (bChapterNr)
2051 SwGetRefField aFld(
2052 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2053 sBkmName,REF_BOOKMARK,0,REF_CHAPTER);
2054 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2056 else
2059 If we are just inserting the contents of the bookmark, then it
2060 is possible that the bookmark is actually a variable, so we
2061 must store it until the end of the document to see if it was,
2062 in which case we'll turn it into a show variable
2064 SwGetRefField aFld(
2065 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2066 sOrigBkmName,REF_BOOKMARK,0,REF_CONTENT);
2067 pReffingStck->NewAttr( *pPaM->GetPoint(), SwFmtFld(aFld) );
2068 pReffingStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_FIELD);
2072 if( bAboveBelow )
2074 SwGetRefField aFld( (SwGetRefFieldType*)
2075 rDoc.GetSysFldType( RES_GETREFFLD ), sBkmName, REF_BOOKMARK, 0,
2076 REF_UPDOWN );
2077 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2079 return FLD_OK;
2082 // Note Reference - Field
2083 eF_ResT SwWW8ImplReader::Read_F_NoteReference( WW8FieldDesc*, String& rStr )
2085 String aBkmName;
2086 bool bChapterNr = false;
2087 bool bAboveBelow = false;
2089 long nRet;
2090 _ReadFieldParams aReadParam( rStr );
2091 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2093 switch( nRet )
2095 case -2:
2096 if( !aBkmName.Len() ) // get name of foot/endnote
2097 aBkmName = aReadParam.GetResult();
2098 break;
2099 case 'r':
2100 bChapterNr = true; // activate flag 'Chapter Number'
2101 break;
2102 case 'p':
2103 bAboveBelow = true;
2104 break;
2105 case 'h':
2106 break;
2107 default:
2108 // unimplemented switch: just do 'nix nought nothing' :-)
2109 break;
2113 // set Sequence No of corresponding Foot-/Endnote to Zero
2114 // (will be corrected in
2115 SwGetRefField aFld( (SwGetRefFieldType*)
2116 rDoc.GetSysFldType( RES_GETREFFLD ), aBkmName, REF_FOOTNOTE, 0,
2117 REF_ONLYNUMBER );
2118 pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld));
2119 pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
2120 if (bAboveBelow)
2122 SwGetRefField aFld2( (SwGetRefFieldType*)
2123 rDoc.GetSysFldType( RES_GETREFFLD ),aBkmName, REF_FOOTNOTE, 0,
2124 REF_UPDOWN );
2125 pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld2));
2126 pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
2128 return FLD_OK;
2131 // "SEITENREF"
2132 eF_ResT SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc*, String& rStr )
2134 String sOrigName;
2135 long nRet;
2136 _ReadFieldParams aReadParam( rStr );
2137 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2139 switch( nRet )
2141 case -2:
2142 if( !sOrigName.Len() )
2143 sOrigName = aReadParam.GetResult();
2144 break;
2148 String sName(GetMappedBookmark(sOrigName));
2150 #if defined(WW_NATIVE_TOC)
2151 if (1) {
2152 ::rtl::OUString aBookmarkName=::rtl::OUString::createFromAscii("_REF");
2153 maFieldStack.back().SetBookmarkName(aBookmarkName);
2154 maFieldStack.back().SetBookmarkType(::rtl::OUString::createFromAscii(ECMA_PAGEREF));
2155 maFieldStack.back().AddParam(rtl::OUString(), sName);
2156 return FLD_TEXT;
2158 #endif
2161 SwGetRefField aFld(
2162 (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ), sName,
2163 REF_BOOKMARK, 0, REF_PAGE );
2165 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2166 return FLD_OK;
2169 // "MACROSCHALTFL"ACHE"
2170 eF_ResT SwWW8ImplReader::Read_F_Macro( WW8FieldDesc*, String& rStr)
2172 String aName;
2173 String aVText;
2174 long nRet;
2175 bool bNewVText = true;
2176 bool bBracket = false;
2177 _ReadFieldParams aReadParam( rStr );
2179 xub_StrLen nOffset = 0;
2181 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2183 switch( nRet )
2185 case -2:
2186 if( !aName.Len() )
2187 aName = aReadParam.GetResult();
2188 else if( !aVText.Len() || bBracket )
2190 nOffset = aReadParam.GetTokenSttPtr() + 1;
2192 if( bBracket )
2193 aVText += ' ';
2194 aVText += aReadParam.GetResult();
2195 if (bNewVText)
2197 bBracket = aVText.EqualsIgnoreCaseAscii('[', 1, 0)
2198 ? true : false;
2199 bNewVText = false;
2201 else if( aVText.GetChar( aVText.Len()-1 ) == ']' )
2202 bBracket = false;
2204 break;
2207 if( !aName.Len() )
2208 return FLD_TAGIGN; // makes no sense without Makro-Name
2210 aName.InsertAscii( "StarOffice.Standard.Modul1.", 0 );
2212 SwMacroField aFld( (SwMacroFieldType*)
2213 rDoc.GetSysFldType( RES_MACROFLD ), aName, aVText );
2214 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2217 WW8_CP nOldCp = pPlcxMan->Where();
2218 WW8_CP nCp = nOldCp + nOffset;
2220 SwPaM aPaM(*pPaM);
2221 aPaM.SetMark();
2222 aPaM.Move(fnMoveBackward);
2223 aPaM.Exchange();
2225 mpPostProcessAttrsInfo = new WW8PostProcessAttrsInfo(nCp, nCp, aPaM);
2227 return FLD_OK;
2230 WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd,
2231 SwPaM & rPaM)
2232 : mbCopy(false),
2233 mnCpStart(nCpStart),
2234 mnCpEnd(nCpEnd),
2235 mPaM(*rPaM.GetPoint(), *rPaM.GetMark()),
2236 mItemSet(rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END - 1)
2240 bool CanUseRemoteLink(const String &rGrfName)
2242 bool bUseRemote = false;
2245 ::ucbhelper::Content aCnt(rGrfName,
2246 uno::Reference<
2247 ucb::XCommandEnvironment >() );
2248 rtl::OUString aTitle;
2250 aCnt.getPropertyValue(rtl::OUString::createFromAscii("Title" ))
2251 >>= aTitle;
2252 bUseRemote = (aTitle.getLength() > 0);
2254 catch ( ... )
2256 // this file did not exist, so we will not set this as graphiclink
2257 bUseRemote = false;
2259 return bUseRemote;
2262 // "EINF"UGENGRAFIK"
2263 eF_ResT SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc*, String& rStr )
2265 String aGrfName;
2266 bool bEmbedded = true;
2268 long nRet;
2269 _ReadFieldParams aReadParam( rStr );
2270 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2272 switch( nRet )
2274 case -2:
2275 if (!aGrfName.Len())
2276 ConvertFFileName(aGrfName, aReadParam.GetResult());
2277 break;
2279 case 'd':
2280 bEmbedded = false; // Embedded-Flag deaktivieren
2281 break;
2283 case 'c':// den Converter-Namen ueberlesen
2284 aReadParam.FindNextStringPiece();
2285 break;
2289 if (!bEmbedded)
2290 bEmbedded = !CanUseRemoteLink(aGrfName);
2292 if (!bEmbedded)
2295 Besonderheit:
2297 Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrmFmt.
2298 Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
2299 wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
2300 wird.
2301 Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
2302 erkannt, dass wir soeben einen Grafik-Link inserted haben und
2303 das passende SwAttrSet wird ins Frame-Format eingesetzt.
2305 SfxItemSet aFlySet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
2306 RES_FRMATR_END-1 );
2307 aFlySet.Put( SwFmtAnchor( FLY_IN_CNTNT ) );
2308 aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
2309 pFlyFmtOfJustInsertedGraphic = rDoc.Insert( *pPaM,
2310 aGrfName,
2311 aEmptyStr,
2312 0, // Graphic*
2313 &aFlySet,
2314 0, 0); // SwFrmFmt*
2315 maGrfNameGenerator.SetUniqueGraphName(pFlyFmtOfJustInsertedGraphic,
2316 INetURLObject(aGrfName).GetBase());
2318 return FLD_READ_FSPA;
2322 String wwSectionNamer::UniqueName()
2324 String aName(msFileLinkSeed);
2325 aName += String::CreateFromInt32(++mnFileSectionNo);
2326 return mrDoc.GetUniqueSectionName(&aName);
2329 // "EINFUEGENTEXT"
2330 eF_ResT SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc* /*pF*/, String& rStr )
2332 String aPara;
2333 String aBook;
2334 long nRet;
2335 _ReadFieldParams aReadParam( rStr );
2336 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2338 switch( nRet )
2340 case -2:
2341 if( !aPara.Len() )
2342 aPara = aReadParam.GetResult();
2343 else if( !aBook.Len() )
2344 aBook = aReadParam.GetResult();
2345 break;
2346 case '*':
2347 //Skip over MERGEFORMAT
2348 aReadParam.SkipToNextToken();
2349 break;
2352 ConvertFFileName(aPara, aPara);
2354 if (aBook.Len() && aBook.GetChar( 0 ) != '\\')
2356 // Bereich aus Quelle ( kein Switch ) ?
2357 ConvertUFName(aBook);
2358 aPara += sfx2::cTokenSeperator;
2359 aPara += sfx2::cTokenSeperator;
2360 aPara += aBook;
2364 ##509##
2365 What we will do is insert a section to be linked to a file, but just in
2366 case the file is not available we will fill in the section with the stored
2367 content of this winword field as a fallback.
2369 SwPosition aTmpPos(*pPaM->GetPoint());
2371 SwSection aSection(FILE_LINK_SECTION, maSectionNameGenerator.UniqueName());
2372 aSection.SetLinkFileName( aPara );
2373 aSection.SetProtect(true);
2375 SwSection*const pSection = rDoc.InsertSwSection(*pPaM, aSection, 0, false);
2376 ASSERT(pSection, "no section inserted");
2377 if (!pSection)
2378 return FLD_TEXT;
2379 const SwSectionNode* pSectionNode = pSection->GetFmt()->GetSectionNode();
2380 ASSERT(pSectionNode, "no section node!");
2381 if (!pSectionNode)
2382 return FLD_TEXT;
2384 pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
2385 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0 );
2387 //we have inserted a section before this point, so adjust pos
2388 //for future page/section segment insertion
2389 maSectionManager.PrependedInlineNode(aTmpPos, *pPaM->GetNode());
2391 return FLD_TEXT;
2394 // "SERIENDRUCKFELD"
2395 eF_ResT SwWW8ImplReader::Read_F_DBField( WW8FieldDesc* pF, String& rStr )
2397 String aName;
2398 long nRet;
2399 _ReadFieldParams aReadParam( rStr );
2400 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2402 switch( nRet )
2404 case -2:
2405 if( !aName.Len() )
2406 aName = aReadParam.GetResult();
2407 break;
2410 SwDBFieldType aD( &rDoc, aName, SwDBData() ); // Datenbank: Nichts
2412 SwFieldType* pFT = rDoc.InsertFldType( aD );
2413 SwDBField aFld( (SwDBFieldType*)pFT );
2414 aFld.SetFieldCode( rStr );
2416 String aResult;
2417 pSBase->WW8ReadString( *pStrm, aResult, pPlcxMan->GetCpOfs()+
2418 pF->nSRes, pF->nLRes, eTextCharSet );
2420 aFld.InitContent(aResult);
2422 rDoc.InsertPoolItem(*pPaM, SwFmtFld( aFld ), 0);
2424 return FLD_OK;
2427 // "N"ACHSTER"
2428 eF_ResT SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc*, String& )
2430 SwDBNextSetFieldType aN;
2431 SwFieldType* pFT = rDoc.InsertFldType( aN );
2432 SwDBNextSetField aFld( (SwDBNextSetFieldType*)pFT, aEmptyStr, aEmptyStr,
2433 SwDBData() ); // Datenbank: Nichts
2434 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2435 return FLD_OK;
2438 // "DATENSATZ"
2439 eF_ResT SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc*, String& )
2441 SwDBSetNumberFieldType aN;
2442 SwFieldType* pFT = rDoc.InsertFldType( aN );
2443 SwDBSetNumberField aFld( (SwDBSetNumberFieldType*)pFT,
2444 SwDBData() ); // Datenbank: Nichts
2445 rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2446 return FLD_OK;
2450 EQ , only the usage for
2451 a. Combined Characters supported, must be exactly in the form that word
2452 only accepts as combined charactersm, i.e.
2453 eq \o(\s\up Y(XXX),\s\do Y(XXX))
2454 b. Ruby Text supported, must be in the form that word recognizes as being
2455 ruby text
2458 eF_ResT SwWW8ImplReader::Read_F_Equation( WW8FieldDesc*, String& rStr )
2460 _ReadFieldParams aReadParam( rStr );
2461 long cChar = aReadParam.SkipToNextToken();
2462 if ('o' == cChar)
2463 Read_SubF_Combined(aReadParam);
2464 else if ('*' == cChar)
2465 Read_SubF_Ruby(aReadParam);
2466 return FLD_OK;
2469 void SwWW8ImplReader::Read_SubF_Combined( _ReadFieldParams& rReadParam)
2471 String sCombinedCharacters;
2472 if ((-2 == rReadParam.SkipToNextToken()) &&
2473 rReadParam.GetResult().EqualsIgnoreCaseAscii('(', 1, 0))
2475 for (int i=0;i<2;i++)
2477 if ('s' == rReadParam.SkipToNextToken())
2479 long cChar = rReadParam.SkipToNextToken();
2480 if (-2 != rReadParam.SkipToNextToken())
2481 break;
2482 String sF = rReadParam.GetResult();
2483 if ((('u' == cChar) && sF.EqualsIgnoreCaseAscii('p', 1, 0))
2484 || (('d' == cChar) && sF.EqualsIgnoreCaseAscii('o', 1, 0)))
2486 if (-2 == rReadParam.SkipToNextToken())
2488 String sPart = rReadParam.GetResult();
2489 xub_StrLen nBegin = sPart.Search('(');
2491 //Word disallows brackets in this field, which
2492 //aids figuring out the case of an end of )) vs )
2493 xub_StrLen nEnd = sPart.Search(')');
2495 if ((nBegin != STRING_NOTFOUND) &&
2496 (nEnd != STRING_NOTFOUND))
2498 sCombinedCharacters +=
2499 sPart.Copy(nBegin+1,nEnd-nBegin-1);
2506 if (sCombinedCharacters.Len())
2508 SwCombinedCharField aFld((SwCombinedCharFieldType*)
2509 rDoc.GetSysFldType(RES_COMBINED_CHARS),sCombinedCharacters);
2510 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2514 void SwWW8ImplReader::Read_SubF_Ruby( _ReadFieldParams& rReadParam)
2516 USHORT nJustificationCode=0;
2517 String sFontName;
2518 UINT32 nFontSize=0;
2519 String sRuby;
2520 String sText;
2521 long nRet;
2522 while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
2524 switch( nRet )
2526 case -2:
2528 String sTemp = rReadParam.GetResult();
2529 if( sTemp.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
2531 sTemp.Erase(0,2);
2532 nJustificationCode = static_cast<USHORT>(sTemp.ToInt32());
2534 else if( sTemp.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
2536 sTemp.Erase(0,3);
2537 nFontSize= static_cast<UINT32>(sTemp.ToInt32());
2539 else if( sTemp.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
2541 sTemp.Erase(0,5);
2542 sFontName = sTemp;
2545 break;
2546 case '*':
2547 break;
2548 case 'o':
2549 while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
2551 if ('u' == nRet)
2553 if (-2 == rReadParam.SkipToNextToken() &&
2554 (rReadParam.GetResult().EqualsIgnoreCaseAscii('p', 1, 0)))
2556 if (-2 == rReadParam.SkipToNextToken())
2558 String sPart = rReadParam.GetResult();
2559 xub_StrLen nBegin = sPart.Search('(');
2561 //Word disallows brackets in this field,
2562 xub_StrLen nEnd = sPart.Search(')');
2564 if ((nBegin != STRING_NOTFOUND) &&
2565 (nEnd != STRING_NOTFOUND))
2567 sRuby = sPart.Copy(nBegin+1,nEnd-nBegin-1);
2569 if (STRING_NOTFOUND ==
2570 (nBegin = sPart.Search(',',nEnd)))
2572 nBegin = sPart.Search(';',nEnd);
2574 nEnd = sPart.SearchBackward(')');
2575 if ((nBegin != STRING_NOTFOUND) &&
2576 (nEnd != STRING_NOTFOUND))
2578 sText = sPart.Copy(nBegin+1,nEnd-nBegin-1);
2585 break;
2589 //Translate and apply
2590 if (sRuby.Len() && sText.Len() && sFontName.Len() && nFontSize)
2592 switch (nJustificationCode)
2594 case 0:
2595 nJustificationCode=1;
2596 break;
2597 case 1:
2598 nJustificationCode=3;
2599 break;
2600 case 2:
2601 nJustificationCode=4;
2602 break;
2603 default:
2604 case 3:
2605 nJustificationCode=0;
2606 break;
2607 case 4:
2608 nJustificationCode=2;
2609 break;
2612 SwFmtRuby aRuby(sRuby);
2613 const SwCharFmt *pCharFmt=0;
2614 //Make a guess at which of asian of western we should be setting
2615 USHORT nScript;
2616 if (pBreakIt->GetBreakIter().is())
2617 nScript = pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
2618 else
2619 nScript = i18n::ScriptType::ASIAN;
2621 //Check to see if we already have a ruby charstyle that this fits
2622 std::vector<const SwCharFmt*>::const_iterator aEnd =
2623 aRubyCharFmts.end();
2624 for(std::vector<const SwCharFmt*>::const_iterator aIter
2625 = aRubyCharFmts.begin(); aIter != aEnd; ++aIter)
2627 const SvxFontHeightItem &rFH =
2628 ItemGet<SvxFontHeightItem>(*(*aIter),
2629 GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2630 if (rFH.GetHeight() == nFontSize*10)
2632 const SvxFontItem &rF = ItemGet<SvxFontItem>(*(*aIter),
2633 GetWhichOfScript(RES_CHRATR_FONT,nScript));
2634 if (rF.GetFamilyName().Equals(sFontName))
2636 pCharFmt=*aIter;
2637 break;
2642 //Create a new char style if necessary
2643 if (!pCharFmt)
2645 SwCharFmt *pFmt=0;
2646 String aNm;
2647 //Take this as the base name
2648 SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT,aNm);
2649 aNm+=String::CreateFromInt32(aRubyCharFmts.size()+1);
2650 pFmt = rDoc.MakeCharFmt(aNm,(SwCharFmt*)rDoc.GetDfltCharFmt());
2651 SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
2652 SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
2653 aEmptyStr,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
2654 aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2655 aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
2656 pFmt->SetFmtAttr(aHeightItem);
2657 pFmt->SetFmtAttr(aFontItem);
2658 aRubyCharFmts.push_back(pFmt);
2659 pCharFmt = pFmt;
2662 //Set the charstyle and justification
2663 aRuby.SetCharFmtName(pCharFmt->GetName());
2664 aRuby.SetCharFmtId(pCharFmt->GetPoolFmtId());
2665 aRuby.SetAdjustment(nJustificationCode);
2667 NewAttr(aRuby);
2668 rDoc.InsertString( *pPaM, sText );
2669 pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_CJK_RUBY );
2673 //-----------------------------------------
2674 // Verzeichnis-Felder
2675 //-----------------------------------------
2677 void lcl_toxMatchACSwitch( SwWW8ImplReader& /*rReader*/,
2678 SwDoc& rDoc,
2679 SwTOXBase& rBase,
2680 _ReadFieldParams& rParam,
2681 SwCaptionDisplay eCaptionType)
2683 xub_StrLen n = rParam.GoToTokenParam();
2684 if( STRING_NOTFOUND != n )
2686 SwTOXType* pType = (SwTOXType*)rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0);
2687 pType->Add( &rBase );
2688 rBase.SetCaptionDisplay( eCaptionType );
2689 // Read Sequence Name and store in TOXBase
2690 String sSeqName( rParam.GetResult() );
2691 lcl_ConvertSequenceName( sSeqName );
2692 rBase.SetSequenceName( sSeqName );
2696 //For all outline styles that are not in the outline numbering add them here as
2697 //custom extra styles
2698 bool SwWW8ImplReader::AddExtraOutlinesAsExtraStyles(SwTOXBase& rBase)
2700 bool bExtras = false;
2701 //This is the case if the winword outline numbering is set while the
2702 //writer one is not
2703 for (USHORT nI = 0; nI < nColls; ++nI)
2705 SwWW8StyInf& rSI = pCollA[nI];
2706 if (rSI.IsOutline())
2708 const SwTxtFmtColl *pFmt = (const SwTxtFmtColl*)(rSI.pFmt);
2709 sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
2710 sal_uInt16 nMaxLevel = rBase.GetLevel();
2711 if (
2712 //nStyleLevel != pFmt->GetOutlineLevel() && //#outline level,zhaojianwei
2713 nStyleLevel != (pFmt->GetAttrOutlineLevel()-1) && //<-end,zhaojianwei
2714 nStyleLevel < nMaxLevel
2717 String sStyles(rBase.GetStyleNames(rSI.nOutlineLevel));
2718 if( sStyles.Len())
2719 sStyles += TOX_STYLE_DELIMITER;
2720 sStyles += pFmt->GetName();
2721 rBase.SetStyleNames(sStyles, rSI.nOutlineLevel);
2722 bExtras = true;
2726 return bExtras;
2729 static void EnsureMaxLevelForTemplates(SwTOXBase& rBase)
2731 //If the TOC contains Template entries at levels > the evaluation level
2732 //that was initially taken from the max normal outline level of the word TOC
2733 //then we cannot use that for the evaluation level because writer cuts off
2734 //all styles above that level, while word just cuts off the "standard"
2735 //outline styles, we have no option but to expand to the highest level
2736 //Word included.
2737 if ((rBase.GetLevel() != MAXLEVEL) && (nsSwTOXElement::TOX_TEMPLATE & rBase.GetCreateType()))
2739 for (USHORT nI = MAXLEVEL; nI > 0; --nI)
2741 String sStyles(rBase.GetStyleNames(nI-1));
2742 if (rBase.GetStyleNames(nI-1).Len())
2744 rBase.SetLevel(nI);
2745 break;
2751 void lcl_toxMatchTSwitch(SwWW8ImplReader& rReader, SwTOXBase& rBase,
2752 _ReadFieldParams& rParam)
2754 xub_StrLen n = rParam.GoToTokenParam();
2755 if( STRING_NOTFOUND != n )
2757 String sParams( rParam.GetResult() );
2758 if( sParams.Len() )
2760 xub_StrLen nIndex = 0;
2762 //#92940# Delimiters between styles and style levels appears to
2763 //allow both ; and ,
2765 String sTemplate( sParams.GetToken(0, ';', nIndex) );
2766 if( STRING_NOTFOUND == nIndex )
2768 nIndex=0;
2769 sTemplate = sParams.GetToken(0, ',', nIndex);
2771 if( STRING_NOTFOUND == nIndex )
2773 const SwFmt* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
2774 if( pStyle )
2775 sTemplate = pStyle->GetName();
2776 // Store Style for Level 0 into TOXBase
2777 rBase.SetStyleNames( sTemplate, 0 );
2779 else while( STRING_NOTFOUND != nIndex )
2781 xub_StrLen nOldIndex=nIndex;
2782 USHORT nLevel = static_cast<USHORT>(
2783 sParams.GetToken(0, ';', nIndex).ToInt32());
2784 if( STRING_NOTFOUND == nIndex )
2786 nIndex = nOldIndex;
2787 nLevel = static_cast<USHORT>(
2788 sParams.GetToken(0, ',', nIndex).ToInt32());
2791 if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
2793 nLevel--;
2794 // Store Style and Level into TOXBase
2795 const SwFmt* pStyle
2796 = rReader.GetStyleWithOrgWWName( sTemplate );
2798 if( pStyle )
2799 sTemplate = pStyle->GetName();
2801 String sStyles( rBase.GetStyleNames( nLevel ) );
2802 if( sStyles.Len() )
2803 sStyles += TOX_STYLE_DELIMITER;
2804 sStyles += sTemplate;
2805 rBase.SetStyleNames( sStyles, nLevel );
2807 // read next style name...
2808 nOldIndex = nIndex;
2809 sTemplate = sParams.GetToken(0, ';', nIndex);
2810 if( STRING_NOTFOUND == nIndex )
2812 nIndex=nOldIndex;
2813 sTemplate = sParams.GetToken(0, ',', nIndex);
2820 USHORT wwSectionManager::CurrentSectionColCount() const
2822 USHORT nIndexCols = 1;
2823 if (!maSegments.empty())
2824 nIndexCols = maSegments.back().maSep.ccolM1 + 1;
2825 return nIndexCols;
2828 //Will there be a new pagebreak at this position (don't know what type
2829 //until later)
2830 bool wwSectionManager::WillHavePageDescHere(SwNodeIndex aIdx) const
2832 bool bRet = false;
2833 if (!maSegments.empty())
2835 if (!maSegments.back().IsContinous() &&
2836 maSegments.back().maStart == aIdx)
2838 bRet = true;
2841 return bRet;
2844 USHORT lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
2846 // GetFormMax() returns level + 1, hence the -1
2847 USHORT nRet = rForm.GetFormMax()-1;
2849 // If the max of this type of TOC is greater than the max of a word
2850 // possible toc, then clip to the word max
2851 if (nRet > WW8ListManager::nMaxLevel)
2852 nRet = WW8ListManager::nMaxLevel;
2854 return nRet;
2857 eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, String& rStr )
2859 #if defined(WW_NATIVE_TOC)
2860 if (1) {
2861 ::rtl::OUString aBookmarkName=::rtl::OUString::createFromAscii("_TOC");
2862 maFieldStack.back().SetBookmarkName(aBookmarkName);
2863 maFieldStack.back().SetBookmarkType(::rtl::OUString::createFromAscii(ECMA_TOC));
2864 // maFieldStack.back().AddParam(::rtl::OUString::createFromAscii("Description"), aFormula.sToolTip);
2865 return FLD_TEXT;
2867 #endif
2869 if (pF->nLRes < 3)
2870 return FLD_TEXT; // ignore (#i25440#)
2872 TOXTypes eTox; // Baue ToxBase zusammen
2873 switch( pF->nId )
2875 case 8:
2876 eTox = TOX_INDEX;
2877 break;
2878 case 13:
2879 eTox = TOX_CONTENT;
2880 break;
2881 default:
2882 eTox = TOX_USER;
2883 break;
2886 USHORT nCreateOf = (eTox == TOX_CONTENT) ? nsSwTOXElement::TOX_OUTLINELEVEL : nsSwTOXElement::TOX_MARK;
2888 USHORT nIndexCols = 1;
2890 const SwTOXType* pType = rDoc.GetTOXType( eTox, 0 );
2891 SwForm aOrigForm(eTox);
2892 SwTOXBase* pBase = new SwTOXBase( pType, aOrigForm, nCreateOf, aEmptyStr );
2893 pBase->SetProtected(maSectionManager.CurrentSectionIsProtected());
2894 switch( eTox ){
2895 case TOX_INDEX:
2897 USHORT eOptions = nsSwTOIOptions::TOI_SAME_ENTRY | nsSwTOIOptions::TOI_CASE_SENSITIVE;
2899 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
2900 // die Parameter \o in 1 bis 9 liegen
2901 // oder der Parameter \f existiert
2902 // oder GARKEINE Switches Parameter angegeben sind.
2903 long nRet;
2904 _ReadFieldParams aReadParam( rStr );
2905 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
2907 switch( nRet )
2909 case 'c':
2911 xub_StrLen n = aReadParam.GoToTokenParam();
2912 if( STRING_NOTFOUND != n )
2914 String sParams( aReadParam.GetResult() );
2915 // if NO String just ignore the \c
2916 if( sParams.Len() )
2918 nIndexCols =
2919 static_cast<USHORT>(sParams.ToInt32());
2923 break;
2924 case 'e':
2926 xub_StrLen n = aReadParam.GoToTokenParam();
2927 if( STRING_NOTFOUND != n ) // if NO String just ignore the \e
2929 String sDelimiter( aReadParam.GetResult() );
2930 SwForm aForm( pBase->GetTOXForm() );
2932 // Attention: if TOX_CONTENT brave
2933 // GetFormMax() returns MAXLEVEL + 1 !!
2934 USHORT nEnd = aForm.GetFormMax()-1;
2936 for(USHORT nLevel = 1;
2937 nLevel <= nEnd;
2938 ++nLevel)
2940 // Levels count from 1
2941 // Level 0 is reserved for CAPTION
2943 // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
2944 // falls es eine Seitenzahl gibt:
2945 FormTokenType ePrevType = TOKEN_END;
2946 FormTokenType eType;
2947 // -> #i21237#
2948 SwFormTokens aPattern =
2949 aForm.GetPattern(nLevel);
2950 SwFormTokens::iterator aIt = aPattern.begin();
2953 eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
2955 if (eType == TOKEN_PAGE_NUMS)
2957 if (TOKEN_TAB_STOP == ePrevType)
2959 aIt--;
2961 if(0x09 == sDelimiter.GetChar(0))
2962 aIt->eTabAlign = SVX_TAB_ADJUST_END;
2963 else
2965 SwFormToken aToken(TOKEN_TEXT);
2966 aToken.sText = sDelimiter;
2967 *aIt = aToken;
2969 aForm.SetPattern(nLevel, aPattern);
2972 eType = TOKEN_END;
2975 ePrevType = eType;
2977 while (TOKEN_END != eType);
2978 // <- #i21237#
2980 pBase->SetTOXForm( aForm );
2983 break;
2984 case 'h':
2986 eOptions |= nsSwTOIOptions::TOI_ALPHA_DELIMITTER;
2988 break;
2991 pBase->SetOptions( eOptions );
2993 break;
2995 case TOX_CONTENT:
2997 bool bIsHyperlink = false;
2998 // TOX_OUTLINELEVEL setzen wir genau dann, wenn
2999 // die Parameter \o in 1 bis 9 liegen
3000 // oder der Parameter \f existiert
3001 // oder GARKEINE Switches Parameter angegeben sind.
3002 USHORT eCreateFrom = 0;
3003 USHORT nMaxLevel = 0;
3004 long nRet;
3005 _ReadFieldParams aReadParam( rStr );
3006 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3008 switch( nRet )
3010 case 'h':
3011 bIsHyperlink = true;
3012 break;
3013 case 'a':
3014 case 'c':
3015 lcl_toxMatchACSwitch(*this, rDoc, *pBase, aReadParam,
3016 ('c' == nRet)
3017 ? CAPTION_COMPLETE
3018 : CAPTION_TEXT );
3019 break;
3020 case 'o':
3022 USHORT nVal;
3023 if( !aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
3024 nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
3025 if( nMaxLevel < nVal )
3026 nMaxLevel = nVal;
3027 eCreateFrom |= nsSwTOXElement::TOX_OUTLINELEVEL;
3029 break;
3030 case 'f':
3031 eCreateFrom |= nsSwTOXElement::TOX_MARK;
3032 break;
3033 case 'l':
3035 USHORT nVal;
3036 if( aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
3038 if( nMaxLevel < nVal )
3039 nMaxLevel = nVal;
3040 eCreateFrom |= nsSwTOXElement::TOX_MARK;
3043 break;
3044 case 't': // paragraphs using special styles shall
3045 // provide the TOX's content
3046 lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
3047 eCreateFrom |= nsSwTOXElement::TOX_TEMPLATE;
3048 break;
3049 case 'p':
3051 xub_StrLen n = aReadParam.GoToTokenParam();
3052 if( STRING_NOTFOUND != n ) // if NO String just ignore the \p
3054 String sDelimiter( aReadParam.GetResult() );
3055 SwForm aForm( pBase->GetTOXForm() );
3057 // Attention: if TOX_CONTENT brave
3058 // GetFormMax() returns MAXLEVEL + 1 !!
3059 USHORT nEnd = aForm.GetFormMax()-1;
3061 for(USHORT nLevel = 1;
3062 nLevel <= nEnd;
3063 ++nLevel)
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 // -> #i21237#
3074 SwFormTokens aPattern = 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)
3084 aIt--;
3086 SwFormToken aToken(TOKEN_TEXT);
3087 aToken.sText = sDelimiter;
3089 *aIt = aToken;
3090 aForm.SetPattern(nLevel,
3091 aPattern);
3093 eType = TOKEN_END;
3095 ePrevType = eType;
3097 while( TOKEN_END != eType );
3098 // <- #i21237#
3100 pBase->SetTOXForm( aForm );
3103 break;
3104 case 'n': // don't print page numbers
3106 // read START and END param
3107 USHORT nStart, nEnd;
3108 if( !aReadParam.GetTokenSttFromTo( &nStart, &nEnd,
3109 WW8ListManager::nMaxLevel ) )
3111 nStart = 1;
3112 nEnd = aOrigForm.GetFormMax()-1;
3114 // remove page numbers from this levels
3115 SwForm aForm( pBase->GetTOXForm() );
3116 if (aForm.GetFormMax() <= nEnd)
3117 nEnd = aForm.GetFormMax()-1;
3118 for (
3119 USHORT nLevel = nStart; nLevel <= nEnd;
3120 ++nLevel
3123 // Levels count from 1
3124 // Level 0 is reserved for CAPTION
3126 // Seitenzahl und ggfs. davorstehenden Tabstop
3127 // entfernen:
3128 FormTokenType eType;
3129 // -> #i21237#
3130 SwFormTokens aPattern = aForm.GetPattern(nLevel);
3131 SwFormTokens::iterator aIt = aPattern.begin();
3134 eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3136 if (eType == TOKEN_PAGE_NUMS)
3138 aIt = aPattern.erase(aIt);
3139 aIt--;
3140 if (
3141 TOKEN_TAB_STOP ==
3142 aIt->eTokenType
3145 aPattern.erase(aIt);
3146 aForm.SetPattern(nLevel, aPattern);
3148 eType = TOKEN_END;
3151 while (TOKEN_END != eType);
3152 // <- #i21237#
3154 pBase->SetTOXForm( aForm );
3156 break;
3159 // the following switches are not (yet) supported
3160 // by good old StarWriter:
3161 case 'b':
3162 case 's':
3163 case 'd':
3164 break;
3169 if (bIsHyperlink)
3171 SwForm aForm(pBase->GetTOXForm());
3172 USHORT nEnd = aForm.GetFormMax()-1;
3173 SwFormToken aLinkStart(TOKEN_LINK_START);
3174 SwFormToken aLinkEnd(TOKEN_LINK_END);
3176 // -> #i21237#
3177 for(USHORT nLevel = 1; nLevel <= nEnd; ++nLevel)
3179 SwFormTokens aPattern = aForm.GetPattern(nLevel);
3181 aPattern.insert(aPattern.begin(), aLinkStart);
3182 aPattern.push_back(aLinkEnd);
3184 aForm.SetPattern(nLevel, aPattern);
3187 // <- #i21237#
3188 pBase->SetTOXForm(aForm);
3191 if (!nMaxLevel)
3192 nMaxLevel = WW8ListManager::nMaxLevel;
3193 pBase->SetLevel(nMaxLevel);
3195 const TOXTypes eType = pBase->GetTOXType()->GetType();
3196 switch( eType )
3198 case TOX_CONTENT:
3200 //If we would be created from outlines, either explictly or by default
3201 //then see if we need extra styles added to the outlines
3202 USHORT eEffectivelyFrom = eCreateFrom ? eCreateFrom : nsSwTOXElement::TOX_OUTLINELEVEL;
3203 if (eEffectivelyFrom & nsSwTOXElement::TOX_OUTLINELEVEL)
3205 if (AddExtraOutlinesAsExtraStyles(*pBase))
3206 eCreateFrom |= (nsSwTOXElement::TOX_TEMPLATE | nsSwTOXElement::TOX_OUTLINELEVEL);
3208 // --> FME 2004-12-16 #i19683# Insert a text token " " between the
3209 // number and entry token. In an ideal world we could handle the
3210 // tab stop between the number and the entry correctly, but I
3211 // currently have no clue how to obtain the tab stop position.
3212 // It is _not_ set at the paragraph style.
3213 SwForm* pForm = 0;
3214 for (USHORT nI = 0; nI < nColls; ++nI)
3216 const SwWW8StyInf& rSI = pCollA[nI];
3217 if (rSI.IsOutlineNumbered())
3219 sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
3220 const SwNumFmt& rFmt = rSI.GetOutlineNumrule()->Get( nStyleLevel );
3221 if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() )
3223 ++nStyleLevel;
3225 if ( !pForm )
3226 pForm = new SwForm( pBase->GetTOXForm() );
3228 SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
3229 SwFormTokens::iterator aIt =
3230 find_if(aPattern.begin(), aPattern.end(),
3231 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3233 if ( aIt != aPattern.end() )
3235 SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
3236 aNumberEntrySeparator.sText = String::CreateFromAscii(" ");
3237 aPattern.insert( ++aIt, aNumberEntrySeparator );
3238 pForm->SetPattern( nStyleLevel, aPattern );
3243 if ( pForm )
3244 pBase->SetTOXForm( *pForm );
3245 // <--
3248 if (eCreateFrom)
3249 pBase->SetCreate(eCreateFrom);
3250 EnsureMaxLevelForTemplates(*pBase);
3252 break;
3253 case TOX_ILLUSTRATIONS:
3255 if( !eCreateFrom )
3256 eCreateFrom = nsSwTOXElement::TOX_SEQUENCE;
3257 pBase->SetCreate( eCreateFrom );
3260 #91214#
3261 We don't know until here if we are an illustration
3262 or not, and so have being used a TOX_CONTENT so far
3263 which has 10 levels, while TOX has only two, this
3264 level is set only in the constructor of SwForm, so
3265 create a new one and copy over anything that could
3266 be set in the old one, and remove entries from the
3267 pattern which do not apply to illustration indices
3269 SwForm aOldForm( pBase->GetTOXForm() );
3270 SwForm aForm( eType );
3271 USHORT nEnd = aForm.GetFormMax()-1;
3273 // -> #i21237#
3274 for(USHORT nLevel = 1; nLevel <= nEnd; ++nLevel)
3276 SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
3278 SwFormTokens::iterator new_end=remove_if(aPattern.begin(), aPattern.end(),
3279 SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3281 aPattern.erase (new_end, aPattern.end() ); // #124710#: table index imported with wrong page number format
3283 aForm.SetPattern(nLevel, aPattern);
3285 aForm.SetTemplate( nLevel,
3286 aOldForm.GetTemplate(nLevel));
3288 // <- #i21237#
3290 pBase->SetTOXForm( aForm );
3292 break;
3293 default:
3294 ASSERT(!this, "Unhandled toc options!");
3295 break;
3298 break;
3299 case TOX_USER:
3300 break;
3301 default:
3302 ASSERT(!this, "Unhandled toc options!");
3303 break;
3304 } // ToxBase fertig
3306 // Update fuer TOX anstossen
3307 rDoc.SetUpdateTOX(true);
3309 // #i21237#
3310 // propagate tab stops from paragraph styles used in TOX to
3311 // patterns of the TOX
3312 pBase->AdjustTabStops(rDoc, TRUE);
3314 //#i10028# inserting a toc implicltly acts like a parabreak
3315 //in word and writer
3316 if (pPaM->GetPoint()->nContent.GetIndex())
3317 AppendTxtNode(*pPaM->GetPoint());
3319 const SwPosition* pPos = pPaM->GetPoint();
3321 SwFltTOX aFltTOX( pBase, nIndexCols );
3323 // test if there is already a break item on this node
3324 if(SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode())
3326 const SfxItemSet* pSet = pNd->GetpSwAttrSet();
3327 if( pSet )
3329 if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false))
3330 aFltTOX.SetHadBreakItem(true);
3331 if (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false))
3332 aFltTOX.SetHadPageDescItem(true);
3336 //Will there be a new pagebreak at this position (don't know what type
3337 //until later)
3338 if (maSectionManager.WillHavePageDescHere(pPos->nNode))
3339 aFltTOX.SetHadPageDescItem(true);
3341 // Setze Anfang in Stack
3342 pReffedStck->NewAttr( *pPos, aFltTOX );
3344 rDoc.InsertTableOf(*pPaM->GetPoint(), *aFltTOX.GetBase());
3346 //inserting a toc inserts a section before this point, so adjust pos
3347 //for future page/section segment insertion
3348 SwPaM aRegion(*pPaM);
3349 aRegion.Move(fnMoveBackward);
3350 ASSERT(rDoc.GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
3351 if (SwTOXBase* pBase2 = (SwTOXBase*)rDoc.GetCurTOX(*aRegion.GetPoint()))
3353 if(nIndexCols>1)
3355 // Set the column number for index
3356 SfxItemSet aSet( rDoc.GetAttrPool(), RES_COL, RES_COL );
3357 SwFmtCol aCol;
3358 aCol.Init( nIndexCols, 708, USHRT_MAX );
3359 aSet.Put( aCol );
3360 pBase2->SetAttrSet( aSet );
3363 maSectionManager.PrependedInlineNode(*pPaM->GetPoint(),
3364 *aRegion.GetNode());
3367 // Setze Ende in Stack
3368 pReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
3370 if (!maApos.back()) //a para end in apo doesn't count
3371 bWasParaEnd = true;
3372 return FLD_OK;
3375 eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, String& /*rStr*/)
3378 #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3379 to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3380 the drawing that we are in the Shape field and respond accordingly
3382 return FLD_TEXT;
3385 eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, String& rStr )
3387 #if defined(WW_NATIVE_TOC)
3388 if (1) {
3389 ::rtl::OUString aBookmarkName=::rtl::OUString::createFromAscii("_HYPERLINK");
3390 maFieldStack.back().SetBookmarkName(aBookmarkName);
3391 maFieldStack.back().SetBookmarkType(::rtl::OUString::createFromAscii(ECMA_HYPERLINK));
3392 // maFieldStack.back().AddParam(::rtl::OUString::createFromAscii("Description"), aFormula.sToolTip);
3393 return FLD_TEXT;
3395 #endif
3397 String sURL, sTarget, sMark;
3398 bool bDataImport = false;
3399 //HYPERLINk "filename" [switches]
3400 bool bOptions=false;
3402 rStr.EraseTrailingChars( 1 );
3404 if (!bDataImport)
3406 long nRet;
3407 _ReadFieldParams aReadParam( rStr );
3408 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3410 switch( nRet )
3412 case -2:
3413 if (!sURL.Len() & !bOptions)
3414 ConvertFFileName(sURL, aReadParam.GetResult());
3415 break;
3417 case 'n':
3418 sTarget.ASSIGN_CONST_ASC( "_blank" );
3419 bOptions = true;
3420 break;
3422 case 'l':
3423 nRet = aReadParam.SkipToNextToken();
3424 bOptions = true;
3425 if( -2 == nRet )
3427 sMark = aReadParam.GetResult();
3428 if( sMark.Len() && '"' == sMark.GetChar( sMark.Len()-1 ))
3429 sMark.Erase( sMark.Len() - 1 );
3432 break;
3433 case 't':
3434 nRet = aReadParam.SkipToNextToken();
3435 bOptions = true;
3436 if (-2 == nRet)
3437 sTarget = aReadParam.GetResult();
3438 break;
3439 case 'h':
3440 case 'm':
3441 ASSERT( !this, "Auswertung fehlt noch - Daten unbekannt" );
3442 case 's': //worthless fake anchor option
3443 bOptions = true;
3444 break;
3449 // das Resultat uebernehmen
3450 ASSERT((sURL.Len() || sMark.Len()), "WW8: Empty URL")
3452 if( sMark.Len() )
3453 ( sURL += INET_MARK_TOKEN ) += sMark;
3455 SwFmtINetFmt aURL( sURL, sTarget );
3457 //As an attribute this needs to be closed, and that'll happen from
3458 //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms
3459 //between the start and begin, their hyperlinks will be set at that time
3460 //as well.
3461 pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL );
3462 return FLD_TEXT;
3465 void lcl_ImportTox(SwDoc &rDoc, SwPaM &rPaM, const String &rStr, bool bIdx)
3467 TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX; // Default
3469 USHORT nLevel = 1;
3471 xub_StrLen n;
3472 String sFldTxt;
3473 long nRet;
3474 _ReadFieldParams aReadParam(rStr);
3475 while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
3476 switch( nRet )
3478 case -2:
3479 if( !sFldTxt.Len() )
3481 // PrimaryKey ohne ":", 2nd dahinter
3482 sFldTxt = aReadParam.GetResult();
3484 break;
3486 case 'f':
3487 n = aReadParam.GoToTokenParam();
3488 if( STRING_NOTFOUND != n )
3490 String sParams( aReadParam.GetResult() );
3491 if( 'C' != sParams.GetChar(0) && 'c' != sParams.GetChar(0) )
3492 eTox = TOX_USER;
3494 break;
3496 case 'l':
3497 n = aReadParam.GoToTokenParam();
3498 if( STRING_NOTFOUND != n )
3500 String sParams( aReadParam.GetResult() );
3501 if( sParams.Len() // if NO String just ignore the \l
3502 && sParams.GetChar( 0 ) > '0'
3503 && sParams.GetChar( 0 ) <= '9' )
3505 nLevel = (USHORT)sParams.ToInt32();
3508 break;
3511 ASSERT( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0 :-(" );
3513 const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
3514 SwTOXMark aM( pT );
3516 if( eTox != TOX_INDEX )
3517 aM.SetLevel( nLevel );
3518 else
3520 xub_StrLen nFnd = sFldTxt.Search( WW8_TOX_LEVEL_DELIM );
3521 if( STRING_NOTFOUND != nFnd ) // it exist levels
3523 aM.SetPrimaryKey( sFldTxt.Copy( 0, nFnd ) );
3524 xub_StrLen nScndFnd =
3525 sFldTxt.Search( WW8_TOX_LEVEL_DELIM, nFnd+1 );
3526 if( STRING_NOTFOUND != nScndFnd )
3528 aM.SetSecondaryKey( sFldTxt.Copy( nFnd+1, nScndFnd - nFnd - 1 ));
3529 nFnd = nScndFnd;
3531 sFldTxt.Erase( 0, nFnd+1 );
3535 if (sFldTxt.Len())
3537 aM.SetAlternativeText( sFldTxt );
3538 rDoc.InsertPoolItem( rPaM, aM, 0 );
3542 void sw::ms::ImportXE(SwDoc &rDoc, SwPaM &rPaM, const String &rStr)
3544 lcl_ImportTox(rDoc, rPaM, rStr, true);
3547 void SwWW8ImplReader::ImportTox( int nFldId, String aStr )
3549 bool bIdx = (nFldId != 9);
3550 lcl_ImportTox(rDoc, *pPaM, aStr, bIdx);
3553 void SwWW8ImplReader::Read_FldVanish( USHORT, const BYTE*, short nLen )
3555 //Meaningless in a style
3556 if (pAktColl || !pPlcxMan)
3557 return;
3559 const int nChunk = 64; //number of characters to read at one time
3561 // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
3562 const static sal_Char *aFldNames[] = { "\x06""INHALT", "\x02""XE", // dt.
3563 "\x02""TC" }; // us
3564 const static BYTE aFldId[] = { 9, 4, 9 };
3566 if( nLen < 0 )
3568 bIgnoreText = false;
3569 return;
3572 // our methode was called from
3573 // ''Skip attributes of field contents'' loop within ReadTextAttr()
3574 if( bIgnoreText )
3575 return;
3577 bIgnoreText = true;
3578 long nOldPos = pStrm->Tell();
3580 WW8_CP nStartCp = pPlcxMan->Where() + pPlcxMan->GetCpOfs();
3582 String sFieldName;
3583 USHORT nFieldLen = pSBase->WW8ReadString( *pStrm, sFieldName, nStartCp,
3584 nChunk, eStructCharSet );
3585 nStartCp+=nFieldLen;
3587 xub_StrLen nC = 0;
3588 //If the first chunk did not start with a field start then
3589 //reset the stream position and give up
3590 if( !nFieldLen || (0x13 != sFieldName.GetChar( nC ))) // Field Start Mark
3592 // If Field End Mark found
3593 if( nFieldLen && (0x15 == sFieldName.GetChar( nC )))
3594 bIgnoreText = false;
3595 pStrm->Seek( nOldPos );
3596 return; // kein Feld zu finden
3599 xub_StrLen nFnd;
3600 //If this chunk does not contain a field end, keep reading chunks
3601 //until we find one, or we run out of text,
3602 while (STRING_NOTFOUND == (nFnd = sFieldName.Search(0x15)))
3604 String sTemp;
3605 nFieldLen = pSBase->WW8ReadString( *pStrm, sTemp,
3606 nStartCp, nChunk, eStructCharSet );
3607 sFieldName+=sTemp;
3608 nStartCp+=nFieldLen;
3609 if (!nFieldLen)
3610 break;
3613 pStrm->Seek( nOldPos );
3615 //if we have no 0x15 give up, otherwise erase everything from the 0x15
3616 //onwards
3617 if (STRING_NOTFOUND == nFnd)
3618 return;
3619 else
3620 sFieldName.Erase(nFnd);
3622 nC++;
3623 while( ' ' == sFieldName.GetChar( nC ))
3624 nC++;
3626 for( int i = 0; i < 3; i++ )
3628 const sal_Char* pName = aFldNames[i];
3629 USHORT nNameLen = *pName++;
3630 if( sFieldName.EqualsIgnoreCaseAscii( pName, nC, nNameLen ) )
3632 ImportTox( aFldId[i], sFieldName.Copy( nC + nNameLen ) );
3633 break; // keine Mehrfachnennungen moeglich
3636 bIgnoreText = true;
3637 pStrm->Seek( nOldPos );
3640 /* vi:set tabstop=4 shiftwidth=4 expandtab: */