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