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>
30 #include <o3tl/string_view.hxx>
32 #include <htmlimp.hxx>
33 #include <htmlpars.hxx>
36 #include <document.hxx>
37 #include <editutil.hxx>
38 #include <stlpool.hxx>
39 #include <stlsheet.hxx>
40 #include <refdata.hxx>
41 #include <rangenam.hxx>
44 #include <tokenarray.hxx>
46 ErrCode
ScFormatFilterPluginImpl::ScImportHTML( SvStream
&rStream
, const OUString
& rBaseURL
, ScDocument
*pDoc
,
47 ScRange
& rRange
, double nOutputFactor
, bool bCalcWidthHeight
, SvNumberFormatter
* pFormatter
,
50 ScHTMLImport
aImp( pDoc
, rBaseURL
, rRange
, bCalcWidthHeight
);
51 ErrCode nErr
= aImp
.Read( rStream
, rBaseURL
);
52 ScRange aR
= aImp
.GetRange();
53 rRange
.aEnd
= aR
.aEnd
;
54 aImp
.WriteToDocument( true, nOutputFactor
, pFormatter
, bConvertDate
);
58 std::unique_ptr
<ScEEAbsImport
> ScFormatFilterPluginImpl::CreateHTMLImport( ScDocument
* pDocP
, const OUString
& rBaseURL
, const ScRange
& rRange
)
60 return std::make_unique
<ScHTMLImport
>( pDocP
, rBaseURL
, rRange
, true/*bCalcWidthHeight*/ );
63 ScHTMLImport::ScHTMLImport( ScDocument
* pDocP
, const OUString
& rBaseURL
, const ScRange
& rRange
, bool bCalcWidthHeight
) :
64 ScEEImport( pDocP
, rRange
)
67 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
68 const OUString
& aPageStyle
= mpDoc
->GetPageStyle( rRange
.aStart
.Tab() );
69 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>(mpDoc
->
70 GetStyleSheetPool()->Find( aPageStyle
, SfxStyleFamily::Page
));
73 const SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
74 const SvxLRSpaceItem
* pLRItem
= &rSet
.Get( ATTR_LRSPACE
);
75 tools::Long nLeftMargin
= pLRItem
->GetLeft();
76 tools::Long nRightMargin
= pLRItem
->GetRight();
77 const SvxULSpaceItem
* pULItem
= &rSet
.Get( ATTR_ULSPACE
);
78 tools::Long nTopMargin
= pULItem
->GetUpper();
79 tools::Long nBottomMargin
= pULItem
->GetLower();
80 aPageSize
= rSet
.Get(ATTR_PAGE_SIZE
).GetSize();
81 if ( !aPageSize
.Width() || !aPageSize
.Height() )
83 OSL_FAIL("PageSize Null ?!?!?");
84 aPageSize
= SvxPaperInfo::GetPaperSize( PAPER_A4
);
86 aPageSize
.AdjustWidth( -(nLeftMargin
+ nRightMargin
) );
87 aPageSize
.AdjustHeight( -(nTopMargin
+ nBottomMargin
) );
88 aPageSize
= pDefaultDev
->LogicToPixel( aPageSize
, MapMode( MapUnit::MapTwip
) );
92 OSL_FAIL("no StyleSheet?!?");
93 aPageSize
= pDefaultDev
->LogicToPixel(
94 SvxPaperInfo::GetPaperSize( PAPER_A4
), MapMode( MapUnit::MapTwip
) );
96 if( bCalcWidthHeight
)
97 mpParser
.reset( new ScHTMLLayoutParser( mpEngine
.get(), rBaseURL
, aPageSize
, pDocP
));
99 mpParser
.reset( new ScHTMLQueryParser( mpEngine
.get(), pDocP
));
102 void ScHTMLImport::InsertRangeName( ScDocument
& rDoc
, const OUString
& rName
, const ScRange
& rRange
)
104 ScComplexRefData aRefData
;
105 aRefData
.InitRange( rRange
);
106 aRefData
.Ref1
.SetFlag3D( true );
107 aRefData
.Ref2
.SetFlag3D( aRefData
.Ref2
.Tab() != aRefData
.Ref1
.Tab() );
108 ScTokenArray
aTokArray(rDoc
);
109 aTokArray
.AddDoubleReference( aRefData
);
110 ScRangeData
* pRangeData
= new ScRangeData( rDoc
, rName
, aTokArray
);
111 rDoc
.GetRangeName()->insert( pRangeData
);
114 void ScHTMLImport::WriteToDocument(
115 bool bSizeColsRows
, double nOutputFactor
, SvNumberFormatter
* pFormatter
, bool bConvertDate
)
117 ScEEImport::WriteToDocument( bSizeColsRows
, nOutputFactor
, pFormatter
, bConvertDate
);
119 const ScHTMLParser
* pParser
= static_cast<ScHTMLParser
*>(mpParser
.get());
120 const ScHTMLTable
* pGlobTable
= pParser
->GetGlobalTable();
124 // set cell borders for HTML table cells
125 pGlobTable
->ApplyCellBorders( mpDoc
, maRange
.aStart
);
127 // correct cell borders for merged cells
128 for ( size_t i
= 0, n
= pParser
->ListSize(); i
< n
; ++i
)
130 const ScEEParseEntry
* pEntry
= pParser
->ListEntry( i
);
131 if( (pEntry
->nColOverlap
> 1) || (pEntry
->nRowOverlap
> 1) )
133 SCTAB nTab
= maRange
.aStart
.Tab();
134 const ScMergeAttr
* pItem
= mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, ATTR_MERGE
);
135 if( pItem
->IsMerged() )
137 SCCOL nColMerge
= pItem
->GetColMerge();
138 SCROW nRowMerge
= pItem
->GetRowMerge();
140 const SvxBoxItem
* pToItem
= mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, ATTR_BORDER
);
141 SvxBoxItem
aNewItem( *pToItem
);
144 const SvxBoxItem
* pFromItem
=
145 mpDoc
->GetAttr( pEntry
->nCol
+ nColMerge
- 1, pEntry
->nRow
, nTab
, ATTR_BORDER
);
146 aNewItem
.SetLine( pFromItem
->GetLine( SvxBoxItemLine::RIGHT
), SvxBoxItemLine::RIGHT
);
150 const SvxBoxItem
* pFromItem
=
151 mpDoc
->GetAttr( pEntry
->nCol
, pEntry
->nRow
+ nRowMerge
- 1, nTab
, ATTR_BORDER
);
152 aNewItem
.SetLine( pFromItem
->GetLine( SvxBoxItemLine::BOTTOM
), SvxBoxItemLine::BOTTOM
);
154 mpDoc
->ApplyAttr( pEntry
->nCol
, pEntry
->nRow
, nTab
, aNewItem
);
159 // create ranges for HTML tables
160 // 1 - entire document
161 ScRange
aNewRange( maRange
.aStart
);
162 aNewRange
.aEnd
.IncCol( static_cast<SCCOL
>(pGlobTable
->GetDocSize( tdCol
)) - 1 );
163 aNewRange
.aEnd
.IncRow( pGlobTable
->GetDocSize( tdRow
) - 1 );
164 InsertRangeName( *mpDoc
, ScfTools::GetHTMLDocName(), aNewRange
);
167 InsertRangeName( *mpDoc
, ScfTools::GetHTMLTablesName(), ScRange( maRange
.aStart
) );
170 SCCOL nColDiff
= maRange
.aStart
.Col();
171 SCROW nRowDiff
= maRange
.aStart
.Row();
172 SCTAB nTabDiff
= maRange
.aStart
.Tab();
174 ScHTMLTable
* pTable
= nullptr;
175 ScHTMLTableId nTableId
= SC_HTML_GLOBAL_TABLE
;
176 ScRange
aErrorRange( ScAddress::UNINITIALIZED
);
177 while( (pTable
= pGlobTable
->FindNestedTable( ++nTableId
)) != nullptr )
179 pTable
->GetDocRange( aNewRange
);
180 if (!aNewRange
.Move( nColDiff
, nRowDiff
, nTabDiff
, aErrorRange
, *mpDoc
))
182 assert(!"can't move");
184 // insert table number as name
185 OUStringBuffer
aName(ScfTools::GetNameFromHTMLIndex(nTableId
));
186 // insert table id as name
187 if (!pTable
->GetTableName().isEmpty())
188 aName
.append(" - " + pTable
->GetTableName());
189 // insert table caption as name
190 if (!pTable
->GetTableCaption().isEmpty())
191 aName
.append(" - " + pTable
->GetTableCaption());
192 const OUString
sName(aName
.makeStringAndClear());
193 if (!mpDoc
->GetRangeName()->findByUpperName(ScGlobal::getCharClass().uppercase(sName
)))
194 InsertRangeName(*mpDoc
, sName
, aNewRange
);
198 OUString
ScFormatFilterPluginImpl::GetHTMLRangeNameList( ScDocument
& rDoc
, const OUString
& rOrigName
)
200 return ScHTMLImport::GetHTMLRangeNameList( rDoc
, rOrigName
);
203 OUString
ScHTMLImport::GetHTMLRangeNameList( const ScDocument
& rDoc
, std::u16string_view rOrigName
)
205 if (rOrigName
.empty())
209 ScRangeName
* pRangeNames
= rDoc
.GetRangeName();
210 ScRangeList aRangeList
;
211 sal_Int32 nStringIx
= 0;
214 OUString
aToken( o3tl::getToken(rOrigName
, 0, ';', nStringIx
) );
215 if( pRangeNames
&& ScfTools::IsHTMLTablesName( aToken
) )
216 { // build list with all HTML tables
217 sal_uLong nIndex
= 1;
220 aToken
= ScfTools::GetNameFromHTMLIndex( nIndex
++ );
221 const ScRangeData
* pRangeData
= pRangeNames
->findByUpperName(ScGlobal::getCharClass().uppercase(aToken
));
225 if( pRangeData
->IsReference( aRange
) && !aRangeList
.Contains( aRange
) )
227 aNewName
= ScGlobal::addToken(aNewName
, aToken
, ';');
228 aRangeList
.push_back( aRange
);
233 aNewName
= ScGlobal::addToken(aNewName
, aToken
, ';');
239 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */