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 "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
23 : #include <editeng/adjustitem.hxx>
24 : #include <editeng/editobj.hxx>
25 : #include <editeng/editview.hxx>
26 : #include <editeng/escapementitem.hxx>
27 : #include <editeng/langitem.hxx>
28 : #include <svx/svdograf.hxx>
29 : #include <svx/svdpage.hxx>
30 : #include <editeng/scripttypeitem.hxx>
31 : #include <svtools/htmlcfg.hxx>
32 : #include <sfx2/sfxhtml.hxx>
33 : #include <svtools/parhtml.hxx>
34 : #include <svl/zforlist.hxx>
35 : #include <vcl/virdev.hxx>
36 : #include <vcl/svapp.hxx>
37 : #include <unotools/syslocale.hxx>
38 : #include <unotools/charclass.hxx>
39 : #include <comphelper/string.hxx>
40 :
41 : #include "eeimport.hxx"
42 : #include "global.hxx"
43 : #include "document.hxx"
44 : #include "editutil.hxx"
45 : #include "stlsheet.hxx"
46 : #include "docpool.hxx"
47 : #include "attrib.hxx"
48 : #include "patattr.hxx"
49 : #include "eeparser.hxx"
50 : #include "drwlayer.hxx"
51 : #include "rangenam.hxx"
52 : #include "progress.hxx"
53 : #include "stringutil.hxx"
54 : #include <rowheightcontext.hxx>
55 : #include "fuinsert.hxx"
56 :
57 : #include "globstr.hrc"
58 :
59 : #include <boost/scoped_ptr.hpp>
60 :
61 1 : ScEEImport::ScEEImport( ScDocument* pDocP, const ScRange& rRange ) :
62 : maRange( rRange ),
63 : mpDoc( pDocP ),
64 1 : mpParser( NULL )
65 : {
66 : const ScPatternAttr* pPattern = mpDoc->GetPattern(
67 1 : maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() );
68 1 : mpEngine = new ScTabEditEngine(*pPattern, mpDoc->GetEditPool(), mpDoc->GetEditPool());
69 1 : mpEngine->SetUpdateMode( false );
70 1 : mpEngine->EnableUndo( false );
71 1 : }
72 :
73 2 : ScEEImport::~ScEEImport()
74 : {
75 : // Sequence important, or else we crash in some dtor!
76 : // Is guaranteed as ScEEImport is base class
77 1 : delete mpEngine; // After Parser!
78 1 : }
79 :
80 1 : sal_uLong ScEEImport::Read( SvStream& rStream, const OUString& rBaseURL )
81 : {
82 1 : sal_uLong nErr = mpParser->Read( rStream, rBaseURL );
83 :
84 : SCCOL nEndCol;
85 : SCROW nEndRow;
86 1 : mpParser->GetDimensions( nEndCol, nEndRow );
87 1 : if ( nEndCol != 0 )
88 : {
89 1 : nEndCol += maRange.aStart.Col() - 1;
90 1 : if ( nEndCol > MAXCOL )
91 0 : nEndCol = MAXCOL;
92 : }
93 : else
94 0 : nEndCol = maRange.aStart.Col();
95 1 : if ( nEndRow != 0 )
96 : {
97 1 : nEndRow += maRange.aStart.Row() - 1;
98 1 : if ( nEndRow > MAXROW )
99 0 : nEndRow = MAXROW;
100 : }
101 : else
102 0 : nEndRow = maRange.aStart.Row();
103 1 : maRange.aEnd.Set( nEndCol, nEndRow, maRange.aStart.Tab() );
104 :
105 1 : return nErr;
106 : }
107 :
108 1 : void ScEEImport::WriteToDocument( bool bSizeColsRows, double nOutputFactor, SvNumberFormatter* pFormatter, bool bConvertDate )
109 : {
110 1 : ScProgress* pProgress = new ScProgress( mpDoc->GetDocumentShell(),
111 1 : ScGlobal::GetRscString( STR_LOAD_DOC ), mpParser->ListSize() );
112 1 : sal_uLong nProgress = 0;
113 :
114 : SCCOL nStartCol, nEndCol;
115 : SCROW nStartRow, nEndRow;
116 : SCTAB nTab;
117 : SCROW nOverlapRowMax, nLastMergedRow;
118 : SCCOL nMergeColAdd;
119 1 : nStartCol = maRange.aStart.Col();
120 1 : nStartRow = maRange.aStart.Row();
121 1 : nTab = maRange.aStart.Tab();
122 1 : nEndCol = maRange.aEnd.Col();
123 1 : nEndRow = maRange.aEnd.Row();
124 1 : nOverlapRowMax = 0;
125 1 : nMergeColAdd = 0;
126 1 : nLastMergedRow = SCROW_MAX;
127 1 : bool bHasGraphics = false;
128 : ScEEParseEntry* pE;
129 1 : if (!pFormatter)
130 0 : pFormatter = mpDoc->GetFormatTable();
131 1 : bool bNumbersEnglishUS = false;
132 1 : if (pFormatter->GetLanguage() == LANGUAGE_SYSTEM)
133 : {
134 : // Automatic language option selected. Check for the global 'use US English' option.
135 1 : SvxHtmlOptions aOpt;
136 1 : bNumbersEnglishUS = aOpt.IsNumbersEnglishUS();
137 : }
138 1 : ScDocumentPool* pDocPool = mpDoc->GetPool();
139 1 : ScRangeName* pRangeNames = mpDoc->GetRangeName();
140 8 : for ( size_t i = 0, n = mpParser->ListSize(); i < n; ++i )
141 : {
142 7 : pE = mpParser->ListEntry( i );
143 7 : SCROW nRow = nStartRow + pE->nRow;
144 7 : if ( nRow != nLastMergedRow )
145 5 : nMergeColAdd = 0;
146 7 : SCCOL nCol = nStartCol + pE->nCol + nMergeColAdd;
147 : // Determine RowMerge
148 : // Pure ColMerge and ColMerge of the first MergeRow already done during parsing
149 7 : if ( nRow <= nOverlapRowMax )
150 : {
151 9 : while ( nCol <= MAXCOL && mpDoc->HasAttrib( nCol, nRow, nTab,
152 3 : nCol, nRow, nTab, HASATTR_OVERLAPPED ) )
153 : {
154 0 : nCol++;
155 0 : nMergeColAdd++;
156 : }
157 3 : nLastMergedRow = nRow;
158 : }
159 : // Add for second run
160 7 : pE->nCol = nCol;
161 7 : pE->nRow = nRow;
162 7 : if ( ValidCol(nCol) && ValidRow(nRow) )
163 : {
164 6 : SfxItemSet aSet = mpEngine->GetAttribs( pE->aSel );
165 : // Remove default: we set left/right ourselves depending on Text or
166 : // Number
167 : // EditView.GetAttribs always returns complete Set filled with
168 : // defaults
169 6 : const SfxPoolItem& rItem = aSet.Get( EE_PARA_JUST );
170 6 : if ( static_cast<const SvxAdjustItem&>(rItem).GetAdjust() == SVX_ADJUST_LEFT )
171 6 : aSet.ClearItem( EE_PARA_JUST );
172 :
173 : // Test whether simple String without mixed attributes
174 6 : bool bSimple = ( pE->aSel.nStartPara == pE->aSel.nEndPara );
175 204 : for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && bSimple; nId++)
176 : {
177 198 : const SfxPoolItem* pItem = 0;
178 198 : SfxItemState eState = aSet.GetItemState( nId, true, &pItem );
179 198 : if (eState == SfxItemState::DONTCARE)
180 0 : bSimple = false;
181 198 : else if (eState == SfxItemState::SET)
182 : {
183 192 : if ( nId == EE_CHAR_ESCAPEMENT ) // Super-/Subscript always via EE
184 : {
185 6 : if ( (SvxEscapement)static_cast<const SvxEscapementItem*>(pItem)->GetEnumValue()
186 : != SVX_ESCAPEMENT_OFF )
187 0 : bSimple = false;
188 : }
189 : }
190 : }
191 6 : if ( bSimple )
192 : { // Contains field commands?
193 6 : SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
194 6 : if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
195 0 : bSimple = false;
196 : }
197 :
198 : // HTML
199 12 : OUString aValStr, aNumStr;
200 : double fVal;
201 6 : sal_uInt32 nNumForm = 0;
202 6 : LanguageType eNumLang = LANGUAGE_NONE;
203 6 : if ( pE->pNumStr )
204 : { // SDNUM needs to be if SDVAL
205 0 : aNumStr = *pE->pNumStr;
206 0 : if ( pE->pValStr )
207 0 : aValStr = *pE->pValStr;
208 : fVal = SfxHTMLParser::GetTableDataOptionsValNum(
209 0 : nNumForm, eNumLang, aValStr, aNumStr, *pFormatter );
210 : }
211 :
212 : // Set attributes
213 12 : ScPatternAttr aAttr( pDocPool );
214 6 : aAttr.GetFromEditItemSet( &aSet );
215 6 : SfxItemSet& rSet = aAttr.GetItemSet();
216 6 : if (!aNumStr.isEmpty())
217 : {
218 0 : rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumForm ) );
219 0 : rSet.Put( SvxLanguageItem( eNumLang, ATTR_LANGUAGE_FORMAT ) );
220 : }
221 6 : const SfxItemSet& rESet = pE->aItemSet;
222 6 : if ( rESet.Count() )
223 : {
224 : const SfxPoolItem* pItem;
225 0 : if ( rESet.GetItemState( ATTR_BACKGROUND, false, &pItem) == SfxItemState::SET )
226 0 : rSet.Put( *pItem );
227 0 : if ( rESet.GetItemState( ATTR_BORDER, false, &pItem) == SfxItemState::SET )
228 0 : rSet.Put( *pItem );
229 0 : if ( rESet.GetItemState( ATTR_SHADOW, false, &pItem) == SfxItemState::SET )
230 0 : rSet.Put( *pItem );
231 : // HTML
232 0 : if ( rESet.GetItemState( ATTR_HOR_JUSTIFY, false, &pItem) == SfxItemState::SET )
233 0 : rSet.Put( *pItem );
234 0 : if ( rESet.GetItemState( ATTR_VER_JUSTIFY, false, &pItem) == SfxItemState::SET )
235 0 : rSet.Put( *pItem );
236 0 : if ( rESet.GetItemState( ATTR_LINEBREAK, false, &pItem) == SfxItemState::SET )
237 0 : rSet.Put( *pItem );
238 0 : if ( rESet.GetItemState( ATTR_FONT_COLOR, false, &pItem) == SfxItemState::SET )
239 0 : rSet.Put( *pItem );
240 0 : if ( rESet.GetItemState( ATTR_FONT_UNDERLINE, false, &pItem) == SfxItemState::SET )
241 0 : rSet.Put( *pItem );
242 : // HTML LATIN/CJK/CTL script type dependent
243 : const SfxPoolItem* pFont;
244 0 : if ( rESet.GetItemState( ATTR_FONT, false, &pFont) != SfxItemState::SET )
245 0 : pFont = 0;
246 : const SfxPoolItem* pHeight;
247 0 : if ( rESet.GetItemState( ATTR_FONT_HEIGHT, false, &pHeight) != SfxItemState::SET )
248 0 : pHeight = 0;
249 : const SfxPoolItem* pWeight;
250 0 : if ( rESet.GetItemState( ATTR_FONT_WEIGHT, false, &pWeight) != SfxItemState::SET )
251 0 : pWeight = 0;
252 : const SfxPoolItem* pPosture;
253 0 : if ( rESet.GetItemState( ATTR_FONT_POSTURE, false, &pPosture) != SfxItemState::SET )
254 0 : pPosture = 0;
255 : // Number format
256 0 : const SfxPoolItem* pNumFmt = NULL;
257 0 : if ( rESet.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SfxItemState::SET )
258 0 : rSet.Put(*pNumFmt);
259 0 : if ( pFont || pHeight || pWeight || pPosture )
260 : {
261 0 : OUString aStr( mpEngine->GetText( pE->aSel ) );
262 0 : SvtScriptType nScriptType = mpDoc->GetStringScriptType( aStr );
263 : const SvtScriptType nScripts[3] = { SvtScriptType::LATIN,
264 0 : SvtScriptType::ASIAN, SvtScriptType::COMPLEX };
265 0 : for ( sal_uInt8 j=0; j<3; ++j )
266 : {
267 0 : if ( nScriptType & nScripts[j] )
268 : {
269 0 : if ( pFont )
270 : rSet.Put( *pFont, ScGlobal::GetScriptedWhichID(
271 0 : nScripts[j], ATTR_FONT ));
272 0 : if ( pHeight )
273 : rSet.Put( *pHeight, ScGlobal::GetScriptedWhichID(
274 0 : nScripts[j], ATTR_FONT_HEIGHT ));
275 0 : if ( pWeight )
276 : rSet.Put( *pWeight, ScGlobal::GetScriptedWhichID(
277 0 : nScripts[j], ATTR_FONT_WEIGHT ));
278 0 : if ( pPosture )
279 : rSet.Put( *pPosture, ScGlobal::GetScriptedWhichID(
280 0 : nScripts[j], ATTR_FONT_POSTURE ));
281 : }
282 0 : }
283 : }
284 : }
285 6 : if ( pE->nColOverlap > 1 || pE->nRowOverlap > 1 )
286 : { // Merged cells, with SfxItemSet.Put() is faster than
287 : // with ScDocument.DoMerge() afterwards
288 0 : ScMergeAttr aMerge( pE->nColOverlap, pE->nRowOverlap );
289 0 : rSet.Put( aMerge );
290 0 : SCROW nRO = 0;
291 0 : if ( pE->nColOverlap > 1 )
292 : mpDoc->ApplyFlagsTab( nCol+1, nRow,
293 : nCol + pE->nColOverlap - 1, nRow, nTab,
294 0 : SC_MF_HOR );
295 0 : if ( pE->nRowOverlap > 1 )
296 : {
297 0 : nRO = nRow + pE->nRowOverlap - 1;
298 : mpDoc->ApplyFlagsTab( nCol, nRow+1,
299 : nCol, nRO , nTab,
300 0 : SC_MF_VER );
301 0 : if ( nRO > nOverlapRowMax )
302 0 : nOverlapRowMax = nRO;
303 : }
304 0 : if ( pE->nColOverlap > 1 && pE->nRowOverlap > 1 )
305 : mpDoc->ApplyFlagsTab( nCol+1, nRow+1,
306 : nCol + pE->nColOverlap - 1, nRO, nTab,
307 0 : SC_MF_HOR | SC_MF_VER );
308 : }
309 : const ScStyleSheet* pStyleSheet =
310 6 : mpDoc->GetPattern( nCol, nRow, nTab )->GetStyleSheet();
311 6 : aAttr.SetStyleSheet( const_cast<ScStyleSheet*>(pStyleSheet) );
312 6 : mpDoc->SetPattern( nCol, nRow, nTab, aAttr, true );
313 :
314 : // Add data
315 6 : if (bSimple)
316 : {
317 6 : ScSetStringParam aParam;
318 6 : aParam.mpNumFormatter = pFormatter;
319 6 : aParam.mbDetectNumberFormat = true;
320 6 : aParam.meSetTextNumFormat = ScSetStringParam::SpecialNumberOnly;
321 6 : aParam.mbHandleApostrophe = false;
322 :
323 6 : if (!aValStr.isEmpty())
324 0 : mpDoc->SetValue( nCol, nRow, nTab, fVal );
325 6 : else if ( !pE->aSel.HasRange() )
326 : {
327 : // maybe ALT text of IMG or similar
328 0 : mpDoc->SetString( nCol, nRow, nTab, pE->aAltText, &aParam );
329 : // If SelRange is completely empty, the succeeding text can be in the same paragraph!
330 : }
331 : else
332 : {
333 6 : OUString aStr;
334 6 : if( pE->bEntirePara )
335 : {
336 0 : aStr = mpEngine->GetText( pE->aSel.nStartPara );
337 : }
338 : else
339 : {
340 6 : aStr = comphelper::string::strip(mpEngine->GetText(pE->aSel), ' ');
341 : }
342 :
343 6 : bool bTextFormat = false;
344 :
345 6 : const SfxPoolItem* pNumFmt = NULL;
346 6 : if (rSet.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SfxItemState::SET)
347 : {
348 0 : sal_uInt32 nNumFmt = static_cast<const SfxUInt32Item*>(pNumFmt)->GetValue();
349 0 : sal_uInt16 nType = pFormatter->GetType(nNumFmt);
350 0 : if (nType == css::util::NumberFormat::TEXT)
351 : // Format is set to Text.
352 0 : bTextFormat = true;
353 : }
354 :
355 : // TODO: RTF import should follow the language tag,
356 : // currently this follows the HTML options for both, HTML
357 : // and RTF.
358 6 : if (bNumbersEnglishUS)
359 : {
360 0 : pFormatter->ChangeIntl( LANGUAGE_ENGLISH_US);
361 0 : sal_uInt32 nIndex = pFormatter->GetStandardIndex( LANGUAGE_ENGLISH_US);
362 0 : double fEnVal = 0.0;
363 0 : if (pFormatter->IsNumberFormat( aStr, nIndex, fEnVal))
364 : {
365 : sal_uInt32 nNewIndex =
366 : pFormatter->GetFormatForLanguageIfBuiltIn(
367 0 : nIndex, LANGUAGE_SYSTEM);
368 : OSL_ENSURE( nNewIndex != nIndex, "ScEEImport::WriteToDocument: NumbersEnglishUS not a built-in format?");
369 0 : pFormatter->GetInputLineString( fEnVal, nNewIndex, aStr);
370 : }
371 : else
372 0 : bTextFormat = true;
373 0 : pFormatter->ChangeIntl( LANGUAGE_SYSTEM);
374 : }
375 :
376 : // #105460#, #i4180# String cells can't contain tabs or linebreaks
377 : // -> replace with spaces
378 6 : aStr = aStr.replaceAll( "\t", " " );
379 6 : aStr = aStr.replaceAll( "\n", " " );
380 :
381 6 : if (bTextFormat)
382 : {
383 0 : aParam.mbDetectNumberFormat = false;
384 0 : aParam.meSetTextNumFormat = ScSetStringParam::Always;
385 : }
386 : else
387 6 : aParam.mbDetectNumberFormat = bConvertDate;
388 :
389 6 : mpDoc->SetString(nCol, nRow, nTab, aStr, &aParam);
390 : }
391 : }
392 : else
393 : {
394 : // The cell will own the text object instance.
395 0 : mpDoc->SetEditText(ScAddress(nCol,nRow,nTab), mpEngine->CreateTextObject(pE->aSel));
396 : }
397 6 : if ( pE->maImageList.size() )
398 0 : bHasGraphics |= GraphicSize( nCol, nRow, nTab, pE );
399 6 : if ( pE->pName )
400 : { // Anchor Name => RangeName
401 0 : if (!pRangeNames->findByUpperName(ScGlobal::pCharClass->uppercase(*pE->pName)))
402 : {
403 : ScRangeData* pData = new ScRangeData( mpDoc, *pE->pName,
404 0 : ScAddress( nCol, nRow, nTab ) );
405 0 : pRangeNames->insert( pData );
406 : }
407 6 : }
408 : }
409 7 : pProgress->SetStateOnPercent( ++nProgress );
410 : }
411 1 : if ( bSizeColsRows )
412 : {
413 : // Column widths
414 1 : ColWidthsMap& rColWidths = mpParser->GetColWidths();
415 1 : if ( !rColWidths.empty() )
416 : {
417 0 : nProgress = 0;
418 0 : pProgress->SetState( nProgress, nEndCol - nStartCol + 1 );
419 0 : for ( SCCOL nCol = nStartCol; nCol <= nEndCol; nCol++ )
420 : {
421 0 : sal_uInt16 nWidth = 0;
422 0 : ColWidthsMap::const_iterator it = rColWidths.find( nCol );
423 0 : if ( it != rColWidths.end() )
424 0 : nWidth = it->second;
425 0 : if ( nWidth )
426 0 : mpDoc->SetColWidth( nCol, nTab, nWidth );
427 0 : pProgress->SetState( ++nProgress );
428 : }
429 : }
430 1 : DELETEZ( pProgress ); // SetOptimalHeight has its own ProgressBar
431 : // Adjust line height, base is 100% zoom
432 1 : Fraction aZoom( 1, 1 );
433 : // Factor is printer to display ratio
434 1 : double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom / nOutputFactor;
435 1 : double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
436 2 : ScopedVclPtrInstance< VirtualDevice > pVirtDev;
437 2 : sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoom, aZoom, pVirtDev);
438 1 : aCxt.setExtraHeight(ScGlobal::nLastRowHeightExtra);
439 1 : mpDoc->SetOptimalHeight(aCxt, 0, nEndRow, 0);
440 :
441 1 : if ( !maRowHeights.empty() )
442 : {
443 0 : for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow++ )
444 : {
445 0 : RowHeightMap::const_iterator it = maRowHeights.find( nRow );
446 0 : sal_uInt16 nHeight = it == maRowHeights.end() ? 0 : it->second;
447 0 : if ( nHeight > mpDoc->GetRowHeight( nRow, nTab ) )
448 0 : mpDoc->SetRowHeight( nRow, nTab, nHeight );
449 : }
450 1 : }
451 : }
452 1 : if ( bHasGraphics )
453 : {
454 : // Insert graphics
455 0 : for ( size_t i = 0, nListSize = mpParser->ListSize(); i < nListSize; ++i )
456 : {
457 0 : pE = mpParser->ListEntry( i );
458 0 : if ( !pE->maImageList.empty() )
459 : {
460 0 : SCCOL nCol = pE->nCol;
461 0 : SCROW nRow = pE->nRow;
462 0 : if ( ValidCol(nCol) && ValidRow(nRow) )
463 0 : InsertGraphic( nCol, nRow, nTab, pE );
464 : }
465 : }
466 : }
467 1 : if ( pProgress )
468 0 : delete pProgress;
469 1 : }
470 :
471 0 : bool ScEEImport::GraphicSize( SCCOL nCol, SCROW nRow, SCTAB /*nTab*/, ScEEParseEntry* pE )
472 : {
473 0 : if ( !pE->maImageList.size() )
474 0 : return false;
475 0 : bool bHasGraphics = false;
476 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
477 : long nWidth, nHeight;
478 0 : nWidth = nHeight = 0;
479 0 : sal_Char nDir = nHorizontal;
480 0 : for ( size_t i = 0; i < pE->maImageList.size() ; ++i )
481 : {
482 0 : ScHTMLImage* pI = &pE->maImageList[ i ];
483 0 : if ( pI->pGraphic )
484 0 : bHasGraphics = true;
485 0 : Size aSizePix = pI->aSize;
486 0 : aSizePix.Width() += 2 * pI->aSpace.X();
487 0 : aSizePix.Height() += 2 * pI->aSpace.Y();
488 0 : Size aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_TWIP ) );
489 0 : if ( nDir & nHorizontal )
490 0 : nWidth += aLogicSize.Width();
491 0 : else if ( nWidth < aLogicSize.Width() )
492 0 : nWidth = aLogicSize.Width();
493 0 : if ( nDir & nVertical )
494 0 : nHeight += aLogicSize.Height();
495 0 : else if ( nHeight < aLogicSize.Height() )
496 0 : nHeight = aLogicSize.Height();
497 0 : nDir = pI->nDir;
498 : }
499 : // Column widths
500 0 : ColWidthsMap& rColWidths = mpParser->GetColWidths();
501 0 : long nThisWidth = 0;
502 0 : ColWidthsMap::const_iterator it = rColWidths.find( nCol );
503 0 : if ( it != rColWidths.end() )
504 0 : nThisWidth = it->second;
505 0 : long nColWidths = nThisWidth;
506 0 : SCCOL nColSpanCol = nCol + pE->nColOverlap;
507 0 : for ( SCCOL nC = nCol + 1; nC < nColSpanCol; nC++ )
508 : {
509 0 : ColWidthsMap::const_iterator it2 = rColWidths.find( nC );
510 0 : if ( it2 != rColWidths.end() )
511 0 : nColWidths += it2->second;
512 : }
513 0 : if ( nWidth > nColWidths )
514 : { // Only insert difference in first column
515 0 : rColWidths[ nCol ] = nWidth - nColWidths + nThisWidth;
516 : }
517 : // Distribute line height difference between all affected lines
518 0 : SCROW nRowSpan = pE->nRowOverlap;
519 0 : nHeight /= nRowSpan;
520 0 : if ( nHeight == 0 )
521 0 : nHeight = 1; // For definite comparison
522 0 : for ( SCROW nR = nRow; nR < nRow + nRowSpan; nR++ )
523 : {
524 0 : RowHeightMap::const_iterator it2 = maRowHeights.find( nR );
525 0 : long nRowHeight = it2 == maRowHeights.end() ? 0 : it2->second;
526 0 : if ( nHeight > nRowHeight )
527 : {
528 0 : maRowHeights[ nR ] = nHeight;
529 : }
530 : }
531 0 : return bHasGraphics;
532 : }
533 :
534 0 : void ScEEImport::InsertGraphic( SCCOL nCol, SCROW nRow, SCTAB nTab,
535 : ScEEParseEntry* pE )
536 : {
537 0 : if ( !pE->maImageList.size() )
538 0 : return ;
539 0 : ScDrawLayer* pModel = mpDoc->GetDrawLayer();
540 0 : if (!pModel)
541 : {
542 0 : mpDoc->InitDrawLayer();
543 0 : pModel = mpDoc->GetDrawLayer();
544 : }
545 0 : SdrPage* pPage = pModel->GetPage( static_cast<sal_uInt16>(nTab) );
546 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
547 :
548 : Point aCellInsertPos(
549 0 : (long)((double) mpDoc->GetColOffset( nCol, nTab ) * HMM_PER_TWIPS),
550 0 : (long)((double) mpDoc->GetRowOffset( nRow, nTab ) * HMM_PER_TWIPS) );
551 :
552 0 : Point aInsertPos( aCellInsertPos );
553 0 : Point aSpace;
554 0 : Size aLogicSize;
555 0 : sal_Char nDir = nHorizontal;
556 0 : for ( size_t i = 0; i < pE->maImageList.size(); ++i )
557 : {
558 0 : ScHTMLImage* pI = &pE->maImageList[ i ];
559 0 : if ( nDir & nHorizontal )
560 : { // Horizontal
561 0 : aInsertPos.X() += aLogicSize.Width();
562 0 : aInsertPos.X() += aSpace.X();
563 0 : aInsertPos.Y() = aCellInsertPos.Y();
564 : }
565 : else
566 : { // Vertical
567 0 : aInsertPos.X() = aCellInsertPos.X();
568 0 : aInsertPos.Y() += aLogicSize.Height();
569 0 : aInsertPos.Y() += aSpace.Y();
570 : }
571 : // Add offset of Spacing
572 0 : aSpace = pDefaultDev->PixelToLogic( pI->aSpace, MapMode( MAP_100TH_MM ) );
573 0 : aInsertPos += aSpace;
574 :
575 0 : Size aSizePix = pI->aSize;
576 0 : aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_100TH_MM ) );
577 :
578 : // Limit size
579 0 : ::ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
580 :
581 0 : if ( pI->pGraphic )
582 : {
583 0 : Rectangle aRect ( aInsertPos, aLogicSize );
584 0 : SdrGrafObj* pObj = new SdrGrafObj( *pI->pGraphic, aRect );
585 : // calling SetGraphicLink here doesn't work
586 0 : pObj->SetName( pI->aURL );
587 :
588 0 : pPage->InsertObject( pObj );
589 :
590 : // SetGraphicLink has to be used after inserting the object,
591 : // otherwise an empty graphic is swapped in and the contact stuff crashes.
592 : // See #i37444#.
593 0 : pObj->SetGraphicLink( pI->aURL, ""/*TODO?*/, pI->aFilterName );
594 :
595 0 : pObj->SetLogicRect( aRect ); // Only after InsertObject!
596 : }
597 0 : nDir = pI->nDir;
598 : }
599 : }
600 :
601 1 : ScEEParser::ScEEParser( EditEngine* pEditP ) :
602 : pEdit( pEditP ),
603 1 : pPool( EditEngine::CreatePool() ),
604 1 : pDocPool( new ScDocumentPool ),
605 : nLastToken(0),
606 : nColCnt(0),
607 : nRowCnt(0),
608 : nColMax(0),
609 3 : nRowMax(0)
610 : {
611 : // pPool is foisted on SvxRTFParser at RTFIMP_START later on
612 1 : pPool->SetSecondaryPool( pDocPool );
613 1 : pPool->FreezeIdRanges();
614 1 : NewActEntry( NULL );
615 1 : }
616 :
617 2 : ScEEParser::~ScEEParser()
618 : {
619 1 : delete pActEntry;
620 1 : if ( !maList.empty() ) maList.clear();
621 :
622 : // Don't delete Pool until the lists have been deleted
623 1 : pPool->SetSecondaryPool( NULL );
624 1 : SfxItemPool::Free(pDocPool);
625 1 : SfxItemPool::Free(pPool);
626 1 : }
627 :
628 1 : void ScEEParser::NewActEntry( ScEEParseEntry* pE )
629 : { // New free-flying pActEntry
630 1 : pActEntry = new ScEEParseEntry( pPool );
631 1 : pActEntry->aSel.nStartPara = (pE ? pE->aSel.nEndPara + 1 : 0);
632 1 : pActEntry->aSel.nStartPos = 0;
633 31 : }
634 :
635 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|