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 :
24 : #include <editeng/adjitem.hxx>
25 : #include <editeng/editobj.hxx>
26 : #include <editeng/editview.hxx>
27 : #include <editeng/escpitem.hxx>
28 : #include <editeng/langitem.hxx>
29 : #include <svx/svdograf.hxx>
30 : #include <svx/svdpage.hxx>
31 : #include <editeng/scripttypeitem.hxx>
32 : #include <svtools/htmlcfg.hxx>
33 : #include <sfx2/sfxhtml.hxx>
34 : #include <svtools/parhtml.hxx>
35 : #include <svl/zforlist.hxx>
36 : #include <vcl/virdev.hxx>
37 : #include <vcl/svapp.hxx>
38 : #include <unotools/syslocale.hxx>
39 : #include <unotools/charclass.hxx>
40 : #include <comphelper/string.hxx>
41 :
42 : #include "eeimport.hxx"
43 : #include "global.hxx"
44 : #include "document.hxx"
45 : #include "editutil.hxx"
46 : #include "stlsheet.hxx"
47 : #include "docpool.hxx"
48 : #include "attrib.hxx"
49 : #include "patattr.hxx"
50 : #include "cell.hxx"
51 : #include "eeparser.hxx"
52 : #include "drwlayer.hxx"
53 : #include "rangenam.hxx"
54 : #include "progress.hxx"
55 : #include "stringutil.hxx"
56 :
57 : #include "globstr.hrc"
58 :
59 : // in fuins1.cxx
60 : extern void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage );
61 :
62 : //------------------------------------------------------------------------
63 :
64 2 : ScEEImport::ScEEImport( ScDocument* pDocP, const ScRange& rRange ) :
65 : maRange( rRange ),
66 : mpDoc( pDocP ),
67 2 : mpParser( NULL )
68 : {
69 : const ScPatternAttr* pPattern = mpDoc->GetPattern(
70 2 : maRange.aStart.Col(), maRange.aStart.Row(), maRange.aStart.Tab() );
71 2 : mpEngine = new ScTabEditEngine( *pPattern, mpDoc->GetEditPool() );
72 2 : mpEngine->SetUpdateMode( false );
73 2 : mpEngine->EnableUndo( false );
74 2 : }
75 :
76 :
77 4 : ScEEImport::~ScEEImport()
78 : {
79 : // Reihenfolge wichtig, sonst knallt's irgendwann irgendwo in irgendeinem Dtor!
80 : // Ist gewaehrleistet, da ScEEImport Basisklasse ist
81 2 : delete mpEngine; // nach Parser!
82 2 : }
83 :
84 :
85 2 : sal_uLong ScEEImport::Read( SvStream& rStream, const String& rBaseURL )
86 : {
87 2 : sal_uLong nErr = mpParser->Read( rStream, rBaseURL );
88 :
89 : SCCOL nEndCol;
90 : SCROW nEndRow;
91 2 : mpParser->GetDimensions( nEndCol, nEndRow );
92 2 : if ( nEndCol != 0 )
93 : {
94 2 : nEndCol += maRange.aStart.Col() - 1;
95 2 : if ( nEndCol > MAXCOL )
96 0 : nEndCol = MAXCOL;
97 : }
98 : else
99 0 : nEndCol = maRange.aStart.Col();
100 2 : if ( nEndRow != 0 )
101 : {
102 2 : nEndRow += maRange.aStart.Row() - 1;
103 2 : if ( nEndRow > MAXROW )
104 0 : nEndRow = MAXROW;
105 : }
106 : else
107 0 : nEndRow = maRange.aStart.Row();
108 2 : maRange.aEnd.Set( nEndCol, nEndRow, maRange.aStart.Tab() );
109 :
110 2 : return nErr;
111 : }
112 :
113 :
114 2 : void ScEEImport::WriteToDocument( bool bSizeColsRows, double nOutputFactor, SvNumberFormatter* pFormatter, bool bConvertDate )
115 : {
116 2 : ScProgress* pProgress = new ScProgress( mpDoc->GetDocumentShell(),
117 2 : ScGlobal::GetRscString( STR_LOAD_DOC ), mpParser->ListSize() );
118 2 : sal_uLong nProgress = 0;
119 :
120 : SCCOL nStartCol, nEndCol;
121 : SCROW nStartRow, nEndRow;
122 : SCTAB nTab;
123 : SCROW nOverlapRowMax, nLastMergedRow;
124 : SCCOL nMergeColAdd;
125 2 : nStartCol = maRange.aStart.Col();
126 2 : nStartRow = maRange.aStart.Row();
127 2 : nTab = maRange.aStart.Tab();
128 2 : nEndCol = maRange.aEnd.Col();
129 2 : nEndRow = maRange.aEnd.Row();
130 2 : nOverlapRowMax = 0;
131 2 : nMergeColAdd = 0;
132 2 : nLastMergedRow = SCROW_MAX;
133 2 : sal_Bool bHasGraphics = false;
134 : ScEEParseEntry* pE;
135 2 : if (!pFormatter)
136 0 : pFormatter = mpDoc->GetFormatTable();
137 2 : bool bNumbersEnglishUS = false;
138 2 : if (pFormatter->GetLanguage() == LANGUAGE_SYSTEM)
139 : {
140 : // Automatic language option selected. Check for the global 'use US English' option.
141 2 : SvxHtmlOptions aOpt;
142 2 : bNumbersEnglishUS = aOpt.IsNumbersEnglishUS();
143 : }
144 2 : ScDocumentPool* pDocPool = mpDoc->GetPool();
145 2 : ScRangeName* pRangeNames = mpDoc->GetRangeName();
146 16 : for ( size_t i = 0, n = mpParser->ListSize(); i < n; ++i )
147 : {
148 14 : pE = mpParser->ListEntry( i );
149 14 : SCROW nRow = nStartRow + pE->nRow;
150 14 : if ( nRow != nLastMergedRow )
151 10 : nMergeColAdd = 0;
152 14 : SCCOL nCol = nStartCol + pE->nCol + nMergeColAdd;
153 : // RowMerge feststellen, pures ColMerge und ColMerge der ersten
154 : // MergeRow bereits beim parsen
155 14 : if ( nRow <= nOverlapRowMax )
156 : {
157 18 : while ( nCol <= MAXCOL && mpDoc->HasAttrib( nCol, nRow, nTab,
158 6 : nCol, nRow, nTab, HASATTR_OVERLAPPED ) )
159 : {
160 0 : nCol++;
161 0 : nMergeColAdd++;
162 : }
163 6 : nLastMergedRow = nRow;
164 : }
165 : // fuer zweiten Durchlauf eintragen
166 14 : pE->nCol = nCol;
167 14 : pE->nRow = nRow;
168 14 : if ( ValidCol(nCol) && ValidRow(nRow) )
169 : {
170 12 : SfxItemSet aSet = mpEngine->GetAttribs( pE->aSel );
171 : // Default raus, wir setzen selber links/rechts je nachdem ob Text
172 : // oder Zahl; EditView.GetAttribs liefert immer kompletten Set
173 : // mit Defaults aufgefuellt
174 12 : const SfxPoolItem& rItem = aSet.Get( EE_PARA_JUST );
175 12 : if ( ((const SvxAdjustItem&)rItem).GetAdjust() == SVX_ADJUST_LEFT )
176 12 : aSet.ClearItem( EE_PARA_JUST );
177 :
178 : // Testen, ob einfacher String ohne gemischte Attribute
179 12 : sal_Bool bSimple = ( pE->aSel.nStartPara == pE->aSel.nEndPara );
180 372 : for (sal_uInt16 nId = EE_CHAR_START; nId <= EE_CHAR_END && bSimple; nId++)
181 : {
182 360 : const SfxPoolItem* pItem = 0;
183 360 : SfxItemState eState = aSet.GetItemState( nId, sal_True, &pItem );
184 360 : if (eState == SFX_ITEM_DONTCARE)
185 0 : bSimple = false;
186 360 : else if (eState == SFX_ITEM_SET)
187 : {
188 348 : if ( nId == EE_CHAR_ESCAPEMENT ) // Hoch-/Tiefstellen immer ueber EE
189 : {
190 12 : if ( (SvxEscapement)((const SvxEscapementItem*)pItem)->GetEnumValue()
191 : != SVX_ESCAPEMENT_OFF )
192 0 : bSimple = false;
193 : }
194 : }
195 : }
196 12 : if ( bSimple )
197 : { // Feldbefehle enthalten?
198 12 : SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
199 12 : if ( eFieldState == SFX_ITEM_DONTCARE || eFieldState == SFX_ITEM_SET )
200 0 : bSimple = false;
201 : }
202 :
203 : // HTML
204 12 : rtl::OUString aValStr, aNumStr;
205 : double fVal;
206 12 : sal_uInt32 nNumForm = 0;
207 12 : LanguageType eNumLang = LANGUAGE_NONE;
208 12 : if ( pE->pNumStr )
209 : { // SDNUM muss sein wenn SDVAL
210 0 : aNumStr = *pE->pNumStr;
211 0 : if ( pE->pValStr )
212 0 : aValStr = *pE->pValStr;
213 : fVal = SfxHTMLParser::GetTableDataOptionsValNum(
214 0 : nNumForm, eNumLang, aValStr, aNumStr, *pFormatter );
215 : }
216 :
217 : // Attribute setzen
218 12 : ScPatternAttr aAttr( pDocPool );
219 12 : aAttr.GetFromEditItemSet( &aSet );
220 12 : SfxItemSet& rSet = aAttr.GetItemSet();
221 12 : if (!aNumStr.isEmpty())
222 : {
223 0 : rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumForm ) );
224 0 : rSet.Put( SvxLanguageItem( eNumLang, ATTR_LANGUAGE_FORMAT ) );
225 : }
226 12 : const SfxItemSet& rESet = pE->aItemSet;
227 12 : if ( rESet.Count() )
228 : {
229 : const SfxPoolItem* pItem;
230 0 : if ( rESet.GetItemState( ATTR_BACKGROUND, false, &pItem) == SFX_ITEM_SET )
231 0 : rSet.Put( *pItem );
232 0 : if ( rESet.GetItemState( ATTR_BORDER, false, &pItem) == SFX_ITEM_SET )
233 0 : rSet.Put( *pItem );
234 0 : if ( rESet.GetItemState( ATTR_SHADOW, false, &pItem) == SFX_ITEM_SET )
235 0 : rSet.Put( *pItem );
236 : // HTML
237 0 : if ( rESet.GetItemState( ATTR_HOR_JUSTIFY, false, &pItem) == SFX_ITEM_SET )
238 0 : rSet.Put( *pItem );
239 0 : if ( rESet.GetItemState( ATTR_VER_JUSTIFY, false, &pItem) == SFX_ITEM_SET )
240 0 : rSet.Put( *pItem );
241 0 : if ( rESet.GetItemState( ATTR_LINEBREAK, false, &pItem) == SFX_ITEM_SET )
242 0 : rSet.Put( *pItem );
243 0 : if ( rESet.GetItemState( ATTR_FONT_COLOR, false, &pItem) == SFX_ITEM_SET )
244 0 : rSet.Put( *pItem );
245 0 : if ( rESet.GetItemState( ATTR_FONT_UNDERLINE, false, &pItem) == SFX_ITEM_SET )
246 0 : rSet.Put( *pItem );
247 : // HTML LATIN/CJK/CTL script type dependent
248 : const SfxPoolItem* pFont;
249 0 : if ( rESet.GetItemState( ATTR_FONT, false, &pFont) != SFX_ITEM_SET )
250 0 : pFont = 0;
251 : const SfxPoolItem* pHeight;
252 0 : if ( rESet.GetItemState( ATTR_FONT_HEIGHT, false, &pHeight) != SFX_ITEM_SET )
253 0 : pHeight = 0;
254 : const SfxPoolItem* pWeight;
255 0 : if ( rESet.GetItemState( ATTR_FONT_WEIGHT, false, &pWeight) != SFX_ITEM_SET )
256 0 : pWeight = 0;
257 : const SfxPoolItem* pPosture;
258 0 : if ( rESet.GetItemState( ATTR_FONT_POSTURE, false, &pPosture) != SFX_ITEM_SET )
259 0 : pPosture = 0;
260 : // Number format
261 0 : const SfxPoolItem* pNumFmt = NULL;
262 0 : if ( rESet.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SFX_ITEM_SET )
263 0 : rSet.Put(*pNumFmt);
264 0 : if ( pFont || pHeight || pWeight || pPosture )
265 : {
266 0 : String aStr( mpEngine->GetText( pE->aSel ) );
267 0 : sal_uInt8 nScriptType = mpDoc->GetStringScriptType( aStr );
268 : const sal_uInt8 nScripts[3] = { SCRIPTTYPE_LATIN,
269 0 : SCRIPTTYPE_ASIAN, SCRIPTTYPE_COMPLEX };
270 0 : for ( sal_uInt8 j=0; j<3; ++j )
271 : {
272 0 : if ( nScriptType & nScripts[j] )
273 : {
274 0 : if ( pFont )
275 : rSet.Put( *pFont, ScGlobal::GetScriptedWhichID(
276 0 : nScripts[j], ATTR_FONT ));
277 0 : if ( pHeight )
278 : rSet.Put( *pHeight, ScGlobal::GetScriptedWhichID(
279 0 : nScripts[j], ATTR_FONT_HEIGHT ));
280 0 : if ( pWeight )
281 : rSet.Put( *pWeight, ScGlobal::GetScriptedWhichID(
282 0 : nScripts[j], ATTR_FONT_WEIGHT ));
283 0 : if ( pPosture )
284 : rSet.Put( *pPosture, ScGlobal::GetScriptedWhichID(
285 0 : nScripts[j], ATTR_FONT_POSTURE ));
286 : }
287 0 : }
288 : }
289 : }
290 12 : if ( pE->nColOverlap > 1 || pE->nRowOverlap > 1 )
291 : { // merged cells, mit SfxItemSet Put schneller als mit
292 : // nachtraeglichem ScDocument DoMerge
293 0 : ScMergeAttr aMerge( pE->nColOverlap, pE->nRowOverlap );
294 0 : rSet.Put( aMerge );
295 0 : SCROW nRO = 0;
296 0 : if ( pE->nColOverlap > 1 )
297 : mpDoc->ApplyFlagsTab( nCol+1, nRow,
298 : nCol + pE->nColOverlap - 1, nRow, nTab,
299 0 : SC_MF_HOR );
300 0 : if ( pE->nRowOverlap > 1 )
301 : {
302 0 : nRO = nRow + pE->nRowOverlap - 1;
303 : mpDoc->ApplyFlagsTab( nCol, nRow+1,
304 : nCol, nRO , nTab,
305 0 : SC_MF_VER );
306 0 : if ( nRO > nOverlapRowMax )
307 0 : nOverlapRowMax = nRO;
308 : }
309 0 : if ( pE->nColOverlap > 1 && pE->nRowOverlap > 1 )
310 : mpDoc->ApplyFlagsTab( nCol+1, nRow+1,
311 : nCol + pE->nColOverlap - 1, nRO, nTab,
312 0 : SC_MF_HOR | SC_MF_VER );
313 : }
314 : const ScStyleSheet* pStyleSheet =
315 12 : mpDoc->GetPattern( nCol, nRow, nTab )->GetStyleSheet();
316 12 : aAttr.SetStyleSheet( (ScStyleSheet*)pStyleSheet );
317 12 : mpDoc->SetPattern( nCol, nRow, nTab, aAttr, sal_True );
318 :
319 : // Daten eintragen
320 12 : if (bSimple)
321 : {
322 12 : ScSetStringParam aParam;
323 12 : aParam.mpNumFormatter = pFormatter;
324 12 : aParam.mbDetectNumberFormat = true;
325 12 : aParam.meSetTextNumFormat = ScSetStringParam::SpecialNumberOnly;
326 12 : aParam.mbHandleApostrophe = false;
327 :
328 12 : if (!aValStr.isEmpty())
329 0 : mpDoc->SetValue( nCol, nRow, nTab, fVal );
330 12 : else if ( !pE->aSel.HasRange() )
331 : {
332 : // maybe ALT text of IMG or similar
333 0 : mpDoc->SetString( nCol, nRow, nTab, pE->aAltText, &aParam );
334 : // wenn SelRange komplett leer kann nachfolgender Text im gleichen Absatz liegen!
335 : }
336 : else
337 : {
338 12 : String aStr;
339 12 : if( pE->bEntirePara )
340 : {
341 0 : aStr = mpEngine->GetText( pE->aSel.nStartPara );
342 : }
343 : else
344 : {
345 12 : aStr = comphelper::string::strip(mpEngine->GetText(pE->aSel), ' ');
346 : }
347 :
348 12 : bool bTextFormat = false;
349 :
350 12 : const SfxPoolItem* pNumFmt = NULL;
351 12 : if (rSet.GetItemState(ATTR_VALUE_FORMAT, false, &pNumFmt) == SFX_ITEM_SET)
352 : {
353 0 : sal_uInt32 nNumFmt = static_cast<const SfxUInt32Item*>(pNumFmt)->GetValue();
354 0 : sal_uInt16 nType = pFormatter->GetType(nNumFmt);
355 0 : if (nType == NUMBERFORMAT_TEXT)
356 : // Format is set to Text.
357 0 : bTextFormat = true;
358 : }
359 :
360 : // TODO: RTF import should follow the language tag,
361 : // currently this follows the HTML options for both, HTML
362 : // and RTF.
363 12 : if (bNumbersEnglishUS)
364 : {
365 0 : pFormatter->ChangeIntl( LANGUAGE_ENGLISH_US);
366 0 : sal_uInt32 nIndex = pFormatter->GetStandardIndex( LANGUAGE_ENGLISH_US);
367 0 : double fEnVal = 0.0;
368 0 : if (pFormatter->IsNumberFormat( aStr, nIndex, fEnVal))
369 : {
370 : sal_uInt32 nNewIndex =
371 : pFormatter->GetFormatForLanguageIfBuiltIn(
372 0 : nIndex, LANGUAGE_SYSTEM);
373 : OSL_ENSURE( nNewIndex != nIndex, "ScEEImport::WriteToDocument: NumbersEnglishUS not a built-in format?");
374 0 : pFormatter->GetInputLineString( fEnVal, nNewIndex, aStr);
375 : }
376 : else
377 0 : bTextFormat = true;
378 0 : pFormatter->ChangeIntl( LANGUAGE_SYSTEM);
379 : }
380 :
381 : // #105460#, #i4180# String cells can't contain tabs or linebreaks
382 : // -> replace with spaces
383 12 : aStr.SearchAndReplaceAll( (sal_Unicode)'\t', (sal_Unicode)' ' );
384 12 : aStr.SearchAndReplaceAll( (sal_Unicode)'\n', (sal_Unicode)' ' );
385 :
386 12 : if (bTextFormat)
387 0 : mpDoc->PutCell( nCol, nRow, nTab, new ScStringCell( aStr));
388 : else
389 : {
390 12 : aParam.mbDetectNumberFormat = bConvertDate;
391 12 : mpDoc->SetString( nCol, nRow, nTab, aStr, &aParam );
392 12 : }
393 : }
394 : }
395 : else
396 : {
397 0 : EditTextObject* pObject = mpEngine->CreateTextObject( pE->aSel );
398 : mpDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pObject,
399 0 : mpDoc, mpEngine->GetEditTextObjectPool() ) );
400 0 : delete pObject;
401 : }
402 12 : if ( pE->maImageList.size() )
403 0 : bHasGraphics |= GraphicSize( nCol, nRow, nTab, pE );
404 12 : if ( pE->pName )
405 : { // Anchor Name => RangeName
406 0 : if (!pRangeNames->findByUpperName(ScGlobal::pCharClass->uppercase(*pE->pName)))
407 : {
408 : ScRangeData* pData = new ScRangeData( mpDoc, *pE->pName,
409 0 : ScAddress( nCol, nRow, nTab ) );
410 0 : pRangeNames->insert( pData );
411 : }
412 12 : }
413 : }
414 14 : pProgress->SetStateOnPercent( ++nProgress );
415 : }
416 2 : if ( bSizeColsRows )
417 : {
418 : // Spaltenbreiten
419 2 : ColWidthsMap& rColWidths = mpParser->GetColWidths();
420 2 : if ( !rColWidths.empty() )
421 : {
422 0 : nProgress = 0;
423 0 : pProgress->SetState( nProgress, nEndCol - nStartCol + 1 );
424 0 : for ( SCCOL nCol = nStartCol; nCol <= nEndCol; nCol++ )
425 : {
426 0 : sal_uInt16 nWidth = 0;
427 0 : ColWidthsMap::const_iterator it = rColWidths.find( nCol );
428 0 : if ( it != rColWidths.end() )
429 0 : nWidth = it->second;
430 0 : if ( nWidth )
431 0 : mpDoc->SetColWidth( nCol, nTab, nWidth );
432 0 : pProgress->SetState( ++nProgress );
433 : }
434 : }
435 2 : DELETEZ( pProgress ); // SetOptimalHeight hat seinen eigenen ProgressBar
436 : // Zeilenhoehen anpassen, Basis 100% Zoom
437 2 : Fraction aZoom( 1, 1 );
438 2 : double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom
439 2 : / nOutputFactor; // Faktor ist Drucker zu Bildschirm
440 2 : double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
441 2 : VirtualDevice aVirtDev;
442 : mpDoc->SetOptimalHeight( 0, nEndRow, 0,
443 : static_cast< sal_uInt16 >( ScGlobal::nLastRowHeightExtra ), &aVirtDev,
444 2 : nPPTX, nPPTY, aZoom, aZoom, false );
445 2 : if ( !maRowHeights.empty() )
446 : {
447 0 : for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow++ )
448 : {
449 0 : RowHeightMap::const_iterator it = maRowHeights.find( nRow );
450 0 : sal_uInt16 nHeight = it == maRowHeights.end() ? 0 : it->second;
451 0 : if ( nHeight > mpDoc->GetRowHeight( nRow, nTab ) )
452 0 : mpDoc->SetRowHeight( nRow, nTab, nHeight );
453 : }
454 2 : }
455 : }
456 2 : if ( bHasGraphics )
457 : {
458 : // Grafiken einfuegen
459 0 : for ( size_t i = 0, nListSize = mpParser->ListSize(); i < nListSize; ++i )
460 : {
461 0 : pE = mpParser->ListEntry( i );
462 0 : if ( !pE->maImageList.empty() )
463 : {
464 0 : SCCOL nCol = pE->nCol;
465 0 : SCROW nRow = pE->nRow;
466 0 : if ( ValidCol(nCol) && ValidRow(nRow) )
467 0 : InsertGraphic( nCol, nRow, nTab, pE );
468 : }
469 : }
470 : }
471 2 : if ( pProgress )
472 0 : delete pProgress;
473 2 : }
474 :
475 :
476 0 : sal_Bool ScEEImport::GraphicSize( SCCOL nCol, SCROW nRow, SCTAB /*nTab*/, ScEEParseEntry* pE )
477 : {
478 0 : if ( !pE->maImageList.size() )
479 0 : return false;
480 0 : sal_Bool bHasGraphics = false;
481 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
482 : long nWidth, nHeight;
483 0 : nWidth = nHeight = 0;
484 0 : sal_Char nDir = nHorizontal;
485 0 : for ( sal_uInt32 i = 0; i < pE->maImageList.size() ; ++i )
486 : {
487 0 : ScHTMLImage* pI = &pE->maImageList[ i ];
488 0 : if ( pI->pGraphic )
489 0 : bHasGraphics = sal_True;
490 0 : Size aSizePix = pI->aSize;
491 0 : aSizePix.Width() += 2 * pI->aSpace.X();
492 0 : aSizePix.Height() += 2 * pI->aSpace.Y();
493 0 : Size aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_TWIP ) );
494 0 : if ( nDir & nHorizontal )
495 0 : nWidth += aLogicSize.Width();
496 0 : else if ( nWidth < aLogicSize.Width() )
497 0 : nWidth = aLogicSize.Width();
498 0 : if ( nDir & nVertical )
499 0 : nHeight += aLogicSize.Height();
500 0 : else if ( nHeight < aLogicSize.Height() )
501 0 : nHeight = aLogicSize.Height();
502 0 : nDir = pI->nDir;
503 : }
504 : // Spaltenbreiten
505 0 : ColWidthsMap& rColWidths = mpParser->GetColWidths();
506 0 : long nThisWidth = 0;
507 0 : ColWidthsMap::const_iterator it = rColWidths.find( nCol );
508 0 : if ( it != rColWidths.end() )
509 0 : nThisWidth = it->second;
510 0 : long nColWidths = nThisWidth;
511 0 : SCCOL nColSpanCol = nCol + pE->nColOverlap;
512 0 : for ( SCCOL nC = nCol + 1; nC < nColSpanCol; nC++ )
513 : {
514 0 : ColWidthsMap::const_iterator it2 = rColWidths.find( nC );
515 0 : if ( it2 != rColWidths.end() )
516 0 : nColWidths += it2->second;
517 : }
518 0 : if ( nWidth > nColWidths )
519 : { // Differenz nur in der ersten Spalte eintragen
520 0 : rColWidths[ nCol ] = nWidth - nColWidths + nThisWidth;
521 : }
522 : // Zeilenhoehen, Differenz auf alle betroffenen Zeilen verteilen
523 0 : SCROW nRowSpan = pE->nRowOverlap;
524 0 : nHeight /= nRowSpan;
525 0 : if ( nHeight == 0 )
526 0 : nHeight = 1; // fuer eindeutigen Vergleich
527 0 : for ( SCROW nR = nRow; nR < nRow + nRowSpan; nR++ )
528 : {
529 0 : RowHeightMap::const_iterator it2 = maRowHeights.find( nR );
530 0 : long nRowHeight = it2 == maRowHeights.end() ? 0 : it2->second;
531 0 : if ( nHeight > nRowHeight )
532 : {
533 0 : maRowHeights[ nR ] = nHeight;
534 : }
535 : }
536 0 : return bHasGraphics;
537 : }
538 :
539 :
540 0 : void ScEEImport::InsertGraphic( SCCOL nCol, SCROW nRow, SCTAB nTab,
541 : ScEEParseEntry* pE )
542 : {
543 0 : if ( !pE->maImageList.size() )
544 0 : return ;
545 0 : ScDrawLayer* pModel = mpDoc->GetDrawLayer();
546 0 : if (!pModel)
547 : {
548 0 : mpDoc->InitDrawLayer();
549 0 : pModel = mpDoc->GetDrawLayer();
550 : }
551 0 : SdrPage* pPage = pModel->GetPage( static_cast<sal_uInt16>(nTab) );
552 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
553 :
554 : Point aCellInsertPos(
555 0 : (long)((double) mpDoc->GetColOffset( nCol, nTab ) * HMM_PER_TWIPS),
556 0 : (long)((double) mpDoc->GetRowOffset( nRow, nTab ) * HMM_PER_TWIPS) );
557 :
558 0 : Point aInsertPos( aCellInsertPos );
559 0 : Point aSpace;
560 0 : Size aLogicSize;
561 0 : sal_Char nDir = nHorizontal;
562 0 : for ( sal_uInt32 i = 0; i < pE->maImageList.size(); ++i )
563 : {
564 0 : ScHTMLImage* pI = &pE->maImageList[ i ];
565 0 : if ( nDir & nHorizontal )
566 : { // horizontal
567 0 : aInsertPos.X() += aLogicSize.Width();
568 0 : aInsertPos.X() += aSpace.X();
569 0 : aInsertPos.Y() = aCellInsertPos.Y();
570 : }
571 : else
572 : { // vertikal
573 0 : aInsertPos.X() = aCellInsertPos.X();
574 0 : aInsertPos.Y() += aLogicSize.Height();
575 0 : aInsertPos.Y() += aSpace.Y();
576 : }
577 : // Offset des Spacings drauf
578 0 : aSpace = pDefaultDev->PixelToLogic( pI->aSpace, MapMode( MAP_100TH_MM ) );
579 0 : aInsertPos += aSpace;
580 :
581 0 : Size aSizePix = pI->aSize;
582 0 : aLogicSize = pDefaultDev->PixelToLogic( aSizePix, MapMode( MAP_100TH_MM ) );
583 : // Groesse begrenzen
584 0 : ::ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
585 :
586 0 : if ( pI->pGraphic )
587 : {
588 0 : Rectangle aRect ( aInsertPos, aLogicSize );
589 0 : SdrGrafObj* pObj = new SdrGrafObj( *pI->pGraphic, aRect );
590 : // calling SetGraphicLink here doesn't work
591 0 : pObj->SetName( pI->aURL );
592 :
593 0 : pPage->InsertObject( pObj );
594 :
595 : // SetGraphicLink has to be used after inserting the object,
596 : // otherwise an empty graphic is swapped in and the contact stuff crashes.
597 : // See #i37444#.
598 0 : pObj->SetGraphicLink( pI->aURL, pI->aFilterName );
599 :
600 0 : pObj->SetLogicRect( aRect ); // erst nach InsertObject !!!
601 : }
602 0 : nDir = pI->nDir;
603 : }
604 : }
605 :
606 :
607 2 : ScEEParser::ScEEParser( EditEngine* pEditP ) :
608 : pEdit( pEditP ),
609 2 : pPool( EditEngine::CreatePool() ),
610 2 : pDocPool( new ScDocumentPool ),
611 : nLastToken(0),
612 : nColCnt(0),
613 : nRowCnt(0),
614 : nColMax(0),
615 6 : nRowMax(0)
616 : {
617 : // pPool wird spaeter bei RTFIMP_START dem SvxRTFParser untergejubelt
618 2 : pPool->SetSecondaryPool( pDocPool );
619 2 : pPool->FreezeIdRanges();
620 2 : NewActEntry( NULL );
621 2 : }
622 :
623 :
624 4 : ScEEParser::~ScEEParser()
625 : {
626 2 : delete pActEntry;
627 2 : if ( !maList.empty() ) maList.clear();
628 :
629 : // Pool erst loeschen nachdem die Listen geloescht wurden
630 2 : pPool->SetSecondaryPool( NULL );
631 2 : SfxItemPool::Free(pDocPool);
632 2 : SfxItemPool::Free(pPool);
633 2 : }
634 :
635 :
636 2 : void ScEEParser::NewActEntry( ScEEParseEntry* pE )
637 : { // neuer freifliegender pActEntry
638 2 : pActEntry = new ScEEParseEntry( pPool );
639 2 : pActEntry->aSel.nStartPara = (pE ? pE->aSel.nEndPara + 1 : 0);
640 2 : pActEntry->aSel.nStartPos = 0;
641 2 : }
642 :
643 :
644 :
645 :
646 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|