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