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 0 : inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt32 nXclRow, SCTAB nScTab )
46 : {
47 0 : rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
48 0 : rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
49 0 : rScPos.SetTab( nScTab );
50 0 : }
51 :
52 : } // namespace
53 :
54 0 : XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) :
55 0 : XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() )
56 : {
57 0 : }
58 :
59 : // cell address ---------------------------------------------------------------
60 :
61 0 : bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn )
62 : {
63 0 : bool bValidCol = rXclPos.mnCol <= mnMaxCol;
64 0 : bool bValidRow = rXclPos.mnRow <= mnMaxRow;
65 0 : bool bValid = bValidCol && bValidRow;
66 0 : if( !bValid && bWarn )
67 : {
68 0 : mbColTrunc |= !bValidCol;
69 0 : mbRowTrunc |= !bValidRow;
70 : mrTracer.TraceInvalidAddress( ScAddress(
71 0 : static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos );
72 : }
73 0 : return bValid;
74 : }
75 :
76 0 : bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
77 : const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
78 : {
79 0 : bool bValid = CheckAddress( rXclPos, bWarn );
80 0 : if( bValid )
81 0 : lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
82 0 : return bValid;
83 : }
84 :
85 0 : ScAddress XclImpAddressConverter::CreateValidAddress(
86 : const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
87 : {
88 0 : ScAddress aScPos( ScAddress::UNINITIALIZED );
89 0 : 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 0 : return aScPos;
96 : }
97 :
98 : // cell range -----------------------------------------------------------------
99 :
100 0 : bool XclImpAddressConverter::ConvertRange( ScRange& rScRange,
101 : const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
102 : {
103 : // check start position
104 0 : bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn );
105 0 : if( bValidStart )
106 : {
107 0 : lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 );
108 :
109 : // check & correct end position
110 0 : sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol;
111 0 : sal_uInt32 nXclRow2 = rXclRange.maLast.mnRow;
112 0 : if( !CheckAddress( rXclRange.maLast, bWarn ) )
113 : {
114 0 : nXclCol2 = ::std::min( nXclCol2, mnMaxCol );
115 0 : nXclRow2 = ::std::min( nXclRow2, mnMaxRow );
116 : }
117 0 : lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 );
118 : }
119 0 : return bValidStart;
120 : }
121 :
122 : // cell range list ------------------------------------------------------------
123 :
124 0 : void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges,
125 : const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn )
126 : {
127 0 : rScRanges.RemoveAll();
128 0 : for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
129 : {
130 0 : ScRange aScRange( ScAddress::UNINITIALIZED );
131 0 : if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) )
132 0 : rScRanges.Append( aScRange );
133 : }
134 0 : }
135 :
136 : // String->EditEngine conversion ==============================================
137 :
138 : namespace {
139 :
140 0 : EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot,
141 : const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex )
142 : {
143 0 : EditTextObject* pTextObj = 0;
144 :
145 0 : const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer();
146 0 : const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex );
147 0 : bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement();
148 :
149 0 : if( rString.IsRich() || bFirstEscaped )
150 : {
151 0 : const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
152 0 : const XclFormatRunVec& rFormats = rString.GetFormats();
153 :
154 : ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ?
155 0 : static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine();
156 0 : rEE.SetText( rString.GetText() );
157 :
158 0 : SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
159 0 : if( bFirstEscaped )
160 0 : rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) );
161 0 : ESelection aSelection;
162 :
163 0 : XclFormatRun aNextRun;
164 0 : XclFormatRunVec::const_iterator aIt = rFormats.begin();
165 0 : XclFormatRunVec::const_iterator aEnd = rFormats.end();
166 :
167 0 : if( aIt != aEnd )
168 0 : aNextRun = *aIt++;
169 : else
170 0 : aNextRun.mnChar = 0xFFFF;
171 :
172 0 : sal_Int32 nLen = rString.GetText().getLength();
173 0 : for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar )
174 : {
175 : // reached new different formatted text portion
176 0 : if( nChar >= aNextRun.mnChar )
177 : {
178 : // send items to edit engine
179 0 : rEE.QuickSetAttribs( aItemSet, aSelection );
180 :
181 : // start new item set
182 0 : aItemSet.ClearItem();
183 0 : rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx );
184 :
185 : // read new formatting information
186 0 : if( aIt != aEnd )
187 0 : aNextRun = *aIt++;
188 : else
189 0 : aNextRun.mnChar = 0xFFFF;
190 :
191 : // reset selection start to current position
192 0 : aSelection.nStartPara = aSelection.nEndPara;
193 0 : aSelection.nStartPos = aSelection.nEndPos;
194 : }
195 :
196 : // set end of selection to current position
197 0 : if( rString.GetText()[ nChar ] == '\n' )
198 : {
199 0 : ++aSelection.nEndPara;
200 0 : aSelection.nEndPos = 0;
201 : }
202 : else
203 0 : ++aSelection.nEndPos;
204 : }
205 :
206 : // send items of last text portion to edit engine
207 0 : rEE.QuickSetAttribs( aItemSet, aSelection );
208 :
209 0 : pTextObj = rEE.CreateTextObject();
210 : }
211 :
212 0 : return pTextObj;
213 : }
214 :
215 : } // namespace
216 :
217 0 : EditTextObject* XclImpStringHelper::CreateTextObject(
218 : const XclImpRoot& rRoot, const XclImpString& rString )
219 : {
220 0 : return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 );
221 : }
222 :
223 0 : void XclImpStringHelper::SetToDocument(
224 : ScDocumentImport& rDoc, const ScAddress& rPos, const XclImpRoot& rRoot,
225 : const XclImpString& rString, sal_uInt16 nXFIndex )
226 : {
227 0 : if (rString.GetText().isEmpty())
228 0 : return;
229 :
230 0 : ::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
231 :
232 0 : if (pTextObj.get())
233 : {
234 0 : rDoc.setEditCell(rPos, pTextObj.release());
235 : }
236 : else
237 : {
238 0 : OUString aStr = rString.GetText();
239 0 : if (aStr.indexOf('\n') != -1 || aStr.indexOf(CHAR_CR) != -1)
240 : {
241 : // Multiline content.
242 0 : ScFieldEditEngine& rEngine = rDoc.getDoc().GetEditEngine();
243 0 : rEngine.SetText(aStr);
244 0 : rDoc.setEditCell(rPos, rEngine.CreateTextObject());
245 : }
246 : else
247 : {
248 : // Normal text cell.
249 0 : rDoc.setStringCell(rPos, aStr);
250 0 : }
251 0 : }
252 : }
253 :
254 : // Header/footer conversion ===================================================
255 :
256 0 : XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
257 : mnHeight( 0 ),
258 0 : mnMaxLineHt( 0 )
259 : {
260 0 : maSel.nStartPara = maSel.nEndPara = 0;
261 0 : maSel.nStartPos = maSel.nEndPos = 0;
262 0 : }
263 :
264 0 : XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
265 : XclImpRoot( rRoot ),
266 0 : mrEE( rRoot.GetHFEditEngine() ),
267 0 : mxFontData( new XclFontData ),
268 0 : meCurrObj( EXC_HF_CENTER )
269 : {
270 0 : }
271 :
272 0 : XclImpHFConverter::~XclImpHFConverter()
273 : {
274 0 : }
275 :
276 0 : void XclImpHFConverter::ParseString( const OUString& rHFString )
277 : {
278 : // edit engine objects
279 0 : mrEE.SetText( EMPTY_OUSTRING );
280 0 : maInfos.clear();
281 0 : maInfos.resize( EXC_HF_PORTION_COUNT );
282 0 : meCurrObj = EXC_HF_CENTER;
283 :
284 : // parser temporaries
285 0 : maCurrText = "";
286 0 : OUString aReadFont; // current font name
287 0 : OUString aReadStyle; // current font style
288 0 : sal_uInt16 nReadHeight = 0; // current font height
289 0 : 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 0 : } eState = xlPSText;
300 :
301 0 : const sal_Unicode* pChar = rHFString.getStr();
302 0 : const sal_Unicode* pNull = pChar + rHFString.getLength(); // pointer to teminating null char
303 0 : while( *pChar )
304 : {
305 0 : switch( eState )
306 : {
307 :
308 : // --- read text character ---
309 :
310 : case xlPSText:
311 : {
312 0 : switch( *pChar )
313 : {
314 : case '&': // new command
315 0 : InsertText();
316 0 : eState = xlPSFunc;
317 0 : break;
318 : case '\n': // line break
319 0 : InsertText();
320 0 : InsertLineBreak();
321 0 : break;
322 : default:
323 0 : maCurrText += OUString(*pChar);
324 : }
325 : }
326 0 : break;
327 :
328 : // --- read control sequence ---
329 :
330 : case xlPSFunc:
331 : {
332 0 : eState = xlPSText;
333 0 : switch( *pChar )
334 : {
335 0 : case '&': maCurrText += "&"; break; // the '&' character
336 :
337 0 : case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
338 0 : case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
339 0 : case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
340 :
341 0 : case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
342 0 : case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
343 0 : case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
344 0 : case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
345 0 : 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 0 : InsertField( SvxFieldItem( SvxExtFileField( EMPTY_OUSTRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
357 0 : 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 0 : aReadFont = "";
386 0 : aReadStyle = "";
387 0 : eState = xlPSFont;
388 0 : break;
389 : default:
390 0 : if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
391 : {
392 0 : nReadHeight = *pChar - '0';
393 0 : eState = xlPSHeight;
394 : }
395 : }
396 : }
397 0 : break;
398 :
399 : // --- read font name ---
400 :
401 : case xlPSFont:
402 : {
403 0 : switch( *pChar )
404 : {
405 : case '\"':
406 0 : --pChar;
407 : // run through
408 : case ',':
409 0 : eState = xlPSFontStyle;
410 0 : break;
411 : default:
412 0 : aReadFont += OUString(*pChar);
413 : }
414 : }
415 0 : break;
416 :
417 : // --- read font style ---
418 :
419 : case xlPSFontStyle:
420 : {
421 0 : switch( *pChar )
422 : {
423 : case '\"':
424 0 : SetAttribs();
425 0 : if( !aReadFont.isEmpty() )
426 0 : mxFontData->maName = aReadFont;
427 0 : mxFontData->maStyle = aReadStyle;
428 0 : eState = xlPSText;
429 0 : break;
430 : default:
431 0 : aReadStyle += OUString(*pChar);
432 : }
433 : }
434 0 : break;
435 :
436 : // --- read font height ---
437 :
438 : case xlPSHeight:
439 : {
440 0 : if( ('0' <= *pChar) && (*pChar <= '9') )
441 : {
442 0 : if( nReadHeight != 0xFFFF )
443 : {
444 0 : nReadHeight *= 10;
445 0 : nReadHeight += (*pChar - '0');
446 0 : if( nReadHeight > 1600 ) // max 1600pt = 32000twips
447 0 : nReadHeight = 0xFFFF;
448 : }
449 : }
450 : else
451 : {
452 0 : if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
453 : {
454 0 : SetAttribs();
455 0 : mxFontData->mnHeight = nReadHeight * 20;
456 : }
457 0 : --pChar;
458 0 : eState = xlPSText;
459 : }
460 : }
461 0 : break;
462 : }
463 0 : ++pChar;
464 : }
465 :
466 : // finalize
467 0 : CreateCurrObject();
468 0 : maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
469 0 : maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
470 0 : maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
471 0 : }
472 :
473 0 : void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
474 : {
475 0 : ScPageHFItem aHFItem( nWhichId );
476 0 : if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
477 0 : aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
478 0 : if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
479 0 : aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
480 0 : if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
481 0 : aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
482 0 : rItemSet.Put( aHFItem );
483 0 : }
484 :
485 0 : sal_Int32 XclImpHFConverter::GetTotalHeight() const
486 : {
487 0 : return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
488 0 : ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
489 : }
490 :
491 : // private --------------------------------------------------------------------
492 :
493 0 : sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
494 : {
495 0 : sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
496 0 : return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
497 : }
498 :
499 0 : sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
500 : {
501 0 : return GetMaxLineHeight( meCurrObj );
502 : }
503 :
504 0 : void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
505 : {
506 0 : sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
507 0 : rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
508 0 : }
509 :
510 0 : void XclImpHFConverter::UpdateCurrMaxLineHeight()
511 : {
512 0 : UpdateMaxLineHeight( meCurrObj );
513 0 : }
514 :
515 0 : void XclImpHFConverter::SetAttribs()
516 : {
517 0 : ESelection& rSel = GetCurrSel();
518 0 : if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
519 : {
520 0 : SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
521 0 : XclImpFont aFont( GetRoot(), *mxFontData );
522 0 : aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
523 0 : mrEE.QuickSetAttribs( aItemSet, rSel );
524 0 : rSel.nStartPara = rSel.nEndPara;
525 0 : rSel.nStartPos = rSel.nEndPos;
526 : }
527 0 : }
528 :
529 0 : void XclImpHFConverter::ResetFontData()
530 : {
531 0 : if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
532 0 : *mxFontData = pFirstFont->GetFontData();
533 : else
534 : {
535 0 : mxFontData->Clear();
536 0 : mxFontData->mnHeight = 200;
537 : }
538 0 : }
539 :
540 0 : void XclImpHFConverter::InsertText()
541 : {
542 0 : if( !maCurrText.isEmpty() )
543 : {
544 0 : ESelection& rSel = GetCurrSel();
545 0 : mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
546 0 : rSel.nEndPos = rSel.nEndPos + maCurrText.getLength();
547 0 : maCurrText = "";
548 0 : UpdateCurrMaxLineHeight();
549 : }
550 0 : }
551 :
552 0 : void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
553 : {
554 0 : ESelection& rSel = GetCurrSel();
555 0 : mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
556 0 : ++rSel.nEndPos;
557 0 : UpdateCurrMaxLineHeight();
558 0 : }
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 0 : void XclImpHFConverter::CreateCurrObject()
571 : {
572 0 : InsertText();
573 0 : SetAttribs();
574 0 : GetCurrObj().reset( mrEE.CreateTextObject() );
575 0 : }
576 :
577 0 : void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
578 : {
579 0 : if( eNew != meCurrObj )
580 : {
581 0 : CreateCurrObject();
582 0 : meCurrObj = eNew;
583 0 : if( GetCurrObj().get() )
584 0 : mrEE.SetText( *GetCurrObj() );
585 : else
586 0 : mrEE.SetText( EMPTY_OUSTRING );
587 0 : ResetFontData();
588 : }
589 0 : }
590 :
591 : // URL conversion =============================================================
592 :
593 : namespace {
594 :
595 0 : void lclAppendUrlChar( OUString& rUrl, sal_Unicode cChar )
596 : {
597 : // encode special characters
598 0 : switch( cChar )
599 : {
600 0 : case '#': rUrl += "%23"; break;
601 0 : case '%': rUrl += "%25"; break;
602 0 : default: rUrl += OUString( cChar );
603 : }
604 0 : }
605 :
606 : } // namespace
607 :
608 0 : 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 0 : } eState = xlUrlInit;
620 :
621 0 : bool bEncoded = true;
622 0 : rbSameWb = false;
623 :
624 0 : sal_Unicode cCurrDrive = 0;
625 0 : OUString aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
626 0 : if( (aDosBase.getLength() > 2) && aDosBase.copy(1,2).equalsAscii( ":\\" ) )
627 0 : cCurrDrive = aDosBase[0];
628 :
629 0 : const sal_Unicode* pChar = rEncodedUrl.getStr();
630 0 : while( *pChar )
631 : {
632 0 : switch( eState )
633 : {
634 :
635 : // --- first character ---
636 :
637 : case xlUrlInit:
638 : {
639 0 : switch( *pChar )
640 : {
641 : case EXC_URLSTART_ENCODED:
642 0 : eState = xlUrlPath;
643 0 : break;
644 : case EXC_URLSTART_SELF:
645 : case EXC_URLSTART_SELFENCODED:
646 0 : rbSameWb = true;
647 0 : eState = xlUrlSheetName;
648 0 : 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 0 : break;
660 :
661 : // --- URL path ---
662 :
663 : case xlUrlPath:
664 : {
665 0 : 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 0 : if( cCurrDrive )
686 : {
687 0 : lclAppendUrlChar( rUrl, cCurrDrive );
688 0 : rUrl += ":";
689 : }
690 : // run through
691 : case EXC_URL_SUBDIR:
692 0 : if( bEncoded )
693 0 : rUrl += "\\";
694 : else // control character in raw name -> DDE link
695 : {
696 0 : rUrl += OUString( EXC_DDE_DELIM );
697 0 : eState = xlUrlRaw;
698 : }
699 0 : 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 0 : lclAppendUrlChar( rUrl, *pChar );
719 : }
720 : }
721 0 : 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 0 : rTabName += OUString( *pChar );
739 0 : break;
740 :
741 : // --- raw read mode ---
742 :
743 : case xlUrlRaw:
744 0 : lclAppendUrlChar( rUrl, *pChar );
745 0 : break;
746 : }
747 :
748 0 : ++pChar;
749 0 : }
750 0 : }
751 :
752 0 : void XclImpUrlHelper::DecodeUrl(
753 : OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const OUString& rEncodedUrl )
754 : {
755 0 : OUString aTabName;
756 0 : OUString aUrl;
757 0 : DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
758 0 : rUrl = aUrl;
759 0 : OSL_ENSURE( aTabName.isEmpty(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
760 0 : }
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 != -1) && (0 < nPos) && (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 0 : XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
777 : mfValue( 0.0 ),
778 0 : mnBoolErr( 0 )
779 : {
780 0 : rStrm >> mnType;
781 0 : switch( mnType )
782 : {
783 : case EXC_CACHEDVAL_EMPTY:
784 0 : rStrm.Ignore( 8 );
785 0 : break;
786 : case EXC_CACHEDVAL_DOUBLE:
787 0 : rStrm >> mfValue;
788 0 : break;
789 : case EXC_CACHEDVAL_STRING:
790 0 : maStr = rStrm.ReadUniString();
791 0 : break;
792 : case EXC_CACHEDVAL_BOOL:
793 : case EXC_CACHEDVAL_ERROR:
794 : {
795 : double fVal;
796 0 : rStrm >> mnBoolErr;
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 0 : }
809 :
810 0 : XclImpCachedValue::~XclImpCachedValue()
811 : {
812 0 : }
813 :
814 0 : const OUString& XclImpCachedValue::GetString() const
815 : {
816 0 : return maStr;
817 : }
818 :
819 0 : sal_uInt16 XclImpCachedValue::GetScError() const
820 : {
821 0 : return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
822 : }
823 :
824 : // Matrix Cached Values ==============================================================
825 :
826 0 : XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
827 : mnScCols( 0 ),
828 0 : mnScRows( 0 )
829 : {
830 0 : mnScCols = rStrm.ReaduInt8();
831 0 : mnScRows = rStrm.ReaduInt16();
832 :
833 0 : if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
834 : {
835 : // in BIFF2-BIFF7: 256 columns represented by 0 columns
836 0 : if( mnScCols == 0 )
837 0 : mnScCols = 256;
838 : }
839 : else
840 : {
841 : // in BIFF8: columns and rows decreaed by 1
842 0 : ++mnScCols;
843 0 : ++mnScRows;
844 : }
845 :
846 0 : for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
847 0 : for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
848 0 : maValueList.push_back( new XclImpCachedValue( rStrm ) );
849 0 : }
850 :
851 0 : XclImpCachedMatrix::~XclImpCachedMatrix()
852 : {
853 0 : }
854 :
855 0 : ScMatrixRef XclImpCachedMatrix::CreateScMatrix( svl::SharedStringPool& rPool ) const
856 : {
857 0 : ScMatrixRef xScMatrix;
858 : OSL_ENSURE( mnScCols * mnScRows == maValueList.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
859 0 : if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.size() )
860 : {
861 0 : xScMatrix = new ScMatrix(mnScCols, mnScRows, 0.0);
862 0 : XclImpValueList::const_iterator itValue = maValueList.begin();
863 0 : for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
864 : {
865 0 : for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
866 : {
867 0 : switch( itValue->GetType() )
868 : {
869 : case EXC_CACHEDVAL_EMPTY:
870 : // Excel shows 0.0 here, not an empty cell
871 0 : xScMatrix->PutEmpty( nScCol, nScRow );
872 0 : break;
873 : case EXC_CACHEDVAL_DOUBLE:
874 0 : xScMatrix->PutDouble( itValue->GetValue(), nScCol, nScRow );
875 0 : break;
876 : case EXC_CACHEDVAL_STRING:
877 0 : xScMatrix->PutString(rPool.intern(itValue->GetString()), nScCol, nScRow);
878 0 : break;
879 : case EXC_CACHEDVAL_BOOL:
880 0 : xScMatrix->PutBoolean( itValue->GetBool(), nScCol, nScRow );
881 0 : break;
882 : case EXC_CACHEDVAL_ERROR:
883 0 : xScMatrix->PutError( itValue->GetScError(), nScCol, nScRow );
884 0 : break;
885 : default:
886 : OSL_FAIL( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
887 0 : xScMatrix->PutEmpty( nScCol, nScRow );
888 : }
889 0 : ++itValue;
890 : }
891 : }
892 : }
893 0 : return xScMatrix;
894 : }
895 :
896 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|