nss: upgrade to release 3.73
[LibreOffice.git] / sc / source / filter / rtf / eeimpars.cxx
blob220c733a4da740e7a96abb237bf31678224c00dd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
23 #include <editeng/adjustitem.hxx>
24 #include <editeng/editobj.hxx>
25 #include <editeng/escapementitem.hxx>
26 #include <editeng/langitem.hxx>
27 #include <svx/svdograf.hxx>
28 #include <svx/svdpage.hxx>
29 #include <svtools/htmlcfg.hxx>
30 #include <sfx2/sfxhtml.hxx>
31 #include <svl/zforlist.hxx>
32 #include <vcl/virdev.hxx>
33 #include <vcl/svapp.hxx>
34 #include <unotools/charclass.hxx>
35 #include <comphelper/string.hxx>
37 #include <eeimport.hxx>
38 #include <global.hxx>
39 #include <document.hxx>
40 #include <editutil.hxx>
41 #include <docpool.hxx>
42 #include <attrib.hxx>
43 #include <patattr.hxx>
44 #include <eeparser.hxx>
45 #include <drwlayer.hxx>
46 #include <rangenam.hxx>
47 #include <progress.hxx>
48 #include <stringutil.hxx>
49 #include <rowheightcontext.hxx>
50 #include <fuinsert.hxx>
52 #include <globstr.hrc>
53 #include <scresid.hxx>
55 #include <memory>
57 ScEEImport::ScEEImport( ScDocument* pDocP, const ScRange& rRange ) :
58 maRange( rRange ),
59 mpDoc( pDocP )
61 const ScPatternAttr* pPattern = mpDoc->GetPattern(
62 maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() );
63 mpEngine.reset( new ScTabEditEngine(*pPattern, mpDoc->GetEditPool(), mpDoc, mpDoc->GetEditPool()) );
64 mpEngine->SetUpdateMode( false );
65 mpEngine->EnableUndo( false );
68 ScEEImport::~ScEEImport()
70 // Sequence important, or else we crash in some dtor!
71 // Is guaranteed as ScEEImport is base class
74 ErrCode ScEEImport::Read( SvStream& rStream, const OUString& rBaseURL )
76 ErrCode nErr = mpParser->Read( rStream, rBaseURL );
78 SCCOL nEndCol;
79 SCROW nEndRow;
80 mpParser->GetDimensions( nEndCol, nEndRow );
81 if ( nEndCol != 0 )
83 nEndCol += maRange.aStart.Col() - 1;
84 if ( nEndCol > mpDoc->MaxCol() )
85 nEndCol = mpDoc->MaxCol();
87 else
88 nEndCol = maRange.aStart.Col();
89 if ( nEndRow != 0 )
91 nEndRow += maRange.aStart.Row() - 1;
92 if ( nEndRow > mpDoc->MaxRow() )
93 nEndRow = mpDoc->MaxRow();
95 else
96 nEndRow = maRange.aStart.Row();
97 maRange.aEnd.Set( nEndCol, nEndRow, maRange.aStart.Tab() );
99 return nErr;
102 namespace
104 bool IsValidSel(const ScTabEditEngine& rEngine, const ESelection& rSel)
106 const auto nParaCount = rEngine.GetParagraphCount();
107 return rSel.nStartPara < nParaCount && rSel.nEndPara < nParaCount;
111 void ScEEImport::WriteToDocument( bool bSizeColsRows, double nOutputFactor, SvNumberFormatter* pFormatter, bool bConvertDate )
113 std::unique_ptr<ScProgress> pProgress( new ScProgress( mpDoc->GetDocumentShell(),
114 ScResId( STR_LOAD_DOC ), mpParser->ListSize(), true ) );
115 sal_uLong nProgress = 0;
117 SCCOL nStartCol, nEndCol;
118 SCROW nStartRow, nEndRow;
119 SCTAB nTab;
120 SCROW nOverlapRowMax, nLastMergedRow;
121 SCCOL nMergeColAdd;
122 nStartCol = maRange.aStart.Col();
123 nStartRow = maRange.aStart.Row();
124 nTab = maRange.aStart.Tab();
125 nEndCol = maRange.aEnd.Col();
126 nEndRow = maRange.aEnd.Row();
127 nOverlapRowMax = 0;
128 nMergeColAdd = 0;
129 nLastMergedRow = SCROW_MAX;
130 bool bHasGraphics = false;
131 ScEEParseEntry* pE;
132 if (!pFormatter)
133 pFormatter = mpDoc->GetFormatTable();
134 bool bNumbersEnglishUS = false;
135 if (pFormatter->GetLanguage() == LANGUAGE_SYSTEM)
137 // Automatic language option selected. Check for the global 'use US English' option.
138 SvxHtmlOptions aOpt;
139 bNumbersEnglishUS = aOpt.IsNumbersEnglishUS();
141 ScDocumentPool* pDocPool = mpDoc->GetPool();
142 ScRangeName* pRangeNames = mpDoc->GetRangeName();
143 for ( size_t i = 0, n = mpParser->ListSize(); i < n; ++i )
145 pE = mpParser->ListEntry( i );
146 SCROW nRow = nStartRow + pE->nRow;
147 if ( nRow != nLastMergedRow )
148 nMergeColAdd = 0;
149 SCCOL nCol = nStartCol + pE->nCol + nMergeColAdd;
150 // Determine RowMerge
151 // Pure ColMerge and ColMerge of the first MergeRow already done during parsing
152 if (nRow <= nOverlapRowMax && mpDoc->ValidCol(nCol))
154 while ( nCol <= mpDoc->MaxCol() && mpDoc->HasAttrib( nCol, nRow, nTab,
155 nCol, nRow, nTab, HasAttrFlags::Overlapped ) )
157 nCol++;
158 nMergeColAdd++;
160 nLastMergedRow = nRow;
162 // Add for second run
163 pE->nCol = nCol;
164 pE->nRow = nRow;
165 if ( mpDoc->ValidCol(nCol) && mpDoc->ValidRow(nRow) )
167 SfxItemSet aSet = mpEngine->GetAttribs( pE->aSel );
168 // Remove default: we set left/right ourselves depending on Text or
169 // Number
170 // EditView.GetAttribs always returns complete Set filled with
171 // defaults
172 const SfxPoolItem& rItem = aSet.Get( EE_PARA_JUST );
173 if ( static_cast<const SvxAdjustItem&>(rItem).GetAdjust() == SvxAdjust::Left )
174 aSet.ClearItem( EE_PARA_JUST );
176 // Test whether simple String without mixed attributes
177 bool bSimple = ( pE->aSel.nStartPara == pE->aSel.nEndPara );
178 for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && bSimple; nId++)
180 const SfxPoolItem* pItem = nullptr;
181 SfxItemState eState = aSet.GetItemState( nId, true, &pItem );
182 if (eState == SfxItemState::DONTCARE)
183 bSimple = false;
184 else if (eState == SfxItemState::SET)
186 if ( nId == EE_CHAR_ESCAPEMENT ) // Super-/Subscript always via EE
188 if ( static_cast<SvxEscapement>(static_cast<const SvxEscapementItem*>(pItem)->GetEnumValue())
189 != SvxEscapement::Off )
190 bSimple = false;
194 if ( bSimple )
195 { // Contains field commands?
196 SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
197 if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
198 bSimple = false;
201 // HTML
202 OUString aValStr, aNumStr;
203 double fVal = 0.0;
204 sal_uInt32 nNumForm = 0;
205 LanguageType eNumLang = LANGUAGE_NONE;
206 if ( pE->pNumStr )
207 { // SDNUM needs to be if SDVAL
208 aNumStr = *pE->pNumStr;
209 if ( pE->pValStr )
210 aValStr = *pE->pValStr;
211 fVal = SfxHTMLParser::GetTableDataOptionsValNum(
212 nNumForm, eNumLang, aValStr, aNumStr, *pFormatter );
215 // Set attributes
216 auto pAttr = std::make_unique<ScPatternAttr>( pDocPool );
217 pAttr->GetFromEditItemSet( &aSet );
218 SfxItemSet* pAttrItemSet = &pAttr->GetItemSet();
219 if (!aNumStr.isEmpty())
221 pAttrItemSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumForm ) );
222 pAttrItemSet->Put( SvxLanguageItem( eNumLang, ATTR_LANGUAGE_FORMAT ) );
224 const SfxItemSet& rESet = pE->aItemSet;
225 if ( rESet.Count() )
227 const SfxPoolItem* pItem;
228 if ( rESet.GetItemState( ATTR_BACKGROUND, false, &pItem) == SfxItemState::SET )
229 pAttrItemSet->Put( *pItem );
230 if ( rESet.GetItemState( ATTR_BORDER, false, &pItem) == SfxItemState::SET )
231 pAttrItemSet->Put( *pItem );
232 if ( rESet.GetItemState( ATTR_SHADOW, false, &pItem) == SfxItemState::SET )
233 pAttrItemSet->Put( *pItem );
234 // HTML
235 if ( rESet.GetItemState( ATTR_HOR_JUSTIFY, false, &pItem) == SfxItemState::SET )
236 pAttrItemSet->Put( *pItem );
237 if ( rESet.GetItemState( ATTR_VER_JUSTIFY, false, &pItem) == SfxItemState::SET )
238 pAttrItemSet->Put( *pItem );
239 if ( rESet.GetItemState( ATTR_LINEBREAK, false, &pItem) == SfxItemState::SET )
240 pAttrItemSet->Put( *pItem );
241 if ( rESet.GetItemState( ATTR_FONT_COLOR, false, &pItem) == SfxItemState::SET )
242 pAttrItemSet->Put( *pItem );
243 if ( rESet.GetItemState( ATTR_FONT_UNDERLINE, false, &pItem) == SfxItemState::SET )
244 pAttrItemSet->Put( *pItem );
245 // HTML LATIN/CJK/CTL script type dependent
246 const SfxPoolItem* pFont;
247 if ( rESet.GetItemState( ATTR_FONT, false, &pFont) != SfxItemState::SET )
248 pFont = nullptr;
249 const SfxPoolItem* pHeight;
250 if ( rESet.GetItemState( ATTR_FONT_HEIGHT, false, &pHeight) != SfxItemState::SET )
251 pHeight = nullptr;
252 const SfxPoolItem* pWeight;
253 if ( rESet.GetItemState( ATTR_FONT_WEIGHT, false, &pWeight) != SfxItemState::SET )
254 pWeight = nullptr;
255 const SfxPoolItem* pPosture;
256 if ( rESet.GetItemState( ATTR_FONT_POSTURE, false, &pPosture) != SfxItemState::SET )
257 pPosture = nullptr;
258 // Number format
259 const SfxPoolItem* pNumFmt = nullptr;
260 if ( rESet.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SfxItemState::SET )
261 pAttrItemSet->Put(*pNumFmt);
262 if ( pFont || pHeight || pWeight || pPosture )
264 OUString aStr( mpEngine->GetText( pE->aSel ) );
265 SvtScriptType nScriptType = mpDoc->GetStringScriptType( aStr );
266 const SvtScriptType nScripts[3] = { SvtScriptType::LATIN,
267 SvtScriptType::ASIAN, SvtScriptType::COMPLEX };
268 for (SvtScriptType nScript : nScripts)
270 if ( nScriptType & nScript )
272 if ( pFont )
274 pAttrItemSet->Put( pFont->CloneSetWhich(
275 ScGlobal::GetScriptedWhichID(nScript, ATTR_FONT )) );
277 if ( pHeight )
279 pAttrItemSet->Put( pHeight->CloneSetWhich(
280 ScGlobal::GetScriptedWhichID(nScript, ATTR_FONT_HEIGHT )) );
282 if ( pWeight )
284 pAttrItemSet->Put( pWeight->CloneSetWhich(
285 ScGlobal::GetScriptedWhichID(nScript, ATTR_FONT_WEIGHT )) );
287 if ( pPosture )
289 pAttrItemSet->Put( pPosture->CloneSetWhich(
290 ScGlobal::GetScriptedWhichID(nScript, ATTR_FONT_POSTURE )) );
296 if ( pE->nColOverlap > 1 || pE->nRowOverlap > 1 )
297 { // Merged cells, with SfxItemSet.Put() is faster than
298 // with ScDocument.DoMerge() afterwards
299 ScMergeAttr aMerge( pE->nColOverlap, pE->nRowOverlap );
300 pAttrItemSet->Put( aMerge );
301 SCROW nRO = 0;
302 if ( pE->nColOverlap > 1 )
303 mpDoc->ApplyFlagsTab( nCol+1, nRow,
304 nCol + pE->nColOverlap - 1, nRow, nTab,
305 ScMF::Hor );
306 if ( pE->nRowOverlap > 1 )
308 nRO = nRow + pE->nRowOverlap - 1;
309 mpDoc->ApplyFlagsTab( nCol, nRow+1,
310 nCol, nRO , nTab,
311 ScMF::Ver );
312 if ( nRO > nOverlapRowMax )
313 nOverlapRowMax = nRO;
315 if ( pE->nColOverlap > 1 && pE->nRowOverlap > 1 )
316 mpDoc->ApplyFlagsTab( nCol+1, nRow+1,
317 nCol + pE->nColOverlap - 1, nRO, nTab,
318 ScMF::Hor | ScMF::Ver );
320 const ScStyleSheet* pStyleSheet =
321 mpDoc->GetPattern( nCol, nRow, nTab )->GetStyleSheet();
322 pAttr->SetStyleSheet( const_cast<ScStyleSheet*>(pStyleSheet) );
323 auto rAttrItemSet2 = mpDoc->SetPattern( nCol, nRow, nTab, std::move(pAttr) )->GetItemSet();
325 // Add data
326 if (bSimple)
328 ScSetStringParam aParam;
329 aParam.mpNumFormatter = pFormatter;
330 aParam.mbDetectNumberFormat = true;
331 aParam.meSetTextNumFormat = ScSetStringParam::SpecialNumberOnly;
332 aParam.mbHandleApostrophe = false;
333 aParam.mbCheckLinkFormula = true;
335 if (!aValStr.isEmpty())
336 mpDoc->SetValue( nCol, nRow, nTab, fVal );
337 else if ( !pE->aSel.HasRange() )
339 // maybe ALT text of IMG or similar
340 mpDoc->SetString( nCol, nRow, nTab, pE->aAltText, &aParam );
341 // If SelRange is completely empty, the succeeding text can be in the same paragraph!
343 else
345 OUString aStr;
346 if( pE->bEntirePara )
348 aStr = mpEngine->GetText( pE->aSel.nStartPara );
350 else
352 aStr = comphelper::string::strip(mpEngine->GetText(pE->aSel), ' ');
355 bool bTextFormat = false;
357 const SfxPoolItem* pNumFmt = nullptr;
358 if (rAttrItemSet2.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SfxItemState::SET)
360 sal_uInt32 nNumFmt = static_cast<const SfxUInt32Item*>(pNumFmt)->GetValue();
361 SvNumFormatType nType = pFormatter->GetType(nNumFmt);
362 if (nType == SvNumFormatType::TEXT)
363 // Format is set to Text.
364 bTextFormat = true;
367 // TODO: RTF import should follow the language tag,
368 // currently this follows the HTML options for both, HTML
369 // and RTF.
370 if (bNumbersEnglishUS)
372 pFormatter->ChangeIntl( LANGUAGE_ENGLISH_US);
373 sal_uInt32 nIndex = pFormatter->GetStandardIndex( LANGUAGE_ENGLISH_US);
374 double fEnVal = 0.0;
375 if (pFormatter->IsNumberFormat( aStr, nIndex, fEnVal))
377 sal_uInt32 nNewIndex =
378 pFormatter->GetFormatForLanguageIfBuiltIn(
379 nIndex, LANGUAGE_SYSTEM);
380 OSL_ENSURE( nNewIndex != nIndex, "ScEEImport::WriteToDocument: NumbersEnglishUS not a built-in format?");
381 pFormatter->GetInputLineString( fEnVal, nNewIndex, aStr);
383 else
384 bTextFormat = true;
385 pFormatter->ChangeIntl( LANGUAGE_SYSTEM);
388 // #105460#, #i4180# String cells can't contain tabs or linebreaks
389 // -> replace with spaces
390 aStr = aStr.replaceAll( "\t", " " );
391 aStr = aStr.replaceAll( "\n", " " );
393 if (bTextFormat)
395 aParam.mbDetectNumberFormat = false;
396 aParam.meSetTextNumFormat = ScSetStringParam::Always;
398 else
399 aParam.mbDetectNumberFormat = bConvertDate;
401 mpDoc->SetString(nCol, nRow, nTab, aStr, &aParam);
404 else if (std::unique_ptr<EditTextObject> pTextObject = IsValidSel(*mpEngine, pE->aSel) ? mpEngine->CreateTextObject(pE->aSel) : nullptr)
406 // The cell will own the text object instance.
407 mpDoc->SetEditText(ScAddress(nCol,nRow,nTab), std::move(pTextObject));
409 if ( !pE->maImageList.empty() )
410 bHasGraphics |= GraphicSize( nCol, nRow, pE );
411 if ( pE->pName )
412 { // Anchor Name => RangeName
413 if (!pRangeNames->findByUpperName(ScGlobal::getCharClassPtr()->uppercase(*pE->pName)))
415 ScRangeData* pData = new ScRangeData( *mpDoc, *pE->pName,
416 ScAddress( nCol, nRow, nTab ) );
417 pRangeNames->insert( pData );
421 pProgress->SetStateOnPercent( ++nProgress );
423 if ( bSizeColsRows )
425 // Column widths
426 ColWidthsMap& rColWidths = mpParser->GetColWidths();
427 if ( !rColWidths.empty() )
429 nProgress = 0;
430 pProgress->SetState( nProgress, nEndCol - nStartCol + 1 );
431 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; nCol++ )
433 sal_uInt16 nWidth = 0;
434 ColWidthsMap::const_iterator it = rColWidths.find( nCol );
435 if ( it != rColWidths.end() )
436 nWidth = it->second;
437 if ( nWidth )
438 mpDoc->SetColWidth( nCol, nTab, nWidth );
439 pProgress->SetState( ++nProgress );
442 pProgress.reset(); // SetOptimalHeight has its own ProgressBar
443 // Adjust line height, base is 100% zoom
444 Fraction aZoom( 1, 1 );
445 // Factor is printer to display ratio
446 double nPPTX = ScGlobal::nScreenPPTX * static_cast<double>(aZoom) / nOutputFactor;
447 double nPPTY = ScGlobal::nScreenPPTY * static_cast<double>(aZoom);
448 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
449 sc::RowHeightContext aCxt(mpDoc->MaxRow(), nPPTX, nPPTY, aZoom, aZoom, pVirtDev);
450 aCxt.setExtraHeight(ScGlobal::nLastRowHeightExtra);
451 mpDoc->SetOptimalHeight(aCxt, 0, nEndRow, 0);
453 if ( !maRowHeights.empty() )
455 for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow++ )
457 RowHeightMap::const_iterator it = maRowHeights.find( nRow );
458 sal_uInt16 nHeight = it == maRowHeights.end() ? 0 : it->second;
459 if ( nHeight > mpDoc->GetRowHeight( nRow, nTab ) )
460 mpDoc->SetRowHeight( nRow, nTab, nHeight );
464 if ( !bHasGraphics )
465 return;
467 // Insert graphics
468 for ( size_t i = 0, nListSize = mpParser->ListSize(); i < nListSize; ++i )
470 pE = mpParser->ListEntry( i );
471 if ( !pE->maImageList.empty() )
473 SCCOL nCol = pE->nCol;
474 SCROW nRow = pE->nRow;
475 if ( mpDoc->ValidCol(nCol) && mpDoc->ValidRow(nRow) )
476 InsertGraphic( nCol, nRow, nTab, pE );
481 bool ScEEImport::GraphicSize( SCCOL nCol, SCROW nRow, ScEEParseEntry* pE )
483 if ( pE->maImageList.empty() )
484 return false;
485 bool bHasGraphics = false;
486 OutputDevice* pDefaultDev = Application::GetDefaultDevice();
487 tools::Long nWidth, nHeight;
488 nWidth = nHeight = 0;
489 char nDir = nHorizontal;
490 for (const std::unique_ptr<ScHTMLImage> & pImage : pE->maImageList)
492 ScHTMLImage* pI = pImage.get();
493 if ( pI->pGraphic )
494 bHasGraphics = true;
495 Size aSizePix = pI->aSize;
496 aSizePix.AdjustWidth(2 * pI->aSpace.X() );
497 aSizePix.AdjustHeight(2 * pI->aSpace.Y() );
498 Size aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MapUnit::MapTwip ) );
499 if ( nDir & nHorizontal )
500 nWidth += aLogicSize.Width();
501 else if ( nWidth < aLogicSize.Width() )
502 nWidth = aLogicSize.Width();
503 if ( nDir & nVertical )
504 nHeight += aLogicSize.Height();
505 else if ( nHeight < aLogicSize.Height() )
506 nHeight = aLogicSize.Height();
507 nDir = pI->nDir;
509 // Column widths
510 ColWidthsMap& rColWidths = mpParser->GetColWidths();
511 tools::Long nThisWidth = 0;
512 ColWidthsMap::const_iterator it = rColWidths.find( nCol );
513 if ( it != rColWidths.end() )
514 nThisWidth = it->second;
515 tools::Long nColWidths = nThisWidth;
516 SCCOL nColSpanCol = nCol + pE->nColOverlap;
517 for ( SCCOL nC = nCol + 1; nC < nColSpanCol; nC++ )
519 ColWidthsMap::const_iterator it2 = rColWidths.find( nC );
520 if ( it2 != rColWidths.end() )
521 nColWidths += it2->second;
523 if ( nWidth > nColWidths )
524 { // Only insert difference in first column
525 rColWidths[ nCol ] = nWidth - nColWidths + nThisWidth;
527 // Distribute line height difference between all affected lines
528 SCROW nRowSpan = pE->nRowOverlap;
529 nHeight /= nRowSpan;
530 if ( nHeight == 0 )
531 nHeight = 1; // For definite comparison
532 for ( SCROW nR = nRow; nR < nRow + nRowSpan; nR++ )
534 RowHeightMap::const_iterator it2 = maRowHeights.find( nR );
535 tools::Long nRowHeight = it2 == maRowHeights.end() ? 0 : it2->second;
536 if ( nHeight > nRowHeight )
538 maRowHeights[ nR ] = nHeight;
541 return bHasGraphics;
544 void ScEEImport::InsertGraphic( SCCOL nCol, SCROW nRow, SCTAB nTab,
545 ScEEParseEntry* pE )
547 if ( pE->maImageList.empty() )
548 return ;
549 ScDrawLayer* pModel = mpDoc->GetDrawLayer();
550 if (!pModel)
552 mpDoc->InitDrawLayer();
553 pModel = mpDoc->GetDrawLayer();
555 SdrPage* pPage = pModel->GetPage( static_cast<sal_uInt16>(nTab) );
556 OutputDevice* pDefaultDev = Application::GetDefaultDevice();
558 Point aCellInsertPos(
559 static_cast<tools::Long>(static_cast<double>(mpDoc->GetColOffset( nCol, nTab )) * HMM_PER_TWIPS),
560 static_cast<tools::Long>(static_cast<double>(mpDoc->GetRowOffset( nRow, nTab )) * HMM_PER_TWIPS) );
562 Point aInsertPos( aCellInsertPos );
563 Point aSpace;
564 Size aLogicSize;
565 char nDir = nHorizontal;
566 for (const std::unique_ptr<ScHTMLImage> & pImage : pE->maImageList)
568 ScHTMLImage* pI = pImage.get();
569 if ( nDir & nHorizontal )
570 { // Horizontal
571 aInsertPos.AdjustX(aLogicSize.Width() );
572 aInsertPos.AdjustX(aSpace.X() );
573 aInsertPos.setY( aCellInsertPos.Y() );
575 else
576 { // Vertical
577 aInsertPos.setX( aCellInsertPos.X() );
578 aInsertPos.AdjustY(aLogicSize.Height() );
579 aInsertPos.AdjustY(aSpace.Y() );
581 // Add offset of Spacing
582 aSpace = pDefaultDev->PixelToLogic( pI->aSpace, MapMode( MapUnit::Map100thMM ) );
583 aInsertPos += aSpace;
585 Size aSizePix = pI->aSize;
586 aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MapUnit::Map100thMM ) );
588 // Limit size
589 ::ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
591 if ( pI->pGraphic )
593 tools::Rectangle aRect ( aInsertPos, aLogicSize );
594 SdrGrafObj* pObj = new SdrGrafObj(
595 *pModel,
596 *pI->pGraphic,
597 aRect);
599 // calling SetGraphicLink here doesn't work
600 pObj->SetName( pI->aURL );
602 pPage->InsertObject( pObj );
604 // SetGraphicLink has to be used after inserting the object,
605 // otherwise an empty graphic is swapped in and the contact stuff crashes.
606 // See #i37444#.
607 pObj->SetGraphicLink( pI->aURL );
609 pObj->SetLogicRect( aRect ); // Only after InsertObject!
611 nDir = pI->nDir;
615 ScEEParser::ScEEParser( EditEngine* pEditP ) :
616 pEdit( pEditP ),
617 pPool( EditEngine::CreatePool() ),
618 pDocPool( new ScDocumentPool ),
619 nRtfLastToken(0),
620 nColCnt(0),
621 nRowCnt(0),
622 nColMax(0),
623 nRowMax(0)
625 // pPool is foisted on SvxRTFParser at RtfImportState::Start later on
626 pPool->SetSecondaryPool( pDocPool );
627 pPool->FreezeIdRanges();
628 NewActEntry( nullptr );
631 ScEEParser::~ScEEParser()
633 mxActEntry.reset();
634 maList.clear();
636 // Don't delete Pool until the lists have been deleted
637 pPool->SetSecondaryPool( nullptr );
638 SfxItemPool::Free(pDocPool);
639 SfxItemPool::Free(pPool);
642 void ScEEParser::NewActEntry( const ScEEParseEntry* pE )
643 { // New free-flying mxActEntry
644 mxActEntry = std::make_shared<ScEEParseEntry>(pPool);
645 mxActEntry->aSel.nStartPara = (pE ? pE->aSel.nEndPara + 1 : 0);
646 mxActEntry->aSel.nStartPos = 0;
649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */