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