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