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