1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <scitems.hxx>
21 #include <osl/diagnose.h>
22 #include <unotools/charclass.hxx>
24 #include <editeng/lrspitem.hxx>
25 #include <editeng/paperinf.hxx>
26 #include <editeng/sizeitem.hxx>
27 #include <editeng/ulspitem.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <vcl/svapp.hxx>
31 #include <htmlimp.hxx>
32 #include <htmlpars.hxx>
35 #include <document.hxx>
36 #include <editutil.hxx>
37 #include <stlpool.hxx>
38 #include <stlsheet.hxx>
39 #include <refdata.hxx>
40 #include <rangenam.hxx>
43 #include <tokenarray.hxx>
45 ErrCode
ScFormatFilterPluginImpl::ScImportHTML( SvStream
&rStream
, const OUString
& rBaseURL
, ScDocument
*pDoc
,
46 ScRange
& rRange
, double nOutputFactor
, bool bCalcWidthHeight
, SvNumberFormatter
* pFormatter
,
49 ScHTMLImport
aImp( pDoc
, rBaseURL
, rRange
, bCalcWidthHeight
);
50 ErrCode nErr
= aImp
.Read( rStream
, rBaseURL
);
51 ScRange aR
= aImp
.GetRange();
52 rRange
.aEnd
= aR
.aEnd
;
53 aImp
.WriteToDocument( true, nOutputFactor
, pFormatter
, bConvertDate
);
57 std::unique_ptr
<ScEEAbsImport
> ScFormatFilterPluginImpl::CreateHTMLImport( ScDocument
* pDocP
, const OUString
& rBaseURL
, const ScRange
& rRange
)
59 return std::make_unique
<ScHTMLImport
>( pDocP
, rBaseURL
, rRange
, true/*bCalcWidthHeight*/ );
62 ScHTMLImport::ScHTMLImport( ScDocument
* pDocP
, const OUString
& rBaseURL
, const ScRange
& rRange
, bool bCalcWidthHeight
) :
63 ScEEImport( pDocP
, rRange
)
66 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
67 const OUString
& aPageStyle
= mpDoc
->GetPageStyle( rRange
.aStart
.Tab() );
68 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>(mpDoc
->
69 GetStyleSheetPool()->Find( aPageStyle
, SfxStyleFamily::Page
));
72 const SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
73 const SvxLRSpaceItem
* pLRItem
= &rSet
.Get( ATTR_LRSPACE
);
74 long nLeftMargin
= pLRItem
->GetLeft();
75 long nRightMargin
= pLRItem
->GetRight();
76 const SvxULSpaceItem
* pULItem
= &rSet
.Get( ATTR_ULSPACE
);
77 long nTopMargin
= pULItem
->GetUpper();
78 long nBottomMargin
= pULItem
->GetLower();
79 aPageSize
= rSet
.Get(ATTR_PAGE_SIZE
).GetSize();
80 if ( !aPageSize
.Width() || !aPageSize
.Height() )
82 OSL_FAIL("PageSize Null ?!?!?");
83 aPageSize
= SvxPaperInfo::GetPaperSize( PAPER_A4
);
85 aPageSize
.AdjustWidth( -(nLeftMargin
+ nRightMargin
) );
86 aPageSize
.AdjustHeight( -(nTopMargin
+ nBottomMargin
) );
87 aPageSize
= pDefaultDev
->LogicToPixel( aPageSize
, MapMode( MapUnit::MapTwip
) );
91 OSL_FAIL("no StyleSheet?!?");
92 aPageSize
= pDefaultDev
->LogicToPixel(
93 SvxPaperInfo::GetPaperSize( PAPER_A4
), MapMode( MapUnit::MapTwip
) );
95 if( bCalcWidthHeight
)
96 mpParser
.reset( new ScHTMLLayoutParser( mpEngine
.get(), rBaseURL
, aPageSize
, pDocP
));
98 mpParser
.reset( new ScHTMLQueryParser( mpEngine
.get(), pDocP
));
101 void ScHTMLImport::InsertRangeName( ScDocument
* pDoc
, const OUString
& rName
, const ScRange
& rRange
)
103 ScComplexRefData aRefData
;
104 aRefData
.InitRange( rRange
);
105 aRefData
.Ref1
.SetFlag3D( true );
106 aRefData
.Ref2
.SetFlag3D( aRefData
.Ref2
.Tab() != aRefData
.Ref1
.Tab() );
107 ScTokenArray aTokArray
;
108 aTokArray
.AddDoubleReference( aRefData
);
109 ScRangeData
* pRangeData
= new ScRangeData( pDoc
, rName
, aTokArray
);
110 pDoc
->GetRangeName()->insert( pRangeData
);
113 void ScHTMLImport::WriteToDocument(
114 bool bSizeColsRows
, double nOutputFactor
, SvNumberFormatter
* pFormatter
, bool bConvertDate
)
116 ScEEImport::WriteToDocument( bSizeColsRows
, nOutputFactor
, pFormatter
, bConvertDate
);
118 const ScHTMLParser
* pParser
= static_cast<ScHTMLParser
*>(mpParser
.get());
119 const ScHTMLTable
* pGlobTable
= pParser
->GetGlobalTable();
123 // set cell borders for HTML table cells
124 pGlobTable
->ApplyCellBorders( mpDoc
, maRange
.aStart
);
126 // correct cell borders for merged cells
127 for ( size_t i
= 0, n
= pParser
->ListSize(); i
< n
; ++i
)
129 const ScEEParseEntry
* pEntry
= pParser
->ListEntry( i
);
130 if( (pEntry
->nColOverlap
> 1) || (pEntry
->nRowOverlap
> 1) )
132 SCTAB nTab
= maRange
.aStart
.Tab();
133 const ScMergeAttr
* pItem
= mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, ATTR_MERGE
);
134 if( pItem
->IsMerged() )
136 SCCOL nColMerge
= pItem
->GetColMerge();
137 SCROW nRowMerge
= pItem
->GetRowMerge();
139 const SvxBoxItem
* pToItem
= mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, ATTR_BORDER
);
140 SvxBoxItem
aNewItem( *pToItem
);
143 const SvxBoxItem
* pFromItem
=
144 mpDoc
->GetAttr( pEntry
->nCol
+ nColMerge
- 1, pEntry
->nRow
, nTab
, ATTR_BORDER
);
145 aNewItem
.SetLine( pFromItem
->GetLine( SvxBoxItemLine::RIGHT
), SvxBoxItemLine::RIGHT
);
149 const SvxBoxItem
* pFromItem
=
150 mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
+ nRowMerge
- 1, nTab
, ATTR_BORDER
);
151 aNewItem
.SetLine( pFromItem
->GetLine( SvxBoxItemLine::BOTTOM
), SvxBoxItemLine::BOTTOM
);
153 mpDoc
->ApplyAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, aNewItem
);
158 // create ranges for HTML tables
159 // 1 - entire document
160 ScRange
aNewRange( maRange
.aStart
);
161 aNewRange
.aEnd
.IncCol( static_cast<SCCOL
>(pGlobTable
->GetDocSize( tdCol
)) - 1 );
162 aNewRange
.aEnd
.IncRow( pGlobTable
->GetDocSize( tdRow
) - 1 );
163 InsertRangeName( mpDoc
, ScfTools::GetHTMLDocName(), aNewRange
);
166 InsertRangeName( mpDoc
, ScfTools::GetHTMLTablesName(), ScRange( maRange
.aStart
) );
169 SCCOL nColDiff
= maRange
.aStart
.Col();
170 SCROW nRowDiff
= maRange
.aStart
.Row();
171 SCTAB nTabDiff
= maRange
.aStart
.Tab();
173 ScHTMLTable
* pTable
= nullptr;
174 ScHTMLTableId nTableId
= SC_HTML_GLOBAL_TABLE
;
175 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
176 while( (pTable
= pGlobTable
->FindNestedTable( ++nTableId
)) != nullptr )
178 pTable
->GetDocRange( aNewRange
);
179 if (!aNewRange
.Move( nColDiff
, nRowDiff
, nTabDiff
, aErrorRange
))
181 assert(!"can't move");
183 // insert table number as name
184 InsertRangeName( mpDoc
, ScfTools::GetNameFromHTMLIndex( nTableId
), aNewRange
);
185 // insert table id as name
186 if (!pTable
->GetTableName().isEmpty())
188 OUString
aName( ScfTools::GetNameFromHTMLName( pTable
->GetTableName() ) );
189 if (!mpDoc
->GetRangeName()->findByUpperName(ScGlobal::pCharClass
->uppercase(aName
)))
190 InsertRangeName( mpDoc
, aName
, aNewRange
);
195 OUString
ScFormatFilterPluginImpl::GetHTMLRangeNameList( ScDocument
* pDoc
, const OUString
& rOrigName
)
197 return ScHTMLImport::GetHTMLRangeNameList( pDoc
, rOrigName
);
200 OUString
ScHTMLImport::GetHTMLRangeNameList( const ScDocument
* pDoc
, const OUString
& rOrigName
)
202 OSL_ENSURE( pDoc
, "ScHTMLImport::GetHTMLRangeNameList - missing document" );
204 if (rOrigName
.isEmpty())
208 ScRangeName
* pRangeNames
= pDoc
->GetRangeName();
209 ScRangeList aRangeList
;
210 sal_Int32 nStringIx
= 0;
213 OUString
aToken( rOrigName
.getToken( 0, ';', nStringIx
) );
214 if( pRangeNames
&& ScfTools::IsHTMLTablesName( aToken
) )
215 { // build list with all HTML tables
216 sal_uLong nIndex
= 1;
219 aToken
= ScfTools::GetNameFromHTMLIndex( nIndex
++ );
220 const ScRangeData
* pRangeData
= pRangeNames
->findByUpperName(ScGlobal::pCharClass
->uppercase(aToken
));
224 if( pRangeData
->IsReference( aRange
) && !aRangeList
.In( aRange
) )
226 aNewName
= ScGlobal::addToken(aNewName
, aToken
, ';');
227 aRangeList
.push_back( aRange
);
232 aNewName
= ScGlobal::addToken(aNewName
, aToken
, ';');
238 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */