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