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