Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <boost/shared_ptr.hpp>
31 : : #include <comphelper/string.hxx>
32 : :
33 : : #define SC_HTMLPARS_CXX
34 : : #include "scitems.hxx"
35 : : #include <editeng/eeitem.hxx>
36 : :
37 : : #include <svtools/htmlcfg.hxx>
38 : : #include <svx/algitem.hxx>
39 : : #include <editeng/colritem.hxx>
40 : : #include <editeng/brshitem.hxx>
41 : : #include <editeng/editeng.hxx>
42 : : #include <editeng/fhgtitem.hxx>
43 : : #include <editeng/fontitem.hxx>
44 : : #include <editeng/postitem.hxx>
45 : : #include <editeng/udlnitem.hxx>
46 : : #include <editeng/wghtitem.hxx>
47 : : #include <editeng/boxitem.hxx>
48 : : #include <editeng/justifyitem.hxx>
49 : : #include <sfx2/objsh.hxx>
50 : : #include <svl/eitem.hxx>
51 : : #include <svl/intitem.hxx>
52 : : #include <svtools/filter.hxx>
53 : : #include <svtools/parhtml.hxx>
54 : : #include <svtools/htmlkywd.hxx>
55 : : #include <svtools/htmltokn.h>
56 : : #include <sfx2/docfile.hxx>
57 : :
58 : : #include <vcl/svapp.hxx>
59 : : #include <tools/urlobj.hxx>
60 : : #include <tools/tenccvt.hxx>
61 : :
62 : : #include "htmlpars.hxx"
63 : : #include "global.hxx"
64 : : #include "document.hxx"
65 : : #include "rangelst.hxx"
66 : :
67 : : #include <orcus/css_parser.hpp>
68 : :
69 : : #include <com/sun/star/document/XDocumentProperties.hpp>
70 : : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
71 : :
72 : : using ::editeng::SvxBorderLine;
73 : : using namespace ::com::sun::star;
74 : :
75 [ + - ][ + - ]: 3 : ScHTMLStyles::ScHTMLStyles() : maEmpty() {}
76 : :
77 : 0 : void ScHTMLStyles::add(const char* pElemName, size_t nElemName, const char* pClassName, size_t nClassName,
78 : : const rtl::OUString& aProp, const rtl::OUString& aValue)
79 : : {
80 [ # # ]: 0 : if (pElemName)
81 : : {
82 [ # # ]: 0 : rtl::OUString aElem(pElemName, nElemName, RTL_TEXTENCODING_UTF8);
83 : 0 : aElem = aElem.toAsciiLowerCase();
84 [ # # ]: 0 : if (pClassName)
85 : : {
86 : : // Both element and class names given.
87 : :
88 [ # # ]: 0 : ElemsType::iterator itrElem = maElemProps.find(aElem);
89 [ # # ][ # # ]: 0 : if (itrElem == maElemProps.end())
[ # # ]
90 : : {
91 : : // new element
92 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
93 [ # # ][ # # ]: 0 : std::auto_ptr<NamePropsType> p(new NamePropsType);
94 : : SAL_WNODEPRECATED_DECLARATIONS_POP
95 [ # # ][ # # ]: 0 : std::pair<ElemsType::iterator, bool> r = maElemProps.insert(aElem, p);
96 [ # # ]: 0 : if (!r.second)
97 : : // insertion failed.
98 : 0 : return;
99 [ # # ][ # # ]: 0 : itrElem = r.first;
100 : : }
101 : :
102 [ # # ]: 0 : NamePropsType* pClsProps = itrElem->second;
103 [ # # ]: 0 : rtl::OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
104 : 0 : aClass = aClass.toAsciiLowerCase();
105 [ # # ]: 0 : insertProp(*pClsProps, aClass, aProp, aValue);
106 : : }
107 : : else
108 : : {
109 : : // Element name only. Add it to the element global.
110 [ # # ]: 0 : insertProp(maElemGlobalProps, aElem, aProp, aValue);
111 [ # # ]: 0 : }
112 : : }
113 : : else
114 : : {
115 [ # # ]: 0 : if (pClassName)
116 : : {
117 : : // Class name only. Add it to the global.
118 [ # # ]: 0 : rtl::OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
119 : 0 : aClass = aClass.toAsciiLowerCase();
120 [ # # ]: 0 : insertProp(maGlobalProps, aClass, aProp, aValue);
121 : : }
122 : : }
123 : : }
124 : :
125 : 0 : const rtl::OUString& ScHTMLStyles::getPropertyValue(
126 : : const rtl::OUString& rElem, const rtl::OUString& rClass, const rtl::OUString& rPropName) const
127 : : {
128 : : // First, look into the element-class storage.
129 : : {
130 [ # # ]: 0 : ElemsType::const_iterator itr = maElemProps.find(rElem);
131 [ # # ][ # # ]: 0 : if (itr != maElemProps.end())
[ # # ]
132 : : {
133 [ # # ]: 0 : const NamePropsType* pClasses = itr->second;
134 [ # # ]: 0 : NamePropsType::const_iterator itr2 = pClasses->find(rClass);
135 [ # # ][ # # ]: 0 : if (itr2 != pClasses->end())
[ # # ]
136 : : {
137 [ # # ]: 0 : const PropsType* pProps = itr2->second;
138 [ # # ]: 0 : PropsType::const_iterator itr3 = pProps->find(rPropName);
139 [ # # ][ # # ]: 0 : if (itr3 != pProps->end())
140 [ # # ]: 0 : return itr3->second;
141 : : }
142 : : }
143 : : }
144 : : // Next, look into the class global storage.
145 : : {
146 [ # # ]: 0 : NamePropsType::const_iterator itr = maGlobalProps.find(rClass);
147 [ # # ][ # # ]: 0 : if (itr != maGlobalProps.end())
[ # # ]
148 : : {
149 [ # # ]: 0 : const PropsType* pProps = itr->second;
150 [ # # ]: 0 : PropsType::const_iterator itr2 = pProps->find(rPropName);
151 [ # # ][ # # ]: 0 : if (itr2 != pProps->end())
152 [ # # ]: 0 : return itr2->second;
153 : : }
154 : : }
155 : : // As the last resort, look into the element global storage.
156 : : {
157 [ # # ]: 0 : NamePropsType::const_iterator itr = maElemGlobalProps.find(rClass);
158 [ # # ][ # # ]: 0 : if (itr != maElemGlobalProps.end())
[ # # ]
159 : : {
160 [ # # ]: 0 : const PropsType* pProps = itr->second;
161 [ # # ]: 0 : PropsType::const_iterator itr2 = pProps->find(rPropName);
162 [ # # ][ # # ]: 0 : if (itr2 != pProps->end())
163 [ # # ]: 0 : return itr2->second;
164 : : }
165 : : }
166 : :
167 : 0 : return maEmpty; // nothing found.
168 : : }
169 : :
170 : 0 : void ScHTMLStyles::insertProp(
171 : : NamePropsType& rStore, const rtl::OUString& aName,
172 : : const rtl::OUString& aProp, const rtl::OUString& aValue)
173 : : {
174 [ # # ]: 0 : NamePropsType::iterator itr = rStore.find(aName);
175 [ # # ][ # # ]: 0 : if (itr == rStore.end())
[ # # ]
176 : : {
177 : : // new element
178 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
179 [ # # ][ # # ]: 0 : std::auto_ptr<PropsType> p(new PropsType);
180 : : SAL_WNODEPRECATED_DECLARATIONS_POP
181 [ # # ][ # # ]: 0 : std::pair<NamePropsType::iterator, bool> r = rStore.insert(aName, p);
182 [ # # ]: 0 : if (!r.second)
183 : : // insertion failed.
184 : 0 : return;
185 : :
186 [ # # ][ # # ]: 0 : itr = r.first;
187 : : }
188 : :
189 [ # # ]: 0 : PropsType* pProps = itr->second;
190 [ # # ]: 0 : pProps->insert(PropsType::value_type(aProp, aValue));
191 : : }
192 : :
193 : : // ============================================================================
194 : : // BASE class for HTML parser classes
195 : : // ============================================================================
196 : :
197 : 3 : ScHTMLParser::ScHTMLParser( EditEngine* pEditEngine, ScDocument* pDoc ) :
198 : : ScEEParser( pEditEngine ),
199 [ + - ]: 3 : mpDoc( pDoc )
200 : : {
201 [ + - ]: 3 : SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
202 [ + + ]: 24 : for( sal_uInt16 nIndex = 0; nIndex < SC_HTML_FONTSIZES; ++nIndex )
203 [ + - ]: 21 : maFontHeights[ nIndex ] = rHtmlOptions.GetFontSize( nIndex ) * 20;
204 : 3 : }
205 : :
206 [ + - ]: 3 : ScHTMLParser::~ScHTMLParser()
207 : : {
208 [ - + ]: 3 : }
209 : :
210 : 0 : ScHTMLStyles& ScHTMLParser::GetStyles()
211 : : {
212 : 0 : return maStyles;
213 : : }
214 : :
215 : 0 : ScDocument& ScHTMLParser::GetDoc()
216 : : {
217 : 0 : return *mpDoc;
218 : : }
219 : :
220 : : // ============================================================================
221 : :
222 : 0 : ScHTMLLayoutParser::ScHTMLLayoutParser(
223 : : EditEngine* pEditP, const String& rBaseURL, const Size& aPageSizeP,
224 : : ScDocument* pDocP ) :
225 : : ScHTMLParser( pEditP, pDocP ),
226 : : aPageSize( aPageSizeP ),
227 : : aBaseURL( rBaseURL ),
228 [ # # ]: 0 : xLockedList( new ScRangeList ),
229 : : pTables( NULL ),
230 [ # # ]: 0 : pColOffset( new ScHTMLColOffset ),
231 [ # # ]: 0 : pLocalColOffset( new ScHTMLColOffset ),
232 : : nFirstTableCell(0),
233 : : nTableLevel(0),
234 : : nTable(0),
235 : : nMaxTable(0),
236 : : nColCntStart(0),
237 : : nMaxCol(0),
238 : : nTableWidth(0),
239 : : nColOffset(0),
240 : : nColOffsetStart(0),
241 : : nMetaCnt(0),
242 : : nOffsetTolerance( SC_HTML_OFFSET_TOLERANCE_SMALL ),
243 : : bTabInTabCell( false ),
244 : : bFirstRow( true ),
245 : : bInCell( false ),
246 [ # # ][ # # ]: 0 : bInTitle( false )
[ # # ][ # # ]
[ # # ][ # # ]
247 : : {
248 [ # # ]: 0 : MakeColNoRef( pLocalColOffset, 0, 0, 0, 0 );
249 [ # # ]: 0 : MakeColNoRef( pColOffset, 0, 0, 0, 0 );
250 : 0 : }
251 : :
252 : :
253 [ # # ]: 0 : ScHTMLLayoutParser::~ScHTMLLayoutParser()
254 : : {
255 [ # # ]: 0 : while ( !aTableStack.empty() )
256 : : {
257 [ # # ]: 0 : ScHTMLTableStackEntry* pS = aTableStack.top();
258 [ # # ]: 0 : aTableStack.pop();
259 : :
260 : 0 : bool found = false;
261 [ # # ]: 0 : for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
262 : : {
263 [ # # ]: 0 : if ( pS->pCellEntry == maList[ i ] )
264 : : {
265 : 0 : found = true;
266 : 0 : break;
267 : : }
268 : : }
269 [ # # ]: 0 : if ( !found )
270 [ # # ][ # # ]: 0 : delete pS->pCellEntry;
271 [ # # ]: 0 : if ( pS->pLocalColOffset != pLocalColOffset )
272 [ # # ]: 0 : delete pS->pLocalColOffset;
273 [ # # ][ # # ]: 0 : delete pS;
274 : : }
275 [ # # ]: 0 : if ( pLocalColOffset )
276 [ # # ]: 0 : delete pLocalColOffset;
277 [ # # ]: 0 : if ( pColOffset )
278 [ # # ]: 0 : delete pColOffset;
279 [ # # ]: 0 : if ( pTables )
280 : : {
281 [ # # ][ # # ]: 0 : for( OuterMap::const_iterator it = pTables->begin(); it != pTables->end(); ++it)
[ # # ][ # # ]
[ # # ]
282 [ # # ][ # # ]: 0 : delete it->second;
283 [ # # ]: 0 : delete pTables;
284 : : }
285 [ # # ]: 0 : }
286 : :
287 : :
288 : 0 : sal_uLong ScHTMLLayoutParser::Read( SvStream& rStream, const String& rBaseURL )
289 : : {
290 [ # # ]: 0 : Link aOldLink = pEdit->GetImportHdl();
291 [ # # ][ # # ]: 0 : pEdit->SetImportHdl( LINK( this, ScHTMLLayoutParser, HTMLImportHdl ) );
292 : :
293 : 0 : SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
294 [ # # ][ # # ]: 0 : bool bLoading = pObjSh && pObjSh->IsLoading();
[ # # ]
295 : :
296 : 0 : SvKeyValueIteratorRef xValues;
297 : 0 : SvKeyValueIterator* pAttributes = NULL;
298 [ # # ]: 0 : if ( bLoading )
299 [ # # ]: 0 : pAttributes = pObjSh->GetHeaderAttributes();
300 : : else
301 : : {
302 : : // When not loading, set up fake http headers to force the SfxHTMLParser to use UTF8
303 : : // (used when pasting from clipboard)
304 : :
305 [ # # ]: 0 : const sal_Char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
306 [ # # ]: 0 : if( pCharSet )
307 : : {
308 [ # # ]: 0 : String aContentType = rtl::OUString( "text/html; charset=" );
309 [ # # ]: 0 : aContentType.AppendAscii( pCharSet );
310 : :
311 [ # # ][ # # ]: 0 : xValues = new SvKeyValueIterator;
[ # # ]
312 [ # # ][ # # ]: 0 : xValues->Append( SvKeyValue( rtl::OUString( OOO_STRING_SVTOOLS_HTML_META_content_type ), aContentType ) );
[ # # ][ # # ]
[ # # ]
313 [ # # ]: 0 : pAttributes = xValues;
314 : : }
315 : : }
316 : :
317 [ # # ]: 0 : sal_uLong nErr = pEdit->Read( rStream, rBaseURL, EE_FORMAT_HTML, pAttributes );
318 : :
319 [ # # ]: 0 : pEdit->SetImportHdl( aOldLink );
320 : : // Spaltenbreiten erzeugen
321 [ # # ]: 0 : Adjust();
322 [ # # ]: 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
323 : 0 : sal_uInt16 nCount = pColOffset->size();
324 [ # # ]: 0 : sal_uLong nOff = (*pColOffset)[0];
325 : 0 : Size aSize;
326 [ # # ]: 0 : for ( sal_uInt16 j = 1; j < nCount; j++ )
327 : : {
328 [ # # ]: 0 : aSize.Width() = (*pColOffset)[j] - nOff;
329 [ # # ][ # # ]: 0 : aSize = pDefaultDev->PixelToLogic( aSize, MapMode( MAP_TWIP ) );
[ # # ]
330 [ # # ]: 0 : maColWidths[ j-1 ] = aSize.Width();
331 [ # # ]: 0 : nOff = (*pColOffset)[j];
332 : : }
333 [ # # ]: 0 : return nErr;
334 : : }
335 : :
336 : :
337 : 0 : const ScHTMLTable* ScHTMLLayoutParser::GetGlobalTable() const
338 : : {
339 : 0 : return 0;
340 : : }
341 : :
342 : :
343 : 0 : void ScHTMLLayoutParser::NewActEntry( ScEEParseEntry* pE )
344 : : {
345 : 0 : ScEEParser::NewActEntry( pE );
346 [ # # ]: 0 : if ( pE )
347 : : {
348 [ # # ]: 0 : if ( !pE->aSel.HasRange() )
349 : : { // komplett leer, nachfolgender Text landet im gleichen Absatz!
350 : 0 : pActEntry->aSel.nStartPara = pE->aSel.nEndPara;
351 : 0 : pActEntry->aSel.nStartPos = pE->aSel.nEndPos;
352 : : }
353 : : }
354 : 0 : pActEntry->aSel.nEndPara = pActEntry->aSel.nStartPara;
355 : 0 : pActEntry->aSel.nEndPos = pActEntry->aSel.nStartPos;
356 : 0 : }
357 : :
358 : :
359 : 0 : void ScHTMLLayoutParser::EntryEnd( ScEEParseEntry* pE, const ESelection& rSel )
360 : : {
361 [ # # ]: 0 : if ( rSel.nEndPara >= pE->aSel.nStartPara )
362 : : {
363 : 0 : pE->aSel.nEndPara = rSel.nEndPara;
364 : 0 : pE->aSel.nEndPos = rSel.nEndPos;
365 : : }
366 [ # # ][ # # ]: 0 : else if ( rSel.nStartPara == pE->aSel.nStartPara - 1 && !pE->aSel.HasRange() )
367 : : { // kein Absatz angehaengt aber leer, nichts tun
368 : : }
369 : : else
370 : : {
371 : : OSL_FAIL( "EntryEnd: EditEngine ESelection End < Start" );
372 : : }
373 : 0 : }
374 : :
375 : :
376 : 0 : void ScHTMLLayoutParser::NextRow( ImportInfo* pInfo )
377 : : {
378 [ # # ]: 0 : if ( bInCell )
379 : 0 : CloseEntry( pInfo );
380 [ # # ]: 0 : if ( nRowMax < ++nRowCnt )
381 : 0 : nRowMax = nRowCnt;
382 : 0 : nColCnt = nColCntStart;
383 : 0 : nColOffset = nColOffsetStart;
384 : 0 : bFirstRow = false;
385 : 0 : }
386 : :
387 : :
388 : 0 : bool ScHTMLLayoutParser::SeekOffset( ScHTMLColOffset* pOffset, sal_uInt16 nOffset,
389 : : SCCOL* pCol, sal_uInt16 nOffsetTol )
390 : : {
391 : : OSL_ENSURE( pOffset, "ScHTMLLayoutParser::SeekOffset - illegal call" );
392 [ # # ]: 0 : ScHTMLColOffset::const_iterator it = pOffset->find( nOffset );
393 [ # # ]: 0 : bool bFound = it != pOffset->end();
394 [ # # ]: 0 : sal_uInt16 nPos = it - pOffset->end();
395 : 0 : *pCol = static_cast<SCCOL>(nPos);
396 [ # # ]: 0 : if ( bFound )
397 : 0 : return true;
398 : 0 : sal_uInt16 nCount = pOffset->size();
399 [ # # ]: 0 : if ( !nCount )
400 : 0 : return false;
401 : : // nPos ist Einfuegeposition, da liegt der Naechsthoehere (oder auch nicht)
402 [ # # ][ # # ]: 0 : if ( nPos < nCount && (((*pOffset)[nPos] - nOffsetTol) <= nOffset) )
[ # # ][ # # ]
403 : 0 : return true;
404 : : // nicht kleiner als alles andere? dann mit Naechstniedrigerem vergleichen
405 [ # # ][ # # ]: 0 : else if ( nPos && (((*pOffset)[nPos-1] + nOffsetTol) >= nOffset) )
[ # # ][ # # ]
406 : : {
407 : 0 : (*pCol)--;
408 : 0 : return true;
409 : : }
410 : 0 : return false;
411 : : }
412 : :
413 : :
414 : 0 : void ScHTMLLayoutParser::MakeCol( ScHTMLColOffset* pOffset, sal_uInt16& nOffset,
415 : : sal_uInt16& nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
416 : : {
417 : : OSL_ENSURE( pOffset, "ScHTMLLayoutParser::MakeCol - illegal call" );
418 : : SCCOL nPos;
419 [ # # ][ # # ]: 0 : if ( SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
420 [ # # ]: 0 : nOffset = (sal_uInt16)(*pOffset)[nPos];
421 : : else
422 [ # # ]: 0 : pOffset->insert( nOffset );
423 [ # # ]: 0 : if ( nWidth )
424 : : {
425 [ # # ][ # # ]: 0 : if ( SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
426 [ # # ]: 0 : nWidth = (sal_uInt16)(*pOffset)[nPos] - nOffset;
427 : : else
428 [ # # ]: 0 : pOffset->insert( nOffset + nWidth );
429 : : }
430 : 0 : }
431 : :
432 : :
433 : 0 : void ScHTMLLayoutParser::MakeColNoRef( ScHTMLColOffset* pOffset, sal_uInt16 nOffset,
434 : : sal_uInt16 nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
435 : : {
436 : : OSL_ENSURE( pOffset, "ScHTMLLayoutParser::MakeColNoRef - illegal call" );
437 : : SCCOL nPos;
438 [ # # ][ # # ]: 0 : if ( SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
439 [ # # ]: 0 : nOffset = (sal_uInt16)(*pOffset)[nPos];
440 : : else
441 [ # # ]: 0 : pOffset->insert( nOffset );
442 [ # # ]: 0 : if ( nWidth )
443 : : {
444 [ # # ][ # # ]: 0 : if ( !SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
445 [ # # ]: 0 : pOffset->insert( nOffset + nWidth );
446 : : }
447 : 0 : }
448 : :
449 : :
450 : 0 : void ScHTMLLayoutParser::ModifyOffset( ScHTMLColOffset* pOffset, sal_uInt16& nOldOffset,
451 : : sal_uInt16& nNewOffset, sal_uInt16 nOffsetTol )
452 : : {
453 : : OSL_ENSURE( pOffset, "ScHTMLLayoutParser::ModifyOffset - illegal call" );
454 : : SCCOL nPos;
455 [ # # ][ # # ]: 0 : if ( !SeekOffset( pOffset, nOldOffset, &nPos, nOffsetTol ) )
456 : : {
457 [ # # ][ # # ]: 0 : if ( SeekOffset( pOffset, nNewOffset, &nPos, nOffsetTol ) )
458 [ # # ]: 0 : nNewOffset = (sal_uInt16)(*pOffset)[nPos];
459 : : else
460 [ # # ]: 0 : pOffset->insert( nNewOffset );
461 : : return ;
462 : : }
463 [ # # ]: 0 : nOldOffset = (sal_uInt16)(*pOffset)[nPos];
464 : : SCCOL nPos2;
465 [ # # ][ # # ]: 0 : if ( SeekOffset( pOffset, nNewOffset, &nPos2, nOffsetTol ) )
466 : : {
467 [ # # ]: 0 : nNewOffset = (sal_uInt16)(*pOffset)[nPos2];
468 : : return ;
469 : : }
470 : 0 : long nDiff = nNewOffset - nOldOffset;
471 [ # # ]: 0 : if ( nDiff < 0 )
472 : : {
473 [ # # ]: 0 : do
474 : : {
475 [ # # ]: 0 : const_cast<sal_uLong&>((*pOffset)[nPos]) += nDiff;
476 : : } while ( nPos-- );
477 : : }
478 : : else
479 : : {
480 [ # # ]: 0 : do
481 : : {
482 [ # # ]: 0 : const_cast<sal_uLong&>((*pOffset)[nPos]) += nDiff;
483 : 0 : } while ( ++nPos < (sal_uInt16)pOffset->size() );
484 : : }
485 : : }
486 : :
487 : :
488 : 0 : void ScHTMLLayoutParser::SkipLocked( ScEEParseEntry* pE, bool bJoin )
489 : : {
490 [ # # ]: 0 : if ( ValidCol(pE->nCol) )
491 : : { // wuerde sonst bei ScAddress falschen Wert erzeugen, evtl. Endlosschleife!
492 : 0 : bool bBadCol = false;
493 : : bool bAgain;
494 : : ScRange aRange( pE->nCol, pE->nRow, 0,
495 : 0 : pE->nCol + pE->nColOverlap - 1, pE->nRow + pE->nRowOverlap - 1, 0 );
496 [ # # ]: 0 : do
497 : : {
498 : 0 : bAgain = false;
499 [ # # ][ # # ]: 0 : for ( size_t i = 0, nRanges = xLockedList->size(); i < nRanges; ++i )
500 : : {
501 [ # # ]: 0 : ScRange* pR = (*xLockedList)[i];
502 [ # # ][ # # ]: 0 : if ( pR->Intersects( aRange ) )
503 : : {
504 : 0 : pE->nCol = pR->aEnd.Col() + 1;
505 : 0 : SCCOL nTmp = pE->nCol + pE->nColOverlap - 1;
506 [ # # ][ # # ]: 0 : if ( pE->nCol > MAXCOL || nTmp > MAXCOL )
507 : 0 : bBadCol = true;
508 : : else
509 : : {
510 : 0 : bAgain = true;
511 : 0 : aRange.aStart.SetCol( pE->nCol );
512 : 0 : aRange.aEnd.SetCol( nTmp );
513 : : }
514 : 0 : break;
515 : : }
516 : : }
517 : : } while ( bAgain );
518 [ # # ][ # # ]: 0 : if ( bJoin && !bBadCol )
519 [ # # ]: 0 : xLockedList->Join( aRange );
520 : : }
521 : 0 : }
522 : :
523 : :
524 : 0 : void ScHTMLLayoutParser::Adjust()
525 : : {
526 [ # # ]: 0 : xLockedList->RemoveAll();
527 : :
528 [ # # ][ # # ]: 0 : ScHTMLAdjustStack aStack;
529 : 0 : ScHTMLAdjustStackEntry* pS = NULL;
530 : 0 : sal_uInt16 nTab = 0;
531 : 0 : SCCOL nLastCol = SCCOL_MAX;
532 : 0 : SCROW nNextRow = 0;
533 : 0 : SCROW nCurRow = 0;
534 : 0 : sal_uInt16 nPageWidth = (sal_uInt16) aPageSize.Width();
535 : 0 : InnerMap* pTab = NULL;
536 [ # # ]: 0 : for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
537 : : {
538 : 0 : ScEEParseEntry* pE = maList[ i ];
539 [ # # ]: 0 : if ( pE->nTab < nTab )
540 : : { // Table beendet
541 [ # # ]: 0 : if ( !aStack.empty() )
542 : : {
543 [ # # ]: 0 : pS = aStack.top();
544 [ # # ]: 0 : aStack.pop();
545 : :
546 : 0 : nLastCol = pS->nLastCol;
547 : 0 : nNextRow = pS->nNextRow;
548 : 0 : nCurRow = pS->nCurRow;
549 : : }
550 : 0 : delete pS;
551 : 0 : pS = NULL;
552 : 0 : nTab = pE->nTab;
553 [ # # ]: 0 : if (pTables)
554 : : {
555 [ # # ][ # # ]: 0 : OuterMap::const_iterator it = pTables->find( nTab );
556 [ # # ][ # # ]: 0 : if ( it != pTables->end() )
[ # # ]
557 [ # # ]: 0 : pTab = it->second;
558 : : }
559 : :
560 : : }
561 : 0 : SCROW nRow = pE->nRow;
562 [ # # ]: 0 : if ( pE->nCol <= nLastCol )
563 : : { // naechste Zeile
564 [ # # ]: 0 : if ( pE->nRow < nNextRow )
565 : 0 : pE->nRow = nCurRow = nNextRow;
566 : : else
567 : 0 : nCurRow = nNextRow = pE->nRow;
568 : 0 : SCROW nR = 0;
569 [ # # ]: 0 : if ( pTab )
570 : : {
571 [ # # ][ # # ]: 0 : InnerMap::const_iterator it = pTab->find( nCurRow );
572 [ # # ][ # # ]: 0 : if ( it != pTab->end() )
[ # # ]
573 [ # # ]: 0 : nR = it->second;
574 : : }
575 [ # # ]: 0 : if ( nR )
576 : 0 : nNextRow += nR;
577 : : else
578 : 0 : nNextRow++;
579 : : }
580 : : else
581 : 0 : pE->nRow = nCurRow;
582 : 0 : nLastCol = pE->nCol; // eingelesene Col
583 [ # # ]: 0 : if ( pE->nTab > nTab )
584 : : { // neue Table
585 : : aStack.push( new ScHTMLAdjustStackEntry(
586 [ # # ][ # # ]: 0 : nLastCol, nNextRow, nCurRow ) );
587 : 0 : nTab = pE->nTab;
588 [ # # ]: 0 : if ( pTables )
589 : : {
590 [ # # ][ # # ]: 0 : OuterMap::const_iterator it = pTables->find( nTab );
591 [ # # ][ # # ]: 0 : if ( it != pTables->end() )
[ # # ]
592 [ # # ]: 0 : pTab = it->second;
593 : : }
594 : : // neuer Zeilenabstand
595 : 0 : SCROW nR = 0;
596 [ # # ]: 0 : if ( pTab )
597 : : {
598 [ # # ][ # # ]: 0 : InnerMap::const_iterator it = pTab->find( nCurRow );
599 [ # # ][ # # ]: 0 : if ( it != pTab->end() )
[ # # ]
600 [ # # ]: 0 : nR = it->second;
601 : : }
602 [ # # ]: 0 : if ( nR )
603 : 0 : nNextRow = nCurRow + nR;
604 : : else
605 : 0 : nNextRow = nCurRow + 1;
606 : : }
607 [ # # ]: 0 : if ( nTab == 0 )
608 : 0 : pE->nWidth = nPageWidth;
609 : : else
610 : : { // echte Table, keine Absaetze auf der Wiese
611 [ # # ]: 0 : if ( pTab )
612 : : {
613 : 0 : SCROW nRowSpan = pE->nRowOverlap;
614 [ # # ]: 0 : for ( SCROW j=0; j < nRowSpan; j++ )
615 : : { // aus merged Zeilen resultierendes RowSpan
616 : 0 : SCROW nRows = 0;
617 [ # # ][ # # ]: 0 : InnerMap::const_iterator it = pTab->find( nRow+j );
618 [ # # ][ # # ]: 0 : if ( it != pTab->end() )
[ # # ]
619 [ # # ]: 0 : nRows = it->second;
620 [ # # ]: 0 : if ( nRows > 1 )
621 : : {
622 : 0 : pE->nRowOverlap += nRows - 1;
623 [ # # ]: 0 : if ( j == 0 )
624 : : { // merged Zeilen verschieben die naechste Zeile
625 : 0 : SCROW nTmp = nCurRow + nRows;
626 [ # # ]: 0 : if ( nNextRow < nTmp )
627 : 0 : nNextRow = nTmp;
628 : : }
629 : : }
630 : : }
631 : : }
632 : : }
633 : : // echte Col
634 [ # # ]: 0 : SeekOffset( pColOffset, pE->nOffset, &pE->nCol, nOffsetTolerance );
635 : 0 : SCCOL nColBeforeSkip = pE->nCol;
636 [ # # ]: 0 : SkipLocked( pE, false );
637 [ # # ]: 0 : if ( pE->nCol != nColBeforeSkip )
638 : : {
639 : 0 : SCCOL nCount = (SCCOL)pColOffset->size();
640 [ # # ]: 0 : if ( nCount <= pE->nCol )
641 : : {
642 [ # # ]: 0 : pE->nOffset = (sal_uInt16) (*pColOffset)[nCount-1];
643 [ # # ]: 0 : MakeCol( pColOffset, pE->nOffset, pE->nWidth, nOffsetTolerance, nOffsetTolerance );
644 : : }
645 : : else
646 : : {
647 [ # # ]: 0 : pE->nOffset = (sal_uInt16) (*pColOffset)[pE->nCol];
648 : : }
649 : : }
650 : : SCCOL nPos;
651 [ # # ][ # # ]: 0 : if ( pE->nWidth && SeekOffset( pColOffset, pE->nOffset + pE->nWidth, &nPos, nOffsetTolerance ) )
[ # # ][ # # ]
652 [ # # ]: 0 : pE->nColOverlap = (nPos > pE->nCol ? nPos - pE->nCol : 1);
653 : : else
654 : : {
655 : : //2do: das muss nicht korrekt sein, ist aber..
656 : 0 : pE->nColOverlap = 1;
657 : : }
658 : : xLockedList->Join( ScRange( pE->nCol, pE->nRow, 0,
659 [ # # ]: 0 : pE->nCol + pE->nColOverlap - 1, pE->nRow + pE->nRowOverlap - 1, 0 ) );
660 : : // MaxDimensions mitfuehren
661 : 0 : SCCOL nColTmp = pE->nCol + pE->nColOverlap;
662 [ # # ]: 0 : if ( nColMax < nColTmp )
663 : 0 : nColMax = nColTmp;
664 : 0 : SCROW nRowTmp = pE->nRow + pE->nRowOverlap;
665 [ # # ]: 0 : if ( nRowMax < nRowTmp )
666 : 0 : nRowMax = nRowTmp;
667 : : }
668 [ # # ]: 0 : while ( !aStack.empty() )
669 : : {
670 [ # # ]: 0 : delete aStack.top();
671 [ # # ]: 0 : aStack.pop();
672 : 0 : }
673 : 0 : }
674 : :
675 : :
676 : 0 : sal_uInt16 ScHTMLLayoutParser::GetWidth( ScEEParseEntry* pE )
677 : : {
678 [ # # ]: 0 : if ( pE->nWidth )
679 : 0 : return pE->nWidth;
680 : : sal_Int32 nTmp = ::std::min( static_cast<sal_Int32>( pE->nCol -
681 : : nColCntStart + pE->nColOverlap),
682 [ # # ]: 0 : static_cast<sal_Int32>( pLocalColOffset->size() - 1));
683 [ # # ]: 0 : SCCOL nPos = (nTmp < 0 ? 0 : static_cast<SCCOL>(nTmp));
684 : 0 : sal_uInt16 nOff2 = (sal_uInt16) (*pLocalColOffset)[nPos];
685 [ # # ]: 0 : if ( pE->nOffset < nOff2 )
686 : 0 : return nOff2 - pE->nOffset;
687 : 0 : return 0;
688 : : }
689 : :
690 : :
691 : 0 : void ScHTMLLayoutParser::SetWidths()
692 : : {
693 : : ScEEParseEntry* pE;
694 : : SCCOL nCol;
695 [ # # ]: 0 : if ( !nTableWidth )
696 : 0 : nTableWidth = (sal_uInt16) aPageSize.Width();
697 : 0 : SCCOL nColsPerRow = nMaxCol - nColCntStart;
698 [ # # ]: 0 : if ( nColsPerRow <= 0 )
699 : 0 : nColsPerRow = 1;
700 [ # # ]: 0 : if ( pLocalColOffset->size() <= 2 )
701 : : { // nur PageSize, es gab keine Width-Angabe
702 : 0 : sal_uInt16 nWidth = nTableWidth / static_cast<sal_uInt16>(nColsPerRow);
703 : 0 : sal_uInt16 nOff = nColOffsetStart;
704 : 0 : pLocalColOffset->clear();
705 [ # # ]: 0 : for ( nCol = 0; nCol <= nColsPerRow; ++nCol, nOff = nOff + nWidth )
706 : : {
707 : 0 : MakeColNoRef( pLocalColOffset, nOff, 0, 0, 0 );
708 : : }
709 : 0 : nTableWidth = (sal_uInt16)(pLocalColOffset->back() - pLocalColOffset->front());
710 [ # # ]: 0 : for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
711 : : {
712 : 0 : pE = maList[ i ];
713 [ # # ]: 0 : if ( pE->nTab == nTable )
714 : : {
715 : 0 : pE->nOffset = (sal_uInt16) (*pLocalColOffset)[pE->nCol - nColCntStart];
716 : 0 : pE->nWidth = 0; // to be recalculated later
717 : : }
718 : : }
719 : : }
720 : : else
721 : : { // einige mit einige ohne Width
722 : : // wieso eigentlich kein pE ?!?
723 [ # # ]: 0 : if ( nFirstTableCell < maList.size() )
724 : : {
725 : 0 : sal_uInt16* pOffsets = new sal_uInt16[ nColsPerRow+1 ];
726 : 0 : memset( pOffsets, 0, (nColsPerRow+1) * sizeof(sal_uInt16) );
727 : 0 : sal_uInt16* pWidths = new sal_uInt16[ nColsPerRow ];
728 : 0 : memset( pWidths, 0, nColsPerRow * sizeof(sal_uInt16) );
729 : 0 : pOffsets[0] = nColOffsetStart;
730 [ # # ]: 0 : for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
731 : : {
732 : 0 : pE = maList[ i ];
733 [ # # ][ # # ]: 0 : if ( pE->nTab == nTable && pE->nWidth )
734 : : {
735 : 0 : nCol = pE->nCol - nColCntStart;
736 [ # # ]: 0 : if ( nCol < nColsPerRow )
737 : : {
738 [ # # ]: 0 : if ( pE->nColOverlap == 1 )
739 : : {
740 [ # # ]: 0 : if ( pWidths[nCol] < pE->nWidth )
741 : 0 : pWidths[nCol] = pE->nWidth;
742 : : }
743 : : else
744 : : { // try to find a single undefined width
745 : 0 : sal_uInt16 nTotal = 0;
746 : 0 : bool bFound = false;
747 : 0 : SCCOL nHere = 0;
748 : 0 : SCCOL nStop = Min( static_cast<SCCOL>(nCol + pE->nColOverlap), nColsPerRow );
749 [ # # ]: 0 : for ( ; nCol < nStop; nCol++ )
750 : : {
751 [ # # ]: 0 : if ( pWidths[nCol] )
752 : 0 : nTotal = nTotal + pWidths[nCol];
753 : : else
754 : : {
755 [ # # ]: 0 : if ( bFound )
756 : : {
757 : 0 : bFound = false;
758 : 0 : break; // for
759 : : }
760 : 0 : bFound = true;
761 : 0 : nHere = nCol;
762 : : }
763 : : }
764 [ # # ][ # # ]: 0 : if ( bFound && pE->nWidth > nTotal )
765 : 0 : pWidths[nHere] = pE->nWidth - nTotal;
766 : : }
767 : : }
768 : : }
769 : : }
770 : 0 : sal_uInt16 nWidths = 0;
771 : 0 : sal_uInt16 nUnknown = 0;
772 [ # # ]: 0 : for ( nCol = 0; nCol < nColsPerRow; nCol++ )
773 : : {
774 [ # # ]: 0 : if ( pWidths[nCol] )
775 : 0 : nWidths = nWidths + pWidths[nCol];
776 : : else
777 : 0 : nUnknown++;
778 : : }
779 [ # # ]: 0 : if ( nUnknown )
780 : : {
781 : : sal_uInt16 nW = ((nWidths < nTableWidth) ?
782 : : ((nTableWidth - nWidths) / nUnknown) :
783 [ # # ]: 0 : (nTableWidth / nUnknown));
784 [ # # ]: 0 : for ( nCol = 0; nCol < nColsPerRow; nCol++ )
785 : : {
786 [ # # ]: 0 : if ( !pWidths[nCol] )
787 : 0 : pWidths[nCol] = nW;
788 : : }
789 : : }
790 [ # # ]: 0 : for ( nCol = 1; nCol <= nColsPerRow; nCol++ )
791 : : {
792 : 0 : pOffsets[nCol] = pOffsets[nCol-1] + pWidths[nCol-1];
793 : : }
794 : 0 : pLocalColOffset->clear();
795 [ # # ]: 0 : for ( nCol = 0; nCol <= nColsPerRow; nCol++ )
796 : : {
797 : 0 : MakeColNoRef( pLocalColOffset, pOffsets[nCol], 0, 0, 0 );
798 : : }
799 : 0 : nTableWidth = pOffsets[nColsPerRow] - pOffsets[0];
800 : :
801 [ # # ]: 0 : for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
802 : : {
803 : 0 : pE = maList[ i ];
804 [ # # ]: 0 : if ( pE->nTab == nTable )
805 : : {
806 : 0 : nCol = pE->nCol - nColCntStart;
807 : : OSL_ENSURE( nCol < nColsPerRow, "ScHTMLLayoutParser::SetWidths: column overflow" );
808 [ # # ]: 0 : if ( nCol < nColsPerRow )
809 : : {
810 : 0 : pE->nOffset = pOffsets[nCol];
811 : 0 : nCol = nCol + pE->nColOverlap;
812 [ # # ]: 0 : if ( nCol > nColsPerRow )
813 : 0 : nCol = nColsPerRow;
814 : 0 : pE->nWidth = pOffsets[nCol] - pE->nOffset;
815 : : }
816 : : }
817 : : }
818 : :
819 [ # # ]: 0 : delete [] pWidths;
820 [ # # ]: 0 : delete [] pOffsets;
821 : : }
822 : : }
823 [ # # ]: 0 : if ( !pLocalColOffset->empty() )
824 : : {
825 : 0 : sal_uInt16 nMax = (sal_uInt16) pLocalColOffset->back();
826 [ # # ]: 0 : if ( aPageSize.Width() < nMax )
827 : 0 : aPageSize.Width() = nMax;
828 : : }
829 [ # # ]: 0 : for ( size_t i = nFirstTableCell, nListSize = maList.size(); i < nListSize; ++i )
830 : : {
831 : 0 : pE = maList[ i ];
832 [ # # ]: 0 : if ( pE->nTab == nTable )
833 : : {
834 [ # # ]: 0 : if ( !pE->nWidth )
835 : : {
836 : 0 : pE->nWidth = GetWidth( pE );
837 : : OSL_ENSURE( pE->nWidth, "SetWidths: pE->nWidth == 0" );
838 : : }
839 : 0 : MakeCol( pColOffset, pE->nOffset, pE->nWidth, nOffsetTolerance, nOffsetTolerance );
840 : : }
841 : : }
842 : 0 : }
843 : :
844 : :
845 : 0 : void ScHTMLLayoutParser::Colonize( ScEEParseEntry* pE )
846 : : {
847 [ # # ]: 0 : if ( pE->nCol == SCCOL_MAX )
848 : 0 : pE->nCol = nColCnt;
849 [ # # ]: 0 : if ( pE->nRow == SCROW_MAX )
850 : 0 : pE->nRow = nRowCnt;
851 : 0 : SCCOL nCol = pE->nCol;
852 [ # # ]: 0 : SkipLocked( pE ); // Spaltenverdraengung nach rechts
853 : :
854 [ # # ]: 0 : if ( nCol < pE->nCol )
855 : : { // verdraengt
856 : 0 : nCol = pE->nCol - nColCntStart;
857 : 0 : SCCOL nCount = static_cast<SCCOL>(pLocalColOffset->size());
858 [ # # ]: 0 : if ( nCol < nCount )
859 [ # # ]: 0 : nColOffset = (sal_uInt16) (*pLocalColOffset)[nCol];
860 : : else
861 [ # # ]: 0 : nColOffset = (sal_uInt16) (*pLocalColOffset)[nCount - 1];
862 : : }
863 : 0 : pE->nOffset = nColOffset;
864 [ # # ]: 0 : sal_uInt16 nWidth = GetWidth( pE );
865 [ # # ]: 0 : MakeCol( pLocalColOffset, pE->nOffset, nWidth, nOffsetTolerance, nOffsetTolerance );
866 [ # # ]: 0 : if ( pE->nWidth )
867 : 0 : pE->nWidth = nWidth;
868 : 0 : nColOffset = pE->nOffset + nWidth;
869 [ # # ]: 0 : if ( nTableWidth < nColOffset - nColOffsetStart )
870 : 0 : nTableWidth = nColOffset - nColOffsetStart;
871 : 0 : }
872 : :
873 : :
874 : 0 : void ScHTMLLayoutParser::CloseEntry( ImportInfo* pInfo )
875 : : {
876 : 0 : bInCell = false;
877 [ # # ]: 0 : if ( bTabInTabCell )
878 : : { // in TableOff vom Stack geholt
879 : 0 : bTabInTabCell = false;
880 : 0 : bool found = false;
881 [ # # ]: 0 : for ( size_t i = 0, nListSize = maList.size(); i < nListSize; ++i )
882 : : {
883 [ # # ]: 0 : if ( pActEntry == maList[ i ] )
884 : : {
885 : 0 : found = true;
886 : 0 : break;
887 : : }
888 : : }
889 [ # # ]: 0 : if ( !found )
890 [ # # ]: 0 : delete pActEntry;
891 : 0 : NewActEntry( maList.back() ); // neuer freifliegender pActEntry
892 : 0 : return ;
893 : : }
894 [ # # ]: 0 : if ( pActEntry->nTab == 0 )
895 : 0 : pActEntry->nWidth = (sal_uInt16) aPageSize.Width();
896 : 0 : Colonize( pActEntry );
897 : 0 : nColCnt = pActEntry->nCol + pActEntry->nColOverlap;
898 [ # # ]: 0 : if ( nMaxCol < nColCnt )
899 : 0 : nMaxCol = nColCnt; // TableStack MaxCol
900 [ # # ]: 0 : if ( nColMax < nColCnt )
901 : 0 : nColMax = nColCnt; // globales MaxCol fuer ScEEParser GetDimensions!
902 : 0 : EntryEnd( pActEntry, pInfo->aSelection );
903 : 0 : ESelection& rSel = pActEntry->aSel;
904 [ # # # # ]: 0 : while ( rSel.nStartPara < rSel.nEndPara
[ # # ]
905 : 0 : && pEdit->GetTextLen( rSel.nStartPara ) == 0 )
906 : : { // vorgehaengte Leerabsaetze strippen
907 : 0 : rSel.nStartPara++;
908 : : }
909 [ # # ][ # # ]: 0 : while ( rSel.nEndPos == 0 && rSel.nEndPara > rSel.nStartPara )
[ # # ]
910 : : { // angehaengte Leerabsaetze strippen
911 : 0 : rSel.nEndPara--;
912 : 0 : rSel.nEndPos = pEdit->GetTextLen( rSel.nEndPara );
913 : : }
914 [ # # ]: 0 : if ( rSel.nStartPara > rSel.nEndPara )
915 : : { // gibt GPF in CreateTextObject
916 : : OSL_FAIL( "CloseEntry: EditEngine ESelection Start > End" );
917 : 0 : rSel.nEndPara = rSel.nStartPara;
918 : : }
919 [ # # ]: 0 : if ( rSel.HasRange() )
920 [ # # ]: 0 : pActEntry->aItemSet.Put( SfxBoolItem( ATTR_LINEBREAK, true ) );
921 : 0 : maList.push_back( pActEntry );
922 : 0 : NewActEntry( pActEntry ); // neuer freifliegender pActEntry
923 : : }
924 : :
925 : :
926 : 0 : IMPL_LINK( ScHTMLLayoutParser, HTMLImportHdl, ImportInfo*, pInfo )
927 : : {
928 [ # # # # : 0 : switch ( pInfo->eState )
# # # #
# ]
929 : : {
930 : : case HTMLIMP_NEXTTOKEN:
931 : 0 : ProcToken( pInfo );
932 : 0 : break;
933 : : case HTMLIMP_UNKNOWNATTR:
934 : 0 : ProcToken( pInfo );
935 : 0 : break;
936 : : case HTMLIMP_START:
937 : 0 : break;
938 : : case HTMLIMP_END:
939 [ # # ]: 0 : if ( pInfo->aSelection.nEndPos )
940 : : {
941 : : // If text remains: create paragraph, without calling CloseEntry().
942 [ # # ]: 0 : if( bInCell ) // ...but only in opened table cells.
943 : : {
944 : 0 : bInCell = false;
945 : 0 : NextRow( pInfo );
946 : 0 : bInCell = true;
947 : : }
948 : 0 : CloseEntry( pInfo );
949 : : }
950 [ # # ]: 0 : while ( nTableLevel > 0 )
951 : 0 : TableOff( pInfo ); // close tables, if </TABLE> missing
952 : 0 : break;
953 : : case HTMLIMP_SETATTR:
954 : 0 : break;
955 : : case HTMLIMP_INSERTTEXT:
956 : 0 : break;
957 : : case HTMLIMP_INSERTPARA:
958 [ # # ]: 0 : if ( nTableLevel < 1 )
959 : : {
960 : 0 : CloseEntry( pInfo );
961 : 0 : NextRow( pInfo );
962 : : }
963 : 0 : break;
964 : : case HTMLIMP_INSERTFIELD:
965 : 0 : break;
966 : : default:
967 : : OSL_FAIL("HTMLImportHdl: unknown ImportInfo.eState");
968 : : }
969 : 0 : return 0;
970 : : }
971 : :
972 : :
973 : : // Groesster Gemeinsamer Teiler nach Euklid (Kettendivision)
974 : : // Sonderfall: 0 und irgendwas geben 1
975 : 0 : SCROW lcl_GGT( SCROW a, SCROW b )
976 : : {
977 [ # # ][ # # ]: 0 : if ( !a || !b )
978 : 0 : return 1;
979 [ # # ][ # # ]: 0 : do
[ # # ]
980 : : {
981 [ # # ]: 0 : if ( a > b )
982 : 0 : a -= SCROW(a / b) * b;
983 : : else
984 : 0 : b -= SCROW(b / a) * a;
985 : : } while ( a && b );
986 [ # # ]: 0 : return ((a != 0) ? a : b);
987 : : }
988 : :
989 : :
990 : : // Kleinstes Gemeinsames Vielfaches: a * b / GGT(a,b)
991 : 0 : SCROW lcl_KGV( SCROW a, SCROW b )
992 : : {
993 [ # # ]: 0 : if ( a > b ) // Ueberlauf unwahrscheinlicher machen
994 : 0 : return (a / lcl_GGT(a,b)) * b;
995 : : else
996 : 0 : return (b / lcl_GGT(a,b)) * a;
997 : : }
998 : :
999 : :
1000 : 0 : void ScHTMLLayoutParser::TableDataOn( ImportInfo* pInfo )
1001 : : {
1002 [ # # ]: 0 : if ( bInCell )
1003 : 0 : CloseEntry( pInfo );
1004 [ # # ]: 0 : if ( !nTableLevel )
1005 : : {
1006 : : OSL_FAIL( "Dummbatz-Dok! <TH> oder <TD> ohne vorheriges <TABLE>" );
1007 : 0 : TableOn( pInfo );
1008 : : }
1009 : 0 : bInCell = true;
1010 : 0 : bool bHorJustifyCenterTH = (pInfo->nToken == HTML_TABLEHEADER_ON);
1011 : 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1012 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1013 : : {
1014 : 0 : const HTMLOption& rOption = rOptions[i];
1015 [ # # # # : 0 : switch( rOption.GetToken() )
# # # #
# ]
1016 : : {
1017 : : case HTML_O_COLSPAN:
1018 : : {
1019 : 0 : pActEntry->nColOverlap = ( SCCOL ) rOption.GetString().ToInt32();
1020 : : }
1021 : 0 : break;
1022 : : case HTML_O_ROWSPAN:
1023 : : {
1024 : 0 : pActEntry->nRowOverlap = ( SCROW ) rOption.GetString().ToInt32();
1025 : : }
1026 : 0 : break;
1027 : : case HTML_O_ALIGN:
1028 : : {
1029 : 0 : bHorJustifyCenterTH = false;
1030 : : SvxCellHorJustify eVal;
1031 : 0 : const String& rOptVal = rOption.GetString();
1032 [ # # ]: 0 : if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) == COMPARE_EQUAL )
1033 : 0 : eVal = SVX_HOR_JUSTIFY_RIGHT;
1034 [ # # ]: 0 : else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) == COMPARE_EQUAL )
1035 : 0 : eVal = SVX_HOR_JUSTIFY_CENTER;
1036 [ # # ]: 0 : else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) == COMPARE_EQUAL )
1037 : 0 : eVal = SVX_HOR_JUSTIFY_LEFT;
1038 : : else
1039 : 0 : eVal = SVX_HOR_JUSTIFY_STANDARD;
1040 [ # # ]: 0 : if ( eVal != SVX_HOR_JUSTIFY_STANDARD )
1041 [ # # ]: 0 : pActEntry->aItemSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY) );
1042 : : }
1043 : 0 : break;
1044 : : case HTML_O_VALIGN:
1045 : : {
1046 : : SvxCellVerJustify eVal;
1047 : 0 : const String& rOptVal = rOption.GetString();
1048 [ # # ]: 0 : if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_top ) == COMPARE_EQUAL )
1049 : 0 : eVal = SVX_VER_JUSTIFY_TOP;
1050 [ # # ]: 0 : else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_middle ) == COMPARE_EQUAL )
1051 : 0 : eVal = SVX_VER_JUSTIFY_CENTER;
1052 [ # # ]: 0 : else if ( rOptVal.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_VA_bottom ) == COMPARE_EQUAL )
1053 : 0 : eVal = SVX_VER_JUSTIFY_BOTTOM;
1054 : : else
1055 : 0 : eVal = SVX_VER_JUSTIFY_STANDARD;
1056 [ # # ]: 0 : pActEntry->aItemSet.Put( SvxVerJustifyItem( eVal, ATTR_VER_JUSTIFY) );
1057 : : }
1058 : 0 : break;
1059 : : case HTML_O_WIDTH:
1060 : : {
1061 : 0 : pActEntry->nWidth = GetWidthPixel( rOption );
1062 : : }
1063 : 0 : break;
1064 : : case HTML_O_BGCOLOR:
1065 : : {
1066 : 0 : Color aColor;
1067 [ # # ]: 0 : rOption.GetColor( aColor );
1068 : : pActEntry->aItemSet.Put(
1069 [ # # ][ # # ]: 0 : SvxBrushItem( aColor, ATTR_BACKGROUND ) );
[ # # ]
1070 : : }
1071 : 0 : break;
1072 : : case HTML_O_SDVAL:
1073 : : {
1074 [ # # ]: 0 : pActEntry->pValStr = new rtl::OUString( rOption.GetString() );
1075 : : }
1076 : 0 : break;
1077 : : case HTML_O_SDNUM:
1078 : : {
1079 [ # # ]: 0 : pActEntry->pNumStr = new rtl::OUString( rOption.GetString() );
1080 : : }
1081 : 0 : break;
1082 : : }
1083 : : }
1084 : 0 : pActEntry->nCol = nColCnt;
1085 : 0 : pActEntry->nRow = nRowCnt;
1086 : 0 : pActEntry->nTab = nTable;
1087 : :
1088 [ # # ]: 0 : if ( bHorJustifyCenterTH )
1089 : : pActEntry->aItemSet.Put(
1090 [ # # ]: 0 : SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY) );
1091 : 0 : }
1092 : :
1093 : :
1094 : 0 : void ScHTMLLayoutParser::TableRowOn( ImportInfo* pInfo )
1095 : : {
1096 [ # # ]: 0 : if ( nColCnt > nColCntStart )
1097 : 0 : NextRow( pInfo ); // das optionale TableRowOff war nicht
1098 : 0 : nColOffset = nColOffsetStart;
1099 : 0 : }
1100 : :
1101 : :
1102 : 0 : void ScHTMLLayoutParser::TableRowOff( ImportInfo* pInfo )
1103 : : {
1104 : 0 : NextRow( pInfo );
1105 : 0 : }
1106 : :
1107 : :
1108 : 0 : void ScHTMLLayoutParser::TableDataOff( ImportInfo* pInfo )
1109 : : {
1110 [ # # ]: 0 : if ( bInCell )
1111 : 0 : CloseEntry( pInfo ); // aber nur wenn's auch eine war
1112 : 0 : }
1113 : :
1114 : :
1115 : 0 : void ScHTMLLayoutParser::TableOn( ImportInfo* pInfo )
1116 : : {
1117 [ # # ]: 0 : String aTabName;
1118 : :
1119 [ # # ]: 0 : if ( ++nTableLevel > 1 )
1120 : : { // Table in Table
1121 : 0 : sal_uInt16 nTmpColOffset = nColOffset; // wird in Colonize noch angepasst
1122 [ # # ]: 0 : Colonize( pActEntry );
1123 : : aTableStack.push( new ScHTMLTableStackEntry(
1124 : : pActEntry, xLockedList, pLocalColOffset, nFirstTableCell,
1125 : : nColCnt, nRowCnt, nColCntStart, nMaxCol, nTable,
1126 : : nTableWidth, nColOffset, nColOffsetStart,
1127 [ # # ][ # # ]: 0 : bFirstRow ) );
[ # # ]
1128 : 0 : sal_uInt16 nLastWidth = nTableWidth;
1129 [ # # ]: 0 : nTableWidth = GetWidth( pActEntry );
1130 [ # # ][ # # ]: 0 : if ( nTableWidth == nLastWidth && nMaxCol - nColCntStart > 1 )
1131 : : { // es muss mehr als einen geben, also kann dieser nicht alles sein
1132 : 0 : nTableWidth = nLastWidth / static_cast<sal_uInt16>((nMaxCol - nColCntStart));
1133 : : }
1134 : 0 : nLastWidth = nTableWidth;
1135 [ # # ]: 0 : if ( pInfo->nToken == HTML_TABLE_ON )
1136 : : { // es kann auch TD oder TH sein, wenn es vorher kein TABLE gab
1137 [ # # ]: 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1138 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1139 : : {
1140 [ # # ]: 0 : const HTMLOption& rOption = rOptions[i];
1141 [ # # # # ]: 0 : switch( rOption.GetToken() )
1142 : : {
1143 : : case HTML_O_WIDTH:
1144 : : { // Prozent: von Dokumentbreite bzw. aeusserer Zelle
1145 [ # # ]: 0 : nTableWidth = GetWidthPixel( rOption );
1146 : : }
1147 : 0 : break;
1148 : : case HTML_O_BORDER:
1149 : : // Border is: ((pOption->GetString().Len() == 0) || (pOption->GetNumber() != 0));
1150 : 0 : break;
1151 : : case HTML_O_ID:
1152 [ # # ]: 0 : aTabName.Assign( rOption.GetString() );
1153 : 0 : break;
1154 : : }
1155 : : }
1156 : : }
1157 : 0 : bInCell = false;
1158 [ # # ][ # # ]: 0 : if ( bTabInTabCell && !(nTableWidth < nLastWidth) )
1159 : : { // mehrere Tabellen in einer Zelle, untereinander
1160 : 0 : bTabInTabCell = false;
1161 [ # # ]: 0 : NextRow( pInfo );
1162 : : }
1163 : : else
1164 : : { // in dieser Zelle geht's los, oder nebeneinander
1165 : 0 : bTabInTabCell = false;
1166 : 0 : nColCntStart = nColCnt;
1167 : 0 : nColOffset = nTmpColOffset;
1168 : 0 : nColOffsetStart = nColOffset;
1169 : : }
1170 : :
1171 : 0 : ScEEParseEntry* pE = NULL;
1172 [ # # ]: 0 : if (maList.size())
1173 [ # # ]: 0 : pE = maList.back();
1174 [ # # ]: 0 : NewActEntry( pE ); // neuer freifliegender pActEntry
1175 [ # # ][ # # ]: 0 : xLockedList = new ScRangeList;
[ # # ]
1176 : : }
1177 : : else
1178 : : { // einfache Table auf Dokumentebene
1179 : 0 : EntryEnd( pActEntry, pInfo->aSelection );
1180 [ # # ]: 0 : if ( pActEntry->aSel.HasRange() )
1181 : : { // noch fliegender Text
1182 [ # # ]: 0 : CloseEntry( pInfo );
1183 [ # # ]: 0 : NextRow( pInfo );
1184 : : }
1185 : : aTableStack.push( new ScHTMLTableStackEntry(
1186 : : pActEntry, xLockedList, pLocalColOffset, nFirstTableCell,
1187 : : nColCnt, nRowCnt, nColCntStart, nMaxCol, nTable,
1188 : : nTableWidth, nColOffset, nColOffsetStart,
1189 [ # # ][ # # ]: 0 : bFirstRow ) );
[ # # ]
1190 : : // As soon as we have multiple tables we need to be tolerant with the offsets.
1191 [ # # ]: 0 : if (nMaxTable > 0)
1192 : 0 : nOffsetTolerance = SC_HTML_OFFSET_TOLERANCE_LARGE;
1193 : 0 : nTableWidth = 0;
1194 [ # # ]: 0 : if ( pInfo->nToken == HTML_TABLE_ON )
1195 : : { // es kann auch TD oder TH sein, wenn es vorher kein TABLE gab
1196 [ # # ]: 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1197 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1198 : : {
1199 [ # # ]: 0 : const HTMLOption& rOption = rOptions[i];
1200 [ # # # # ]: 0 : switch( rOption.GetToken() )
1201 : : {
1202 : : case HTML_O_WIDTH:
1203 : : { // Prozent: von Dokumentbreite bzw. aeusserer Zelle
1204 [ # # ]: 0 : nTableWidth = GetWidthPixel( rOption );
1205 : : }
1206 : 0 : break;
1207 : : case HTML_O_BORDER:
1208 : : //BorderOn is: ((pOption->GetString().Len() == 0) || (pOption->GetNumber() != 0));
1209 : 0 : break;
1210 : : case HTML_O_ID:
1211 [ # # ]: 0 : aTabName.Assign( rOption.GetString() );
1212 : 0 : break;
1213 : : }
1214 : : }
1215 : : }
1216 : : }
1217 : 0 : nTable = ++nMaxTable;
1218 : 0 : bFirstRow = true;
1219 : 0 : nFirstTableCell = maList.size();
1220 : :
1221 [ # # ][ # # ]: 0 : pLocalColOffset = new ScHTMLColOffset;
1222 [ # # ][ # # ]: 0 : MakeColNoRef( pLocalColOffset, nColOffsetStart, 0, 0, 0 );
1223 : 0 : }
1224 : :
1225 : :
1226 : 0 : void ScHTMLLayoutParser::TableOff( ImportInfo* pInfo )
1227 : : {
1228 [ # # ]: 0 : if ( bInCell )
1229 : 0 : CloseEntry( pInfo );
1230 [ # # ]: 0 : if ( nColCnt > nColCntStart )
1231 : 0 : TableRowOff( pInfo ); // das optionale TableRowOff war nicht
1232 [ # # ]: 0 : if ( !nTableLevel )
1233 : : {
1234 : : OSL_FAIL( "Dummbatz-Dok! </TABLE> ohne oeffnendes <TABLE>" );
1235 : 0 : return ;
1236 : : }
1237 [ # # ]: 0 : if ( --nTableLevel > 0 )
1238 : : { // Table in Table beendet
1239 [ # # ]: 0 : if ( !aTableStack.empty() )
1240 : : {
1241 : 0 : ScHTMLTableStackEntry* pS = aTableStack.top();
1242 : 0 : aTableStack.pop();
1243 : :
1244 : 0 : ScEEParseEntry* pE = pS->pCellEntry;
1245 : 0 : SCROW nRows = nRowCnt - pS->nRowCnt;
1246 [ # # ]: 0 : if ( nRows > 1 )
1247 : : { // Groesse der Tabelle an dieser Position eintragen
1248 : 0 : SCROW nRow = pS->nRowCnt;
1249 : 0 : sal_uInt16 nTab = pS->nTable;
1250 [ # # ]: 0 : if ( !pTables )
1251 [ # # ][ # # ]: 0 : pTables = new OuterMap;
1252 : : // Hoehen der aeusseren Table
1253 [ # # ][ # # ]: 0 : OuterMap::const_iterator it = pTables->find( nTab );
1254 : : InnerMap* pTab1;
1255 [ # # ][ # # ]: 0 : if ( it == pTables->end() )
[ # # ]
1256 : : {
1257 [ # # ][ # # ]: 0 : pTab1 = new InnerMap;
1258 [ # # ]: 0 : (*pTables)[ nTab ] = pTab1;
1259 : : }
1260 : : else
1261 [ # # ]: 0 : pTab1 = it->second;
1262 : 0 : SCROW nRowSpan = pE->nRowOverlap;
1263 : : SCROW nRowKGV;
1264 : : SCROW nRowsPerRow1; // aeussere Table
1265 : : SCROW nRowsPerRow2; // innere Table
1266 [ # # ]: 0 : if ( nRowSpan > 1 )
1267 : : { // KGV auf das sich aussere und innere Zeilen
1268 : : // abbilden lassen
1269 : 0 : nRowKGV = lcl_KGV( nRowSpan, nRows );
1270 : 0 : nRowsPerRow1 = nRowKGV / nRowSpan;
1271 : 0 : nRowsPerRow2 = nRowKGV / nRows;
1272 : : }
1273 : : else
1274 : : {
1275 : 0 : nRowKGV = nRowsPerRow1 = nRows;
1276 : 0 : nRowsPerRow2 = 1;
1277 : : }
1278 : 0 : InnerMap* pTab2 = NULL;
1279 [ # # ]: 0 : if ( nRowsPerRow2 > 1 )
1280 : : { // Hoehen der inneren Table
1281 [ # # ][ # # ]: 0 : pTab2 = new InnerMap;
1282 [ # # ]: 0 : (*pTables)[ nTable ] = pTab2;
1283 : : }
1284 : : // void* Data-Entry der Table-Class fuer das
1285 : : // Hoehen-Mapping missbrauchen
1286 [ # # ]: 0 : if ( nRowKGV > 1 )
1287 : : {
1288 [ # # ]: 0 : if ( nRowsPerRow1 > 1 )
1289 : : { // aussen
1290 [ # # ]: 0 : for ( SCROW j=0; j < nRowSpan; j++ )
1291 : : {
1292 : 0 : sal_uLong nRowKey = nRow + j;
1293 [ # # ]: 0 : SCROW nR = (*pTab1)[ nRowKey ];
1294 [ # # ]: 0 : if ( !nR )
1295 [ # # ]: 0 : (*pTab1)[ nRowKey ] = nRowsPerRow1;
1296 [ # # ]: 0 : else if ( nRowsPerRow1 > nR )
1297 [ # # ]: 0 : (*pTab1)[ nRowKey ] = nRowsPerRow1;
1298 : : //2do: wie geht das noch besser?
1299 [ # # ][ # # ]: 0 : else if ( nRowsPerRow1 < nR && nRowSpan == 1
[ # # ]
1300 : : && nTable == nMaxTable )
1301 : : { // Platz uebrig, evtl. besser mergen
1302 : 0 : SCROW nAdd = nRowsPerRow1 - (nR % nRowsPerRow1);
1303 : 0 : nR += nAdd;
1304 [ # # ]: 0 : if ( (nR % nRows) == 0 )
1305 : : { // nur wenn abbildbar
1306 [ # # ]: 0 : SCROW nR2 = (*pTab1)[ nRowKey+1 ];
1307 [ # # ]: 0 : if ( nR2 > nAdd )
1308 : : { // nur wenn wirklich Platz
1309 [ # # ]: 0 : (*pTab1)[ nRowKey ] = nR;
1310 [ # # ]: 0 : (*pTab1)[ nRowKey+1 ] = nR2 - nAdd;
1311 : 0 : nRowsPerRow2 = nR / nRows;
1312 : : }
1313 : : }
1314 : : }
1315 : : }
1316 : : }
1317 [ # # ]: 0 : if ( nRowsPerRow2 > 1 )
1318 : : { // innen
1319 [ # # ]: 0 : if ( !pTab2 )
1320 : : { // nRowsPerRow2 kann erhoeht worden sein
1321 [ # # ][ # # ]: 0 : pTab2 = new InnerMap;
1322 [ # # ]: 0 : (*pTables)[ nTable ] = pTab2;
1323 : : }
1324 [ # # ]: 0 : for ( SCROW j=0; j < nRows; j++ )
1325 : : {
1326 : 0 : sal_uLong nRowKey = nRow + j;
1327 [ # # ]: 0 : (*pTab2)[ nRowKey ] = nRowsPerRow2;
1328 : : }
1329 : : }
1330 : : }
1331 : : }
1332 : :
1333 : 0 : SetWidths();
1334 : :
1335 [ # # ]: 0 : if ( !pE->nWidth )
1336 : 0 : pE->nWidth = nTableWidth;
1337 [ # # ]: 0 : else if ( pE->nWidth < nTableWidth )
1338 : : {
1339 : 0 : sal_uInt16 nOldOffset = pE->nOffset + pE->nWidth;
1340 : 0 : sal_uInt16 nNewOffset = pE->nOffset + nTableWidth;
1341 [ # # ]: 0 : ModifyOffset( pS->pLocalColOffset, nOldOffset, nNewOffset, nOffsetTolerance );
1342 : 0 : sal_uInt16 nTmp = nNewOffset - pE->nOffset - pE->nWidth;
1343 : 0 : pE->nWidth = nNewOffset - pE->nOffset;
1344 : 0 : pS->nTableWidth = pS->nTableWidth + nTmp;
1345 [ # # ]: 0 : if ( pS->nColOffset >= nOldOffset )
1346 : 0 : pS->nColOffset = pS->nColOffset + nTmp;
1347 : : }
1348 : :
1349 : 0 : nColCnt = pE->nCol + pE->nColOverlap;
1350 : 0 : nRowCnt = pS->nRowCnt;
1351 : 0 : nColCntStart = pS->nColCntStart;
1352 : 0 : nMaxCol = pS->nMaxCol;
1353 : 0 : nTable = pS->nTable;
1354 : 0 : nTableWidth = pS->nTableWidth;
1355 : 0 : nFirstTableCell = pS->nFirstTableCell;
1356 : 0 : nColOffset = pS->nColOffset;
1357 : 0 : nColOffsetStart = pS->nColOffsetStart;
1358 : 0 : bFirstRow = pS->bFirstRow;
1359 : 0 : xLockedList = pS->xLockedList;
1360 [ # # ]: 0 : if ( pLocalColOffset )
1361 [ # # ]: 0 : delete pLocalColOffset;
1362 : 0 : pLocalColOffset = pS->pLocalColOffset;
1363 [ # # ]: 0 : delete pActEntry;
1364 : : // pActEntry bleibt erstmal erhalten falls da noch 'ne Table in
1365 : : // der gleichen Zelle aufgemacht werden sollte (in HTML ist ja
1366 : : // alles moeglich..) und wird in CloseEntry deleted
1367 : 0 : pActEntry = pE;
1368 [ # # ]: 0 : delete pS;
1369 : : }
1370 : 0 : bTabInTabCell = true;
1371 : 0 : bInCell = true;
1372 : : }
1373 : : else
1374 : : { // einfache Table beendet
1375 : 0 : SetWidths();
1376 : 0 : nMaxCol = 0;
1377 : 0 : nTable = 0;
1378 [ # # ]: 0 : if ( !aTableStack.empty() )
1379 : : {
1380 : 0 : ScHTMLTableStackEntry* pS = aTableStack.top();
1381 : 0 : aTableStack.pop();
1382 [ # # ]: 0 : if ( pLocalColOffset )
1383 [ # # ]: 0 : delete pLocalColOffset;
1384 : 0 : pLocalColOffset = pS->pLocalColOffset;
1385 [ # # ]: 0 : delete pS;
1386 : : }
1387 : : }
1388 : : }
1389 : :
1390 : :
1391 : 0 : void ScHTMLLayoutParser::Image( ImportInfo* pInfo )
1392 : : {
1393 [ # # ]: 0 : ScHTMLImage* pImage = new ScHTMLImage;
1394 [ # # ]: 0 : pActEntry->maImageList.push_back( pImage );
1395 [ # # ]: 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1396 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1397 : : {
1398 [ # # ]: 0 : const HTMLOption& rOption = rOptions[i];
1399 [ # # # # : 0 : switch( rOption.GetToken() )
# # # ]
1400 : : {
1401 : : case HTML_O_SRC:
1402 : : {
1403 [ # # ][ # # ]: 0 : pImage->aURL = INetURLObject::GetAbsURL( aBaseURL, rOption.GetString() );
1404 : : }
1405 : 0 : break;
1406 : : case HTML_O_ALT:
1407 : : {
1408 [ # # ]: 0 : if ( !pActEntry->bHasGraphic )
1409 : : { // ALT text only if not any image loaded
1410 [ # # ]: 0 : if (!pActEntry->aAltText.isEmpty())
1411 [ # # ]: 0 : pActEntry->aAltText += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("; "));
1412 : :
1413 [ # # ]: 0 : pActEntry->aAltText += rOption.GetString();
1414 : : }
1415 : : }
1416 : 0 : break;
1417 : : case HTML_O_WIDTH:
1418 : : {
1419 [ # # ]: 0 : pImage->aSize.Width() = (long)rOption.GetNumber();
1420 : : }
1421 : 0 : break;
1422 : : case HTML_O_HEIGHT:
1423 : : {
1424 [ # # ]: 0 : pImage->aSize.Height() = (long)rOption.GetNumber();
1425 : : }
1426 : 0 : break;
1427 : : case HTML_O_HSPACE:
1428 : : {
1429 [ # # ]: 0 : pImage->aSpace.X() = (long)rOption.GetNumber();
1430 : : }
1431 : 0 : break;
1432 : : case HTML_O_VSPACE:
1433 : : {
1434 [ # # ]: 0 : pImage->aSpace.Y() = (long)rOption.GetNumber();
1435 : : }
1436 : 0 : break;
1437 : : }
1438 : : }
1439 [ # # ]: 0 : if (pImage->aURL.isEmpty())
1440 : : {
1441 : : OSL_FAIL( "Image: Grafik ohne URL ?!?" );
1442 : : return ;
1443 : : }
1444 : :
1445 : : sal_uInt16 nFormat;
1446 [ # # ][ # # ]: 0 : Graphic* pGraphic = new Graphic;
1447 [ # # ]: 0 : GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
1448 [ # # ]: 0 : if ( GRFILTER_OK != GraphicFilter::LoadGraphic( pImage->aURL, pImage->aFilterName,
1449 [ # # ][ # # ]: 0 : *pGraphic, &rFilter, &nFormat ) )
[ # # ][ # # ]
[ # # ]
1450 : : {
1451 [ # # ][ # # ]: 0 : delete pGraphic;
1452 : : return ; // dumm gelaufen
1453 : : }
1454 [ # # ]: 0 : if ( !pActEntry->bHasGraphic )
1455 : : { // discard any ALT text in this cell if we have any image
1456 : 0 : pActEntry->bHasGraphic = true;
1457 : 0 : pActEntry->aAltText = rtl::OUString();
1458 : : }
1459 [ # # ][ # # ]: 0 : pImage->aFilterName = rFilter.GetImportFormatName( nFormat );
[ # # ]
1460 : 0 : pImage->pGraphic = pGraphic;
1461 [ # # ][ # # ]: 0 : if ( !(pImage->aSize.Width() && pImage->aSize.Height()) )
[ # # ]
1462 : : {
1463 [ # # ]: 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
1464 : : pImage->aSize = pDefaultDev->LogicToPixel( pGraphic->GetPrefSize(),
1465 [ # # ][ # # ]: 0 : pGraphic->GetPrefMapMode() );
[ # # ][ # # ]
1466 : : }
1467 [ # # ]: 0 : if ( pActEntry->maImageList.size() > 0 )
1468 : : {
1469 : 0 : long nWidth = 0;
1470 [ # # ]: 0 : for ( sal_uInt32 i=0; i < pActEntry->maImageList.size(); ++i )
1471 : : {
1472 [ # # ]: 0 : ScHTMLImage* pI = &pActEntry->maImageList[ i ];
1473 [ # # ]: 0 : if ( pI->nDir & nHorizontal )
1474 : 0 : nWidth += pI->aSize.Width() + 2 * pI->aSpace.X();
1475 : : else
1476 : 0 : nWidth = 0;
1477 : : }
1478 [ # # # # ]: 0 : if ( pActEntry->nWidth
[ # # ]
1479 : 0 : && (nWidth + pImage->aSize.Width() + 2 * pImage->aSpace.X()
1480 : : >= pActEntry->nWidth) )
1481 [ # # ]: 0 : pActEntry->maImageList.back().nDir = nVertical;
1482 : : }
1483 : : }
1484 : :
1485 : :
1486 : 0 : void ScHTMLLayoutParser::ColOn( ImportInfo* pInfo )
1487 : : {
1488 : 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1489 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1490 : : {
1491 : 0 : const HTMLOption& rOption = rOptions[i];
1492 [ # # ]: 0 : switch( rOption.GetToken() )
1493 : : {
1494 : : case HTML_O_WIDTH:
1495 : : {
1496 [ # # ]: 0 : sal_uInt16 nVal = GetWidthPixel( rOption );
1497 [ # # ]: 0 : MakeCol( pLocalColOffset, nColOffset, nVal, 0, 0 );
1498 : 0 : nColOffset = nColOffset + nVal;
1499 : : }
1500 : 0 : break;
1501 : : }
1502 : : }
1503 : 0 : }
1504 : :
1505 : :
1506 : 0 : sal_uInt16 ScHTMLLayoutParser::GetWidthPixel( const HTMLOption& rOption )
1507 : : {
1508 : 0 : const String& rOptVal = rOption.GetString();
1509 [ # # ]: 0 : if ( rOptVal.Search('%') != STRING_NOTFOUND )
1510 : : { // Prozent
1511 [ # # ]: 0 : sal_uInt16 nW = (nTableWidth ? nTableWidth : (sal_uInt16) aPageSize.Width());
1512 : 0 : return (sal_uInt16)((rOption.GetNumber() * nW) / 100);
1513 : : }
1514 : : else
1515 : : {
1516 [ # # ]: 0 : if ( rOptVal.Search('*') != STRING_NOTFOUND )
1517 : : { // relativ zu was?!?
1518 : : //todo: ColArray aller relativen Werte sammeln und dann MakeCol
1519 : 0 : return 0;
1520 : : }
1521 : : else
1522 : 0 : return (sal_uInt16)rOption.GetNumber(); // Pixel
1523 : : }
1524 : : }
1525 : :
1526 : :
1527 : 0 : void ScHTMLLayoutParser::AnchorOn( ImportInfo* pInfo )
1528 : : {
1529 : 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1530 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1531 : : {
1532 : 0 : const HTMLOption& rOption = rOptions[i];
1533 [ # # ]: 0 : switch( rOption.GetToken() )
1534 : : {
1535 : : case HTML_O_NAME:
1536 : : {
1537 [ # # ]: 0 : pActEntry->pName = new rtl::OUString(rOption.GetString());
1538 : : }
1539 : 0 : break;
1540 : : }
1541 : : }
1542 : 0 : }
1543 : :
1544 : :
1545 : 0 : bool ScHTMLLayoutParser::IsAtBeginningOfText( ImportInfo* pInfo )
1546 : : {
1547 : 0 : ESelection& rSel = pActEntry->aSel;
1548 : : return rSel.nStartPara == rSel.nEndPara &&
1549 : : rSel.nStartPara <= pInfo->aSelection.nEndPara &&
1550 [ # # ][ # # ]: 0 : pEdit->GetTextLen( rSel.nStartPara ) == 0;
[ # # ]
1551 : : }
1552 : :
1553 : :
1554 : 0 : void ScHTMLLayoutParser::FontOn( ImportInfo* pInfo )
1555 : : {
1556 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1557 : : { // nur am Anfang des Textes, gilt dann fuer gesamte Zelle
1558 : 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(pInfo->pParser)->GetOptions();
1559 [ # # ]: 0 : for (size_t i = 0, n = rOptions.size(); i < n; ++i)
1560 : : {
1561 : 0 : const HTMLOption& rOption = rOptions[i];
1562 [ # # # # ]: 0 : switch( rOption.GetToken() )
1563 : : {
1564 : : case HTML_O_FACE :
1565 : : {
1566 : 0 : const String& rFace = rOption.GetString();
1567 [ # # ]: 0 : String aFontName;
1568 : 0 : xub_StrLen nPos = 0;
1569 [ # # ]: 0 : while( nPos != STRING_NOTFOUND )
1570 : : {
1571 : : // Fontliste, VCL: Semikolon als Separator, HTML: Komma
1572 [ # # ]: 0 : String aFName = rFace.GetToken( 0, ',', nPos );
1573 [ # # ][ # # ]: 0 : aFName = comphelper::string::strip(aFName, ' ');
[ # # ]
1574 [ # # ]: 0 : if( aFontName.Len() )
1575 [ # # ]: 0 : aFontName += ';';
1576 [ # # ]: 0 : aFontName += aFName;
1577 [ # # ]: 0 : }
1578 [ # # ]: 0 : if ( aFontName.Len() )
1579 : : pActEntry->aItemSet.Put( SvxFontItem( FAMILY_DONTKNOW,
1580 [ # # ]: 0 : aFontName, EMPTY_STRING, PITCH_DONTKNOW,
1581 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_DONTKNOW, ATTR_FONT ) );
[ # # ][ # # ]
1582 : : }
1583 : 0 : break;
1584 : : case HTML_O_SIZE :
1585 : : {
1586 : 0 : sal_uInt16 nSize = (sal_uInt16) rOption.GetNumber();
1587 [ # # ]: 0 : if ( nSize == 0 )
1588 : 0 : nSize = 1;
1589 [ # # ]: 0 : else if ( nSize > SC_HTML_FONTSIZES )
1590 : 0 : nSize = SC_HTML_FONTSIZES;
1591 : : pActEntry->aItemSet.Put( SvxFontHeightItem(
1592 [ # # ]: 0 : maFontHeights[nSize-1], 100, ATTR_FONT_HEIGHT ) );
1593 : : }
1594 : 0 : break;
1595 : : case HTML_O_COLOR :
1596 : : {
1597 : 0 : Color aColor;
1598 [ # # ]: 0 : rOption.GetColor( aColor );
1599 [ # # ][ # # ]: 0 : pActEntry->aItemSet.Put( SvxColorItem( aColor, ATTR_FONT_COLOR ) );
[ # # ]
1600 : : }
1601 : 0 : break;
1602 : : }
1603 : : }
1604 : : }
1605 : 0 : }
1606 : :
1607 : :
1608 : 0 : void ScHTMLLayoutParser::ProcToken( ImportInfo* pInfo )
1609 : : {
1610 : 0 : bool bSetLastToken = true;
1611 [ # # # # : 0 : switch ( pInfo->nToken )
# # # # #
# # # # #
# # # # #
# # # # ]
1612 : : {
1613 : : case HTML_META:
1614 : : {
1615 : 0 : HTMLParser* pParser = static_cast<HTMLParser*>(pInfo->pParser);
1616 : : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1617 [ # # ][ # # ]: 0 : mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
1618 : : pParser->ParseMetaOptions(
1619 [ # # ]: 0 : xDPS->getDocumentProperties(),
1620 [ # # ][ # # ]: 0 : mpDoc->GetDocumentShell()->GetHeaderAttributes() );
[ # # ]
1621 : : }
1622 : 0 : break;
1623 : : case HTML_TITLE_ON:
1624 : : {
1625 : 0 : bInTitle = true;
1626 : 0 : aString = rtl::OUString();
1627 : : }
1628 : 0 : break;
1629 : : case HTML_TITLE_OFF:
1630 : : {
1631 [ # # ][ # # ]: 0 : if ( bInTitle && !aString.isEmpty() )
[ # # ]
1632 : : {
1633 : : // Leerzeichen von Zeilenumbruechen raus
1634 : 0 : aString = aString.trim();
1635 : : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1636 : : mpDoc->GetDocumentShell()->GetModel(),
1637 [ # # ][ # # ]: 0 : uno::UNO_QUERY_THROW);
1638 [ # # ][ # # ]: 0 : xDPS->getDocumentProperties()->setTitle(aString);
[ # # ][ # # ]
1639 : : }
1640 : 0 : bInTitle = false;
1641 : : }
1642 : 0 : break;
1643 : : case HTML_TABLE_ON:
1644 : : {
1645 : 0 : TableOn( pInfo );
1646 : : }
1647 : 0 : break;
1648 : : case HTML_COL_ON:
1649 : : {
1650 : 0 : ColOn( pInfo );
1651 : : }
1652 : 0 : break;
1653 : : case HTML_TABLEHEADER_ON: // oeffnet Zelle
1654 : : {
1655 [ # # ]: 0 : if ( bInCell )
1656 : 0 : CloseEntry( pInfo );
1657 : : // bInCell nicht true setzen, das macht TableDataOn
1658 : : pActEntry->aItemSet.Put(
1659 [ # # ]: 0 : SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT) );
1660 : : } // fall thru
1661 : : case HTML_TABLEDATA_ON: // oeffnet Zelle
1662 : : {
1663 : 0 : TableDataOn( pInfo );
1664 : : }
1665 : 0 : break;
1666 : : case HTML_TABLEHEADER_OFF:
1667 : : case HTML_TABLEDATA_OFF: // schliesst Zelle
1668 : : {
1669 : 0 : TableDataOff( pInfo );
1670 : : }
1671 : 0 : break;
1672 : : case HTML_TABLEROW_ON: // vor erster Zelle in Row
1673 : : {
1674 : 0 : TableRowOn( pInfo );
1675 : : }
1676 : 0 : break;
1677 : : case HTML_TABLEROW_OFF: // nach letzter Zelle in Row
1678 : : {
1679 : 0 : TableRowOff( pInfo );
1680 : : }
1681 : 0 : break;
1682 : : case HTML_TABLE_OFF:
1683 : : {
1684 : 0 : TableOff( pInfo );
1685 : : }
1686 : 0 : break;
1687 : : case HTML_IMAGE:
1688 : : {
1689 : 0 : Image( pInfo );
1690 : : }
1691 : 0 : break;
1692 : : case HTML_PARABREAK_OFF:
1693 : : { // nach einem Image geht es vertikal weiter
1694 [ # # ]: 0 : if ( pActEntry->maImageList.size() > 0 )
1695 : 0 : pActEntry->maImageList.back().nDir = nVertical;
1696 : : }
1697 : 0 : break;
1698 : : case HTML_ANCHOR_ON:
1699 : : {
1700 : 0 : AnchorOn( pInfo );
1701 : : }
1702 : 0 : break;
1703 : : case HTML_FONT_ON :
1704 : : {
1705 : 0 : FontOn( pInfo );
1706 : : }
1707 : 0 : break;
1708 : : case HTML_BIGPRINT_ON :
1709 : : {
1710 : : //tpdo: aktuelle Fontgroesse merken und einen groesser
1711 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1712 : : pActEntry->aItemSet.Put( SvxFontHeightItem(
1713 [ # # ]: 0 : maFontHeights[3], 100, ATTR_FONT_HEIGHT ) );
1714 : : }
1715 : 0 : break;
1716 : : case HTML_SMALLPRINT_ON :
1717 : : {
1718 : : //todo: aktuelle Fontgroesse merken und einen kleiner
1719 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1720 : : pActEntry->aItemSet.Put( SvxFontHeightItem(
1721 [ # # ]: 0 : maFontHeights[0], 100, ATTR_FONT_HEIGHT ) );
1722 : : }
1723 : 0 : break;
1724 : : case HTML_BOLD_ON :
1725 : : case HTML_STRONG_ON :
1726 : : {
1727 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1728 : : pActEntry->aItemSet.Put( SvxWeightItem( WEIGHT_BOLD,
1729 [ # # ]: 0 : ATTR_FONT_WEIGHT ) );
1730 : : }
1731 : 0 : break;
1732 : : case HTML_ITALIC_ON :
1733 : : case HTML_EMPHASIS_ON :
1734 : : case HTML_ADDRESS_ON :
1735 : : case HTML_BLOCKQUOTE_ON :
1736 : : case HTML_BLOCKQUOTE30_ON :
1737 : : case HTML_CITIATION_ON :
1738 : : case HTML_VARIABLE_ON :
1739 : : {
1740 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1741 : : pActEntry->aItemSet.Put( SvxPostureItem( ITALIC_NORMAL,
1742 [ # # ]: 0 : ATTR_FONT_POSTURE ) );
1743 : : }
1744 : 0 : break;
1745 : : case HTML_DEFINSTANCE_ON :
1746 : : {
1747 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1748 : : {
1749 : : pActEntry->aItemSet.Put( SvxWeightItem( WEIGHT_BOLD,
1750 [ # # ]: 0 : ATTR_FONT_WEIGHT ) );
1751 : : pActEntry->aItemSet.Put( SvxPostureItem( ITALIC_NORMAL,
1752 [ # # ]: 0 : ATTR_FONT_POSTURE ) );
1753 : : }
1754 : : }
1755 : 0 : break;
1756 : : case HTML_UNDERLINE_ON :
1757 : : {
1758 [ # # ]: 0 : if ( IsAtBeginningOfText( pInfo ) )
1759 : : pActEntry->aItemSet.Put( SvxUnderlineItem( UNDERLINE_SINGLE,
1760 [ # # ]: 0 : ATTR_FONT_UNDERLINE ) );
1761 : : }
1762 : 0 : break;
1763 : : case HTML_TEXTTOKEN:
1764 : : {
1765 [ # # ]: 0 : if ( bInTitle )
1766 : 0 : aString += pInfo->aText;
1767 : : }
1768 : 0 : break;
1769 : : default:
1770 : : { // nLastToken nicht setzen!
1771 : 0 : bSetLastToken = false;
1772 : : }
1773 : : }
1774 [ # # ]: 0 : if ( bSetLastToken )
1775 : 0 : nLastToken = pInfo->nToken;
1776 : 0 : }
1777 : :
1778 : :
1779 : :
1780 : : // ============================================================================
1781 : : // HTML DATA QUERY PARSER
1782 : : // ============================================================================
1783 : :
1784 : : template< typename Type >
1785 : 0 : inline Type getLimitedValue( const Type& rValue, const Type& rMin, const Type& rMax )
1786 : 0 : { return ::std::max( ::std::min( rValue, rMax ), rMin ); }
1787 : :
1788 : 84 : ScHTMLEntry::ScHTMLEntry( const SfxItemSet& rItemSet, ScHTMLTableId nTableId ) :
1789 : : ScEEParseEntry( rItemSet ),
1790 : 84 : mbImportAlways( false )
1791 : : {
1792 : 84 : nTab = nTableId;
1793 : 84 : bEntirePara = false;
1794 : 84 : }
1795 : :
1796 : 120 : bool ScHTMLEntry::HasContents() const
1797 : : {
1798 [ + - ][ + + ]: 120 : return mbImportAlways || aSel.HasRange() || !aAltText.isEmpty() || IsTable();
[ + - ][ + + ]
1799 : : }
1800 : :
1801 : 21 : void ScHTMLEntry::AdjustStart( const ImportInfo& rInfo )
1802 : : {
1803 : : // set start position
1804 : 21 : aSel.nStartPara = rInfo.aSelection.nStartPara;
1805 : 21 : aSel.nStartPos = rInfo.aSelection.nStartPos;
1806 : : // adjust end position
1807 [ + - ][ + - ]: 21 : if( (aSel.nEndPara < aSel.nStartPara) || ((aSel.nEndPara == aSel.nStartPara) && (aSel.nEndPos < aSel.nStartPos)) )
[ - + ]
1808 : : {
1809 : 0 : aSel.nEndPara = aSel.nStartPara;
1810 : 0 : aSel.nEndPos = aSel.nStartPos;
1811 : : }
1812 : 21 : }
1813 : :
1814 : 96 : void ScHTMLEntry::AdjustEnd( const ImportInfo& rInfo )
1815 : : {
1816 : : OSL_ENSURE( (aSel.nEndPara < rInfo.aSelection.nEndPara) ||
1817 : : ((aSel.nEndPara == rInfo.aSelection.nEndPara) && (aSel.nEndPos <= rInfo.aSelection.nEndPos)),
1818 : : "ScHTMLQueryParser::AdjustEntryEnd - invalid end position" );
1819 : : // set end position
1820 : 96 : aSel.nEndPara = rInfo.aSelection.nEndPara;
1821 : 96 : aSel.nEndPos = rInfo.aSelection.nEndPos;
1822 : 96 : }
1823 : :
1824 : 78 : void ScHTMLEntry::Strip( const EditEngine& rEditEngine )
1825 : : {
1826 : : // strip leading empty paragraphs
1827 [ + + ][ + - ]: 96 : while( (aSel.nStartPara < aSel.nEndPara) && (rEditEngine.GetTextLen( aSel.nStartPara ) <= aSel.nStartPos) )
[ + + ]
1828 : : {
1829 : 18 : ++aSel.nStartPara;
1830 : 18 : aSel.nStartPos = 0;
1831 : : }
1832 : : // strip trailing empty paragraphs
1833 [ - + ][ # # ]: 78 : while( (aSel.nStartPara < aSel.nEndPara) && (aSel.nEndPos == 0) )
[ - + ]
1834 : : {
1835 : 0 : --aSel.nEndPara;
1836 : 0 : aSel.nEndPos = rEditEngine.GetTextLen( aSel.nEndPara );
1837 : : }
1838 : 78 : }
1839 : :
1840 : : // ============================================================================
1841 : :
1842 : : /** A map of ScHTMLTable objects.
1843 : :
1844 : : Organizes the tables with a unique table key. Stores nested tables inside
1845 : : the parent table and forms in this way a tree structure of tables. An
1846 : : instance of this class ownes the contained table objects and deletes them
1847 : : on destruction.
1848 : : */
1849 : : class ScHTMLTableMap
1850 : : {
1851 : : private:
1852 : : typedef ::boost::shared_ptr< ScHTMLTable > ScHTMLTablePtr;
1853 : : typedef ::std::map< ScHTMLTableId, ScHTMLTablePtr > ScHTMLTableStdMap;
1854 : :
1855 : : public:
1856 : : typedef ScHTMLTableStdMap::iterator iterator;
1857 : : typedef ScHTMLTableStdMap::const_iterator const_iterator;
1858 : :
1859 : : private:
1860 : : ScHTMLTable& mrParentTable; /// Reference to parent table.
1861 : : ScHTMLTableStdMap maTables; /// Container for all table objects.
1862 : : mutable ScHTMLTable* mpCurrTable; /// Current table, used for fast search.
1863 : :
1864 : : public:
1865 : : explicit ScHTMLTableMap( ScHTMLTable& rParentTable );
1866 : : virtual ~ScHTMLTableMap();
1867 : :
1868 : : inline iterator begin() { return maTables.begin(); }
1869 : 12 : inline const_iterator begin() const { return maTables.begin(); }
1870 : : inline iterator end() { return maTables.end(); }
1871 : 12 : inline const_iterator end() const { return maTables.end(); }
1872 : : inline bool empty() const { return maTables.empty(); }
1873 : :
1874 : : /** Returns the specified table.
1875 : : @param nTableId Unique identifier of the table.
1876 : : @param bDeep true = searches deep in all nested table; false = only in this container. */
1877 : : ScHTMLTable* FindTable( ScHTMLTableId nTableId, bool bDeep = true ) const;
1878 : :
1879 : : /** Inserts a new table into the container. This container owns the created table.
1880 : : @param bPreFormText true = New table is based on preformatted text (<pre> tag). */
1881 : : ScHTMLTable* CreateTable( const ImportInfo& rInfo, bool bPreFormText );
1882 : :
1883 : : private:
1884 : : /** Sets a working table with its index for search optimization. */
1885 : 15 : inline void SetCurrTable( ScHTMLTable* pTable ) const
1886 [ + + ]: 15 : { if( pTable ) mpCurrTable = pTable; }
1887 : : };
1888 : :
1889 : : // ----------------------------------------------------------------------------
1890 : :
1891 : 3 : ScHTMLTableMap::ScHTMLTableMap( ScHTMLTable& rParentTable ) :
1892 : : mrParentTable(rParentTable),
1893 : 3 : mpCurrTable(NULL)
1894 : : {
1895 : 3 : }
1896 : :
1897 : 3 : ScHTMLTableMap::~ScHTMLTableMap()
1898 : : {
1899 [ - + ]: 6 : }
1900 : :
1901 : 12 : ScHTMLTable* ScHTMLTableMap::FindTable( ScHTMLTableId nTableId, bool bDeep ) const
1902 : : {
1903 : 12 : ScHTMLTable* pResult = 0;
1904 [ + - ][ + + ]: 12 : if( mpCurrTable && (nTableId == mpCurrTable->GetTableId()) )
[ + + ]
1905 : 9 : pResult = mpCurrTable; // cached table
1906 : : else
1907 : : {
1908 [ + - ]: 3 : const_iterator aFind = maTables.find( nTableId );
1909 [ - + ]: 3 : if( aFind != maTables.end() )
1910 : 3 : pResult = aFind->second.get(); // table from this container
1911 : : }
1912 : :
1913 : : // not found -> search deep in nested tables
1914 [ + + ][ + - ]: 12 : if( !pResult && bDeep )
1915 [ + - ][ + + ]: 6 : for( const_iterator aIter = begin(), aEnd = end(); !pResult && (aIter != aEnd); ++aIter )
[ + + ]
1916 [ + - ]: 3 : pResult = aIter->second->FindNestedTable( nTableId );
1917 : :
1918 : 12 : SetCurrTable( pResult );
1919 : 12 : return pResult;
1920 : : }
1921 : :
1922 : 3 : ScHTMLTable* ScHTMLTableMap::CreateTable( const ImportInfo& rInfo, bool bPreFormText )
1923 : : {
1924 [ + - ]: 3 : ScHTMLTable* pTable = new ScHTMLTable( mrParentTable, rInfo, bPreFormText );
1925 [ + - ][ + - ]: 3 : maTables[ pTable->GetTableId() ].reset( pTable );
1926 : 3 : SetCurrTable( pTable );
1927 : 3 : return pTable;
1928 : : }
1929 : :
1930 : : // ----------------------------------------------------------------------------
1931 : :
1932 : : /** Simplified forward iterator for convenience.
1933 : :
1934 : : Before the iterator can be dereferenced, it must be tested with the is()
1935 : : method. The iterator may be invalid directly after construction (e.g. empty
1936 : : container).
1937 : : */
1938 : : class ScHTMLTableIterator
1939 : : {
1940 : : public:
1941 : : /** Constructs the iterator for the passed table map.
1942 : : @param pTableMap Pointer to the table map (is allowed to be NULL). */
1943 : : explicit ScHTMLTableIterator( const ScHTMLTableMap* pTableMap );
1944 : :
1945 [ + + ][ + + ]: 27 : inline bool is() const { return mpTableMap && maIter != maEnd; }
1946 : 9 : inline ScHTMLTable* operator->() { return maIter->second.get(); }
1947 : : inline ScHTMLTable& operator*() { return *maIter->second; }
1948 : 9 : inline ScHTMLTableIterator& operator++() { ++maIter; return *this; }
1949 : :
1950 : : private:
1951 : : ScHTMLTableMap::const_iterator maIter;
1952 : : ScHTMLTableMap::const_iterator maEnd;
1953 : : const ScHTMLTableMap* mpTableMap;
1954 : : };
1955 : :
1956 : 18 : ScHTMLTableIterator::ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ) :
1957 : 18 : mpTableMap(pTableMap)
1958 : : {
1959 [ + + ]: 18 : if( pTableMap )
1960 : : {
1961 : 9 : maIter = pTableMap->begin();
1962 : 9 : maEnd = pTableMap->end();
1963 : : }
1964 : 18 : }
1965 : :
1966 : : // ============================================================================
1967 : :
1968 : 6 : ScHTMLTableAutoId::ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ) :
1969 : : mnTableId( rnUnusedId ),
1970 : 6 : mrnUnusedId( rnUnusedId )
1971 : : {
1972 : 6 : ++mrnUnusedId;
1973 : 6 : }
1974 : :
1975 : : // ----------------------------------------------------------------------------
1976 : :
1977 : 3 : ScHTMLTable::ScHTMLTable( ScHTMLTable& rParentTable, const ImportInfo& rInfo, bool bPreFormText ) :
1978 : : mpParentTable( &rParentTable ),
1979 : : maTableId( rParentTable.maTableId.mrnUnusedId ),
1980 : 3 : maTableItemSet( rParentTable.GetCurrItemSet() ),
1981 : : mrEditEngine( rParentTable.mrEditEngine ),
1982 : : mrEEParseList( rParentTable.mrEEParseList ),
1983 : : mpCurrEntryList( 0 ),
1984 : : maSize( 1, 1 ),
1985 : : mpParser(rParentTable.mpParser),
1986 : : mbBorderOn( false ),
1987 : : mbPreFormText( bPreFormText ),
1988 : : mbRowOn( false ),
1989 : : mbDataOn( false ),
1990 [ + - ][ + - ]: 12 : mbPushEmptyLine( false )
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ]
[ # # # # ]
1991 : : {
1992 [ - + ]: 3 : if( mbPreFormText )
1993 : : {
1994 [ # # ]: 0 : ImplRowOn();
1995 [ # # ]: 0 : ImplDataOn( ScHTMLSize( 1, 1 ) );
1996 : : }
1997 : : else
1998 : : {
1999 [ + - ]: 3 : ProcessFormatOptions( maTableItemSet, rInfo );
2000 [ + - ]: 3 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
2001 [ + - ][ + - ]: 3 : HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
2002 [ # # ][ + - ]: 3 : for (; itr != itrEnd; ++itr)
[ - + ]
2003 : : {
2004 [ # # ]: 0 : switch( itr->GetToken() )
[ # # # ]
2005 : : {
2006 : : case HTML_O_BORDER:
2007 [ # # ][ # # ]: 0 : mbBorderOn = ((itr->GetString().Len() == 0) || (itr->GetNumber() != 0));
[ # # ][ # # ]
[ # # ]
2008 : 0 : break;
2009 : : case HTML_O_ID:
2010 [ # # ][ # # ]: 0 : maTableName = itr->GetString();
2011 : 0 : break;
2012 : : }
2013 : : }
2014 : : }
2015 : :
2016 [ + - ]: 3 : CreateNewEntry( rInfo );
2017 [ # # # # ]: 3 : }
2018 : :
2019 : 3 : ScHTMLTable::ScHTMLTable(
2020 : : SfxItemPool& rPool,
2021 : : EditEngine& rEditEngine,
2022 : : ::std::vector< ScEEParseEntry* >& rEEParseList,
2023 : : ScHTMLTableId& rnUnusedId, ScHTMLParser* pParser
2024 : : ) :
2025 : : mpParentTable( 0 ),
2026 : : maTableId( rnUnusedId ),
2027 : : maTableItemSet( rPool ),
2028 : : mrEditEngine( rEditEngine ),
2029 : : mrEEParseList( rEEParseList ),
2030 : : mpCurrEntryList( 0 ),
2031 : : maSize( 1, 1 ),
2032 : : mpParser(pParser),
2033 : : mbBorderOn( false ),
2034 : : mbPreFormText( false ),
2035 : : mbRowOn( false ),
2036 : : mbDataOn( false ),
2037 [ + - ][ + - ]: 9 : mbPushEmptyLine( false )
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ]
[ # # # # ]
2038 : : {
2039 : : // open the first "cell" of the document
2040 [ + - ]: 3 : ImplRowOn();
2041 [ + - ]: 3 : ImplDataOn( ScHTMLSize( 1, 1 ) );
2042 [ + - ][ + - ]: 3 : mxCurrEntry = CreateEntry();
2043 [ # # # # ]: 3 : }
2044 : :
2045 [ + - ][ + - ]: 18 : ScHTMLTable::~ScHTMLTable()
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
2046 : : {
2047 [ + - ]: 27 : }
[ + + - + ]
2048 : :
2049 : 84 : const SfxItemSet& ScHTMLTable::GetCurrItemSet() const
2050 : : {
2051 : : // first try cell item set, then row item set, then table item set
2052 [ + + ][ + + ]: 84 : return mxDataItemSet.get() ? *mxDataItemSet : (mxRowItemSet.get() ? *mxRowItemSet : maTableItemSet);
2053 : : }
2054 : :
2055 : 63 : ScHTMLSize ScHTMLTable::GetSpan( const ScHTMLPos& rCellPos ) const
2056 : : {
2057 : 63 : ScHTMLSize aSpan( 1, 1 );
2058 : 63 : const ScRange* pRange = NULL;
2059 [ + - + - ]: 189 : if( ( (pRange = maVMergedCells.Find( rCellPos.MakeAddr() ) ) != 0)
[ - + ][ + - ]
[ - + # # ]
[ + - ]
2060 [ + - ][ # # ]: 126 : || ( (pRange = maHMergedCells.Find( rCellPos.MakeAddr() ) ) != 0)
2061 : : )
2062 : 0 : aSpan.Set( pRange->aEnd.Col() - pRange->aStart.Col() + 1, pRange->aEnd.Row() - pRange->aStart.Row() + 1 );
2063 : 63 : return aSpan;
2064 : : }
2065 : :
2066 : 9 : ScHTMLTable* ScHTMLTable::FindNestedTable( ScHTMLTableId nTableId ) const
2067 : : {
2068 [ + + ]: 9 : return mxNestedTables.get() ? mxNestedTables->FindTable( nTableId, true ) : 0;
2069 : : }
2070 : :
2071 : 0 : void ScHTMLTable::PutItem( const SfxPoolItem& rItem )
2072 : : {
2073 : : OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PutItem - no current entry" );
2074 [ # # ][ # # ]: 0 : if( mxCurrEntry.get() && mxCurrEntry->IsEmpty() )
[ # # ]
2075 : 0 : mxCurrEntry->GetItemSet().Put( rItem );
2076 : 0 : }
2077 : :
2078 : 39 : void ScHTMLTable::PutText( const ImportInfo& rInfo )
2079 : : {
2080 : : OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PutText - no current entry" );
2081 [ + - ]: 39 : if( mxCurrEntry.get() )
2082 : : {
2083 [ + - ][ + + ]: 39 : if( !mxCurrEntry->HasContents() && IsSpaceCharInfo( rInfo ) )
[ + + ]
2084 : 21 : mxCurrEntry->AdjustStart( rInfo );
2085 : : else
2086 : 18 : mxCurrEntry->AdjustEnd( rInfo );
2087 : : }
2088 : 39 : }
2089 : :
2090 : 18 : void ScHTMLTable::InsertPara( const ImportInfo& rInfo )
2091 : : {
2092 [ + - ][ + - ]: 18 : if( mxCurrEntry.get() && mbDataOn && !IsEmptyCell() )
[ - + ][ - + ]
2093 : 0 : mxCurrEntry->SetImportAlways();
2094 : 18 : PushEntry( rInfo );
2095 : 18 : CreateNewEntry( rInfo );
2096 : 18 : InsertLeadingEmptyLine();
2097 : 18 : }
2098 : :
2099 : 0 : void ScHTMLTable::BreakOn()
2100 : : {
2101 : : // empty line, if <br> is at start of cell
2102 [ # # ][ # # ]: 0 : mbPushEmptyLine = !mbPreFormText && mbDataOn && IsEmptyCell();
[ # # ]
2103 : 0 : }
2104 : :
2105 : 0 : void ScHTMLTable::HeadingOn()
2106 : : {
2107 : : // call directly, InsertPara() has not been called before
2108 : 0 : InsertLeadingEmptyLine();
2109 : 0 : }
2110 : :
2111 : 18 : void ScHTMLTable::InsertLeadingEmptyLine()
2112 : : {
2113 : : // empty line, if <p>, </p>, <h?>, or </h*> are not at start of cell
2114 [ + - ][ + - ]: 18 : mbPushEmptyLine = !mbPreFormText && mbDataOn && !IsEmptyCell();
[ + - ]
2115 : 18 : }
2116 : :
2117 : 0 : void ScHTMLTable::AnchorOn()
2118 : : {
2119 : : OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::AnchorOn - no current entry" );
2120 : : // don't skip entries with single hyperlinks
2121 [ # # ]: 0 : if( mxCurrEntry.get() )
2122 : 0 : mxCurrEntry->SetImportAlways();
2123 : 0 : }
2124 : :
2125 : 3 : ScHTMLTable* ScHTMLTable::TableOn( const ImportInfo& rInfo )
2126 : : {
2127 : 3 : PushEntry( rInfo );
2128 : 3 : return InsertNestedTable( rInfo, false );
2129 : : }
2130 : :
2131 : 3 : ScHTMLTable* ScHTMLTable::TableOff( const ImportInfo& rInfo )
2132 : : {
2133 [ - + ]: 3 : return mbPreFormText ? this : CloseTable( rInfo );
2134 : : }
2135 : :
2136 : 0 : ScHTMLTable* ScHTMLTable::PreOn( const ImportInfo& rInfo )
2137 : : {
2138 : 0 : PushEntry( rInfo );
2139 : 0 : return InsertNestedTable( rInfo, true );
2140 : : }
2141 : :
2142 : 0 : ScHTMLTable* ScHTMLTable::PreOff( const ImportInfo& rInfo )
2143 : : {
2144 [ # # ]: 0 : return mbPreFormText ? CloseTable( rInfo ) : this;
2145 : : }
2146 : :
2147 : 6 : void ScHTMLTable::RowOn( const ImportInfo& rInfo )
2148 : : {
2149 : 6 : PushEntry( rInfo, true );
2150 [ + - ][ + - ]: 6 : if( mpParentTable && !mbPreFormText ) // no rows allowed in global and preformatted tables
2151 : : {
2152 : 6 : ImplRowOn();
2153 : 6 : ProcessFormatOptions( *mxRowItemSet, rInfo );
2154 : : }
2155 : 6 : CreateNewEntry( rInfo );
2156 : 6 : }
2157 : :
2158 : 6 : void ScHTMLTable::RowOff( const ImportInfo& rInfo )
2159 : : {
2160 : 6 : PushEntry( rInfo, true );
2161 [ + - ][ + - ]: 6 : if( mpParentTable && !mbPreFormText ) // no rows allowed in global and preformatted tables
2162 : 6 : ImplRowOff();
2163 : 6 : CreateNewEntry( rInfo );
2164 : 6 : }
2165 : :
2166 : : namespace {
2167 : :
2168 : : /**
2169 : : * Decode a numbert format string stored in Excel-generated HTML's CSS
2170 : : * region.
2171 : : */
2172 : 0 : rtl::OUString decodeNumberFormat(const rtl::OUString& rFmt)
2173 : : {
2174 : 0 : rtl::OUStringBuffer aBuf;
2175 : 0 : const sal_Unicode* p = rFmt.getStr();
2176 : 0 : sal_Int32 n = rFmt.getLength();
2177 [ # # ]: 0 : for (sal_Int32 i = 0; i < n; ++i, ++p)
2178 : : {
2179 [ # # ]: 0 : if (*p == '\\')
2180 : : {
2181 : : // Skip '\'.
2182 : 0 : ++i;
2183 : 0 : ++p;
2184 : :
2185 : : // Parse all subsequent digits until first non-digit is found.
2186 : 0 : sal_Int32 nDigitCount = 0;
2187 : 0 : const sal_Unicode* p1 = p;
2188 [ # # ]: 0 : for (; i < n; ++i, ++p, ++nDigitCount)
2189 : : {
2190 [ # # ][ # # ]: 0 : if (*p < '0' || '9' < *p)
2191 : : {
2192 : 0 : --i;
2193 : 0 : --p;
2194 : 0 : break;
2195 : : }
2196 : :
2197 : : }
2198 [ # # ]: 0 : if (nDigitCount)
2199 : : {
2200 : 0 : sal_Int32 nVal = rtl::OUString(p1, nDigitCount).toInt32(16);
2201 [ # # ]: 0 : aBuf.append(static_cast<sal_Unicode>(nVal));
2202 : : }
2203 : : }
2204 : : else
2205 [ # # ]: 0 : aBuf.append(*p);
2206 : : }
2207 [ # # ]: 0 : return aBuf.makeStringAndClear();
2208 : : }
2209 : :
2210 : : }
2211 : :
2212 : 18 : void ScHTMLTable::DataOn( const ImportInfo& rInfo )
2213 : : {
2214 : 18 : PushEntry( rInfo, true );
2215 [ + - ][ + - ]: 18 : if( mpParentTable && !mbPreFormText ) // no cells allowed in global and preformatted tables
2216 : : {
2217 : : // read needed options from the <td> tag
2218 : 18 : ScHTMLSize aSpanSize( 1, 1 );
2219 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2220 : 18 : ::std::auto_ptr<rtl::OUString> pValStr, pNumStr;
2221 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2222 [ + - ]: 18 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
2223 [ + - ][ + - ]: 18 : HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
2224 : 18 : sal_uInt32 nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
2225 [ # # ][ + - ]: 18 : for (; itr != itrEnd; ++itr)
[ - + ]
2226 : : {
2227 [ # # ][ # # : 0 : switch (itr->GetToken())
# # # # ]
2228 : : {
2229 : : case HTML_O_COLSPAN:
2230 [ # # ][ # # ]: 0 : aSpanSize.mnCols = static_cast<SCCOL>( getLimitedValue<sal_Int32>( itr->GetString().ToInt32(), 1, 256 ) );
[ # # ]
2231 : 0 : break;
2232 : : case HTML_O_ROWSPAN:
2233 [ # # ][ # # ]: 0 : aSpanSize.mnRows = static_cast<SCROW>( getLimitedValue<sal_Int32>( itr->GetString().ToInt32(), 1, 256 ) );
[ # # ]
2234 : 0 : break;
2235 : : case HTML_O_SDVAL:
2236 [ # # ][ # # ]: 0 : pValStr.reset(new rtl::OUString(itr->GetString()));
[ # # ]
2237 : 0 : break;
2238 : : case HTML_O_SDNUM:
2239 [ # # ][ # # ]: 0 : pNumStr.reset(new rtl::OUString(itr->GetString()));
[ # # ]
2240 : 0 : break;
2241 : : case HTML_O_CLASS:
2242 : : {
2243 : : // Pick up the number format associated with this class (if
2244 : : // any).
2245 [ # # ]: 0 : rtl::OUString aElem(RTL_CONSTASCII_USTRINGPARAM("td"));
2246 [ # # ][ # # ]: 0 : rtl::OUString aClass = itr->GetString();
2247 [ # # ]: 0 : rtl::OUString aProp(RTL_CONSTASCII_USTRINGPARAM("mso-number-format"));
2248 : 0 : const ScHTMLStyles& rStyles = mpParser->GetStyles();
2249 [ # # ]: 0 : const rtl::OUString& rVal = rStyles.getPropertyValue(aElem, aClass, aProp);
2250 [ # # ]: 0 : rtl::OUString aNumFmt = decodeNumberFormat(rVal);
2251 : :
2252 [ # # ][ # # ]: 0 : nNumberFormat = GetFormatTable()->GetEntryKey(aNumFmt);
[ # # ][ # # ]
2253 [ # # ]: 0 : if (nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
2254 : : {
2255 : 0 : xub_StrLen nErrPos = 0;
2256 : : short nDummy;
2257 [ # # ][ # # ]: 0 : bool bValidFmt = GetFormatTable()->PutEntry(aNumFmt, nErrPos, nDummy, nNumberFormat);
2258 [ # # ]: 0 : if (!bValidFmt)
2259 : 0 : nNumberFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
2260 : 0 : }
2261 : : }
2262 : 0 : break;
2263 : : }
2264 : : }
2265 : :
2266 [ + - ]: 18 : ImplDataOn( aSpanSize );
2267 : :
2268 [ - + ]: 18 : if (nNumberFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
2269 [ # # ][ # # ]: 0 : mxDataItemSet->Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat) );
[ # # ]
2270 : :
2271 [ + - ]: 18 : ProcessFormatOptions( *mxDataItemSet, rInfo );
2272 [ + - ]: 18 : CreateNewEntry( rInfo );
2273 : 18 : mxCurrEntry->pValStr = pValStr.release();
2274 : 18 : mxCurrEntry->pNumStr = pNumStr.release();
2275 : : }
2276 : : else
2277 : 0 : CreateNewEntry( rInfo );
2278 : 18 : }
2279 : :
2280 : 18 : void ScHTMLTable::DataOff( const ImportInfo& rInfo )
2281 : : {
2282 : 18 : PushEntry( rInfo, true );
2283 [ + - ][ + - ]: 18 : if( mpParentTable && !mbPreFormText ) // no cells allowed in global and preformatted tables
2284 : 18 : ImplDataOff();
2285 : 18 : CreateNewEntry( rInfo );
2286 : 18 : }
2287 : :
2288 : 3 : void ScHTMLTable::BodyOn( const ImportInfo& rInfo )
2289 : : {
2290 : 3 : bool bPushed = PushEntry( rInfo );
2291 [ + - ]: 3 : if( !mpParentTable )
2292 : : {
2293 : : // do not start new row, if nothing (no title) precedes the body.
2294 [ + - ][ - + ]: 3 : if( bPushed || !mbRowOn )
2295 : 0 : ImplRowOn();
2296 [ + - ][ - + ]: 3 : if( bPushed || !mbDataOn )
2297 [ # # ]: 0 : ImplDataOn( ScHTMLSize( 1, 1 ) );
2298 : 3 : ProcessFormatOptions( *mxDataItemSet, rInfo );
2299 : : }
2300 : 3 : CreateNewEntry( rInfo );
2301 : 3 : }
2302 : :
2303 : 3 : void ScHTMLTable::BodyOff( const ImportInfo& rInfo )
2304 : : {
2305 : 3 : PushEntry( rInfo );
2306 [ + - ]: 3 : if( !mpParentTable )
2307 : : {
2308 : 3 : ImplDataOff();
2309 : 3 : ImplRowOff();
2310 : : }
2311 : 3 : CreateNewEntry( rInfo );
2312 : 3 : }
2313 : :
2314 : 3 : ScHTMLTable* ScHTMLTable::CloseTable( const ImportInfo& rInfo )
2315 : : {
2316 [ + - ]: 3 : if( mpParentTable ) // not allowed to close global table
2317 : : {
2318 : 3 : PushEntry( rInfo, mbDataOn );
2319 : 3 : ImplDataOff();
2320 : 3 : ImplRowOff();
2321 : 3 : mpParentTable->PushTableEntry( GetTableId() );
2322 : 3 : mpParentTable->CreateNewEntry( rInfo );
2323 [ - + ]: 3 : if( mbPreFormText ) // enclose preformatted table with empty lines in parent table
2324 : 0 : mpParentTable->InsertLeadingEmptyLine();
2325 : 3 : return mpParentTable;
2326 : : }
2327 : 3 : return this;
2328 : : }
2329 : :
2330 : 0 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const
2331 : : {
2332 : 0 : const ScSizeVec& rSizes = maCumSizes[ eOrient ];
2333 : 0 : size_t nIndex = static_cast< size_t >( nCellPos );
2334 [ # # ]: 0 : if( nIndex >= rSizes.size() ) return 0;
2335 [ # # ]: 0 : return (nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]);
2336 : : }
2337 : :
2338 : 84 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellBegin, SCCOLROW nCellEnd ) const
2339 : : {
2340 : 84 : const ScSizeVec& rSizes = maCumSizes[ eOrient ];
2341 [ + - ]: 84 : size_t nBeginIdx = static_cast< size_t >( ::std::max< SCCOLROW >( nCellBegin, 0 ) );
2342 [ + - ]: 84 : size_t nEndIdx = static_cast< size_t >( ::std::min< SCCOLROW >( nCellEnd, static_cast< SCCOLROW >( rSizes.size() ) ) );
2343 [ + + ]: 84 : if (nBeginIdx >= nEndIdx ) return 0;
2344 [ + + ]: 84 : return rSizes[ nEndIdx - 1 ] - ((nBeginIdx == 0) ? 0 : rSizes[ nBeginIdx - 1 ]);
2345 : : }
2346 : :
2347 : 27 : SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient ) const
2348 : : {
2349 : 27 : const ScSizeVec& rSizes = maCumSizes[ eOrient ];
2350 [ - + ]: 27 : return rSizes.empty() ? 0 : rSizes.back();
2351 : : }
2352 : :
2353 : 21 : ScHTMLSize ScHTMLTable::GetDocSize( const ScHTMLPos& rCellPos ) const
2354 : : {
2355 [ + - ]: 21 : ScHTMLSize aCellSpan = GetSpan( rCellPos );
2356 : : return ScHTMLSize(
2357 [ + - ]: 21 : static_cast< SCCOL >( GetDocSize( tdCol, rCellPos.mnCol, rCellPos.mnCol + aCellSpan.mnCols ) ),
2358 [ + - ]: 42 : static_cast< SCROW >( GetDocSize( tdRow, rCellPos.mnRow, rCellPos.mnRow + aCellSpan.mnRows ) ) );
2359 : : }
2360 : :
2361 : 42 : SCCOLROW ScHTMLTable::GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const
2362 : : {
2363 : 42 : return maDocBasePos.Get( eOrient ) + GetDocSize( eOrient, 0, nCellPos );
2364 : : }
2365 : :
2366 : 21 : ScHTMLPos ScHTMLTable::GetDocPos( const ScHTMLPos& rCellPos ) const
2367 : : {
2368 : : return ScHTMLPos(
2369 : 21 : static_cast< SCCOL >( GetDocPos( tdCol, rCellPos.mnCol ) ),
2370 : 42 : static_cast< SCROW >( GetDocPos( tdRow, rCellPos.mnRow ) ) );
2371 : : }
2372 : :
2373 : 3 : void ScHTMLTable::GetDocRange( ScRange& rRange ) const
2374 : : {
2375 : 3 : rRange.aStart = rRange.aEnd = maDocBasePos.MakeAddr();
2376 : 3 : rRange.aEnd.Move( static_cast< SCsCOL >( GetDocSize( tdCol ) ) - 1, static_cast< SCsROW >( GetDocSize( tdRow ) ) - 1, 0 );
2377 : 3 : }
2378 : :
2379 : 6 : void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const
2380 : : {
2381 : : OSL_ENSURE( pDoc, "ScHTMLTable::ApplyCellBorders - no document" );
2382 [ + - ][ - + ]: 6 : if( pDoc && mbBorderOn )
2383 : : {
2384 : 0 : const SCCOL nLastCol = maSize.mnCols - 1;
2385 : 0 : const SCROW nLastRow = maSize.mnRows - 1;
2386 : 0 : const long nOuterLine = DEF_LINE_WIDTH_2;
2387 : 0 : const long nInnerLine = DEF_LINE_WIDTH_0;
2388 [ # # ]: 0 : SvxBorderLine aOuterLine(0, nOuterLine, table::BorderLineStyle::SOLID);
2389 [ # # ]: 0 : SvxBorderLine aInnerLine(0, nInnerLine, table::BorderLineStyle::SOLID);
2390 [ # # ]: 0 : SvxBoxItem aBorderItem( ATTR_BORDER );
2391 : :
2392 [ # # ]: 0 : for( SCCOL nCol = 0; nCol <= nLastCol; ++nCol )
2393 : : {
2394 [ # # ]: 0 : SvxBorderLine* pLeftLine = (nCol == 0) ? &aOuterLine : &aInnerLine;
2395 [ # # ]: 0 : SvxBorderLine* pRightLine = (nCol == nLastCol) ? &aOuterLine : &aInnerLine;
2396 [ # # ]: 0 : SCCOL nCellCol1 = static_cast< SCCOL >( GetDocPos( tdCol, nCol ) ) + rFirstPos.Col();
2397 [ # # ]: 0 : SCCOL nCellCol2 = nCellCol1 + static_cast< SCCOL >( GetDocSize( tdCol, nCol ) ) - 1;
2398 [ # # ]: 0 : for( SCROW nRow = 0; nRow <= nLastRow; ++nRow )
2399 : : {
2400 [ # # ]: 0 : SvxBorderLine* pTopLine = (nRow == 0) ? &aOuterLine : &aInnerLine;
2401 [ # # ]: 0 : SvxBorderLine* pBottomLine = (nRow == nLastRow) ? &aOuterLine : &aInnerLine;
2402 [ # # ]: 0 : SCROW nCellRow1 = GetDocPos( tdRow, nRow ) + rFirstPos.Row();
2403 [ # # ]: 0 : SCROW nCellRow2 = nCellRow1 + GetDocSize( tdRow, nRow ) - 1;
2404 [ # # ]: 0 : for( SCCOL nCellCol = nCellCol1; nCellCol <= nCellCol2; ++nCellCol )
2405 : : {
2406 [ # # ][ # # ]: 0 : aBorderItem.SetLine( (nCellCol == nCellCol1) ? pLeftLine : 0, BOX_LINE_LEFT );
2407 [ # # ][ # # ]: 0 : aBorderItem.SetLine( (nCellCol == nCellCol2) ? pRightLine : 0, BOX_LINE_RIGHT );
2408 [ # # ]: 0 : for( SCROW nCellRow = nCellRow1; nCellRow <= nCellRow2; ++nCellRow )
2409 : : {
2410 [ # # ][ # # ]: 0 : aBorderItem.SetLine( (nCellRow == nCellRow1) ? pTopLine : 0, BOX_LINE_TOP );
2411 [ # # ][ # # ]: 0 : aBorderItem.SetLine( (nCellRow == nCellRow2) ? pBottomLine : 0, BOX_LINE_BOTTOM );
2412 [ # # ]: 0 : pDoc->ApplyAttr( nCellCol, nCellRow, rFirstPos.Tab(), aBorderItem );
2413 : : }
2414 : : }
2415 : : }
2416 [ # # ]: 0 : }
2417 : : }
2418 : :
2419 [ + - ][ + - ]: 9 : for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
[ + - ][ + + ]
2420 [ + - ][ + - ]: 3 : aIter->ApplyCellBorders( pDoc, rFirstPos );
2421 : 6 : }
2422 : :
2423 : 0 : SvNumberFormatter* ScHTMLTable::GetFormatTable()
2424 : : {
2425 : 0 : return mpParser->GetDoc().GetFormatTable();
2426 : : }
2427 : :
2428 : : // ----------------------------------------------------------------------------
2429 : :
2430 : 84 : bool ScHTMLTable::IsEmptyCell() const
2431 : : {
2432 [ + + ][ + + ]: 84 : return mpCurrEntryList && mpCurrEntryList->empty();
2433 : : }
2434 : :
2435 : 39 : bool ScHTMLTable::IsSpaceCharInfo( const ImportInfo& rInfo )
2436 : : {
2437 [ + - ][ + + ]: 39 : return (rInfo.nToken == HTML_TEXTTOKEN) && (rInfo.aText.Len() == 1) && (rInfo.aText.GetChar( 0 ) == ' ');
[ + - ]
2438 : : }
2439 : :
2440 : 81 : ScHTMLTable::ScHTMLEntryPtr ScHTMLTable::CreateEntry() const
2441 : : {
2442 [ + - ]: 81 : return ScHTMLEntryPtr( new ScHTMLEntry( GetCurrItemSet() ) );
2443 : : }
2444 : :
2445 : 78 : void ScHTMLTable::CreateNewEntry( const ImportInfo& rInfo )
2446 : : {
2447 : : OSL_ENSURE( !mxCurrEntry.get(), "ScHTMLTable::CreateNewEntry - old entry still present" );
2448 : 78 : mxCurrEntry = CreateEntry();
2449 : 78 : mxCurrEntry->aSel = rInfo.aSelection;
2450 : 78 : }
2451 : :
2452 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2453 : 21 : void ScHTMLTable::ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rxEntry )
2454 : : {
2455 : : // HTML entry list does not own the entries
2456 [ + - ]: 21 : rEntryList.push_back( rxEntry.get() );
2457 : : // mrEEParseList (reference to member of ScEEParser) owns the entries
2458 [ + - ]: 21 : mrEEParseList.push_back( rxEntry.release() );
2459 : 21 : }
2460 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2461 : :
2462 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2463 : 81 : bool ScHTMLTable::PushEntry( ScHTMLEntryPtr& rxEntry )
2464 : : {
2465 : 81 : bool bPushed = false;
2466 [ + - ][ + + ]: 81 : if( rxEntry.get() && rxEntry->HasContents() )
[ + + ]
2467 : : {
2468 [ + - ]: 21 : if( mpCurrEntryList )
2469 : : {
2470 [ - + ]: 21 : if( mbPushEmptyLine )
2471 : : {
2472 [ # # ][ # # ]: 0 : ScHTMLEntryPtr xEmptyEntry = CreateEntry();
2473 [ # # ]: 0 : ImplPushEntryToList( *mpCurrEntryList, xEmptyEntry );
2474 [ # # ]: 0 : mbPushEmptyLine = false;
2475 : : }
2476 : 21 : ImplPushEntryToList( *mpCurrEntryList, rxEntry );
2477 : 21 : bPushed = true;
2478 : : }
2479 [ # # ]: 0 : else if( mpParentTable )
2480 : : {
2481 : 0 : bPushed = mpParentTable->PushEntry( rxEntry );
2482 : : }
2483 : : else
2484 : : {
2485 : : OSL_FAIL( "ScHTMLTable::PushEntry - cannot push entry, no parent found" );
2486 : : }
2487 : : }
2488 : 81 : return bPushed;
2489 : : }
2490 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2491 : :
2492 : 78 : bool ScHTMLTable::PushEntry( const ImportInfo& rInfo, bool bLastInCell )
2493 : : {
2494 : : OSL_ENSURE( mxCurrEntry.get(), "ScHTMLTable::PushEntry - no current entry" );
2495 : 78 : bool bPushed = false;
2496 [ + - ]: 78 : if( mxCurrEntry.get() )
2497 : : {
2498 : 78 : mxCurrEntry->AdjustEnd( rInfo );
2499 : 78 : mxCurrEntry->Strip( mrEditEngine );
2500 : :
2501 : : // import entry always, if it is the last in cell, and cell is still empty
2502 [ - + ][ - + ]: 78 : if( bLastInCell && IsEmptyCell() )
[ + + ]
2503 : : {
2504 : 0 : mxCurrEntry->SetImportAlways();
2505 : : // don't insert empty lines before single empty entries
2506 [ # # ]: 0 : if( mxCurrEntry->IsEmpty() )
2507 : 0 : mbPushEmptyLine = false;
2508 : : }
2509 : :
2510 : 78 : bPushed = PushEntry( mxCurrEntry );
2511 : 78 : mxCurrEntry.reset();
2512 : : }
2513 : 78 : return bPushed;
2514 : : }
2515 : :
2516 : 3 : bool ScHTMLTable::PushTableEntry( ScHTMLTableId nTableId )
2517 : : {
2518 : : OSL_ENSURE( nTableId != SC_HTML_GLOBAL_TABLE, "ScHTMLTable::PushTableEntry - cannot push global table" );
2519 : 3 : bool bPushed = false;
2520 [ + - ]: 3 : if( nTableId != SC_HTML_GLOBAL_TABLE )
2521 : : {
2522 [ + - ][ + - ]: 3 : ScHTMLEntryPtr xEntry( new ScHTMLEntry( maTableItemSet, nTableId ) );
2523 [ + - ][ + - ]: 3 : bPushed = PushEntry( xEntry );
2524 : : }
2525 : 3 : return bPushed;
2526 : : }
2527 : :
2528 : 42 : ScHTMLTable* ScHTMLTable::GetExistingTable( ScHTMLTableId nTableId ) const
2529 : : {
2530 : 6 : ScHTMLTable* pTable = ((nTableId != SC_HTML_GLOBAL_TABLE) && mxNestedTables.get()) ?
2531 [ + + + - ]: 48 : mxNestedTables->FindTable( nTableId, false ) : 0;
2532 : : OSL_ENSURE( pTable || (nTableId == SC_HTML_GLOBAL_TABLE), "ScHTMLTable::GetExistingTable - table not found" );
2533 : 42 : return pTable;
2534 : : }
2535 : :
2536 : 3 : ScHTMLTable* ScHTMLTable::InsertNestedTable( const ImportInfo& rInfo, bool bPreFormText )
2537 : : {
2538 [ + - ]: 3 : if( !mxNestedTables.get() )
2539 [ + - ]: 3 : mxNestedTables.reset( new ScHTMLTableMap( *this ) );
2540 [ - + ]: 3 : if( bPreFormText ) // enclose new preformatted table with empty lines
2541 : 0 : InsertLeadingEmptyLine();
2542 : 3 : return mxNestedTables->CreateTable( rInfo, bPreFormText );
2543 : : }
2544 : :
2545 : 21 : void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize )
2546 : : {
2547 : : ScRange* pRange;
2548 : :
2549 : : /* Find an unused cell by skipping all merged ranges that cover the
2550 : : current cell position stored in maCurrCell. */
2551 [ + - ][ + - ]: 21 : while( ((pRange = maVMergedCells.Find( maCurrCell.MakeAddr() )) != 0) || ((pRange = maHMergedCells.Find( maCurrCell.MakeAddr() )) != 0) )
[ + - ][ - + ]
[ + - ][ + - ]
[ - + # #
# # ]
2552 : 0 : maCurrCell.mnCol = pRange->aEnd.Col() + 1;
2553 [ + - ]: 21 : mpCurrEntryList = &maEntryMap[ maCurrCell ];
2554 : :
2555 : : /* If the new cell is merged horizontally, try to find collisions with
2556 : : other vertically merged ranges. In this case, shrink existing
2557 : : vertically merged ranges (do not shrink the new cell). */
2558 : 21 : SCCOL nColEnd = maCurrCell.mnCol + rSpanSize.mnCols;
2559 [ + - ][ + + ]: 42 : for( ScAddress aAddr( maCurrCell.MakeAddr() ); aAddr.Col() < nColEnd; aAddr.IncCol() )
2560 [ + - ][ - + ]: 21 : if( (pRange = maVMergedCells.Find( aAddr )) != 0 )
2561 : 0 : pRange->aEnd.SetRow( maCurrCell.mnRow - 1 );
2562 : :
2563 : : // insert the new range into the cell lists
2564 : 21 : ScRange aNewRange( maCurrCell.MakeAddr() );
2565 [ + - ]: 21 : aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 );
2566 [ - + ]: 21 : if( rSpanSize.mnRows > 1 )
2567 : : {
2568 [ # # ]: 0 : maVMergedCells.Append( aNewRange );
2569 : : /* Do not insert vertically merged ranges into maUsedCells yet,
2570 : : because they may be shrunken (see above). The final vertically
2571 : : merged ranges are inserted in FillEmptyCells(). */
2572 : : }
2573 : : else
2574 : : {
2575 [ - + ]: 21 : if( rSpanSize.mnCols > 1 )
2576 [ # # ]: 0 : maHMergedCells.Append( aNewRange );
2577 : : /* Insert horizontally merged ranges and single cells into
2578 : : maUsedCells, they will not be changed anymore. */
2579 [ + - ]: 21 : maUsedCells.Join( aNewRange );
2580 : : }
2581 : :
2582 : : // adjust table size
2583 [ + - ]: 21 : maSize.mnCols = ::std::max< SCCOL >( maSize.mnCols, aNewRange.aEnd.Col() + 1 );
2584 [ + - ]: 21 : maSize.mnRows = ::std::max< SCROW >( maSize.mnRows, aNewRange.aEnd.Row() + 1 );
2585 : 21 : }
2586 : :
2587 : 9 : void ScHTMLTable::ImplRowOn()
2588 : : {
2589 [ - + ]: 9 : if( mbRowOn )
2590 : 0 : ImplRowOff();
2591 [ + - ]: 9 : mxRowItemSet.reset( new SfxItemSet( maTableItemSet ) );
2592 : 9 : maCurrCell.mnCol = 0;
2593 : 9 : mbRowOn = true;
2594 : 9 : mbDataOn = false;
2595 : 9 : }
2596 : :
2597 : 12 : void ScHTMLTable::ImplRowOff()
2598 : : {
2599 [ - + ]: 12 : if( mbDataOn )
2600 : 0 : ImplDataOff();
2601 [ + + ]: 12 : if( mbRowOn )
2602 : : {
2603 : 9 : mxRowItemSet.reset();
2604 : 9 : ++maCurrCell.mnRow;
2605 : 9 : mbRowOn = mbDataOn = false;
2606 : : }
2607 : 12 : }
2608 : :
2609 : 21 : void ScHTMLTable::ImplDataOn( const ScHTMLSize& rSpanSize )
2610 : : {
2611 [ - + ]: 21 : if( mbDataOn )
2612 : 0 : ImplDataOff();
2613 [ - + ]: 21 : if( !mbRowOn )
2614 : 0 : ImplRowOn();
2615 [ + - ]: 21 : mxDataItemSet.reset( new SfxItemSet( *mxRowItemSet ) );
2616 : 21 : InsertNewCell( rSpanSize );
2617 : 21 : mbDataOn = true;
2618 : 21 : mbPushEmptyLine = false;
2619 : 21 : }
2620 : :
2621 : 24 : void ScHTMLTable::ImplDataOff()
2622 : : {
2623 [ + + ]: 24 : if( mbDataOn )
2624 : : {
2625 : 21 : mxDataItemSet.reset();
2626 : 21 : ++maCurrCell.mnCol;
2627 : 21 : mpCurrEntryList = 0;
2628 : 21 : mbDataOn = false;
2629 : : }
2630 : 24 : }
2631 : :
2632 : 30 : void ScHTMLTable::ProcessFormatOptions( SfxItemSet& rItemSet, const ImportInfo& rInfo )
2633 : : {
2634 : : // special handling for table header cells
2635 [ - + ]: 30 : if( rInfo.nToken == HTML_TABLEHEADER_ON )
2636 : : {
2637 [ # # ][ # # ]: 0 : rItemSet.Put( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
[ # # ]
2638 [ # # ][ # # ]: 0 : rItemSet.Put( SvxHorJustifyItem( SVX_HOR_JUSTIFY_CENTER, ATTR_HOR_JUSTIFY ) );
[ # # ]
2639 : : }
2640 : :
2641 [ + - ]: 30 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
2642 [ + - ][ + - ]: 30 : HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
2643 [ # # ][ + - ]: 30 : for (; itr != itrEnd; ++itr)
[ - + ]
2644 : : {
2645 [ # # ]: 0 : switch( itr->GetToken() )
[ # # # # ]
2646 : : {
2647 : : case HTML_O_ALIGN:
2648 : : {
2649 : 0 : SvxCellHorJustify eVal = SVX_HOR_JUSTIFY_STANDARD;
2650 [ # # ]: 0 : const String& rOptVal = itr->GetString();
2651 [ # # ][ # # ]: 0 : if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
2652 : 0 : eVal = SVX_HOR_JUSTIFY_RIGHT;
2653 [ # # ][ # # ]: 0 : else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) )
2654 : 0 : eVal = SVX_HOR_JUSTIFY_CENTER;
2655 [ # # ][ # # ]: 0 : else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
2656 : 0 : eVal = SVX_HOR_JUSTIFY_LEFT;
2657 [ # # ]: 0 : if( eVal != SVX_HOR_JUSTIFY_STANDARD )
2658 [ # # ][ # # ]: 0 : rItemSet.Put( SvxHorJustifyItem( eVal, ATTR_HOR_JUSTIFY ) );
[ # # ]
2659 : : }
2660 : 0 : break;
2661 : :
2662 : : case HTML_O_VALIGN:
2663 : : {
2664 : 0 : SvxCellVerJustify eVal = SVX_VER_JUSTIFY_STANDARD;
2665 [ # # ]: 0 : const String& rOptVal = itr->GetString();
2666 [ # # ][ # # ]: 0 : if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_top ) )
2667 : 0 : eVal = SVX_VER_JUSTIFY_TOP;
2668 [ # # ][ # # ]: 0 : else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_middle ) )
2669 : 0 : eVal = SVX_VER_JUSTIFY_CENTER;
2670 [ # # ][ # # ]: 0 : else if( rOptVal.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_VA_bottom ) )
2671 : 0 : eVal = SVX_VER_JUSTIFY_BOTTOM;
2672 [ # # ]: 0 : if( eVal != SVX_VER_JUSTIFY_STANDARD )
2673 [ # # ][ # # ]: 0 : rItemSet.Put( SvxVerJustifyItem( eVal, ATTR_VER_JUSTIFY ) );
[ # # ]
2674 : : }
2675 : 0 : break;
2676 : :
2677 : : case HTML_O_BGCOLOR:
2678 : : {
2679 : 0 : Color aColor;
2680 [ # # ][ # # ]: 0 : itr->GetColor( aColor );
2681 [ # # ][ # # ]: 0 : rItemSet.Put( SvxBrushItem( aColor, ATTR_BACKGROUND ) );
[ # # ]
2682 : : }
2683 : 0 : break;
2684 : : }
2685 : : }
2686 : 30 : }
2687 : :
2688 : 42 : void ScHTMLTable::SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nSize )
2689 : : {
2690 : : OSL_ENSURE( nCellPos >= 0, "ScHTMLTable::SetDocSize - unexpected negative position" );
2691 : 42 : ScSizeVec& rSizes = maCumSizes[ eOrient ];
2692 : 42 : size_t nIndex = static_cast< size_t >( nCellPos );
2693 : : // expand with height/width == 1
2694 [ + + ]: 63 : while( nIndex >= rSizes.size() )
2695 [ + + ][ + - ]: 21 : rSizes.push_back( rSizes.empty() ? 1 : (rSizes.back() + 1) );
2696 : : // update size of passed position and all following
2697 : : // #i109987# only grow, don't shrink - use the largest needed size
2698 [ + + ]: 42 : SCsCOLROW nDiff = nSize - ((nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]));
2699 [ + + ]: 42 : if( nDiff > 0 )
2700 [ + - ][ + - ]: 12 : for( ScSizeVec::iterator aIt = rSizes.begin() + nIndex, aEnd = rSizes.end(); aIt != aEnd; ++aIt )
[ + - ][ + + ]
2701 [ + - ]: 6 : *aIt += nDiff;
2702 : 42 : }
2703 : :
2704 : 42 : void ScHTMLTable::CalcNeededDocSize(
2705 : : ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nCellSpan, SCCOLROW nRealDocSize )
2706 : : {
2707 : 42 : SCCOLROW nDiffSize = 0;
2708 : : // in merged columns/rows: reduce needed size by size of leading columns
2709 [ - + ]: 42 : while( nCellSpan > 1 )
2710 : : {
2711 [ # # ]: 0 : nDiffSize += GetDocSize( eOrient, nCellPos );
2712 : 0 : --nCellSpan;
2713 : 0 : ++nCellPos;
2714 : : }
2715 : : // set remaining needed size to last column/row
2716 [ + - ]: 42 : nRealDocSize -= ::std::min< SCCOLROW >( nRealDocSize - 1, nDiffSize );
2717 [ + - ]: 42 : SetDocSize( eOrient, nCellPos, nRealDocSize );
2718 : 42 : }
2719 : :
2720 : : // ----------------------------------------------------------------------------
2721 : :
2722 : 6 : void ScHTMLTable::FillEmptyCells()
2723 : : {
2724 [ + - ][ + - ]: 9 : for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
[ + - ][ + + ]
2725 [ + - ][ + - ]: 3 : aIter->FillEmptyCells();
2726 : :
2727 : : // insert the final vertically merged ranges into maUsedCells
2728 [ - + ]: 6 : for ( size_t i = 0, nRanges = maVMergedCells.size(); i < nRanges; ++i )
2729 : : {
2730 : 0 : ScRange* pRange = maVMergedCells[ i ];
2731 : 0 : maUsedCells.Join( *pRange );
2732 : : }
2733 : :
2734 [ + - ][ + + ]: 15 : for( ScAddress aAddr; aAddr.Row() < maSize.mnRows; aAddr.IncRow() )
2735 : : {
2736 [ + - ][ + + ]: 30 : for( aAddr.SetCol( 0 ); aAddr.Col() < maSize.mnCols; aAddr.IncCol() )
2737 : : {
2738 [ + - ][ - + ]: 21 : if( !maUsedCells.Find( aAddr ) )
2739 : : {
2740 : : // create a range for the lock list (used to calc. cell span)
2741 : 0 : ScRange aRange( aAddr );
2742 [ # # ][ # # ]: 0 : do
[ # # ]
2743 : : {
2744 [ # # ]: 0 : aRange.aEnd.IncCol();
2745 : : }
2746 [ # # ]: 0 : while( (aRange.aEnd.Col() < maSize.mnCols) && !maUsedCells.Find( aRange.aEnd ) );
2747 [ # # ]: 0 : aRange.aEnd.IncCol( -1 );
2748 [ # # ]: 0 : maUsedCells.Join( aRange );
2749 : :
2750 : : // insert a dummy entry
2751 [ # # ][ # # ]: 0 : ScHTMLEntryPtr xEntry = CreateEntry();
2752 [ # # ][ # # ]: 0 : ImplPushEntryToList( maEntryMap[ ScHTMLPos( aAddr ) ], xEntry );
[ # # ][ # # ]
2753 : : }
2754 : : }
2755 : : }
2756 : 6 : }
2757 : :
2758 : 6 : void ScHTMLTable::RecalcDocSize()
2759 : : {
2760 : : // recalc table sizes recursively from inner to outer
2761 [ + - ][ + - ]: 9 : for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter )
[ + - ][ + + ]
2762 [ + - ][ + - ]: 3 : aIter->RecalcDocSize();
2763 : :
2764 : : /* Two passes: first calculates the sizes of single columns/rows, then
2765 : : the sizes of spanned columns/rows. This allows to fill nested tables
2766 : : into merged cells optimally. */
2767 : : static const sal_uInt16 PASS_SINGLE = 0;
2768 : : static const sal_uInt16 PASS_SPANNED = 1;
2769 [ + + ]: 18 : for( sal_uInt16 nPass = PASS_SINGLE; nPass <= PASS_SPANNED; ++nPass )
2770 : : {
2771 : : // iterate through every table cell
2772 : 12 : ScHTMLEntryMap::const_iterator aMapIterEnd = maEntryMap.end();
2773 [ + + ]: 54 : for( ScHTMLEntryMap::const_iterator aMapIter = maEntryMap.begin(); aMapIter != aMapIterEnd; ++aMapIter )
2774 : : {
2775 : 42 : const ScHTMLPos& rCellPos = aMapIter->first;
2776 [ + - ]: 42 : ScHTMLSize aCellSpan = GetSpan( rCellPos );
2777 : :
2778 : 42 : const ScHTMLEntryList& rEntryList = aMapIter->second;
2779 : 42 : ScHTMLEntryList::const_iterator aListIter;
2780 : 42 : ScHTMLEntryList::const_iterator aListIterEnd = rEntryList.end();
2781 : :
2782 : : // process the dimension of the current cell in this pass?
2783 : : // (pass is single and span is 1) or (pass is not single and span is not 1)
2784 : 42 : bool bProcessColWidth = ((nPass == PASS_SINGLE) == (aCellSpan.mnCols == 1));
2785 : 42 : bool bProcessRowHeight = ((nPass == PASS_SINGLE) == (aCellSpan.mnRows == 1));
2786 [ - + ][ + + ]: 42 : if( bProcessColWidth || bProcessRowHeight )
2787 : : {
2788 : 21 : ScHTMLSize aDocSize( 1, 0 ); // resulting size of the cell in document
2789 : :
2790 : : // expand the cell size for each cell parse entry
2791 [ + + ]: 42 : for( aListIter = rEntryList.begin(); aListIter != aListIterEnd; ++aListIter )
2792 : : {
2793 [ + - ]: 21 : ScHTMLTable* pTable = GetExistingTable( (*aListIter)->GetTableId() );
2794 : : // find entry with maximum width
2795 [ + - ][ + + ]: 21 : if( bProcessColWidth && pTable )
2796 [ + - ][ + - ]: 3 : aDocSize.mnCols = ::std::max( aDocSize.mnCols, static_cast< SCCOL >( pTable->GetDocSize( tdCol ) ) );
2797 : : // add up height of each entry
2798 [ + - ]: 21 : if( bProcessRowHeight )
2799 [ + + ][ + - ]: 21 : aDocSize.mnRows += pTable ? pTable->GetDocSize( tdRow ) : 1;
2800 : : }
2801 [ - + ]: 21 : if( !aDocSize.mnRows )
2802 : 0 : aDocSize.mnRows = 1;
2803 : :
2804 [ + - ]: 21 : if( bProcessColWidth )
2805 [ + - ]: 21 : CalcNeededDocSize( tdCol, rCellPos.mnCol, aCellSpan.mnCols, aDocSize.mnCols );
2806 [ + - ]: 21 : if( bProcessRowHeight )
2807 [ + - ]: 21 : CalcNeededDocSize( tdRow, rCellPos.mnRow, aCellSpan.mnRows, aDocSize.mnRows );
2808 : : }
2809 : : }
2810 : : }
2811 : 6 : }
2812 : :
2813 : 6 : void ScHTMLTable::RecalcDocPos( const ScHTMLPos& rBasePos )
2814 : : {
2815 : 6 : maDocBasePos = rBasePos;
2816 : : // after the previous assignment it is allowed to call GetDocPos() methods
2817 : :
2818 : : // iterate through every table cell
2819 : 6 : ScHTMLEntryMap::iterator aMapIterEnd = maEntryMap.end();
2820 [ + + ]: 27 : for( ScHTMLEntryMap::iterator aMapIter = maEntryMap.begin(); aMapIter != aMapIterEnd; ++aMapIter )
2821 : : {
2822 : : // fixed doc position of the entire cell (first entry)
2823 [ + - ]: 21 : const ScHTMLPos aCellDocPos( GetDocPos( aMapIter->first ) );
2824 : : // fixed doc size of the entire cell
2825 [ + - ]: 21 : const ScHTMLSize aCellDocSize( GetDocSize( aMapIter->first ) );
2826 : :
2827 : : // running doc position for single entries
2828 : 21 : ScHTMLPos aEntryDocPos( aCellDocPos );
2829 : :
2830 : 21 : ScHTMLEntryList& rEntryList = aMapIter->second;
2831 : 21 : ScHTMLEntry* pEntry = 0;
2832 : 21 : ScHTMLEntryList::iterator aListIterEnd = rEntryList.end();
2833 [ + + ]: 42 : for( ScHTMLEntryList::iterator aListIter = rEntryList.begin(); aListIter != aListIterEnd; ++aListIter )
2834 : : {
2835 : 21 : pEntry = *aListIter;
2836 [ + + ][ + - ]: 21 : if( ScHTMLTable* pTable = GetExistingTable( pEntry->GetTableId() ) )
2837 : : {
2838 [ + - ]: 3 : pTable->RecalcDocPos( aEntryDocPos ); // recalc nested table
2839 : 3 : pEntry->nCol = SCCOL_MAX;
2840 : 3 : pEntry->nRow = SCROW_MAX;
2841 [ + - ]: 3 : SCROW nTableRows = static_cast< SCROW >( pTable->GetDocSize( tdRow ) );
2842 : :
2843 : : // use this entry to pad empty space right of table
2844 [ - + ]: 3 : if( mpParentTable ) // ... but not in global table
2845 : : {
2846 [ # # ]: 0 : SCCOL nStartCol = aEntryDocPos.mnCol + static_cast< SCCOL >( pTable->GetDocSize( tdCol ) );
2847 : 0 : SCCOL nNextCol = aEntryDocPos.mnCol + aCellDocSize.mnCols;
2848 [ # # ]: 0 : if( nStartCol < nNextCol )
2849 : : {
2850 : 0 : pEntry->nCol = nStartCol;
2851 : 0 : pEntry->nRow = aEntryDocPos.mnRow;
2852 : 0 : pEntry->nColOverlap = nNextCol - nStartCol;
2853 : 0 : pEntry->nRowOverlap = nTableRows;
2854 : : }
2855 : : }
2856 : 3 : aEntryDocPos.mnRow += nTableRows;
2857 : : }
2858 : : else
2859 : : {
2860 : 18 : pEntry->nCol = aEntryDocPos.mnCol;
2861 : 18 : pEntry->nRow = aEntryDocPos.mnRow;
2862 [ + - ]: 18 : if( mpParentTable ) // do not merge in global table
2863 : 18 : pEntry->nColOverlap = aCellDocSize.mnCols;
2864 : 18 : ++aEntryDocPos.mnRow;
2865 : : }
2866 : : }
2867 : :
2868 : : // pEntry points now to last entry.
2869 [ + - ]: 21 : if( pEntry )
2870 : : {
2871 [ + - ][ + + ]: 21 : if( (pEntry == rEntryList.front()) && (pEntry->GetTableId() == SC_HTML_NO_TABLE) )
[ + + ]
2872 : : {
2873 : : // pEntry is the only entry in this cell - merge rows of cell with single non-table entry.
2874 : 18 : pEntry->nRowOverlap = aCellDocSize.mnRows;
2875 : : }
2876 : : else
2877 : : {
2878 : : // fill up incomplete entry lists
2879 : 3 : SCROW nFirstUnusedRow = aCellDocPos.mnRow + aCellDocSize.mnRows;
2880 [ - + ]: 3 : while( aEntryDocPos.mnRow < nFirstUnusedRow )
2881 : : {
2882 [ # # ][ # # ]: 0 : ScHTMLEntryPtr xDummyEntry( new ScHTMLEntry( pEntry->GetItemSet() ) );
2883 : 0 : xDummyEntry->nCol = aEntryDocPos.mnCol;
2884 : 0 : xDummyEntry->nRow = aEntryDocPos.mnRow;
2885 : 0 : xDummyEntry->nColOverlap = aCellDocSize.mnCols;
2886 [ # # ]: 0 : ImplPushEntryToList( rEntryList, xDummyEntry );
2887 : 0 : ++aEntryDocPos.mnRow;
2888 [ # # ]: 0 : }
2889 : : }
2890 : : }
2891 : : }
2892 : 6 : }
2893 : :
2894 : : // ============================================================================
2895 : :
2896 : 3 : ScHTMLGlobalTable::ScHTMLGlobalTable(
2897 : : SfxItemPool& rPool,
2898 : : EditEngine& rEditEngine,
2899 : : ::std::vector< ScEEParseEntry* >& rEEParseList,
2900 : : ScHTMLTableId& rnUnusedId,
2901 : : ScHTMLParser* pParser
2902 : : ) :
2903 : 3 : ScHTMLTable( rPool, rEditEngine, rEEParseList, rnUnusedId, pParser )
2904 : : {
2905 : 3 : }
2906 : :
2907 : 3 : ScHTMLGlobalTable::~ScHTMLGlobalTable()
2908 : : {
2909 [ - + ]: 6 : }
2910 : :
2911 : 3 : void ScHTMLGlobalTable::Recalc()
2912 : : {
2913 : : // Fills up empty cells with a dummy entry. */
2914 : 3 : FillEmptyCells();
2915 : : // recalc table sizes of all nested tables and this table
2916 : 3 : RecalcDocSize();
2917 : : // recalc document positions of all entries in this table and in nested tables
2918 : 3 : RecalcDocPos( GetDocPos() );
2919 : 3 : }
2920 : :
2921 : : // ============================================================================
2922 : :
2923 : 3 : ScHTMLQueryParser::ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc ) :
2924 : : ScHTMLParser( pEditEngine, pDoc ),
2925 : : mnUnusedId( SC_HTML_GLOBAL_TABLE ),
2926 : 3 : mbTitleOn( false )
2927 : : {
2928 : : mxGlobTable.reset(
2929 [ + - ][ + - ]: 3 : new ScHTMLGlobalTable(*pPool, *pEdit, maList, mnUnusedId, this));
2930 : 3 : mpCurrTable = mxGlobTable.get();
2931 : 3 : }
2932 : :
2933 [ + - ]: 3 : ScHTMLQueryParser::~ScHTMLQueryParser()
2934 : : {
2935 [ - + ]: 6 : }
2936 : :
2937 : 3 : sal_uLong ScHTMLQueryParser::Read( SvStream& rStrm, const String& rBaseURL )
2938 : : {
2939 : 3 : SvKeyValueIteratorRef xValues;
2940 : 3 : SvKeyValueIterator* pAttributes = 0;
2941 : :
2942 : 3 : SfxObjectShell* pObjSh = mpDoc->GetDocumentShell();
2943 [ + - ][ + - ]: 3 : if( pObjSh && pObjSh->IsLoading() )
[ + - ][ + - ]
2944 : : {
2945 [ + - ]: 3 : pAttributes = pObjSh->GetHeaderAttributes();
2946 : : }
2947 : : else
2948 : : {
2949 : : /* When not loading, set up fake HTTP headers to force the SfxHTMLParser
2950 : : to use UTF8 (used when pasting from clipboard) */
2951 [ # # ]: 0 : const sal_Char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
2952 [ # # ]: 0 : if( pCharSet )
2953 : : {
2954 [ # # ]: 0 : String aContentType = rtl::OUString( "text/html; charset=" );
2955 [ # # ]: 0 : aContentType.AppendAscii( pCharSet );
2956 : :
2957 [ # # ][ # # ]: 0 : xValues = new SvKeyValueIterator;
[ # # ]
2958 [ # # ][ # # ]: 0 : xValues->Append( SvKeyValue( rtl::OUString( OOO_STRING_SVTOOLS_HTML_META_content_type ), aContentType ) );
[ # # ][ # # ]
[ # # ]
2959 [ # # ]: 0 : pAttributes = xValues;
2960 : : }
2961 : : }
2962 : :
2963 [ + - ]: 3 : Link aOldLink = pEdit->GetImportHdl();
2964 [ + - ][ + - ]: 3 : pEdit->SetImportHdl( LINK( this, ScHTMLQueryParser, HTMLImportHdl ) );
2965 [ + - ]: 3 : sal_uLong nErr = pEdit->Read( rStrm, rBaseURL, EE_FORMAT_HTML, pAttributes );
2966 [ + - ]: 3 : pEdit->SetImportHdl( aOldLink );
2967 : :
2968 [ + - ]: 3 : mxGlobTable->Recalc();
2969 [ + - ]: 3 : nColMax = static_cast< SCCOL >( mxGlobTable->GetDocSize( tdCol ) - 1 );
2970 [ + - ]: 3 : nRowMax = static_cast< SCROW >( mxGlobTable->GetDocSize( tdRow ) - 1 );
2971 : :
2972 [ + - ]: 3 : return nErr;
2973 : : }
2974 : :
2975 : 3 : const ScHTMLTable* ScHTMLQueryParser::GetGlobalTable() const
2976 : : {
2977 : 3 : return mxGlobTable.get();
2978 : : }
2979 : :
2980 : 102 : void ScHTMLQueryParser::ProcessToken( const ImportInfo& rInfo )
2981 : : {
2982 [ - - - - : 102 : switch( rInfo.nToken )
- + + + -
- - + + +
+ + + - -
- - - - -
- - + ]
2983 : : {
2984 : : // --- meta data ---
2985 : 0 : case HTML_META: MetaOn( rInfo ); break; // <meta>
2986 : :
2987 : : // --- title handling ---
2988 : 0 : case HTML_TITLE_ON: TitleOn( rInfo ); break; // <title>
2989 : 0 : case HTML_TITLE_OFF: TitleOff( rInfo ); break; // </title>
2990 : :
2991 : 0 : case HTML_STYLE_ON: break;
2992 [ # # ]: 0 : case HTML_STYLE_OFF: ParseStyle(rInfo.aText); break;
2993 : :
2994 : : // --- body handling ---
2995 : 3 : case HTML_BODY_ON: mpCurrTable->BodyOn( rInfo ); break; // <body>
2996 : 3 : case HTML_BODY_OFF: mpCurrTable->BodyOff( rInfo ); break; // </body>
2997 : :
2998 : : // --- insert text ---
2999 : 39 : case HTML_TEXTTOKEN: InsertText( rInfo ); break; // any text
3000 : 0 : case HTML_LINEBREAK: mpCurrTable->BreakOn(); break; // <br>
3001 : : case HTML_HEAD1_ON: // <h1>
3002 : : case HTML_HEAD2_ON: // <h2>
3003 : : case HTML_HEAD3_ON: // <h3>
3004 : : case HTML_HEAD4_ON: // <h4>
3005 : : case HTML_HEAD5_ON: // <h5>
3006 : : case HTML_HEAD6_ON: // <h6>
3007 : 0 : case HTML_PARABREAK_ON: mpCurrTable->HeadingOn(); break; // <p>
3008 : :
3009 : : // --- misc. contents ---
3010 : 0 : case HTML_ANCHOR_ON: mpCurrTable->AnchorOn(); break; // <a>
3011 : :
3012 : : // --- table handling ---
3013 : 3 : case HTML_TABLE_ON: TableOn( rInfo ); break; // <table>
3014 : 3 : case HTML_TABLE_OFF: TableOff( rInfo ); break; // </table>
3015 : 6 : case HTML_TABLEROW_ON: mpCurrTable->RowOn( rInfo ); break; // <tr>
3016 : 6 : case HTML_TABLEROW_OFF: mpCurrTable->RowOff( rInfo ); break; // </tr>
3017 : : case HTML_TABLEHEADER_ON: // <th>
3018 : 18 : case HTML_TABLEDATA_ON: mpCurrTable->DataOn( rInfo ); break; // <td>
3019 : : case HTML_TABLEHEADER_OFF: // </th>
3020 : 18 : case HTML_TABLEDATA_OFF: mpCurrTable->DataOff( rInfo ); break; // </td>
3021 : 0 : case HTML_PREFORMTXT_ON: PreOn( rInfo ); break; // <pre>
3022 : 0 : case HTML_PREFORMTXT_OFF: PreOff( rInfo ); break; // </pre>
3023 : :
3024 : : // --- formatting ---
3025 : 0 : case HTML_FONT_ON: FontOn( rInfo ); break; // <font>
3026 : :
3027 : : case HTML_BIGPRINT_ON: // <big>
3028 : : //! TODO: store current font size, use following size
3029 [ # # ]: 0 : mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ 3 ], 100, ATTR_FONT_HEIGHT ) );
3030 : 0 : break;
3031 : : case HTML_SMALLPRINT_ON: // <small>
3032 : : //! TODO: store current font size, use preceding size
3033 [ # # ]: 0 : mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ 0 ], 100, ATTR_FONT_HEIGHT ) );
3034 : 0 : break;
3035 : :
3036 : : case HTML_BOLD_ON: // <b>
3037 : : case HTML_STRONG_ON: // <strong>
3038 [ # # ]: 0 : mpCurrTable->PutItem( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
3039 : 0 : break;
3040 : :
3041 : : case HTML_ITALIC_ON: // <i>
3042 : : case HTML_EMPHASIS_ON: // <em>
3043 : : case HTML_ADDRESS_ON: // <address>
3044 : : case HTML_BLOCKQUOTE_ON: // <blockquote>
3045 : : case HTML_BLOCKQUOTE30_ON: // <bq>
3046 : : case HTML_CITIATION_ON: // <cite>
3047 : : case HTML_VARIABLE_ON: // <var>
3048 [ # # ]: 0 : mpCurrTable->PutItem( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
3049 : 0 : break;
3050 : :
3051 : : case HTML_DEFINSTANCE_ON: // <dfn>
3052 [ # # ]: 0 : mpCurrTable->PutItem( SvxWeightItem( WEIGHT_BOLD, ATTR_FONT_WEIGHT ) );
3053 [ # # ]: 0 : mpCurrTable->PutItem( SvxPostureItem( ITALIC_NORMAL, ATTR_FONT_POSTURE ) );
3054 : 0 : break;
3055 : :
3056 : : case HTML_UNDERLINE_ON: // <u>
3057 [ # # ]: 0 : mpCurrTable->PutItem( SvxUnderlineItem( UNDERLINE_SINGLE, ATTR_FONT_UNDERLINE ) );
3058 : 0 : break;
3059 : : }
3060 : 102 : }
3061 : :
3062 : 39 : void ScHTMLQueryParser::InsertText( const ImportInfo& rInfo )
3063 : : {
3064 : 39 : mpCurrTable->PutText( rInfo );
3065 [ - + ]: 39 : if( mbTitleOn )
3066 [ # # ]: 0 : maTitle.append(rInfo.aText);
3067 : 39 : }
3068 : :
3069 : 0 : void ScHTMLQueryParser::FontOn( const ImportInfo& rInfo )
3070 : : {
3071 [ # # ]: 0 : const HTMLOptions& rOptions = static_cast<HTMLParser*>(rInfo.pParser)->GetOptions();
3072 [ # # ][ # # ]: 0 : HTMLOptions::const_iterator itr = rOptions.begin(), itrEnd = rOptions.end();
3073 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
3074 : : {
3075 [ # # ]: 0 : switch( itr->GetToken() )
[ # # # # ]
3076 : : {
3077 : : case HTML_O_FACE :
3078 : : {
3079 [ # # ]: 0 : const String& rFace = itr->GetString();
3080 [ # # ]: 0 : String aFontName;
3081 : 0 : xub_StrLen nPos = 0;
3082 [ # # ]: 0 : while( nPos != STRING_NOTFOUND )
3083 : : {
3084 : : // font list separator: VCL = ';' HTML = ','
3085 [ # # ][ # # ]: 0 : String aFName = comphelper::string::strip(rFace.GetToken(0, ',', nPos), ' ');
[ # # ][ # # ]
[ # # ]
3086 [ # # ]: 0 : ScGlobal::AddToken( aFontName, aFName, ';' );
3087 [ # # ]: 0 : }
3088 [ # # ]: 0 : if ( aFontName.Len() )
3089 : : mpCurrTable->PutItem( SvxFontItem( FAMILY_DONTKNOW,
3090 [ # # ]: 0 : aFontName, EMPTY_STRING, PITCH_DONTKNOW,
3091 [ # # ][ # # ]: 0 : RTL_TEXTENCODING_DONTKNOW, ATTR_FONT ) );
[ # # ][ # # ]
3092 : : }
3093 : 0 : break;
3094 : : case HTML_O_SIZE :
3095 : : {
3096 [ # # ][ # # ]: 0 : sal_uInt32 nSize = getLimitedValue< sal_uInt32 >( itr->GetNumber(), 1, SC_HTML_FONTSIZES );
[ # # ]
3097 [ # # ][ # # ]: 0 : mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ nSize - 1 ], 100, ATTR_FONT_HEIGHT ) );
[ # # ]
3098 : : }
3099 : 0 : break;
3100 : : case HTML_O_COLOR :
3101 : : {
3102 : 0 : Color aColor;
3103 [ # # ][ # # ]: 0 : itr->GetColor( aColor );
3104 [ # # ][ # # ]: 0 : mpCurrTable->PutItem( SvxColorItem( aColor, ATTR_FONT_COLOR ) );
[ # # ]
3105 : : }
3106 : 0 : break;
3107 : : }
3108 : : }
3109 : 0 : }
3110 : :
3111 : 0 : void ScHTMLQueryParser::MetaOn( const ImportInfo& rInfo )
3112 : : {
3113 [ # # ]: 0 : if( mpDoc->GetDocumentShell() )
3114 : : {
3115 : 0 : HTMLParser* pParser = static_cast< HTMLParser* >( rInfo.pParser );
3116 : :
3117 : : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3118 [ # # ][ # # ]: 0 : mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
3119 : : pParser->ParseMetaOptions(
3120 [ # # ]: 0 : xDPS->getDocumentProperties(),
3121 [ # # ][ # # ]: 0 : mpDoc->GetDocumentShell()->GetHeaderAttributes() );
[ # # ]
3122 : : }
3123 : 0 : }
3124 : :
3125 : 0 : void ScHTMLQueryParser::TitleOn( const ImportInfo& /*rInfo*/ )
3126 : : {
3127 : 0 : mbTitleOn = true;
3128 : 0 : maTitle.makeStringAndClear();
3129 : 0 : }
3130 : :
3131 : 0 : void ScHTMLQueryParser::TitleOff( const ImportInfo& rInfo )
3132 : : {
3133 [ # # ]: 0 : if( mbTitleOn )
3134 : : {
3135 [ # # ]: 0 : rtl::OUString aTitle = maTitle.makeStringAndClear().trim();
3136 [ # # ][ # # ]: 0 : if (!aTitle.isEmpty() && mpDoc->GetDocumentShell())
[ # # ]
3137 : : {
3138 : : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3139 [ # # ][ # # ]: 0 : mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
3140 : :
3141 [ # # ][ # # ]: 0 : xDPS->getDocumentProperties()->setTitle(aTitle);
[ # # ][ # # ]
3142 : : }
3143 [ # # ]: 0 : InsertText( rInfo );
3144 : 0 : mbTitleOn = false;
3145 : : }
3146 : 0 : }
3147 : :
3148 : 3 : void ScHTMLQueryParser::TableOn( const ImportInfo& rInfo )
3149 : : {
3150 : 3 : mpCurrTable = mpCurrTable->TableOn( rInfo );
3151 : 3 : }
3152 : :
3153 : 3 : void ScHTMLQueryParser::TableOff( const ImportInfo& rInfo )
3154 : : {
3155 : 3 : mpCurrTable = mpCurrTable->TableOff( rInfo );
3156 : 3 : }
3157 : :
3158 : 0 : void ScHTMLQueryParser::PreOn( const ImportInfo& rInfo )
3159 : : {
3160 : 0 : mpCurrTable = mpCurrTable->PreOn( rInfo );
3161 : 0 : }
3162 : :
3163 : 0 : void ScHTMLQueryParser::PreOff( const ImportInfo& rInfo )
3164 : : {
3165 : 0 : mpCurrTable = mpCurrTable->PreOff( rInfo );
3166 : 0 : }
3167 : :
3168 : 0 : void ScHTMLQueryParser::CloseTable( const ImportInfo& rInfo )
3169 : : {
3170 : 0 : mpCurrTable = mpCurrTable->CloseTable( rInfo );
3171 : 0 : }
3172 : :
3173 : : namespace {
3174 : :
3175 : : /**
3176 : : * Handler class for the CSS parser.
3177 : : */
3178 : 0 : class CSSHandler
3179 : : {
3180 : : struct MemStr
3181 : : {
3182 : : const char* mp;
3183 : : size_t mn;
3184 : :
3185 : 0 : MemStr() : mp(NULL), mn(0) {}
3186 : 0 : MemStr(const char* p, size_t n) : mp(p), mn(n) {}
3187 : 0 : MemStr(const MemStr& r) : mp(r.mp), mn(r.mn) {}
3188 : 0 : MemStr& operator=(const MemStr& r)
3189 : : {
3190 : 0 : mp = r.mp;
3191 : 0 : mn = r.mn;
3192 : 0 : return *this;
3193 : : }
3194 : : };
3195 : :
3196 : : typedef std::pair<MemStr, MemStr> SelectorName; // element : class
3197 : : typedef std::vector<SelectorName> SelectorNames;
3198 : : SelectorNames maSelectorNames; /// current selector names.
3199 : : MemStr maPropName; /// current property name.
3200 : : MemStr maPropValue; /// current property value.
3201 : :
3202 : : ScHTMLStyles& mrStyles;
3203 : : public:
3204 : 0 : CSSHandler(ScHTMLStyles& rStyles) : mrStyles(rStyles) {}
3205 : :
3206 : 0 : void at_rule_name(const char* /*p*/, size_t /*n*/)
3207 : : {
3208 : : // For now, we ignore at-rule properties.
3209 : 0 : }
3210 : :
3211 : 0 : void selector_name(const char* p_elem, size_t n_elem, const char* p_class, size_t n_class)
3212 : : {
3213 : 0 : MemStr aElem(p_elem, n_elem), aClass(p_class, n_class);
3214 : 0 : SelectorName aName(aElem, aClass);
3215 [ # # ]: 0 : maSelectorNames.push_back(aName);
3216 : 0 : }
3217 : :
3218 : 0 : void property_name(const char* p, size_t n)
3219 : : {
3220 : 0 : maPropName = MemStr(p, n);
3221 : 0 : }
3222 : :
3223 : 0 : void value(const char* p, size_t n)
3224 : : {
3225 : 0 : maPropValue = MemStr(p, n);
3226 : 0 : }
3227 : :
3228 : 0 : void begin_parse() {}
3229 : :
3230 : 0 : void end_parse() {}
3231 : :
3232 : 0 : void begin_block() {}
3233 : :
3234 : 0 : void end_block()
3235 : : {
3236 : 0 : maSelectorNames.clear();
3237 : 0 : }
3238 : :
3239 : 0 : void begin_property() {}
3240 : :
3241 : 0 : void end_property()
3242 : : {
3243 [ # # ][ # # ]: 0 : SelectorNames::const_iterator itr = maSelectorNames.begin(), itrEnd = maSelectorNames.end();
3244 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
3245 : : {
3246 : : // Add this property to the collection for each selector.
3247 : 0 : const SelectorName& rSelName = *itr;
3248 : 0 : const MemStr& rElem = rSelName.first;
3249 : 0 : const MemStr& rClass = rSelName.second;
3250 [ # # ]: 0 : rtl::OUString aName(maPropName.mp, maPropName.mn, RTL_TEXTENCODING_UTF8);
3251 [ # # ]: 0 : rtl::OUString aValue(maPropValue.mp, maPropValue.mn, RTL_TEXTENCODING_UTF8);
3252 [ # # ]: 0 : mrStyles.add(rElem.mp, rElem.mn, rClass.mp, rClass.mn, aName, aValue);
3253 : 0 : }
3254 : 0 : maPropName = MemStr();
3255 : 0 : maPropValue = MemStr();
3256 : 0 : }
3257 : : };
3258 : :
3259 : : }
3260 : :
3261 : 0 : void ScHTMLQueryParser::ParseStyle(const rtl::OUString& rStrm)
3262 : : {
3263 [ # # ]: 0 : rtl::OString aStr = rtl::OUStringToOString(rStrm, RTL_TEXTENCODING_UTF8);
3264 [ # # ]: 0 : CSSHandler aHdl(GetStyles());
3265 : 0 : orcus::css_parser<CSSHandler> aParser(aStr.getStr(), aStr.getLength(), aHdl);
3266 : : try
3267 : : {
3268 [ # # ]: 0 : aParser.parse();
3269 : : }
3270 : 0 : catch (const orcus::css_parse_error&)
3271 : : {
3272 : : // Parsing of CSS failed. Do nothing for now.
3273 : 0 : }
3274 [ # # ]: 0 : }
3275 : :
3276 : : // ----------------------------------------------------------------------------
3277 : :
3278 : 165 : IMPL_LINK( ScHTMLQueryParser, HTMLImportHdl, const ImportInfo*, pInfo )
3279 : : {
3280 [ + + + + : 165 : switch( pInfo->eState )
+ - ]
3281 : : {
3282 : : case HTMLIMP_START:
3283 : 3 : break;
3284 : :
3285 : : case HTMLIMP_NEXTTOKEN:
3286 : : case HTMLIMP_UNKNOWNATTR:
3287 : 102 : ProcessToken( *pInfo );
3288 : 102 : break;
3289 : :
3290 : : case HTMLIMP_INSERTPARA:
3291 : 18 : mpCurrTable->InsertPara( *pInfo );
3292 : 18 : break;
3293 : :
3294 : : case HTMLIMP_SETATTR:
3295 : : case HTMLIMP_INSERTTEXT:
3296 : : case HTMLIMP_INSERTFIELD:
3297 : 39 : break;
3298 : :
3299 : : case HTMLIMP_END:
3300 [ - + ]: 3 : while( mpCurrTable->GetTableId() != SC_HTML_GLOBAL_TABLE )
3301 : 0 : CloseTable( *pInfo );
3302 : 3 : break;
3303 : :
3304 : : default:
3305 : : OSL_FAIL( "ScHTMLQueryParser::HTMLImportHdl - unknown ImportInfo::eState" );
3306 : : }
3307 : 165 : return 0;
3308 : : }
3309 : :
3310 : : // ============================================================================
3311 : :
3312 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|