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 <sal/types.h>
21 : #include <tools/solar.h>
22 : #include <comphelper/processfactory.hxx>
23 : #include <comphelper/storagehelper.hxx>
24 : #include <comphelper/string.hxx>
25 : #include <sot/storinfo.hxx>
26 : #include <com/sun/star/embed/XStorage.hpp>
27 : #include <com/sun/star/embed/ElementModes.hpp>
28 : #include <com/sun/star/embed/XTransactedObject.hpp>
29 : #include <com/sun/star/io/XStream.hpp>
30 :
31 : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
32 : #include <svl/urihelper.hxx>
33 : #include <svl/zforlist.hxx>
34 : #include <svl/zformat.hxx>
35 : #include <sfx2/linkmgr.hxx>
36 :
37 : #include <ucbhelper/content.hxx>
38 :
39 : #include <com/sun/star/i18n/ScriptType.hpp>
40 : #include <hintids.hxx>
41 : #include <editeng/fontitem.hxx>
42 : #include <editeng/fhgtitem.hxx>
43 : #include <editeng/langitem.hxx>
44 : #include <fmtfld.hxx>
45 : #include <fmtanchr.hxx>
46 : #include <pam.hxx>
47 : #include <doc.hxx>
48 : #include <charatr.hxx>
49 : #include <flddat.hxx>
50 : #include <docufld.hxx>
51 : #include <reffld.hxx>
52 : #include <IMark.hxx>
53 : #include <expfld.hxx>
54 : #include <dbfld.hxx>
55 : #include <usrfld.hxx>
56 : #include <tox.hxx>
57 : #include <section.hxx>
58 : #include <ndtxt.hxx>
59 : #include <fmtinfmt.hxx>
60 : #include <chpfld.hxx>
61 : #include <ftnidx.hxx>
62 : #include <txtftn.hxx>
63 : #include <viewsh.hxx>
64 : #include <shellres.hxx>
65 : #include <fmtruby.hxx>
66 : #include <charfmt.hxx>
67 : #include <txtatr.hxx>
68 : #include <breakit.hxx>
69 : #include <fmtclds.hxx>
70 : #include <pagedesc.hxx>
71 : #include <SwStyleNameMapper.hxx>
72 :
73 : #include "ww8scan.hxx"
74 : #include "ww8par.hxx"
75 : #include "ww8par2.hxx"
76 : #include "writerhelper.hxx"
77 : #include "fields.hxx"
78 : #include <unotools/fltrcfg.hxx>
79 : #include <xmloff/odffields.hxx>
80 :
81 : #include <algorithm>
82 :
83 : #define MAX_FIELDLEN 64000
84 :
85 : #define WW8_TOX_LEVEL_DELIM ':'
86 :
87 : using namespace ::com::sun::star;
88 : using namespace msfilter::util;
89 : using namespace sw::util;
90 : using namespace sw::mark;
91 : using namespace std; // #i24377#
92 : using namespace nsSwDocInfoSubType;
93 :
94 : // Bookmarks
95 :
96 : namespace
97 : {
98 : // #120879# - helper method to identify a bookmark name to match the internal TOC bookmark naming convention
99 17 : bool IsTOCBookmarkName( const ::rtl::OUString& rName )
100 : {
101 17 : return rName.startsWith("_Toc");
102 : }
103 : }
104 :
105 34 : long SwWW8ImplReader::Read_Book(WW8PLCFManResult*)
106 : {
107 : // should also work via pRes.nCo2OrIdx
108 34 : WW8PLCFx_Book* pB = pPlcxMan->GetBook();
109 34 : if( !pB )
110 : {
111 : OSL_ENSURE( pB, "WW8PLCFx_Book - Pointer does not exist" );
112 0 : return 0;
113 : }
114 :
115 34 : eBookStatus eB = pB->GetStatus();
116 34 : if (eB & BOOK_IGNORE)
117 0 : return 0; // ignore bookmark
118 :
119 34 : if (pB->GetIsEnd())
120 : {
121 17 : pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
122 34 : pB->GetHandle(), (eB & BOOK_FIELD)!=0);
123 17 : return 0;
124 : }
125 :
126 : // "_Hlt*" are unnecessary
127 17 : const OUString* pName = pB->GetName();
128 : // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available.
129 : // So the hidden bookmarks inside for hyperlink jumping also should be kept.
130 34 : if ( !pName ||
131 17 : pName->startsWithIgnoreAsciiCase( "_Hlt" ) )
132 : {
133 0 : return 0;
134 : }
135 :
136 : // do NOT call ToUpper as the bookmark name can also be a hyperlink target!
137 :
138 17 : OUString aVal;
139 17 : if( SwFltGetFlag( nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
140 : {
141 : // set variable for translation bookmark
142 0 : long nLen = pB->GetLen();
143 0 : if( nLen > MAX_FIELDLEN )
144 0 : nLen = MAX_FIELDLEN;
145 :
146 0 : long nOldPos = pStrm->Tell();
147 : nLen = pSBase->WW8ReadString( *pStrm, aVal, pB->GetStartPos(), nLen,
148 0 : eStructCharSet );
149 0 : pStrm->Seek( nOldPos );
150 :
151 : // now here the implementation of the old "QuoteString" and
152 : // I hope with a better performance as before. It's also only
153 : // needed if the filterflags say we will convert bookmarks
154 : // to SetExpFields! And this the exception!
155 :
156 0 : OUString sHex("\\x");
157 : bool bSetAsHex;
158 : bool bAllowCr = SwFltGetFlag(nFieldFlags,
159 0 : SwFltControlStack::ALLOW_FLD_CR) ? true : false;
160 :
161 0 : for( sal_Int32 nI = 0;
162 0 : nI < aVal.getLength() && aVal.getLength() < (MAX_FIELDLEN - 4);
163 : ++nI )
164 : {
165 0 : const sal_Unicode cChar = aVal[nI];
166 0 : switch( cChar )
167 : {
168 : case 0x0b:
169 : case 0x0c:
170 : case 0x0d:
171 0 : if( bAllowCr )
172 0 : aVal = aVal.replaceAt( nI, 1, "\n" ), bSetAsHex = false;
173 : else
174 0 : bSetAsHex = true;
175 0 : break;
176 :
177 : case 0xFE:
178 : case 0xFF:
179 0 : bSetAsHex = true;
180 0 : break;
181 :
182 : default:
183 0 : bSetAsHex = 0x20 > cChar;
184 0 : break;
185 : }
186 :
187 0 : if( bSetAsHex )
188 : {
189 : //all Hex-Numbers with \x before
190 0 : OUString sTmp( sHex );
191 0 : if( cChar < 0x10 )
192 0 : sTmp += "0";
193 0 : sTmp += OUString::number( cChar, 16 );
194 0 : aVal = aVal.replaceAt( nI, 1 , sTmp );
195 0 : nI += sTmp.getLength() - 1;
196 : }
197 : }
198 :
199 0 : if ( aVal.getLength() > (MAX_FIELDLEN - 4))
200 0 : aVal = aVal.copy( 0, MAX_FIELDLEN - 4 );
201 : }
202 :
203 : //e.g. inserting bookmark around field result, so we need to put
204 : //it around the entire writer field, as we don't have the separation
205 : //of field and field result of word, see #i16941#
206 17 : SwPosition aStart(*pPaM->GetPoint());
207 17 : if (!maFieldStack.empty())
208 : {
209 3 : const WW8FieldEntry &rTest = maFieldStack.back();
210 3 : aStart = rTest.maStartPos;
211 : }
212 :
213 34 : const OUString sOrigName = BookmarkToWriter(*pName);
214 : pReffedStck->NewAttr( aStart,
215 17 : SwFltBookmark( sOrigName, aVal, pB->GetHandle(), IsTOCBookmarkName( sOrigName ) ));
216 34 : return 0;
217 : }
218 :
219 : // general help methods to separate parameters
220 :
221 : /// translate FieldParameter names into the system character set and
222 : /// at the same time, douple backslashes are converted into single ones
223 5 : OUString SwWW8ImplReader::ConvertFFileName(const OUString& rOrg)
224 : {
225 5 : OUString aName = rOrg;
226 5 : aName = aName.replaceAll("\\\\", OUString('\\'));
227 5 : aName = aName.replaceAll("%20", OUString(' '));
228 :
229 : // remove attached quotation marks
230 5 : if (aName.endsWith("\""))
231 0 : aName = aName.copy(0, aName.getLength()-1);
232 :
233 : // Need the more sophisticated url converter.
234 5 : if (!aName.isEmpty())
235 10 : aName = URIHelper::SmartRel2Abs(
236 5 : INetURLObject(sBaseURL), aName, Link(), false);
237 :
238 5 : return aName;
239 : }
240 :
241 : namespace
242 : {
243 : /// translate FieldParameter names into the
244 : /// system character set and makes them uppercase
245 0 : void ConvertUFName( OUString& rName )
246 : {
247 0 : rName = GetAppCharClass().uppercase( rName );
248 0 : }
249 : }
250 :
251 0 : static void lcl_ConvertSequenceName(OUString& rSequenceName)
252 : {
253 0 : ConvertUFName(rSequenceName);
254 0 : if ('0' <= rSequenceName[0] && '9' >= rSequenceName[0])
255 0 : rSequenceName = "_" + rSequenceName;
256 0 : }
257 :
258 : // FindParaStart() finds 1st Parameter that follows '\' and cToken
259 : // and returns start of this parameter or -1
260 7 : sal_Int32 FindParaStart( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
261 : {
262 7 : bool bStr = false; // ignore inside a string
263 :
264 56 : for( sal_Int32 nBuf = 0; nBuf+1 < rStr.getLength(); nBuf++ )
265 : {
266 53 : if( rStr[ nBuf ] == '"' )
267 0 : bStr = !bStr;
268 :
269 106 : if( !bStr
270 53 : && rStr[ nBuf ] == '\\'
271 61 : && ( rStr[ nBuf + 1 ] == cToken
272 0 : || rStr[ nBuf + 1 ] == cToken2 ) )
273 : {
274 4 : nBuf += 2;
275 : // skip spaces between cToken and its parameters
276 20 : while( nBuf < rStr.getLength()
277 8 : && rStr[ nBuf ] == ' ' )
278 4 : nBuf++;
279 : // return start of parameters
280 4 : return nBuf < rStr.getLength() ? nBuf : -1;
281 : }
282 : }
283 3 : return -1;
284 : }
285 :
286 : // FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
287 : // ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
288 : // und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
289 7 : OUString FindPara( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
290 : {
291 : sal_Int32 n2; // end
292 7 : sal_Int32 n = FindParaStart( rStr, cToken, cToken2 ); // start
293 7 : if( n == -1)
294 3 : return OUString();
295 :
296 8 : if( rStr[ n ] == '"'
297 4 : || rStr[ n ] == 132 )
298 : { // Anfuehrungszeichen vor Para
299 1 : n++; // Anfuehrungszeichen ueberlesen
300 1 : n2 = n; // ab hier nach Ende suchen
301 47 : while( n2 < rStr.getLength()
302 23 : && rStr[ n2 ] != 147
303 46 : && rStr[ n2 ] != '"' )
304 22 : n2++; // Ende d. Paras suchen
305 : }
306 : else
307 : { // keine Anfuehrungszeichen
308 3 : n2 = n; // ab hier nach Ende suchen
309 75 : while( n2 < rStr.getLength()
310 36 : && rStr[ n2 ] != ' ' )
311 33 : n2++; // Ende d. Paras suchen
312 : }
313 4 : return rStr.copy( n, n2-n );
314 : }
315 :
316 6 : static SvxExtNumType GetNumTypeFromName(const OUString& rStr,
317 : bool bAllowPageDesc = false)
318 : {
319 6 : SvxExtNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
320 6 : if( rStr.startsWithIgnoreAsciiCase( "Arabi" ) ) // Arabisch, Arabic
321 0 : eTyp = SVX_NUM_ARABIC;
322 6 : else if( rStr.startsWith( "misch" ) ) // r"omisch
323 0 : eTyp = SVX_NUM_ROMAN_LOWER;
324 6 : else if( rStr.startsWith( "MISCH" ) ) // R"OMISCH
325 0 : eTyp = SVX_NUM_ROMAN_UPPER;
326 6 : else if( rStr.startsWithIgnoreAsciiCase( "alphabeti" ) )// alphabetisch, alphabetic
327 0 : eTyp = ( rStr[0] == 'A' )
328 : ? SVX_NUM_CHARS_UPPER_LETTER_N
329 0 : : SVX_NUM_CHARS_LOWER_LETTER_N;
330 6 : else if( rStr.startsWithIgnoreAsciiCase( "roman" ) ) // us
331 0 : eTyp = ( rStr[0] == 'R' )
332 : ? SVX_NUM_ROMAN_UPPER
333 0 : : SVX_NUM_ROMAN_LOWER;
334 6 : return eTyp;
335 : }
336 :
337 6 : static SvxExtNumType GetNumberPara(const OUString& rStr, bool bAllowPageDesc = false)
338 : {
339 6 : OUString s( FindPara( rStr, '*', '*' ) ); // Ziffernart
340 6 : SvxExtNumType aType = GetNumTypeFromName( s, bAllowPageDesc );
341 6 : return aType;
342 : }
343 :
344 1 : bool SwWW8ImplReader::ForceFieldLanguage(SwField &rFld, sal_uInt16 nLang)
345 : {
346 1 : bool bRet(false);
347 :
348 : const SvxLanguageItem *pLang =
349 1 : (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
350 : OSL_ENSURE(pLang, "impossible");
351 1 : sal_uInt16 nDefault = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
352 :
353 1 : if (nLang != nDefault)
354 : {
355 0 : rFld.SetAutomaticLanguage(false);
356 0 : rFld.SetLanguage(nLang);
357 0 : bRet = true;
358 : }
359 :
360 1 : return bRet;
361 : }
362 :
363 0 : OUString GetWordDefaultDateStringAsUS(SvNumberFormatter* pFormatter, sal_uInt16 nLang)
364 : {
365 : //Get the system date in the correct final language layout, convert to
366 : //a known language and modify the 2 digit year part to be 4 digit, and
367 : //convert back to the correct language layout.
368 0 : sal_uLong nIndex = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, nLang);
369 :
370 : SvNumberformat aFormat = const_cast<SvNumberformat &>
371 0 : (*(pFormatter->GetEntry(nIndex)));
372 0 : aFormat.ConvertLanguage(*pFormatter, nLang, LANGUAGE_ENGLISH_US);
373 :
374 0 : OUString sParams(aFormat.GetFormatstring());
375 : // #i36594#
376 : // Fix provided by mloiseleur@openoffice.org.
377 : // A default date can have already 4 year digits, in some case
378 0 : const sal_Int32 pos = sParams.indexOf("YYYY");
379 0 : if ( pos == -1 )
380 : {
381 0 : sParams = sParams.replaceFirst("YY", "YYYY");
382 : }
383 0 : return sParams;
384 : }
385 :
386 1 : short SwWW8ImplReader::GetTimeDatePara(OUString& rStr, sal_uInt32& rFormat,
387 : sal_uInt16 &rLang, int nWhichDefault, bool bHijri)
388 : {
389 1 : bool bRTL = false;
390 1 : if (pPlcxMan && !bVer67)
391 : {
392 1 : const sal_uInt8 *pResult = pPlcxMan->HasCharSprm(0x85A);
393 1 : if (pResult && *pResult)
394 0 : bRTL = true;
395 : }
396 1 : RES_CHRATR eLang = bRTL ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
397 1 : const SvxLanguageItem *pLang = (SvxLanguageItem*)GetFmtAttr( static_cast< sal_uInt16 >(eLang));
398 : OSL_ENSURE(pLang, "impossible");
399 1 : rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
400 :
401 1 : SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
402 1 : OUString sParams( FindPara( rStr, '@', '@' ) );// Date/Time
403 1 : if (sParams.isEmpty())
404 : {
405 0 : bool bHasTime = false;
406 0 : switch (nWhichDefault)
407 : {
408 : case ww::ePRINTDATE:
409 : case ww::eSAVEDATE:
410 0 : sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
411 0 : sParams += " HH:MM:SS AM/PM";
412 0 : bHasTime = true;
413 0 : break;
414 : case ww::eCREATEDATE:
415 0 : sParams += "DD/MM/YYYY HH:MM:SS";
416 0 : bHasTime = true;
417 0 : break;
418 : default:
419 : case ww::eDATE:
420 0 : sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
421 0 : break;
422 : }
423 :
424 0 : if (bHijri)
425 0 : sParams = "[~hijri]" + sParams;
426 :
427 0 : sal_Int32 nCheckPos = 0;
428 0 : short nType = NUMBERFORMAT_DEFINED;
429 0 : rFormat = 0;
430 :
431 0 : OUString sTemp(sParams);
432 : pFormatter->PutandConvertEntry(sTemp, nCheckPos, nType, rFormat,
433 0 : LANGUAGE_ENGLISH_US, rLang);
434 0 : sParams = sTemp;
435 :
436 0 : return bHasTime ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE;
437 : }
438 :
439 : sal_uLong nFmtIdx =
440 : sw::ms::MSDateTimeFormatToSwFormat(sParams, pFormatter, rLang, bHijri,
441 1 : GetFib().lid);
442 1 : short nNumFmtType = NUMBERFORMAT_UNDEFINED;
443 1 : if (nFmtIdx)
444 1 : nNumFmtType = pFormatter->GetType(nFmtIdx);
445 1 : rFormat = nFmtIdx;
446 :
447 1 : return nNumFmtType;
448 : }
449 :
450 : // Felder
451 :
452 : // Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
453 73 : void SwWW8ImplReader::UpdateFields()
454 : {
455 73 : rDoc.SetUpdateExpFldStat(true); // JP: neu fuer alles wichtige
456 73 : rDoc.SetInitDBFields(true); // Datenbank-Felder auch
457 73 : }
458 :
459 57 : sal_uInt16 SwWW8ImplReader::End_Field()
460 : {
461 57 : sal_uInt16 nRet = 0;
462 57 : WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
463 : OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer nicht da");
464 57 : WW8_CP nCP = 0;
465 57 : if (!pF || !pF->EndPosIsFieldEnd(nCP))
466 31 : return nRet;
467 :
468 26 : const SvtFilterOptions &rOpt = SvtFilterOptions::Get();
469 26 : sal_Bool bUseEnhFields = rOpt.IsUseEnhancedFields();
470 :
471 : OSL_ENSURE(!maFieldStack.empty(), "Empty field stack\n");
472 26 : if (!maFieldStack.empty())
473 : {
474 : /*
475 : only hyperlinks currently need to be handled like this, for the other
476 : cases we have inserted a field not an attribute with an unknown end
477 : point
478 : */
479 26 : nRet = maFieldStack.back().mnFieldId;
480 26 : switch (nRet)
481 : {
482 : case 70:
483 1 : if (bUseEnhFields && pPaM!=NULL && pPaM->GetPoint()!=NULL) {
484 1 : SwPosition aEndPos = *pPaM->GetPoint();
485 2 : SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
486 1 : IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
487 : IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeFieldBookmark(
488 1 : aFldPam, maFieldStack.back().GetBookmarkName(), ODF_FORMTEXT ) );
489 : OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
490 1 : if (pFieldmark!=NULL) {
491 1 : const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
492 1 : pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
493 1 : }
494 : }
495 1 : break;
496 : // Doing corresponding status management for TOC field, index field, hyperlink field and page reference field
497 : case 13://TOX
498 : case 8://index
499 0 : if (mbLoadingTOCCache)
500 : {
501 0 : maTOXEndCps.insert(nCP);
502 0 : mbLoadingTOCCache = false;
503 0 : if ( pPaM->End() &&
504 0 : pPaM->End()->nNode.GetNode().GetTxtNode() &&
505 0 : pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0 )
506 : {
507 0 : JoinNode(*pPaM);
508 : }
509 : else
510 : {
511 0 : mbCareLastParaEndInToc = true;
512 : }
513 :
514 0 : if (mpPosAfterTOC)
515 : {
516 0 : *pPaM = *mpPosAfterTOC;
517 0 : delete mpPosAfterTOC;
518 0 : mpPosAfterTOC = 0;
519 : }
520 : }
521 0 : break;
522 : case 37://REF
523 0 : if (mbLoadingTOCCache && !mbLoadingTOCHyperlink)
524 : {
525 0 : pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
526 : }
527 0 : break;
528 : case 88:
529 6 : if (mbLoadingTOCHyperlink)
530 0 : mbLoadingTOCHyperlink = false;
531 6 : pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
532 6 : break;
533 : case 36:
534 : case 68:
535 : //Move outside the section associated with this type of field
536 0 : *pPaM->GetPoint() = maFieldStack.back().maStartPos;
537 0 : break;
538 : default:
539 19 : OUString aCode = maFieldStack.back().GetBookmarkCode();
540 19 : if ( !aCode.isEmpty() )
541 : {
542 : // Unhandled field with stored code
543 0 : SwPosition aEndPos = *pPaM->GetPoint();
544 : SwPaM aFldPam(
545 0 : maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(),
546 0 : aEndPos.nNode, aEndPos.nContent.GetIndex());
547 :
548 0 : IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
549 :
550 : IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
551 : aFldPam,
552 0 : maFieldStack.back().GetBookmarkName(),
553 0 : ODF_UNHANDLED );
554 0 : if ( pFieldmark )
555 : {
556 0 : const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
557 0 : pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
558 0 : OUString sFieldId = OUString::number( maFieldStack.back().mnFieldId );
559 0 : pFieldmark->GetParameters()->insert(
560 : std::pair< OUString, uno::Any > (
561 : ODF_ID_PARAM,
562 0 : uno::makeAny( sFieldId ) ) );
563 0 : pFieldmark->GetParameters()->insert(
564 : std::pair< OUString, uno::Any > (
565 : ODF_CODE_PARAM,
566 0 : uno::makeAny( aCode ) ) );
567 :
568 0 : if ( maFieldStack.back().mnObjLocFc > 0 )
569 : {
570 : // Store the OLE object as an internal link
571 0 : OUString sOleId('_');
572 0 : sOleId += OUString::number( maFieldStack.back().mnObjLocFc );
573 :
574 0 : SvStorageRef xSrc0 = pStg->OpenSotStorage(OUString(SL::aObjectPool));
575 0 : SvStorageRef xSrc1 = xSrc0->OpenSotStorage( sOleId, STREAM_READ );
576 :
577 : // Store it now!
578 0 : uno::Reference< embed::XStorage > xDocStg = GetDoc().GetDocStorage();
579 0 : if (xDocStg.is())
580 : {
581 0 : uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
582 0 : "OLELinks", embed::ElementModes::WRITE );
583 0 : SotStorageRef xObjDst = SotStorage::OpenOLEStorage( xOleStg, sOleId );
584 :
585 0 : if ( xObjDst.Is() )
586 : {
587 0 : xSrc1->CopyTo( xObjDst );
588 :
589 0 : if ( !xObjDst->GetError() )
590 0 : xObjDst->Commit();
591 : }
592 :
593 0 : uno::Reference< embed::XTransactedObject > xTransact( xOleStg, uno::UNO_QUERY );
594 0 : if ( xTransact.is() )
595 0 : xTransact->commit();
596 : }
597 :
598 : // Store the OLE Id as a parameter
599 0 : pFieldmark->GetParameters()->insert(
600 : std::pair< OUString, uno::Any >(
601 0 : ODF_OLE_PARAM, uno::makeAny( OUString( sOleId ) ) ) );
602 0 : }
603 0 : }
604 : }
605 :
606 19 : break;
607 : }
608 26 : maFieldStack.pop_back();
609 : }
610 26 : return nRet;
611 : }
612 :
613 0 : bool AcceptableNestedField(sal_uInt16 nFieldCode)
614 : {
615 0 : switch (nFieldCode)
616 : {
617 : case 8: // allow recursive field in TOC...
618 : case 13: // allow recursive field in TOC...
619 : case 36:
620 : case 68:
621 : case 79:
622 : case 88:
623 : // Accept AutoTextList field as nested field.
624 : // Thus, the field result is imported as plain text.
625 : case 89:
626 0 : return true;
627 : default:
628 0 : return false;
629 : }
630 : }
631 :
632 26 : WW8FieldEntry::WW8FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw()
633 26 : : maStartPos(rPos), mnFieldId(nFieldId), mnObjLocFc(0)
634 : {
635 26 : }
636 :
637 26 : WW8FieldEntry::WW8FieldEntry(const WW8FieldEntry &rOther) throw()
638 26 : : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId), mnObjLocFc(rOther.mnObjLocFc)
639 : {
640 26 : }
641 :
642 0 : void WW8FieldEntry::Swap(WW8FieldEntry &rOther) throw()
643 : {
644 0 : std::swap(maStartPos, rOther.maStartPos);
645 0 : std::swap(mnFieldId, rOther.mnFieldId);
646 0 : }
647 :
648 0 : WW8FieldEntry &WW8FieldEntry::operator=(const WW8FieldEntry &rOther) throw()
649 : {
650 0 : WW8FieldEntry aTemp(rOther);
651 0 : Swap(aTemp);
652 0 : return *this;
653 : }
654 :
655 1 : OUString WW8FieldEntry::GetBookmarkName()
656 : {
657 1 : return msBookmarkName;
658 : }
659 :
660 19 : OUString WW8FieldEntry::GetBookmarkCode()
661 : {
662 19 : return msMarkCode;
663 : }
664 :
665 1 : void WW8FieldEntry::SetBookmarkName(const OUString& bookmarkName)
666 : {
667 1 : msBookmarkName=bookmarkName;
668 1 : }
669 :
670 1 : void WW8FieldEntry::SetBookmarkType(const OUString& bookmarkType)
671 : {
672 1 : msMarkType=bookmarkType;
673 1 : }
674 :
675 0 : void WW8FieldEntry::SetBookmarkCode(const OUString& bookmarkCode)
676 : {
677 0 : msMarkCode = bookmarkCode;
678 0 : }
679 :
680 3 : ::sw::mark::IFieldmark::parameter_map_t& WW8FieldEntry::getParameters()
681 : {
682 3 : return maParams;
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 57 : 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 57 : WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
798 : OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer nicht da");
799 :
800 57 : if (!pF || !pF->StartPosIsFieldStart())
801 31 : return 0;
802 :
803 26 : bool bNested = false;
804 26 : 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 26 : bool bOk = pF->GetPara(pRes->nCp2OrIdx, aF);
817 :
818 : OSL_ENSURE(bOk, "WW8: Bad Field!\n");
819 26 : if (aF.nId == 33) aF.bCodeNest=false; // do not recurse into nested page fields
820 26 : bool bCodeNest = aF.bCodeNest;
821 26 : if ( aF.nId == 6 ) bCodeNest = false; // We can handle them and loose the inner data
822 :
823 26 : maFieldStack.push_back(WW8FieldEntry(*pPaM->GetPoint(), aF.nId));
824 :
825 26 : if (bNested)
826 0 : return 0;
827 :
828 26 : sal_uInt16 n = (aF.nId <= eMax) ? aF.nId : static_cast<sal_uInt16>(eMax);
829 26 : sal_uInt16 nI = n / 32; // # des sal_uInt32
830 26 : sal_uInt32 nMask = 1 << ( n % 32 ); // Maske fuer Bits
831 :
832 26 : 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 26 : if( nFieldTagAlways[nI] & nMask ) // Flag: Tag it
839 0 : return Read_F_Tag( &aF ); // Resultat nicht als Text
840 :
841 26 : if( !bOk || !aF.nId ) // Feld kaputt
842 0 : return aF.nLen; // -> ignorieren
843 :
844 26 : 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 26 : if (aF.nId != 88 && pPlcxMan->GetDoingDrawTextBox())
854 4 : return aF.nLen;
855 :
856 : // keine Routine vorhanden
857 22 : 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 22 : long nOldPos = pStrm->Tell();
898 22 : OUString aStr;
899 22 : 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 22 : aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
908 44 : 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 22 : 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 22 : eF_ResT eRes = (this->*aWW8FieldTab[aF.nId])( &aF, aStr );
919 22 : pStrm->Seek( nOldPos );
920 :
921 22 : switch ( eRes )
922 : {
923 : case FLD_OK:
924 8 : 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 14 : if (aF.nLRes)
935 14 : 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 22 : }
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 : rDoc.InsertString(*pPaM, aName,
1033 0 : IDocumentContentOperations::INS_NOHINTEXPAND);
1034 : }
1035 : else
1036 : { // normal tagggen
1037 :
1038 : SwFieldType* pFT = rDoc.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.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.GetSysFldType( RES_INPUTFLD )),
1100 0 : aDef, aQ, INP_TXT, 0, false );
1101 0 : rDoc.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 noticable 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->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 1 : OUString SwWW8ImplReader::GetMappedBookmark(const OUString &rOrigName)
1235 : {
1236 1 : OUString sName(BookmarkToWriter(rOrigName));
1237 : OSL_ENSURE(pPlcxMan,"no pPlcxMan");
1238 1 : 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 1 : pReffingStck->aFieldVarNames.find(sName);
1244 :
1245 2 : return (aResult == pReffingStck->aFieldVarNames.end())
1246 2 : ? 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 : SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.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.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.InsertFldType( aT );
1311 : }
1312 : SwSetExpField aFld( (SwSetExpFieldType*)pNumFldType, OUString(),
1313 0 : GetNumberPara( rStr ) );
1314 0 : aFld.SetValue( ++nFldNum );
1315 0 : rDoc.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 : SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.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.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1393 0 : return FLD_OK;
1394 : }
1395 :
1396 1 : eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, OUString& rStr )
1397 : {
1398 1 : sal_uInt16 nSub=0;
1399 : // RegInfoFormat, DefaultFormat fuer DocInfoFelder
1400 1 : sal_uInt16 nReg = DI_SUB_AUTHOR;
1401 1 : bool bDateTime = false;
1402 :
1403 1 : 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.GetSysFldType( RES_DOCINFOFLD ), DI_CUSTOM|nReg, aDocProperty, GetFieldResult( pF ) );
1513 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1514 :
1515 0 : return FLD_OK;
1516 0 : }
1517 : }
1518 :
1519 1 : 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 1 : nSub = DI_CHANGE;
1556 1 : nReg = DI_SUB_DATE;
1557 1 : bDateTime = true;
1558 1 : 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 1 : sal_uInt32 nFormat = 0;
1570 :
1571 1 : sal_uInt16 nLang(0);
1572 1 : if (bDateTime)
1573 : {
1574 1 : short nDT = GetTimeDatePara(rStr, nFormat, nLang, pF->nId);
1575 1 : 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 1 : nReg = DI_SUB_DATE;
1585 1 : break;
1586 : default:
1587 0 : nReg = DI_SUB_DATE;
1588 0 : break;
1589 : }
1590 : }
1591 :
1592 1 : OUString aData;
1593 : // Extract DOCVARIABLE varname
1594 1 : 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 : aReadParam.SkipToNextToken();
1611 0 : break;
1612 : }
1613 0 : }
1614 :
1615 0 : aData = comphelper::string::remove(aData, '"');
1616 : }
1617 :
1618 : SwDocInfoField aFld( (SwDocInfoFieldType*)
1619 1 : rDoc.GetSysFldType( RES_DOCINFOFLD ), nSub|nReg, aData, nFormat );
1620 1 : if (bDateTime)
1621 1 : ForceFieldLanguage(aFld, nLang);
1622 1 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1623 :
1624 1 : 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.GetSysFldType( RES_DOCINFOFLD ),
1633 0 : DI_CREATE|DI_SUB_AUTHOR, OUString() );
1634 0 : rDoc.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.GetSysFldType( RES_TEMPLNAMEFLD ), FF_NAME );
1642 0 : rDoc.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.GetSysFldType(RES_DATETIMEFLD ), DATEFLD, nFormat);
1697 0 : ForceFieldLanguage(aFld, nLang);
1698 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1699 : }
1700 0 : else if (nDT == NUMBERFORMAT_TIME)
1701 : {
1702 : SwDateTimeField aFld((SwDateTimeFieldType*)
1703 0 : rDoc.GetSysFldType(RES_DATETIMEFLD), TIMEFLD, nFormat);
1704 0 : ForceFieldLanguage(aFld, nLang);
1705 0 : rDoc.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 : aReadParam.SkipToNextToken();
1728 0 : break;
1729 : default:
1730 : OSL_ENSURE(!this, "unknown option in FileName field");
1731 0 : break;
1732 : }
1733 0 : }
1734 :
1735 : SwFileNameField aFld(
1736 0 : (SwFileNameFieldType*)rDoc.GetSysFldType(RES_FILENAMEFLD), eType);
1737 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1738 0 : return FLD_OK;
1739 : }
1740 :
1741 0 : eF_ResT SwWW8ImplReader::Read_F_Anz( WW8FieldDesc* pF, OUString& rStr )
1742 : {
1743 0 : sal_uInt16 nSub = DS_PAGE; // page number
1744 0 : 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 0 : rDoc.GetSysFldType( RES_DOCSTATFLD ), nSub,
1750 0 : GetNumberPara( rStr ) );
1751 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1752 0 : return FLD_OK;
1753 : }
1754 :
1755 6 : eF_ResT SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc*, OUString& rStr )
1756 : {
1757 : // page number
1758 : SwPageNumberField aFld( (SwPageNumberFieldType*)
1759 6 : rDoc.GetSysFldType( RES_PAGENUMBERFLD ), PG_RANDOM,
1760 12 : GetNumberPara(rStr, true));
1761 :
1762 6 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
1763 6 : 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.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.InsertString(*pPaM, OUString("###"));
1828 : }
1829 :
1830 0 : return FLD_OK;
1831 : }
1832 :
1833 : // "EINBETTEN"
1834 4 : eF_ResT SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc*, OUString& rStr )
1835 : {
1836 4 : OUString sHost;
1837 :
1838 8 : WW8ReadFieldParams aReadParam( rStr );
1839 : for (;;)
1840 : {
1841 9 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
1842 9 : if ( nRet==-1 )
1843 4 : break;
1844 5 : switch( nRet )
1845 : {
1846 : case -2:
1847 4 : sHost = aReadParam.GetResult();
1848 4 : break;
1849 :
1850 : case 's':
1851 : // use ObjectSize
1852 1 : break;
1853 : }
1854 5 : }
1855 :
1856 4 : if( bObj && nPicLocFc )
1857 0 : nObjLocFc = nPicLocFc;
1858 4 : bEmbeddObj = true;
1859 8 : 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 : SwFieldType* pFT = rDoc.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.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 1 : eF_ResT SwWW8ImplReader::Read_F_Ref( WW8FieldDesc*, OUString& rStr )
1900 : { // Reference - Field
1901 1 : OUString sOrigBkmName;
1902 1 : REFERENCEMARK eFormat = REF_CONTENT;
1903 :
1904 2 : WW8ReadFieldParams aReadParam( rStr );
1905 : for (;;)
1906 : {
1907 5 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
1908 5 : if ( nRet==-1 )
1909 1 : break;
1910 4 : switch( nRet )
1911 : {
1912 : case -2:
1913 2 : if( sOrigBkmName.isEmpty() ) // get name of bookmark
1914 1 : sOrigBkmName = aReadParam.GetResult();
1915 2 : 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 refering 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 1 : eFormat = REF_NUMBER;
1932 1 : 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 1 : break;
1942 : default:
1943 : // unimplemented switch: just do 'nix nought nothing' :-)
1944 0 : break;
1945 : }
1946 4 : }
1947 :
1948 1 : OUString sBkmName(GetMappedBookmark(sOrigBkmName));
1949 :
1950 : SwGetRefField aFld(
1951 1 : (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
1952 3 : sBkmName,REF_BOOKMARK,0,eFormat);
1953 :
1954 1 : 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 1 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
1968 : }
1969 3 : 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.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.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 0 : eF_ResT SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc*, OUString& rStr )
2024 : {
2025 0 : OUString sOrigName;
2026 0 : WW8ReadFieldParams aReadParam( rStr );
2027 : for (;;)
2028 : {
2029 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2030 0 : if ( nRet==-1 )
2031 0 : break;
2032 0 : else if ( nRet == -2 && sOrigName.isEmpty() )
2033 : {
2034 0 : sOrigName = aReadParam.GetResult();
2035 : }
2036 0 : }
2037 :
2038 0 : const OUString sName(GetMappedBookmark(sOrigName));
2039 :
2040 : // loading page reference field in TOC
2041 0 : if (mbLoadingTOCCache )
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 ( !mbLoadingTOCHyperlink && !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 0 : OUString sPageRefBookmarkName;
2078 0 : 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 0 : sPageRefBookmarkName = sName;
2088 : }
2089 0 : SwGetRefField aFld( (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
2090 0 : sPageRefBookmarkName, REF_BOOKMARK, 0, REF_PAGE );
2091 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2092 :
2093 0 : 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 : ? true : false;
2154 0 : bNewVText = false;
2155 : }
2156 0 : else if( aVText.endsWith("]") )
2157 0 : bBracket = false;
2158 : }
2159 0 : break;
2160 : }
2161 0 : }
2162 0 : if( aName.isEmpty() )
2163 0 : return FLD_TAGIGN; // makes no sense without Makro-Name
2164 :
2165 : //try converting macro symbol according to macro name
2166 0 : bool bApplyWingdings = ConvertMacroSymbol( aName, aVText );
2167 0 : aName = "StarOffice.Standard.Modul1." + aName;
2168 :
2169 : SwMacroField aFld( (SwMacroFieldType*)
2170 0 : rDoc.GetSysFldType( RES_MACROFLD ), aName, aVText );
2171 :
2172 0 : if( !bApplyWingdings )
2173 : {
2174 :
2175 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2176 0 : WW8_CP nOldCp = pPlcxMan->Where();
2177 0 : WW8_CP nCp = nOldCp + nOffset;
2178 :
2179 0 : SwPaM aPaM(*pPaM);
2180 0 : aPaM.SetMark();
2181 0 : aPaM.Move(fnMoveBackward);
2182 0 : aPaM.Exchange();
2183 :
2184 0 : mpPostProcessAttrsInfo = new WW8PostProcessAttrsInfo(nCp, nCp, aPaM);
2185 : }
2186 : else
2187 : {
2188 : //set Wingdings font
2189 0 : sal_uInt16 i = 0;
2190 0 : for ( ; i < pFonts->GetMax(); i++ )
2191 : {
2192 : FontFamily eFamily;
2193 0 : OUString aFontName;
2194 : FontPitch ePitch;
2195 : rtl_TextEncoding eSrcCharSet;
2196 0 : if( GetFontParams( i, eFamily, aFontName, ePitch, eSrcCharSet )
2197 0 : && aFontName=="Wingdings" )
2198 : {
2199 0 : break;
2200 : }
2201 0 : }
2202 :
2203 0 : if ( i < pFonts->GetMax() )
2204 : {
2205 :
2206 0 : SetNewFontAttr( i, true, RES_CHRATR_FONT );
2207 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2208 0 : pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
2209 0 : ResetCharSetVars();
2210 : }
2211 : }
2212 :
2213 0 : return FLD_OK;
2214 : }
2215 :
2216 0 : WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd,
2217 : SwPaM & rPaM)
2218 : : mbCopy(false),
2219 : mnCpStart(nCpStart),
2220 : mnCpEnd(nCpEnd),
2221 0 : mPaM(*rPaM.GetPoint(), *rPaM.GetMark()),
2222 0 : mItemSet(rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END - 1)
2223 : {
2224 0 : }
2225 :
2226 0 : bool CanUseRemoteLink(const OUString &rGrfName)
2227 : {
2228 0 : bool bUseRemote = false;
2229 : try
2230 : {
2231 : ::ucbhelper::Content aCnt(rGrfName,
2232 : uno::Reference< ucb::XCommandEnvironment >(),
2233 0 : comphelper::getProcessComponentContext() );
2234 0 : OUString aTitle;
2235 :
2236 0 : aCnt.getPropertyValue("Title") >>= aTitle;
2237 0 : bUseRemote = !aTitle.isEmpty();
2238 : }
2239 0 : catch ( ... )
2240 : {
2241 : // this file did not exist, so we will not set this as graphiclink
2242 0 : bUseRemote = false;
2243 : }
2244 0 : return bUseRemote;
2245 : }
2246 :
2247 : // "EINF"UGENGRAFIK"
2248 0 : eF_ResT SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc*, OUString& rStr )
2249 : {
2250 0 : OUString aGrfName;
2251 0 : bool bEmbedded = true;
2252 :
2253 0 : WW8ReadFieldParams aReadParam( rStr );
2254 : for (;;)
2255 : {
2256 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2257 0 : if ( nRet==-1 )
2258 0 : break;
2259 0 : switch( nRet )
2260 : {
2261 : case -2:
2262 0 : if (aGrfName.isEmpty())
2263 0 : aGrfName = ConvertFFileName(aReadParam.GetResult());
2264 0 : break;
2265 :
2266 : case 'd':
2267 0 : bEmbedded = false;
2268 0 : break;
2269 :
2270 : case 'c':// den Converter-Namen ueberlesen
2271 0 : aReadParam.FindNextStringPiece();
2272 0 : break;
2273 : }
2274 0 : }
2275 :
2276 0 : if (!bEmbedded)
2277 0 : bEmbedded = !CanUseRemoteLink(aGrfName);
2278 :
2279 0 : if (!bEmbedded)
2280 : {
2281 : /*
2282 : Besonderheit:
2283 :
2284 : Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrmFmt.
2285 : Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
2286 : wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
2287 : wird.
2288 : Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
2289 : erkannt, dass wir soeben einen Grafik-Link inserted haben und
2290 : das passende SwAttrSet wird ins Frame-Format eingesetzt.
2291 : */
2292 0 : SfxItemSet aFlySet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
2293 0 : RES_FRMATR_END-1 );
2294 0 : aFlySet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
2295 0 : aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
2296 : pFlyFmtOfJustInsertedGraphic = rDoc.Insert( *pPaM,
2297 : aGrfName,
2298 : OUString(),
2299 : 0, // Graphic*
2300 : &aFlySet,
2301 0 : 0, 0); // SwFrmFmt*
2302 : maGrfNameGenerator.SetUniqueGraphName(pFlyFmtOfJustInsertedGraphic,
2303 0 : INetURLObject(aGrfName).GetBase());
2304 : }
2305 0 : return FLD_READ_FSPA;
2306 : }
2307 :
2308 0 : OUString wwSectionNamer::UniqueName()
2309 : {
2310 0 : const OUString aName(msFileLinkSeed + OUString::number(++mnFileSectionNo));
2311 0 : return mrDoc.GetUniqueSectionName(&aName);
2312 : }
2313 :
2314 : // "EINFUEGENTEXT"
2315 0 : eF_ResT SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc* /*pF*/, OUString& rStr )
2316 : {
2317 0 : OUString aPara;
2318 0 : OUString aBook;
2319 0 : WW8ReadFieldParams aReadParam( rStr );
2320 : for (;;)
2321 : {
2322 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2323 0 : if ( nRet==-1 )
2324 0 : break;
2325 0 : switch( nRet )
2326 : {
2327 : case -2:
2328 0 : if( aPara.isEmpty() )
2329 0 : aPara = aReadParam.GetResult();
2330 0 : else if( aBook.isEmpty() )
2331 0 : aBook = aReadParam.GetResult();
2332 0 : break;
2333 : case '*':
2334 : //Skip over MERGEFORMAT
2335 0 : aReadParam.SkipToNextToken();
2336 0 : break;
2337 : }
2338 0 : }
2339 0 : aPara = ConvertFFileName(aPara);
2340 :
2341 0 : if (!aBook.isEmpty() && aBook[ 0 ] != '\\')
2342 : {
2343 : // Bereich aus Quelle ( kein Switch ) ?
2344 0 : ConvertUFName(aBook);
2345 0 : aPara += OUString(sfx2::cTokenSeparator);
2346 0 : aPara += OUString(sfx2::cTokenSeparator);
2347 0 : aPara += aBook;
2348 : }
2349 :
2350 : /*
2351 : ##509##
2352 : What we will do is insert a section to be linked to a file, but just in
2353 : case the file is not available we will fill in the section with the stored
2354 : content of this winword field as a fallback.
2355 : */
2356 0 : SwPosition aTmpPos(*pPaM->GetPoint());
2357 :
2358 : SwSectionData aSection(FILE_LINK_SECTION,
2359 0 : maSectionNameGenerator.UniqueName());
2360 0 : aSection.SetLinkFileName( aPara );
2361 0 : aSection.SetProtectFlag(true);
2362 :
2363 : SwSection *const pSection =
2364 0 : rDoc.InsertSwSection(*pPaM, aSection, 0, 0, false);
2365 : OSL_ENSURE(pSection, "no section inserted");
2366 0 : if (!pSection)
2367 0 : return FLD_TEXT;
2368 0 : const SwSectionNode* pSectionNode = pSection->GetFmt()->GetSectionNode();
2369 : OSL_ENSURE(pSectionNode, "no section node!");
2370 0 : if (!pSectionNode)
2371 0 : return FLD_TEXT;
2372 :
2373 0 : pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
2374 0 : pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0 );
2375 :
2376 : //we have inserted a section before this point, so adjust pos
2377 : //for future page/section segment insertion
2378 0 : maSectionManager.PrependedInlineNode(aTmpPos, *pPaM->GetNode());
2379 :
2380 0 : return FLD_TEXT;
2381 : }
2382 :
2383 : // "SERIENDRUCKFELD"
2384 0 : eF_ResT SwWW8ImplReader::Read_F_DBField( WW8FieldDesc* pF, OUString& rStr )
2385 : {
2386 0 : OUString aName;
2387 0 : WW8ReadFieldParams aReadParam( rStr );
2388 : for (;;)
2389 : {
2390 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2391 0 : if ( nRet==-1 )
2392 0 : break;
2393 0 : switch( nRet )
2394 : {
2395 : case -2:
2396 0 : if( aName.isEmpty() )
2397 0 : aName = aReadParam.GetResult();
2398 0 : break;
2399 : }
2400 0 : }
2401 0 : SwDBFieldType aD( &rDoc, aName, SwDBData() ); // Datenbank: Nichts
2402 :
2403 0 : SwFieldType* pFT = rDoc.InsertFldType( aD );
2404 0 : SwDBField aFld( (SwDBFieldType*)pFT );
2405 0 : aFld.SetFieldCode( rStr );
2406 :
2407 0 : OUString aResult;
2408 0 : pSBase->WW8ReadString( *pStrm, aResult, pPlcxMan->GetCpOfs()+
2409 0 : pF->nSRes, pF->nLRes, eTextCharSet );
2410 :
2411 0 : aFld.InitContent(aResult);
2412 :
2413 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld( aFld ), 0);
2414 :
2415 0 : return FLD_OK;
2416 : }
2417 :
2418 : // "N"ACHSTER"
2419 0 : eF_ResT SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc*, OUString& )
2420 : {
2421 0 : SwDBNextSetFieldType aN;
2422 0 : SwFieldType* pFT = rDoc.InsertFldType( aN );
2423 : SwDBNextSetField aFld( (SwDBNextSetFieldType*)pFT, OUString(), OUString(),
2424 0 : SwDBData() ); // Datenbank: Nichts
2425 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2426 0 : return FLD_OK;
2427 : }
2428 :
2429 : // "DATENSATZ"
2430 0 : eF_ResT SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc*, OUString& )
2431 : {
2432 0 : SwDBSetNumberFieldType aN;
2433 0 : SwFieldType* pFT = rDoc.InsertFldType( aN );
2434 : SwDBSetNumberField aFld( (SwDBSetNumberFieldType*)pFT,
2435 0 : SwDBData() ); // Datenbank: Nichts
2436 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
2437 0 : return FLD_OK;
2438 : }
2439 :
2440 : /*
2441 : EQ , only the usage for
2442 : a. Combined Characters supported, must be exactly in the form that word
2443 : only accepts as combined charactersm, i.e.
2444 : eq \o(\s\up Y(XXX),\s\do Y(XXX))
2445 : b. Ruby Text supported, must be in the form that word recognizes as being
2446 : ruby text
2447 : ...
2448 : */
2449 0 : eF_ResT SwWW8ImplReader::Read_F_Equation( WW8FieldDesc*, OUString& rStr )
2450 : {
2451 0 : WW8ReadFieldParams aReadParam( rStr );
2452 0 : const sal_Int32 cChar = aReadParam.SkipToNextToken();
2453 0 : if ('o' == cChar || 'O' == cChar)
2454 : {
2455 0 : EquationResult aResult(ParseCombinedChars(rStr));
2456 :
2457 0 : if (aResult.sType == "Input")
2458 : {
2459 0 : SwInputField aFld( static_cast<SwInputFieldType*>(rDoc.GetSysFldType( RES_INPUTFLD )),
2460 0 : aResult.sResult, aResult.sResult, INP_TXT, 0 );
2461 0 : rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 ); // insert input field
2462 : }
2463 0 : else if (aResult.sType == "CombinedCharacters")
2464 : {
2465 : SwCombinedCharField aFld((SwCombinedCharFieldType*)
2466 0 : rDoc.GetSysFldType(RES_COMBINED_CHARS), aResult.sType);
2467 0 : rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2468 0 : }
2469 : }
2470 0 : else if ('*' == cChar)
2471 0 : Read_SubF_Ruby(aReadParam);
2472 :
2473 0 : return FLD_OK;
2474 : }
2475 :
2476 0 : void SwWW8ImplReader::Read_SubF_Ruby( WW8ReadFieldParams& rReadParam)
2477 : {
2478 0 : sal_uInt16 nJustificationCode=0;
2479 0 : OUString sFontName;
2480 0 : sal_uInt32 nFontSize=0;
2481 0 : OUString sRuby;
2482 0 : OUString sText;
2483 : for (;;)
2484 : {
2485 0 : const sal_Int32 nRet = rReadParam.SkipToNextToken();
2486 0 : if ( nRet==-1 )
2487 0 : break;
2488 0 : switch( nRet )
2489 : {
2490 : case -2:
2491 : {
2492 0 : OUString sTemp = rReadParam.GetResult();
2493 0 : if( sTemp.startsWithIgnoreAsciiCase( "jc" ) )
2494 : {
2495 0 : sTemp = sTemp.copy(2);
2496 0 : nJustificationCode = static_cast<sal_uInt16>(sTemp.toInt32());
2497 : }
2498 0 : else if( sTemp.startsWithIgnoreAsciiCase( "hps" ) )
2499 : {
2500 0 : sTemp = sTemp.copy(3);
2501 0 : nFontSize= static_cast<sal_uInt32>(sTemp.toInt32());
2502 : }
2503 0 : else if( sTemp.startsWithIgnoreAsciiCase( "Font:" ) )
2504 : {
2505 0 : sTemp = sTemp.copy(5);
2506 0 : sFontName = sTemp;
2507 0 : }
2508 : }
2509 0 : break;
2510 : case '*':
2511 0 : break;
2512 : case 'o':
2513 : for (;;)
2514 : {
2515 0 : const sal_Int32 nRes = rReadParam.SkipToNextToken();
2516 0 : if ( nRes==-1 )
2517 0 : break;
2518 0 : if ('u' == nRes)
2519 : {
2520 0 : if (-2 == rReadParam.SkipToNextToken() &&
2521 0 : rReadParam.GetResult().startsWithIgnoreAsciiCase("p"))
2522 : {
2523 0 : if (-2 == rReadParam.SkipToNextToken())
2524 : {
2525 0 : OUString sPart = rReadParam.GetResult();
2526 0 : sal_Int32 nBegin = sPart.indexOf('(');
2527 :
2528 : //Word disallows brackets in this field,
2529 0 : sal_Int32 nEnd = sPart.indexOf(')');
2530 :
2531 0 : if ((nBegin != -1) &&
2532 : (nEnd != -1))
2533 : {
2534 0 : sRuby = sPart.copy(nBegin+1,nEnd-nBegin-1);
2535 : }
2536 0 : if (-1 ==
2537 : (nBegin = sPart.indexOf(',',nEnd)))
2538 : {
2539 0 : nBegin = sPart.indexOf(';',nEnd);
2540 : }
2541 0 : nEnd = sPart.lastIndexOf(')');
2542 0 : if ((nBegin != -1) && (nEnd != -1))
2543 : {
2544 0 : sText = sPart.copy(nBegin+1,nEnd-nBegin-1);
2545 0 : }
2546 : }
2547 : }
2548 : }
2549 :
2550 0 : }
2551 0 : break;
2552 : }
2553 0 : }
2554 :
2555 : //Translate and apply
2556 0 : if (!sRuby.isEmpty() && !sText.isEmpty() && !sFontName.isEmpty() && nFontSize)
2557 : {
2558 0 : switch (nJustificationCode)
2559 : {
2560 : case 0:
2561 0 : nJustificationCode=1;
2562 0 : break;
2563 : case 1:
2564 0 : nJustificationCode=3;
2565 0 : break;
2566 : case 2:
2567 0 : nJustificationCode=4;
2568 0 : break;
2569 : default:
2570 : case 3:
2571 0 : nJustificationCode=0;
2572 0 : break;
2573 : case 4:
2574 0 : nJustificationCode=2;
2575 0 : break;
2576 : }
2577 :
2578 0 : SwFmtRuby aRuby(sRuby);
2579 0 : const SwCharFmt *pCharFmt=0;
2580 : //Make a guess at which of asian of western we should be setting
2581 : sal_uInt16 nScript;
2582 0 : if (g_pBreakIt->GetBreakIter().is())
2583 0 : nScript = g_pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
2584 : else
2585 0 : nScript = i18n::ScriptType::ASIAN;
2586 :
2587 : //Check to see if we already have a ruby charstyle that this fits
2588 : std::vector<const SwCharFmt*>::const_iterator aEnd =
2589 0 : aRubyCharFmts.end();
2590 0 : for(std::vector<const SwCharFmt*>::const_iterator aIter
2591 0 : = aRubyCharFmts.begin(); aIter != aEnd; ++aIter)
2592 : {
2593 : const SvxFontHeightItem &rFH =
2594 0 : ItemGet<SvxFontHeightItem>(*(*aIter),
2595 0 : GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2596 0 : if (rFH.GetHeight() == nFontSize*10)
2597 : {
2598 0 : const SvxFontItem &rF = ItemGet<SvxFontItem>(*(*aIter),
2599 0 : GetWhichOfScript(RES_CHRATR_FONT,nScript));
2600 0 : if (rF.GetFamilyName().equals(sFontName))
2601 : {
2602 0 : pCharFmt=*aIter;
2603 0 : break;
2604 : }
2605 : }
2606 : }
2607 :
2608 : //Create a new char style if necessary
2609 0 : if (!pCharFmt)
2610 : {
2611 0 : SwCharFmt *pFmt=0;
2612 0 : OUString aNm;
2613 : //Take this as the base name
2614 0 : SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT,aNm);
2615 0 : aNm+=OUString::number(aRubyCharFmts.size()+1);
2616 0 : pFmt = rDoc.MakeCharFmt(aNm,(SwCharFmt*)rDoc.GetDfltCharFmt());
2617 0 : SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
2618 : SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
2619 0 : OUString(), PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
2620 0 : aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2621 0 : aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
2622 0 : pFmt->SetFmtAttr(aHeightItem);
2623 0 : pFmt->SetFmtAttr(aFontItem);
2624 0 : aRubyCharFmts.push_back(pFmt);
2625 0 : pCharFmt = pFmt;
2626 : }
2627 :
2628 : //Set the charstyle and justification
2629 0 : aRuby.SetCharFmtName(pCharFmt->GetName());
2630 0 : aRuby.SetCharFmtId(pCharFmt->GetPoolFmtId());
2631 0 : aRuby.SetAdjustment(nJustificationCode);
2632 :
2633 0 : NewAttr(aRuby);
2634 0 : rDoc.InsertString( *pPaM, sText );
2635 0 : pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_CJK_RUBY );
2636 0 : }
2637 0 : }
2638 :
2639 : // "table of ..." fields
2640 :
2641 0 : static void lcl_toxMatchACSwitch( SwWW8ImplReader& /*rReader*/,
2642 : SwDoc& rDoc,
2643 : SwTOXBase& rBase,
2644 : WW8ReadFieldParams& rParam,
2645 : SwCaptionDisplay eCaptionType)
2646 : {
2647 0 : if ( rParam.GoToTokenParam() )
2648 : {
2649 0 : SwTOXType* pType = (SwTOXType*)rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0);
2650 0 : rBase.RegisterToTOXType( *pType );
2651 0 : rBase.SetCaptionDisplay( eCaptionType );
2652 : // Read Sequence Name and store in TOXBase
2653 0 : OUString sSeqName( rParam.GetResult() );
2654 0 : lcl_ConvertSequenceName( sSeqName );
2655 0 : rBase.SetSequenceName( sSeqName );
2656 : }
2657 0 : }
2658 :
2659 : //For all outline styles that are not in the outline numbering add them here as
2660 : //custom extra styles
2661 0 : bool SwWW8ImplReader::AddExtraOutlinesAsExtraStyles(SwTOXBase& rBase)
2662 : {
2663 0 : bool bExtras = false;
2664 : //This is the case if the winword outline numbering is set while the
2665 : //writer one is not
2666 0 : for (sal_uInt16 nI = 0; nI < vColl.size(); ++nI)
2667 : {
2668 0 : SwWW8StyInf& rSI = vColl[nI];
2669 0 : if (rSI.IsOutline())
2670 : {
2671 0 : const SwTxtFmtColl *pFmt = (const SwTxtFmtColl*)(rSI.pFmt);
2672 0 : sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
2673 0 : sal_uInt16 nMaxLevel = rBase.GetLevel();
2674 0 : if (
2675 0 : nStyleLevel != (pFmt->GetAttrOutlineLevel()-1) &&
2676 : nStyleLevel < nMaxLevel
2677 : )
2678 : {
2679 0 : OUString sStyles(rBase.GetStyleNames(rSI.nOutlineLevel));
2680 0 : if ( !sStyles.isEmpty())
2681 0 : sStyles += OUString(TOX_STYLE_DELIMITER);
2682 0 : sStyles += pFmt->GetName();
2683 0 : rBase.SetStyleNames(sStyles, rSI.nOutlineLevel);
2684 0 : bExtras = true;
2685 : }
2686 : }
2687 : }
2688 0 : return bExtras;
2689 : }
2690 :
2691 0 : static void EnsureMaxLevelForTemplates(SwTOXBase& rBase)
2692 : {
2693 : //If the TOC contains Template entries at levels > the evaluation level
2694 : //that was initially taken from the max normal outline level of the word TOC
2695 : //then we cannot use that for the evaluation level because writer cuts off
2696 : //all styles above that level, while word just cuts off the "standard"
2697 : //outline styles, we have no option but to expand to the highest level
2698 : //Word included.
2699 0 : if ((rBase.GetLevel() != MAXLEVEL) && (nsSwTOXElement::TOX_TEMPLATE & rBase.GetCreateType()))
2700 : {
2701 0 : for (sal_uInt16 nI = MAXLEVEL; nI > 0; --nI)
2702 : {
2703 0 : if (!rBase.GetStyleNames(nI-1).isEmpty())
2704 : {
2705 0 : rBase.SetLevel(nI);
2706 0 : break;
2707 : }
2708 : }
2709 : }
2710 0 : }
2711 :
2712 0 : static void lcl_toxMatchTSwitch(SwWW8ImplReader& rReader, SwTOXBase& rBase,
2713 : WW8ReadFieldParams& rParam)
2714 : {
2715 0 : if ( rParam.GoToTokenParam() )
2716 : {
2717 0 : OUString sParams( rParam.GetResult() );
2718 0 : if( !sParams.isEmpty() )
2719 : {
2720 0 : sal_Int32 nIndex = 0;
2721 :
2722 : // Delimiters between styles and style levels appears to allow both ; and ,
2723 :
2724 0 : OUString sTemplate( sParams.getToken(0, ';', nIndex) );
2725 0 : if( -1 == nIndex )
2726 : {
2727 0 : nIndex=0;
2728 0 : sTemplate = sParams.getToken(0, ',', nIndex);
2729 : }
2730 0 : if( -1 == nIndex )
2731 : {
2732 0 : const SwFmt* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
2733 0 : if( pStyle )
2734 0 : sTemplate = pStyle->GetName();
2735 : // Store Style for Level 0 into TOXBase
2736 0 : rBase.SetStyleNames( sTemplate, 0 );
2737 : }
2738 0 : else while( -1 != nIndex )
2739 : {
2740 0 : sal_Int32 nOldIndex=nIndex;
2741 : sal_uInt16 nLevel = static_cast<sal_uInt16>(
2742 0 : sParams.getToken(0, ';', nIndex).toInt32());
2743 0 : if( -1 == nIndex )
2744 : {
2745 0 : nIndex = nOldIndex;
2746 : nLevel = static_cast<sal_uInt16>(
2747 0 : sParams.getToken(0, ',', nIndex).toInt32());
2748 : }
2749 :
2750 0 : if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
2751 : {
2752 0 : nLevel--;
2753 : // Store Style and Level into TOXBase
2754 : const SwFmt* pStyle
2755 0 : = rReader.GetStyleWithOrgWWName( sTemplate );
2756 :
2757 0 : if( pStyle )
2758 0 : sTemplate = pStyle->GetName();
2759 :
2760 0 : OUString sStyles( rBase.GetStyleNames( nLevel ) );
2761 0 : if( !sStyles.isEmpty() )
2762 0 : sStyles += OUString(TOX_STYLE_DELIMITER);
2763 0 : sStyles += sTemplate;
2764 0 : rBase.SetStyleNames( sStyles, nLevel );
2765 : }
2766 : // read next style name...
2767 0 : nOldIndex = nIndex;
2768 0 : sTemplate = sParams.getToken(0, ';', nIndex);
2769 0 : if( -1 == nIndex )
2770 : {
2771 0 : nIndex=nOldIndex;
2772 0 : sTemplate = sParams.getToken(0, ',', nIndex);
2773 : }
2774 0 : }
2775 0 : }
2776 : }
2777 0 : }
2778 :
2779 0 : sal_uInt16 wwSectionManager::CurrentSectionColCount() const
2780 : {
2781 0 : sal_uInt16 nIndexCols = 1;
2782 0 : if (!maSegments.empty())
2783 0 : nIndexCols = maSegments.back().maSep.ccolM1 + 1;
2784 0 : return nIndexCols;
2785 : }
2786 :
2787 : //Will there be a new pagebreak at this position (don't know what type
2788 : //until later)
2789 0 : bool wwSectionManager::WillHavePageDescHere(SwNodeIndex aIdx) const
2790 : {
2791 0 : bool bRet = false;
2792 0 : if (!maSegments.empty())
2793 : {
2794 0 : if (!maSegments.back().IsContinuous() &&
2795 0 : maSegments.back().maStart == aIdx)
2796 : {
2797 0 : bRet = true;
2798 : }
2799 : }
2800 0 : return bRet;
2801 : }
2802 :
2803 0 : static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
2804 : {
2805 : // GetFormMax() returns level + 1, hence the -1
2806 0 : sal_uInt16 nRet = rForm.GetFormMax()-1;
2807 :
2808 : // If the max of this type of TOC is greater than the max of a word
2809 : // possible toc, then clip to the word max
2810 0 : if (nRet > WW8ListManager::nMaxLevel)
2811 0 : nRet = WW8ListManager::nMaxLevel;
2812 :
2813 0 : return nRet;
2814 : }
2815 :
2816 0 : eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, OUString& rStr )
2817 : {
2818 0 : mbLoadingTOCCache = true;
2819 :
2820 0 : if (pF->nLRes < 3)
2821 0 : return FLD_TEXT; // ignore (#i25440#)
2822 :
2823 : TOXTypes eTox; // create a ToxBase
2824 0 : switch( pF->nId )
2825 : {
2826 : case 8:
2827 0 : eTox = TOX_INDEX;
2828 0 : break;
2829 : case 13:
2830 0 : eTox = TOX_CONTENT;
2831 0 : break;
2832 : default:
2833 0 : eTox = TOX_USER;
2834 0 : break;
2835 : }
2836 :
2837 0 : sal_uInt16 nCreateOf = (eTox == TOX_CONTENT) ? nsSwTOXElement::TOX_OUTLINELEVEL : nsSwTOXElement::TOX_MARK;
2838 :
2839 0 : sal_uInt16 nIndexCols = 1;
2840 :
2841 0 : const SwTOXType* pType = rDoc.GetTOXType( eTox, 0 );
2842 0 : SwForm aOrigForm(eTox);
2843 0 : SwTOXBase* pBase = new SwTOXBase( pType, aOrigForm, nCreateOf, OUString() );
2844 0 : pBase->SetProtected(maSectionManager.CurrentSectionIsProtected());
2845 0 : switch( eTox ){
2846 : case TOX_INDEX:
2847 : {
2848 0 : sal_uInt16 eOptions = nsSwTOIOptions::TOI_SAME_ENTRY | nsSwTOIOptions::TOI_CASE_SENSITIVE;
2849 :
2850 : // TOX_OUTLINELEVEL setzen wir genau dann, wenn
2851 : // die Parameter \o in 1 bis 9 liegen
2852 : // oder der Parameter \f existiert
2853 : // oder GARKEINE Switches Parameter angegeben sind.
2854 0 : WW8ReadFieldParams aReadParam( rStr );
2855 : for (;;)
2856 : {
2857 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2858 0 : if ( nRet==-1 )
2859 0 : break;
2860 0 : switch( nRet )
2861 : {
2862 : case 'c':
2863 0 : if ( aReadParam.GoToTokenParam() )
2864 : {
2865 0 : const OUString sParams( aReadParam.GetResult() );
2866 : // if NO OUString just ignore the \c
2867 0 : if( !sParams.isEmpty() )
2868 : {
2869 0 : nIndexCols = static_cast<sal_uInt16>(sParams.toInt32());
2870 0 : }
2871 : }
2872 0 : break;
2873 : case 'e':
2874 : {
2875 0 : if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \e
2876 : {
2877 0 : OUString sDelimiter( aReadParam.GetResult() );
2878 0 : SwForm aForm( pBase->GetTOXForm() );
2879 :
2880 : // Attention: if TOX_CONTENT brave
2881 : // GetFormMax() returns MAXLEVEL + 1 !!
2882 0 : sal_uInt16 nEnd = aForm.GetFormMax()-1;
2883 :
2884 0 : for(sal_uInt16 nLevel = 1;
2885 : nLevel <= nEnd;
2886 : ++nLevel)
2887 : {
2888 : // Levels count from 1
2889 : // Level 0 is reserved for CAPTION
2890 :
2891 : // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
2892 : // falls es eine Seitenzahl gibt:
2893 0 : FormTokenType ePrevType = TOKEN_END;
2894 : FormTokenType eType;
2895 : // -> #i21237#
2896 : SwFormTokens aPattern =
2897 0 : aForm.GetPattern(nLevel);
2898 0 : SwFormTokens::iterator aIt = aPattern.begin();
2899 0 : do
2900 : {
2901 0 : eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
2902 :
2903 0 : if (eType == TOKEN_PAGE_NUMS)
2904 : {
2905 0 : if (TOKEN_TAB_STOP == ePrevType)
2906 : {
2907 0 : --aIt;
2908 :
2909 0 : if(0x09 == sDelimiter[0])
2910 0 : aIt->eTabAlign = SVX_TAB_ADJUST_END;
2911 : else
2912 : {
2913 0 : SwFormToken aToken(TOKEN_TEXT);
2914 0 : aToken.sText = sDelimiter;
2915 0 : *aIt = aToken;
2916 : }
2917 0 : aForm.SetPattern(nLevel, aPattern);
2918 : }
2919 :
2920 0 : eType = TOKEN_END;
2921 : }
2922 :
2923 0 : ePrevType = eType;
2924 : }
2925 : while (TOKEN_END != eType);
2926 : // <- #i21237#
2927 0 : }
2928 0 : pBase->SetTOXForm( aForm );
2929 : }
2930 : }
2931 0 : break;
2932 : case 'h':
2933 : {
2934 0 : eOptions |= nsSwTOIOptions::TOI_ALPHA_DELIMITTER;
2935 : }
2936 0 : break;
2937 : }
2938 0 : }
2939 0 : pBase->SetOptions( eOptions );
2940 : }
2941 0 : break;
2942 :
2943 : case TOX_CONTENT:
2944 : {
2945 0 : bool bIsHyperlink = false;
2946 0 : bool bShowPage = true;
2947 : // TOX_OUTLINELEVEL setzen wir genau dann, wenn
2948 : // die Parameter \o in 1 bis 9 liegen
2949 : // oder der Parameter \f existiert
2950 : // oder GARKEINE Switches Parameter angegeben sind.
2951 0 : sal_uInt16 eCreateFrom = 0;
2952 0 : sal_Int32 nMaxLevel = 0;
2953 0 : WW8ReadFieldParams aReadParam( rStr );
2954 : for (;;)
2955 : {
2956 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
2957 0 : if ( nRet==-1 )
2958 0 : break;
2959 0 : switch( nRet )
2960 : {
2961 : case 'h':
2962 0 : bIsHyperlink = true;
2963 0 : break;
2964 : case 'a':
2965 : case 'c':
2966 : lcl_toxMatchACSwitch(*this, rDoc, *pBase, aReadParam,
2967 : ('c' == nRet)
2968 : ? CAPTION_COMPLETE
2969 0 : : CAPTION_TEXT );
2970 0 : break;
2971 : case 'o':
2972 : {
2973 : sal_Int32 nVal;
2974 0 : if( !aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
2975 0 : nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
2976 0 : if( nMaxLevel < nVal )
2977 0 : nMaxLevel = nVal;
2978 0 : eCreateFrom |= nsSwTOXElement::TOX_OUTLINELEVEL;
2979 : }
2980 0 : break;
2981 : case 'f':
2982 0 : eCreateFrom |= nsSwTOXElement::TOX_MARK;
2983 0 : break;
2984 : case 'l':
2985 : {
2986 : sal_Int32 nVal;
2987 0 : if( aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
2988 : {
2989 0 : if( nMaxLevel < nVal )
2990 0 : nMaxLevel = nVal;
2991 0 : eCreateFrom |= nsSwTOXElement::TOX_MARK;
2992 : }
2993 : }
2994 0 : break;
2995 : case 't': // paragraphs using special styles shall
2996 : // provide the TOX's content
2997 0 : lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
2998 0 : eCreateFrom |= nsSwTOXElement::TOX_TEMPLATE;
2999 0 : break;
3000 : case 'p':
3001 : {
3002 0 : if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \p
3003 : {
3004 0 : OUString sDelimiter( aReadParam.GetResult() );
3005 0 : SwForm aForm( pBase->GetTOXForm() );
3006 :
3007 : // Attention: if TOX_CONTENT brave
3008 : // GetFormMax() returns MAXLEVEL + 1 !!
3009 0 : sal_uInt16 nEnd = aForm.GetFormMax()-1;
3010 :
3011 0 : for(sal_uInt16 nLevel = 1;
3012 : nLevel <= nEnd;
3013 : ++nLevel)
3014 : {
3015 : // Levels count from 1
3016 : // Level 0 is reserved for CAPTION
3017 :
3018 : // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
3019 : // falls es eine Seitenzahl gibt:
3020 0 : FormTokenType ePrevType = TOKEN_END;
3021 : FormTokenType eType;
3022 :
3023 : // -> #i21237#
3024 0 : SwFormTokens aPattern = aForm.GetPattern(nLevel);
3025 0 : SwFormTokens::iterator aIt = aPattern.begin();
3026 0 : do
3027 : {
3028 0 : eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3029 :
3030 0 : if (eType == TOKEN_PAGE_NUMS)
3031 : {
3032 0 : if (TOKEN_TAB_STOP == ePrevType)
3033 : {
3034 0 : --aIt;
3035 :
3036 0 : SwFormToken aToken(TOKEN_TEXT);
3037 0 : aToken.sText = sDelimiter;
3038 :
3039 0 : *aIt = aToken;
3040 : aForm.SetPattern(nLevel,
3041 0 : aPattern);
3042 : }
3043 0 : eType = TOKEN_END;
3044 : }
3045 0 : ePrevType = eType;
3046 : }
3047 : while( TOKEN_END != eType );
3048 : // <- #i21237#
3049 0 : }
3050 0 : pBase->SetTOXForm( aForm );
3051 : }
3052 : }
3053 0 : break;
3054 : case 'n': // don't print page numbers
3055 : {
3056 : // read START and END param
3057 0 : sal_Int32 nStart(0);
3058 0 : sal_Int32 nEnd(0);
3059 0 : if( !aReadParam.GetTokenSttFromTo( &nStart, &nEnd,
3060 0 : WW8ListManager::nMaxLevel ) )
3061 : {
3062 0 : nStart = 1;
3063 0 : nEnd = aOrigForm.GetFormMax()-1;
3064 : }
3065 : // remove page numbers from this levels
3066 0 : SwForm aForm( pBase->GetTOXForm() );
3067 0 : if (aForm.GetFormMax() <= nEnd)
3068 0 : nEnd = aForm.GetFormMax()-1;
3069 0 : for ( sal_Int32 nLevel = nStart; nLevel<=nEnd; ++nLevel )
3070 : {
3071 : // Levels count from 1
3072 : // Level 0 is reserved for CAPTION
3073 :
3074 : // Seitenzahl und ggfs. davorstehenden Tabstop
3075 : // entfernen:
3076 : FormTokenType eType;
3077 : // -> #i21237#
3078 0 : SwFormTokens aPattern = aForm.GetPattern(nLevel);
3079 0 : SwFormTokens::iterator aIt = aPattern.begin();
3080 0 : do
3081 : {
3082 0 : eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3083 :
3084 0 : if (eType == TOKEN_PAGE_NUMS)
3085 : {
3086 0 : aIt = aPattern.erase(aIt);
3087 0 : --aIt;
3088 0 : if (
3089 0 : TOKEN_TAB_STOP ==
3090 0 : aIt->eTokenType
3091 : )
3092 : {
3093 0 : aPattern.erase(aIt);
3094 0 : aForm.SetPattern(nLevel, aPattern);
3095 : }
3096 0 : eType = TOKEN_END;
3097 : }
3098 : }
3099 : while (TOKEN_END != eType);
3100 : // <- #i21237#
3101 0 : }
3102 0 : pBase->SetTOXForm( aForm );
3103 : }
3104 0 : break;
3105 :
3106 : /*
3107 : // the following switches are not (yet) supported
3108 : // by good old StarWriter:
3109 : case 'b':
3110 : case 's':
3111 : case 'd':
3112 : break;
3113 : */
3114 : }
3115 0 : }
3116 :
3117 : // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens
3118 : // also include the hyperlinks and page references
3119 0 : SwFormToken aLinkStart(TOKEN_LINK_START);
3120 0 : SwFormToken aLinkEnd(TOKEN_LINK_END);
3121 0 : aLinkStart.sCharStyleName = "Index Link";
3122 0 : aLinkEnd.sCharStyleName = "Index Link";
3123 0 : SwForm aForm(pBase->GetTOXForm());
3124 0 : sal_uInt16 nEnd = aForm.GetFormMax()-1;
3125 :
3126 0 : for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
3127 : {
3128 0 : SwFormTokens aPattern = aForm.GetPattern(nLevel);
3129 0 : if ( bIsHyperlink )
3130 : {
3131 0 : aPattern.insert(aPattern.begin(), aLinkStart);
3132 : }
3133 0 : else if ( bShowPage )
3134 : {
3135 0 : for (SwFormTokens::iterator aItr = aPattern.begin();aItr!= aPattern.end();++aItr)
3136 : {
3137 0 : if (aItr->eTokenType == TOKEN_PAGE_NUMS)
3138 : {
3139 0 : aPattern.insert(aItr,aLinkStart);
3140 0 : break;
3141 : }
3142 : }
3143 : }
3144 0 : aPattern.push_back(aLinkEnd);
3145 0 : aForm.SetPattern(nLevel, aPattern);
3146 0 : }
3147 0 : pBase->SetTOXForm(aForm);
3148 :
3149 0 : if (!nMaxLevel)
3150 0 : nMaxLevel = WW8ListManager::nMaxLevel;
3151 0 : pBase->SetLevel(nMaxLevel);
3152 :
3153 0 : const TOXTypes eType = pBase->GetTOXType()->GetType();
3154 0 : switch( eType )
3155 : {
3156 : case TOX_CONTENT:
3157 : {
3158 : //If we would be created from outlines, either explictly or by default
3159 : //then see if we need extra styles added to the outlines
3160 0 : sal_uInt16 eEffectivelyFrom = eCreateFrom ? eCreateFrom : nsSwTOXElement::TOX_OUTLINELEVEL;
3161 0 : if (eEffectivelyFrom & nsSwTOXElement::TOX_OUTLINELEVEL)
3162 : {
3163 0 : if (AddExtraOutlinesAsExtraStyles(*pBase))
3164 0 : eCreateFrom |= (nsSwTOXElement::TOX_TEMPLATE | nsSwTOXElement::TOX_OUTLINELEVEL);
3165 :
3166 : // #i19683# Insert a text token " " between the number and entry token.
3167 : // In an ideal world we could handle the tab stop between the number and
3168 : // the entry correctly, but I currently have no clue how to obtain
3169 : // the tab stop position. It is _not_ set at the paragraph style.
3170 0 : SwForm* pForm = 0;
3171 0 : for (sal_uInt16 nI = 0; nI < vColl.size(); ++nI)
3172 : {
3173 0 : const SwWW8StyInf& rSI = vColl[nI];
3174 0 : if (rSI.IsOutlineNumbered())
3175 : {
3176 0 : sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
3177 0 : const SwNumFmt& rFmt = rSI.GetOutlineNumrule()->Get( nStyleLevel );
3178 0 : if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() )
3179 : {
3180 0 : ++nStyleLevel;
3181 :
3182 0 : if ( !pForm )
3183 0 : pForm = new SwForm( pBase->GetTOXForm() );
3184 :
3185 0 : SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
3186 : SwFormTokens::iterator aIt =
3187 : find_if(aPattern.begin(), aPattern.end(),
3188 0 : SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3189 :
3190 0 : if ( aIt != aPattern.end() )
3191 : {
3192 0 : SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
3193 0 : aNumberEntrySeparator.sText = " ";
3194 0 : aPattern.insert( ++aIt, aNumberEntrySeparator );
3195 0 : pForm->SetPattern( nStyleLevel, aPattern );
3196 0 : }
3197 : }
3198 : }
3199 : }
3200 0 : if ( pForm )
3201 : {
3202 0 : pBase->SetTOXForm( *pForm );
3203 0 : delete pForm;
3204 : }
3205 : }
3206 :
3207 0 : if (eCreateFrom)
3208 0 : pBase->SetCreate(eCreateFrom);
3209 0 : EnsureMaxLevelForTemplates(*pBase);
3210 : }
3211 0 : break;
3212 : case TOX_ILLUSTRATIONS:
3213 : {
3214 0 : if( !eCreateFrom )
3215 0 : eCreateFrom = nsSwTOXElement::TOX_SEQUENCE;
3216 0 : pBase->SetCreate( eCreateFrom );
3217 :
3218 : /*
3219 : We don't know until here if we are an illustration
3220 : or not, and so have being used a TOX_CONTENT so far
3221 : which has 10 levels, while TOX has only two, this
3222 : level is set only in the constructor of SwForm, so
3223 : create a new one and copy over anything that could
3224 : be set in the old one, and remove entries from the
3225 : pattern which do not apply to illustration indices
3226 : */
3227 0 : SwForm aOldForm( pBase->GetTOXForm() );
3228 0 : SwForm aNewForm( eType );
3229 0 : sal_uInt16 nNewEnd = aNewForm.GetFormMax()-1;
3230 :
3231 : // #i21237#
3232 0 : for(sal_uInt16 nLevel = 1; nLevel <= nNewEnd; ++nLevel)
3233 : {
3234 0 : SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
3235 : SwFormTokens::iterator new_end =
3236 0 : remove_if(aPattern.begin(), aPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3237 0 : aPattern.erase(new_end, aPattern.end() ); // table index imported with wrong page number format
3238 0 : aForm.SetPattern( nLevel, aPattern );
3239 0 : aForm.SetTemplate( nLevel, aOldForm.GetTemplate(nLevel) );
3240 0 : }
3241 :
3242 0 : pBase->SetTOXForm( aNewForm );
3243 : }
3244 0 : break;
3245 : default:
3246 : OSL_ENSURE(!this, "Unhandled toc options!");
3247 0 : break;
3248 0 : }
3249 : }
3250 0 : break;
3251 : case TOX_USER:
3252 0 : break;
3253 : default:
3254 : OSL_ENSURE(!this, "Unhandled toc options!");
3255 0 : break;
3256 : } // ToxBase fertig
3257 :
3258 : // #i21237# - propagate tab stops from paragraph styles used in TOX to patterns of the TOX
3259 0 : pBase->AdjustTabStops( rDoc );
3260 :
3261 : //#i10028# inserting a toc implicltly acts like a parabreak in word and writer
3262 0 : if ( pPaM->End() &&
3263 0 : pPaM->End()->nNode.GetNode().GetTxtNode() &&
3264 0 : pPaM->End()->nNode.GetNode().GetTxtNode()->Len() != 0 )
3265 : {
3266 0 : mbCareFirstParaEndInToc = true;
3267 : }
3268 :
3269 0 : if (pPaM->GetPoint()->nContent.GetIndex())
3270 0 : AppendTxtNode(*pPaM->GetPoint());
3271 :
3272 0 : const SwPosition* pPos = pPaM->GetPoint();
3273 :
3274 0 : SwFltTOX aFltTOX( pBase, nIndexCols );
3275 :
3276 : // test if there is already a break item on this node
3277 0 : if(SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode())
3278 : {
3279 0 : const SfxItemSet* pSet = pNd->GetpSwAttrSet();
3280 0 : if( pSet )
3281 : {
3282 0 : if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false))
3283 0 : aFltTOX.SetHadBreakItem(true);
3284 0 : if (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false))
3285 0 : aFltTOX.SetHadPageDescItem(true);
3286 : }
3287 : }
3288 :
3289 : //Will there be a new pagebreak at this position (don't know what type
3290 : //until later)
3291 0 : if (maSectionManager.WillHavePageDescHere(pPos->nNode))
3292 0 : aFltTOX.SetHadPageDescItem(true);
3293 :
3294 : // Setze Anfang in Stack
3295 0 : pReffedStck->NewAttr( *pPos, aFltTOX );
3296 :
3297 0 : rDoc.InsertTableOf(*pPaM->GetPoint(), *aFltTOX.GetBase());
3298 :
3299 : //The TOC field representation contents should be inserted into TOC section, but not after TOC section.
3300 : //So we need update the document position when loading TOC representation and after loading TOC;
3301 0 : if (mpPosAfterTOC)
3302 : {
3303 0 : delete mpPosAfterTOC;
3304 : }
3305 0 : mpPosAfterTOC = new SwPaM(*pPaM);
3306 0 : (*pPaM).Move(fnMoveBackward);
3307 0 : SwPaM aRegion(*pPaM);
3308 :
3309 : OSL_ENSURE(rDoc.GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
3310 0 : if (SwTOXBase* pBase2 = (SwTOXBase*)rDoc.GetCurTOX(*aRegion.GetPoint()))
3311 : {
3312 0 : pBase2->SetMSTOCExpression(rStr);
3313 :
3314 0 : if ( nIndexCols > 1 )
3315 : {
3316 : // Set the column number for index
3317 0 : SfxItemSet aSet( rDoc.GetAttrPool(), RES_COL, RES_COL );
3318 0 : SwFmtCol aCol;
3319 0 : aCol.Init( nIndexCols, 708, USHRT_MAX );
3320 0 : aSet.Put( aCol );
3321 0 : pBase2->SetAttrSet( aSet );
3322 : }
3323 :
3324 : // inserting a toc inserts a section before this point, so adjust pos
3325 : // for future page/section segment insertion
3326 0 : maSectionManager.PrependedInlineNode( *mpPosAfterTOC->GetPoint(), *aRegion.GetNode() );
3327 : }
3328 :
3329 : // Setze Ende in Stack
3330 0 : pReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
3331 :
3332 0 : if (!maApos.back()) //a para end in apo doesn't count
3333 0 : bWasParaEnd = true;
3334 :
3335 : //Return FLD_TEXT, instead of FLD_OK
3336 : //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed
3337 : //FLD_OK means the current field loading is finished. The rest part should be ignored.
3338 0 : return FLD_TEXT;
3339 : }
3340 :
3341 3 : eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, OUString& /*rStr*/)
3342 : {
3343 : /*
3344 : #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3345 : to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3346 : the drawing that we are in the Shape field and respond accordingly
3347 : */
3348 3 : return FLD_TEXT;
3349 : }
3350 :
3351 6 : eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, OUString& rStr )
3352 : {
3353 12 : OUString sURL, sTarget, sMark;
3354 6 : bool bDataImport = false;
3355 : //HYPERLINK "filename" [switches]
3356 :
3357 6 : rStr = comphelper::string::stripEnd(rStr, 1);
3358 :
3359 6 : if (!bDataImport)
3360 : {
3361 6 : bool bOptions = false;
3362 6 : WW8ReadFieldParams aReadParam( rStr );
3363 : for (;;)
3364 : {
3365 11 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
3366 11 : if ( nRet==-1 )
3367 6 : break;
3368 5 : switch( nRet )
3369 : {
3370 : case -2:
3371 5 : if (sURL.isEmpty() && !bOptions)
3372 5 : sURL = ConvertFFileName(aReadParam.GetResult());
3373 5 : break;
3374 :
3375 : case 'n':
3376 0 : sTarget = "_blank";
3377 0 : bOptions = true;
3378 0 : break;
3379 :
3380 : case 'l':
3381 0 : bOptions = true;
3382 0 : if ( aReadParam.SkipToNextToken()==-2 )
3383 : {
3384 0 : sMark = aReadParam.GetResult();
3385 0 : if( sMark.endsWith("\""))
3386 : {
3387 0 : sMark = sMark.copy( 0, sMark.getLength() - 1 );
3388 : }
3389 : // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
3390 0 : if ( IsTOCBookmarkName( sMark ) )
3391 : {
3392 0 : OUString sTmp = IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix();
3393 0 : sTmp += sMark;
3394 0 : sMark = sTmp;
3395 : // track <sMark> as referenced TOC bookmark.
3396 0 : pReffedStck->aReferencedTOCBookmarks.insert( sMark );
3397 : }
3398 :
3399 0 : if (mbLoadingTOCCache)
3400 : {
3401 0 : mbLoadingTOCHyperlink = true;//on loading a TOC field nested hyperlink field
3402 : }
3403 : }
3404 0 : break;
3405 : case 't':
3406 0 : bOptions = true;
3407 0 : if ( aReadParam.SkipToNextToken()==-2 )
3408 0 : sTarget = aReadParam.GetResult();
3409 0 : break;
3410 : case 'h':
3411 : case 'm':
3412 : OSL_ENSURE( !this, "Auswertung fehlt noch - Daten unbekannt" );
3413 : //fall-through
3414 : case 's': //worthless fake anchor option
3415 0 : bOptions = true;
3416 0 : break;
3417 : }
3418 5 : }
3419 : }
3420 :
3421 : // das Resultat uebernehmen
3422 : OSL_ENSURE(!sURL.isEmpty() || !sMark.isEmpty(), "WW8: Empty URL");
3423 :
3424 6 : if( !sMark.isEmpty() )
3425 0 : ( sURL += "#" ) += sMark;
3426 :
3427 6 : SwFmtINetFmt aURL( sURL, sTarget );
3428 : // If on loading TOC field, change the default style into the "index link"
3429 6 : if (mbLoadingTOCCache)
3430 : {
3431 0 : OUString sLinkStyle("Index Link");
3432 : sal_uInt16 nPoolId =
3433 0 : SwStyleNameMapper::GetPoolIdFromUIName( sLinkStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
3434 0 : aURL.SetVisitedFmtAndId( sLinkStyle, nPoolId );
3435 0 : aURL.SetINetFmtAndId( sLinkStyle, nPoolId );
3436 : }
3437 :
3438 : //As an attribute this needs to be closed, and that'll happen from
3439 : //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms
3440 : //between the start and begin, their hyperlinks will be set at that time
3441 : //as well.
3442 6 : pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL );
3443 12 : return FLD_TEXT;
3444 : }
3445 :
3446 0 : static void lcl_ImportTox(SwDoc &rDoc, SwPaM &rPaM, const OUString &rStr, bool bIdx)
3447 : {
3448 0 : TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX; // Default
3449 :
3450 0 : sal_uInt16 nLevel = 1;
3451 :
3452 0 : OUString sFldTxt;
3453 0 : WW8ReadFieldParams aReadParam(rStr);
3454 : for (;;)
3455 : {
3456 0 : const sal_Int32 nRet = aReadParam.SkipToNextToken();
3457 0 : if ( nRet==-1 )
3458 0 : break;
3459 0 : switch( nRet )
3460 : {
3461 : case -2:
3462 0 : if( sFldTxt.isEmpty() )
3463 : {
3464 : // PrimaryKey ohne ":", 2nd dahinter
3465 0 : sFldTxt = aReadParam.GetResult();
3466 : }
3467 0 : break;
3468 :
3469 : case 'f':
3470 0 : if ( aReadParam.GoToTokenParam() )
3471 : {
3472 0 : const OUString sParams( aReadParam.GetResult() );
3473 0 : if( sParams[0]!='C' && sParams[0]!='c' )
3474 0 : eTox = TOX_USER;
3475 : }
3476 0 : break;
3477 :
3478 : case 'l':
3479 0 : if ( aReadParam.GoToTokenParam() )
3480 : {
3481 0 : const OUString sParams( aReadParam.GetResult() );
3482 : // if NO String just ignore the \l
3483 0 : if( !sParams.isEmpty() && sParams[0]>'0' && sParams[0]<='9' )
3484 : {
3485 0 : nLevel = (sal_uInt16)sParams.toInt32();
3486 0 : }
3487 : }
3488 0 : break;
3489 : }
3490 0 : }
3491 :
3492 : OSL_ENSURE( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0 :-(" );
3493 :
3494 0 : const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
3495 0 : SwTOXMark aM( pT );
3496 :
3497 0 : if( eTox != TOX_INDEX )
3498 0 : aM.SetLevel( nLevel );
3499 : else
3500 : {
3501 0 : sal_Int32 nFnd = sFldTxt.indexOf( WW8_TOX_LEVEL_DELIM );
3502 0 : if( -1 != nFnd ) // it exist levels
3503 : {
3504 0 : aM.SetPrimaryKey( sFldTxt.copy( 0, nFnd ) );
3505 0 : sal_Int32 nScndFnd = sFldTxt.indexOf( WW8_TOX_LEVEL_DELIM, nFnd+1 );
3506 0 : if( -1 != nScndFnd )
3507 : {
3508 0 : aM.SetSecondaryKey( sFldTxt.copy( nFnd+1, nScndFnd - nFnd - 1 ));
3509 0 : nFnd = nScndFnd;
3510 : }
3511 0 : sFldTxt = sFldTxt.copy( nFnd+1 );
3512 : }
3513 : }
3514 :
3515 0 : if (!sFldTxt.isEmpty())
3516 : {
3517 0 : aM.SetAlternativeText( sFldTxt );
3518 0 : rDoc.InsertPoolItem( rPaM, aM, 0 );
3519 0 : }
3520 0 : }
3521 :
3522 0 : void sw::ms::ImportXE(SwDoc &rDoc, SwPaM &rPaM, const OUString &rStr)
3523 : {
3524 0 : lcl_ImportTox(rDoc, rPaM, rStr, true);
3525 0 : }
3526 :
3527 0 : void SwWW8ImplReader::ImportTox( int nFldId, const OUString& aStr )
3528 : {
3529 0 : bool bIdx = (nFldId != 9);
3530 0 : lcl_ImportTox(rDoc, *pPaM, aStr, bIdx);
3531 0 : }
3532 :
3533 16 : void SwWW8ImplReader::Read_FldVanish( sal_uInt16, const sal_uInt8*, short nLen )
3534 : {
3535 : //Meaningless in a style
3536 16 : if (pAktColl || !pPlcxMan)
3537 16 : return;
3538 :
3539 16 : const int nChunk = 64; //number of characters to read at one time
3540 :
3541 : // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
3542 : const static sal_Char *aFldNames[] = { "\x06""INHALT", "\x02""XE", // dt.
3543 : "\x02""TC" }; // us
3544 : const static sal_uInt8 aFldId[] = { 9, 4, 9 };
3545 :
3546 16 : if( nLen < 0 )
3547 : {
3548 8 : bIgnoreText = false;
3549 8 : return;
3550 : }
3551 :
3552 : // our methode was called from
3553 : // ''Skip attributes of field contents'' loop within ReadTextAttr()
3554 8 : if( bIgnoreText )
3555 7 : return;
3556 :
3557 1 : bIgnoreText = true;
3558 1 : long nOldPos = pStrm->Tell();
3559 :
3560 1 : WW8_CP nStartCp = pPlcxMan->Where() + pPlcxMan->GetCpOfs();
3561 :
3562 1 : OUString sFieldName;
3563 : sal_Int32 nFieldLen = pSBase->WW8ReadString( *pStrm, sFieldName, nStartCp,
3564 1 : nChunk, eStructCharSet );
3565 1 : nStartCp+=nFieldLen;
3566 :
3567 1 : sal_Int32 nC = 0;
3568 : //If the first chunk did not start with a field start then
3569 : //reset the stream position and give up
3570 1 : if( !nFieldLen || sFieldName[nC]!=0x13 ) // Field Start Mark
3571 : {
3572 : // If Field End Mark found
3573 1 : if( nFieldLen && sFieldName[nC]==0x15 )
3574 0 : bIgnoreText = false;
3575 1 : pStrm->Seek( nOldPos );
3576 1 : return; // kein Feld zu finden
3577 : }
3578 :
3579 : sal_Int32 nFnd;
3580 : //If this chunk does not contain a field end, keep reading chunks
3581 : //until we find one, or we run out of text,
3582 : for (;;)
3583 : {
3584 0 : nFnd = sFieldName.indexOf(0x15);
3585 : //found field end, we can stop now
3586 0 : if (nFnd != -1)
3587 0 : break;
3588 0 : OUString sTemp;
3589 : nFieldLen = pSBase->WW8ReadString( *pStrm, sTemp,
3590 0 : nStartCp, nChunk, eStructCharSet );
3591 0 : sFieldName+=sTemp;
3592 0 : nStartCp+=nFieldLen;
3593 0 : if (!nFieldLen)
3594 0 : break;
3595 0 : }
3596 :
3597 0 : pStrm->Seek( nOldPos );
3598 :
3599 : //if we have no 0x15 give up, otherwise erase everything from the 0x15
3600 : //onwards
3601 0 : if (nFnd<0)
3602 0 : return;
3603 :
3604 0 : sFieldName = sFieldName.copy(0, nFnd);
3605 :
3606 0 : nC++;
3607 0 : while ( sFieldName[nC]==' ' )
3608 0 : nC++;
3609 :
3610 0 : for( int i = 0; i < 3; i++ )
3611 : {
3612 0 : const sal_Char* pName = aFldNames[i];
3613 0 : const sal_Int32 nNameLen = static_cast<sal_Int32>(*pName++);
3614 0 : if( sFieldName.matchIgnoreAsciiCaseAsciiL( pName, nNameLen, nC ) )
3615 : {
3616 0 : ImportTox( aFldId[i], sFieldName.copy( nC + nNameLen ) );
3617 0 : break; // keine Mehrfachnennungen moeglich
3618 : }
3619 : }
3620 0 : bIgnoreText = true;
3621 0 : pStrm->Seek( nOldPos );
3622 33 : }
3623 :
3624 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|