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_sc.hxx"
26 #include "xihelper.hxx"
27 #include <svl/itemset.hxx>
28 #include <editeng/editobj.hxx>
29 #include <tools/urlobj.hxx>
30 #include "scitems.hxx"
31 #include <editeng/eeitem.hxx>
32 #include <editeng/flditem.hxx>
33 #include "document.hxx"
34 #include "cell.hxx"
35 #include "rangelst.hxx"
36 #include "editutil.hxx"
37 #include "attrib.hxx"
38 #include "xltracer.hxx"
39 #include "xistream.hxx"
40 #include "xistyle.hxx"
41
42 #include "excform.hxx"
43
44 // Excel->Calc cell address/range conversion ==================================
45
46 namespace {
47
48 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
lclFillAddress(ScAddress & rScPos,sal_uInt16 nXclCol,sal_uInt16 nXclRow,SCTAB nScTab)49 inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt16 nXclRow, SCTAB nScTab )
50 {
51 rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
52 rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
53 rScPos.SetTab( nScTab );
54 }
55
56 } // namespace
57
58 // ----------------------------------------------------------------------------
59
XclImpAddressConverter(const XclImpRoot & rRoot)60 XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) :
61 XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() )
62 {
63 }
64
65 // cell address ---------------------------------------------------------------
66
CheckAddress(const XclAddress & rXclPos,bool bWarn)67 bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn )
68 {
69 bool bValidCol = rXclPos.mnCol <= mnMaxCol;
70 bool bValidRow = rXclPos.mnRow <= mnMaxRow;
71 bool bValid = bValidCol && bValidRow;
72 if( !bValid && bWarn )
73 {
74 mbColTrunc |= !bValidCol;
75 mbRowTrunc |= !bValidRow;
76 mrTracer.TraceInvalidAddress( ScAddress(
77 static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos );
78 }
79 return bValid;
80 }
81
ConvertAddress(ScAddress & rScPos,const XclAddress & rXclPos,SCTAB nScTab,bool bWarn)82 bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
83 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
84 {
85 bool bValid = CheckAddress( rXclPos, bWarn );
86 if( bValid )
87 lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
88 return bValid;
89 }
90
CreateValidAddress(const XclAddress & rXclPos,SCTAB nScTab,bool bWarn)91 ScAddress XclImpAddressConverter::CreateValidAddress(
92 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
93 {
94 ScAddress aScPos( ScAddress::UNINITIALIZED );
95 if( !ConvertAddress( aScPos, rXclPos, nScTab, bWarn ) )
96 {
97 aScPos.SetCol( static_cast< SCCOL >( ::std::min( rXclPos.mnCol, mnMaxCol ) ) );
98 aScPos.SetRow( static_cast< SCROW >( ::std::min( rXclPos.mnRow, mnMaxRow ) ) );
99 aScPos.SetTab( limit_cast< SCTAB >( nScTab, 0, maMaxPos.Tab() ) );
100 }
101 return aScPos;
102 }
103
104 // cell range -----------------------------------------------------------------
105
CheckRange(const XclRange & rXclRange,bool bWarn)106 bool XclImpAddressConverter::CheckRange( const XclRange& rXclRange, bool bWarn )
107 {
108 return CheckAddress( rXclRange.maFirst, bWarn ) && CheckAddress( rXclRange.maLast, bWarn );
109 }
110
ConvertRange(ScRange & rScRange,const XclRange & rXclRange,SCTAB nScTab1,SCTAB nScTab2,bool bWarn)111 bool XclImpAddressConverter::ConvertRange( ScRange& rScRange,
112 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
113 {
114 // check start position
115 bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn );
116 if( bValidStart )
117 {
118 lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 );
119
120 // check & correct end position
121 sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol;
122 sal_uInt16 nXclRow2 = rXclRange.maLast.mnRow;
123 if( !CheckAddress( rXclRange.maLast, bWarn ) )
124 {
125 nXclCol2 = ::std::min( nXclCol2, mnMaxCol );
126 nXclRow2 = ::std::min( nXclRow2, mnMaxRow );
127 }
128 lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 );
129 }
130 return bValidStart;
131 }
132
133 //UNUSED2009-05 ScRange XclImpAddressConverter::CreateValidRange(
134 //UNUSED2009-05 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
135 //UNUSED2009-05 {
136 //UNUSED2009-05 return ScRange(
137 //UNUSED2009-05 CreateValidAddress( rXclRange.maFirst, nScTab1, bWarn ),
138 //UNUSED2009-05 CreateValidAddress( rXclRange.maLast, nScTab2, bWarn ) );
139 //UNUSED2009-05 }
140
141 // cell range list ------------------------------------------------------------
142
143 //UNUSED2009-05 bool XclImpAddressConverter::CheckRangeList( const XclRangeList& rXclRanges, bool bWarn )
144 //UNUSED2009-05 {
145 //UNUSED2009-05 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
146 //UNUSED2009-05 if( !CheckRange( *aIt, bWarn ) )
147 //UNUSED2009-05 return false;
148 //UNUSED2009-05 return true;
149 //UNUSED2009-05 }
150
ConvertRangeList(ScRangeList & rScRanges,const XclRangeList & rXclRanges,SCTAB nScTab,bool bWarn)151 void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges,
152 const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn )
153 {
154 rScRanges.RemoveAll();
155 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
156 {
157 ScRange aScRange( ScAddress::UNINITIALIZED );
158 if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) )
159 rScRanges.Append( aScRange );
160 }
161 }
162
163 // String->EditEngine conversion ==============================================
164
165 namespace {
166
lclCreateTextObject(const XclImpRoot & rRoot,const XclImpString & rString,XclFontItemType eType,sal_uInt16 nXFIndex)167 EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot,
168 const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex )
169 {
170 EditTextObject* pTextObj = 0;
171
172 const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer();
173 const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex );
174 bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement();
175
176 if( rString.IsRich() || bFirstEscaped )
177 {
178 const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
179 const XclFormatRunVec& rFormats = rString.GetFormats();
180
181 ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ?
182 static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine();
183 rEE.SetText( rString.GetText() );
184
185 SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
186 if( bFirstEscaped )
187 rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) );
188 ESelection aSelection;
189
190 XclFormatRun aNextRun;
191 XclFormatRunVec::const_iterator aIt = rFormats.begin();
192 XclFormatRunVec::const_iterator aEnd = rFormats.end();
193
194 if( aIt != aEnd )
195 aNextRun = *aIt++;
196 else
197 aNextRun.mnChar = 0xFFFF;
198
199 xub_StrLen nLen = rString.GetText().Len();
200 for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar )
201 {
202 // reached new different formatted text portion
203 if( nChar >= aNextRun.mnChar )
204 {
205 // send items to edit engine
206 rEE.QuickSetAttribs( aItemSet, aSelection );
207
208 // start new item set
209 aItemSet.ClearItem();
210 rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx );
211
212 // read new formatting information
213 if( aIt != aEnd )
214 aNextRun = *aIt++;
215 else
216 aNextRun.mnChar = 0xFFFF;
217
218 // reset selection start to current position
219 aSelection.nStartPara = aSelection.nEndPara;
220 aSelection.nStartPos = aSelection.nEndPos;
221 }
222
223 // set end of selection to current position
224 if( rString.GetText().GetChar( nChar ) == '\n' )
225 {
226 ++aSelection.nEndPara;
227 aSelection.nEndPos = 0;
228 }
229 else
230 ++aSelection.nEndPos;
231 }
232
233 // send items of last text portion to edit engine
234 rEE.QuickSetAttribs( aItemSet, aSelection );
235
236 pTextObj = rEE.CreateTextObject();
237 }
238
239 return pTextObj;
240 }
241
242 } // namespace
243
CreateTextObject(const XclImpRoot & rRoot,const XclImpString & rString)244 EditTextObject* XclImpStringHelper::CreateTextObject(
245 const XclImpRoot& rRoot, const XclImpString& rString )
246 {
247 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 );
248 }
249
250 //UNUSED2009-05 EditTextObject* XclImpStringHelper::CreateNoteObject(
251 //UNUSED2009-05 const XclImpRoot& rRoot, const XclImpString& rString )
252 //UNUSED2009-05 {
253 //UNUSED2009-05 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_NOTE, 0 );
254 //UNUSED2009-05 }
255
CreateCell(const XclImpRoot & rRoot,const XclImpString & rString,sal_uInt16 nXFIndex)256 ScBaseCell* XclImpStringHelper::CreateCell(
257 const XclImpRoot& rRoot, const XclImpString& rString, sal_uInt16 nXFIndex )
258 {
259 ScBaseCell* pCell = 0;
260
261 if( rString.GetText().Len() )
262 {
263 ::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
264 ScDocument& rDoc = rRoot.GetDoc();
265
266 if( pTextObj.get() )
267 // ScEditCell creates own copy of text object
268 pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
269 else
270 pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
271 }
272
273 return pCell;
274 }
275
276 // Header/footer conversion ===================================================
277
XclImpHFPortionInfo()278 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
279 mnHeight( 0 ),
280 mnMaxLineHt( 0 )
281 {
282 maSel.nStartPara = maSel.nEndPara = 0;
283 maSel.nStartPos = maSel.nEndPos = 0;
284 }
285
286 // ----------------------------------------------------------------------------
287
XclImpHFConverter(const XclImpRoot & rRoot)288 XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
289 XclImpRoot( rRoot ),
290 mrEE( rRoot.GetHFEditEngine() ),
291 mxFontData( new XclFontData ),
292 meCurrObj( EXC_HF_CENTER )
293 {
294 }
295
~XclImpHFConverter()296 XclImpHFConverter::~XclImpHFConverter()
297 {
298 }
299
ParseString(const String & rHFString)300 void XclImpHFConverter::ParseString( const String& rHFString )
301 {
302 // edit engine objects
303 mrEE.SetText( EMPTY_STRING );
304 maInfos.clear();
305 maInfos.resize( EXC_HF_PORTION_COUNT );
306 meCurrObj = EXC_HF_CENTER;
307
308 // parser temporaries
309 maCurrText.Erase();
310 String aReadFont; // current font name
311 String aReadStyle; // current font style
312 sal_uInt16 nReadHeight = 0; // current font height
313 ResetFontData();
314
315 /** State of the parser. */
316 enum XclHFParserState
317 {
318 xlPSText, /// Read text, search for functions.
319 xlPSFunc, /// Read function (token following a '&').
320 xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
321 xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"').
322 xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit).
323 } eState = xlPSText;
324
325 const sal_Unicode* pChar = rHFString.GetBuffer();
326 const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char
327 while( *pChar )
328 {
329 switch( eState )
330 {
331
332 // --- read text character ---
333
334 case xlPSText:
335 {
336 switch( *pChar )
337 {
338 case '&': // new command
339 InsertText();
340 eState = xlPSFunc;
341 break;
342 case '\n': // line break
343 InsertText();
344 InsertLineBreak();
345 break;
346 default:
347 maCurrText += *pChar;
348 }
349 }
350 break;
351
352 // --- read control sequence ---
353
354 case xlPSFunc:
355 {
356 eState = xlPSText;
357 switch( *pChar )
358 {
359 case '&': maCurrText += '&'; break; // the '&' character
360
361 case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
362 case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
363 case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
364
365 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
366 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
367 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
368 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
369 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name
370
371 case 'Z': // file path
372 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name
373 if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') )
374 {
375 // &Z&F found - ignore the &F part
376 pChar += 2;
377 }
378 break;
379 case 'F': // file name
380 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
381 break;
382
383 case 'U': // underline
384 SetAttribs();
385 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
386 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
387 break;
388 case 'E': // double underline
389 SetAttribs();
390 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
391 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
392 break;
393 case 'S': // strikeout
394 SetAttribs();
395 mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
396 break;
397 case 'X': // superscript
398 SetAttribs();
399 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
400 EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
401 break;
402 case 'Y': // subsrcipt
403 SetAttribs();
404 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
405 EXC_FONTESC_NONE : EXC_FONTESC_SUB;
406 break;
407
408 case '\"': // font name
409 aReadFont.Erase();
410 aReadStyle.Erase();
411 eState = xlPSFont;
412 break;
413 default:
414 if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
415 {
416 nReadHeight = *pChar - '0';
417 eState = xlPSHeight;
418 }
419 }
420 }
421 break;
422
423 // --- read font name ---
424
425 case xlPSFont:
426 {
427 switch( *pChar )
428 {
429 case '\"':
430 --pChar;
431 // run through
432 case ',':
433 eState = xlPSFontStyle;
434 break;
435 default:
436 aReadFont += *pChar;
437 }
438 }
439 break;
440
441 // --- read font style ---
442
443 case xlPSFontStyle:
444 {
445 switch( *pChar )
446 {
447 case '\"':
448 SetAttribs();
449 if( aReadFont.Len() )
450 mxFontData->maName = aReadFont;
451 mxFontData->maStyle = aReadStyle;
452 eState = xlPSText;
453 break;
454 default:
455 aReadStyle += *pChar;
456 }
457 }
458 break;
459
460 // --- read font height ---
461
462 case xlPSHeight:
463 {
464 if( ('0' <= *pChar) && (*pChar <= '9') )
465 {
466 if( nReadHeight != 0xFFFF )
467 {
468 nReadHeight *= 10;
469 nReadHeight += (*pChar - '0');
470 if( nReadHeight > 1600 ) // max 1600pt = 32000twips
471 nReadHeight = 0xFFFF;
472 }
473 }
474 else
475 {
476 if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
477 {
478 SetAttribs();
479 mxFontData->mnHeight = nReadHeight * 20;
480 }
481 --pChar;
482 eState = xlPSText;
483 }
484 }
485 break;
486 }
487 ++pChar;
488 }
489
490 // finalize
491 CreateCurrObject();
492 maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
493 maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
494 maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
495 }
496
FillToItemSet(SfxItemSet & rItemSet,sal_uInt16 nWhichId) const497 void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
498 {
499 ScPageHFItem aHFItem( nWhichId );
500 if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
501 aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
502 if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
503 aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
504 if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
505 aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
506 rItemSet.Put( aHFItem );
507 }
508
GetTotalHeight() const509 sal_Int32 XclImpHFConverter::GetTotalHeight() const
510 {
511 return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
512 ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
513 }
514
515 // private --------------------------------------------------------------------
516
GetMaxLineHeight(XclImpHFPortion ePortion) const517 sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
518 {
519 sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
520 return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
521 }
522
GetCurrMaxLineHeight() const523 sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
524 {
525 return GetMaxLineHeight( meCurrObj );
526 }
527
UpdateMaxLineHeight(XclImpHFPortion ePortion)528 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
529 {
530 sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
531 rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
532 }
533
UpdateCurrMaxLineHeight()534 void XclImpHFConverter::UpdateCurrMaxLineHeight()
535 {
536 UpdateMaxLineHeight( meCurrObj );
537 }
538
SetAttribs()539 void XclImpHFConverter::SetAttribs()
540 {
541 ESelection& rSel = GetCurrSel();
542 if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
543 {
544 SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
545 XclImpFont aFont( GetRoot(), *mxFontData );
546 aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
547 mrEE.QuickSetAttribs( aItemSet, rSel );
548 rSel.nStartPara = rSel.nEndPara;
549 rSel.nStartPos = rSel.nEndPos;
550 }
551 }
552
ResetFontData()553 void XclImpHFConverter::ResetFontData()
554 {
555 if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
556 *mxFontData = pFirstFont->GetFontData();
557 else
558 {
559 mxFontData->Clear();
560 mxFontData->mnHeight = 200;
561 }
562 }
563
InsertText()564 void XclImpHFConverter::InsertText()
565 {
566 if( maCurrText.Len() )
567 {
568 ESelection& rSel = GetCurrSel();
569 mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
570 rSel.nEndPos = rSel.nEndPos + maCurrText.Len();
571 maCurrText.Erase();
572 UpdateCurrMaxLineHeight();
573 }
574 }
575
InsertField(const SvxFieldItem & rFieldItem)576 void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
577 {
578 ESelection& rSel = GetCurrSel();
579 mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
580 ++rSel.nEndPos;
581 UpdateCurrMaxLineHeight();
582 }
583
InsertLineBreak()584 void XclImpHFConverter::InsertLineBreak()
585 {
586 ESelection& rSel = GetCurrSel();
587 mrEE.QuickInsertText( String( '\n' ), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
588 ++rSel.nEndPara;
589 rSel.nEndPos = 0;
590 GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
591 GetCurrInfo().mnMaxLineHt = 0;
592 }
593
CreateCurrObject()594 void XclImpHFConverter::CreateCurrObject()
595 {
596 InsertText();
597 SetAttribs();
598 GetCurrObj().reset( mrEE.CreateTextObject() );
599 }
600
SetNewPortion(XclImpHFPortion eNew)601 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
602 {
603 if( eNew != meCurrObj )
604 {
605 CreateCurrObject();
606 meCurrObj = eNew;
607 if( GetCurrObj().get() )
608 mrEE.SetText( *GetCurrObj() );
609 else
610 mrEE.SetText( EMPTY_STRING );
611 ResetFontData();
612 }
613 }
614
615 // URL conversion =============================================================
616
617 namespace {
618
lclAppendUrlChar(String & rUrl,sal_Unicode cChar)619 void lclAppendUrlChar( String& rUrl, sal_Unicode cChar )
620 {
621 // #126855# encode special characters
622 switch( cChar )
623 {
624 case '#': rUrl.AppendAscii( "%23" ); break;
625 case '%': rUrl.AppendAscii( "%25" ); break;
626 default: rUrl.Append( cChar );
627 }
628 }
629
630 } // namespace
631
DecodeUrl(String & rUrl,String & rTabName,bool & rbSameWb,const XclImpRoot & rRoot,const String & rEncodedUrl)632 void XclImpUrlHelper::DecodeUrl(
633 String& rUrl, String& rTabName, bool& rbSameWb,
634 const XclImpRoot& rRoot, const String& rEncodedUrl )
635 {
636 enum
637 {
638 xlUrlInit, /// Initial state, read string mode character.
639 xlUrlPath, /// Read URL path.
640 xlUrlFileName, /// Read file name.
641 xlUrlSheetName, /// Read sheet name.
642 xlUrlRaw /// Raw mode. No control characters will occur.
643 } eState = xlUrlInit;
644
645 bool bEncoded = true;
646 rbSameWb = false;
647
648 sal_Unicode cCurrDrive = 0;
649 String aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
650 if( (aDosBase.Len() > 2) && aDosBase.EqualsAscii( ":\\", 1, 2 ) )
651 cCurrDrive = aDosBase.GetChar( 0 );
652
653 const sal_Unicode* pChar = rEncodedUrl.GetBuffer();
654 while( *pChar )
655 {
656 switch( eState )
657 {
658
659 // --- first character ---
660
661 case xlUrlInit:
662 {
663 switch( *pChar )
664 {
665 case EXC_URLSTART_ENCODED:
666 eState = xlUrlPath;
667 break;
668 case EXC_URLSTART_SELF:
669 case EXC_URLSTART_SELFENCODED:
670 rbSameWb = true;
671 eState = xlUrlSheetName;
672 break;
673 case '[':
674 bEncoded = false;
675 eState = xlUrlFileName;
676 break;
677 default:
678 bEncoded = false;
679 lclAppendUrlChar( rUrl, *pChar );
680 eState = xlUrlPath;
681 }
682 }
683 break;
684
685 // --- URL path ---
686
687 case xlUrlPath:
688 {
689 switch( *pChar )
690 {
691 case EXC_URL_DOSDRIVE:
692 {
693 if( *(pChar + 1) )
694 {
695 ++pChar;
696 if( *pChar == '@' )
697 rUrl.AppendAscii( "\\\\" );
698 else
699 {
700 lclAppendUrlChar( rUrl, *pChar );
701 rUrl.AppendAscii( ":\\" );
702 }
703 }
704 else
705 rUrl.AppendAscii( "<NULL-DRIVE!>" );
706 }
707 break;
708 case EXC_URL_DRIVEROOT:
709 if( cCurrDrive )
710 {
711 lclAppendUrlChar( rUrl, cCurrDrive );
712 rUrl.Append( ':' );
713 }
714 // run through
715 case EXC_URL_SUBDIR:
716 if( bEncoded )
717 rUrl.Append( '\\' );
718 else // control character in raw name -> DDE link
719 {
720 rUrl.Append( EXC_DDE_DELIM );
721 eState = xlUrlRaw;
722 }
723 break;
724 case EXC_URL_PARENTDIR:
725 rUrl.AppendAscii( "..\\" );
726 break;
727 case EXC_URL_RAW:
728 {
729 if( *(pChar + 1) )
730 {
731 xub_StrLen nLen = *++pChar;
732 for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
733 lclAppendUrlChar( rUrl, *++pChar );
734 // rUrl.Append( ':' );
735 }
736 }
737 break;
738 case '[':
739 eState = xlUrlFileName;
740 break;
741 default:
742 lclAppendUrlChar( rUrl, *pChar );
743 }
744 }
745 break;
746
747 // --- file name ---
748
749 case xlUrlFileName:
750 {
751 switch( *pChar )
752 {
753 case ']': eState = xlUrlSheetName; break;
754 default: lclAppendUrlChar( rUrl, *pChar );
755 }
756 }
757 break;
758
759 // --- sheet name ---
760
761 case xlUrlSheetName:
762 rTabName.Append( *pChar );
763 break;
764
765 // --- raw read mode ---
766
767 case xlUrlRaw:
768 lclAppendUrlChar( rUrl, *pChar );
769 break;
770 }
771
772 ++pChar;
773 }
774 }
775
DecodeUrl(String & rUrl,bool & rbSameWb,const XclImpRoot & rRoot,const String & rEncodedUrl)776 void XclImpUrlHelper::DecodeUrl(
777 String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl )
778 {
779 String aTabName;
780 DecodeUrl( rUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
781 DBG_ASSERT( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
782 }
783
DecodeLink(String & rApplic,String & rTopic,const String rEncUrl)784 bool XclImpUrlHelper::DecodeLink( String& rApplic, String& rTopic, const String rEncUrl )
785 {
786 xub_StrLen nPos = rEncUrl.Search( EXC_DDE_DELIM );
787 if( (nPos != STRING_NOTFOUND) && (0 < nPos) && (nPos + 1 < rEncUrl.Len()) )
788 {
789 rApplic = rEncUrl.Copy( 0, nPos );
790 rTopic = rEncUrl.Copy( nPos + 1 );
791 return true;
792 }
793 return false;
794 }
795
796 // Cached Values ==============================================================
797
XclImpCachedValue(XclImpStream & rStrm)798 XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
799 mfValue( 0.0 ),
800 mnBoolErr( 0 )
801 {
802 rStrm >> mnType;
803 switch( mnType )
804 {
805 case EXC_CACHEDVAL_EMPTY:
806 rStrm.Ignore( 8 );
807 break;
808 case EXC_CACHEDVAL_DOUBLE:
809 rStrm >> mfValue;
810 break;
811 case EXC_CACHEDVAL_STRING:
812 mxStr.reset( new String( rStrm.ReadUniString() ) );
813 break;
814 case EXC_CACHEDVAL_BOOL:
815 case EXC_CACHEDVAL_ERROR:
816 {
817 double fVal;
818 rStrm >> mnBoolErr;
819 rStrm.Ignore( 7 );
820
821 const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
822 XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
823 if( pScTokArr )
824 mxTokArr.reset( pScTokArr->Clone() );
825 }
826 break;
827 default:
828 DBG_ERRORFILE( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
829 }
830 }
831
~XclImpCachedValue()832 XclImpCachedValue::~XclImpCachedValue()
833 {
834 }
835
GetScError() const836 sal_uInt16 XclImpCachedValue::GetScError() const
837 {
838 return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
839 }
840
841 // Matrix Cached Values ==============================================================
842
XclImpCachedMatrix(XclImpStream & rStrm)843 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
844 mnScCols( 0 ),
845 mnScRows( 0 )
846 {
847 mnScCols = rStrm.ReaduInt8();
848 mnScRows = rStrm.ReaduInt16();
849
850 if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
851 {
852 // in BIFF2-BIFF7: 256 columns represented by 0 columns
853 if( mnScCols == 0 )
854 mnScCols = 256;
855 }
856 else
857 {
858 // in BIFF8: columns and rows decreaed by 1
859 ++mnScCols;
860 ++mnScRows;
861 }
862
863 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
864 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
865 maValueList.Append( new XclImpCachedValue( rStrm ) );
866 }
867
~XclImpCachedMatrix()868 XclImpCachedMatrix::~XclImpCachedMatrix()
869 {
870 }
871
CreateScMatrix() const872 ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
873 {
874 ScMatrixRef xScMatrix;
875 DBG_ASSERT( mnScCols * mnScRows == maValueList.Count(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
876 if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.Count() )
877 {
878 xScMatrix = new ScMatrix( mnScCols, mnScRows );
879 const XclImpCachedValue* pValue = maValueList.First();
880 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
881 {
882 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
883 {
884 switch( pValue->GetType() )
885 {
886 case EXC_CACHEDVAL_EMPTY:
887 // Excel shows 0.0 here, not an empty cell
888 xScMatrix->PutEmpty( nScCol, nScRow );
889 break;
890 case EXC_CACHEDVAL_DOUBLE:
891 xScMatrix->PutDouble( pValue->GetValue(), nScCol, nScRow );
892 break;
893 case EXC_CACHEDVAL_STRING:
894 xScMatrix->PutString( pValue->GetString(), nScCol, nScRow );
895 break;
896 case EXC_CACHEDVAL_BOOL:
897 xScMatrix->PutBoolean( pValue->GetBool(), nScCol, nScRow );
898 break;
899 case EXC_CACHEDVAL_ERROR:
900 xScMatrix->PutError( pValue->GetScError(), nScCol, nScRow );
901 break;
902 default:
903 DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
904 xScMatrix->PutEmpty( nScCol, nScRow );
905 }
906 pValue = maValueList.Next();
907 }
908 }
909 }
910 return xScMatrix;
911 }
912
913 // ============================================================================
914
915