30 #include <editeng/editeng.hxx>
49 #include <osl/diagnose.h>
51 #include <rtl/tencinfo.h>
56 #include <document.hxx>
59 #include <orcus/css_parser.hpp>
61 #include <com/sun/star/document/XDocumentProperties.hpp>
62 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
63 #include <com/sun/star/frame/XModel.hpp>
66 using ::editeng::SvxBorderLine;
71 void ScHTMLStyles::add(
const char* pElemName,
size_t nElemName,
const char* pClassName,
size_t nClassName,
72 const OUString& aProp,
const OUString& aValue)
76 OUString aElem(pElemName, nElemName, RTL_TEXTENCODING_UTF8);
77 aElem = aElem.toAsciiLowerCase();
81 ElemsType::iterator itrElem =
m_ElemProps.find(aElem);
85 std::pair<ElemsType::iterator, bool> r =
86 m_ElemProps.insert(std::make_pair(aElem, std::make_unique<NamePropsType>()));
94 OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
95 aClass = aClass.toAsciiLowerCase();
109 OUString aClass(pClassName, nClassName, RTL_TEXTENCODING_UTF8);
110 aClass = aClass.toAsciiLowerCase();
117 const OUString& rElem,
const OUString& rClass,
const OUString& rPropName)
const
125 NamePropsType::const_iterator itr2 = pClasses->find(rClass);
126 if (itr2 != pClasses->end())
128 const PropsType *
const pProps = itr2->second.get();
129 PropsType::const_iterator itr3 = pProps->find(rPropName);
130 if (itr3 != pProps->end())
140 const PropsType *
const pProps = itr->second.get();
141 PropsType::const_iterator itr2 = pProps->find(rPropName);
142 if (itr2 != pProps->end())
151 const PropsType *
const pProps = itr->second.get();
152 PropsType::const_iterator itr2 = pProps->find(rPropName);
153 if (itr2 != pProps->end())
163 const OUString& aProp,
const OUString& aValue)
165 NamePropsType::iterator itr = rStore.find(aName);
166 if (itr == rStore.end())
169 std::pair<NamePropsType::iterator, bool> r =
170 rStore.insert(std::make_pair(aName, std::make_unique<PropsType>()));
178 PropsType *
const pProps = itr->second.get();
179 pProps->emplace(aProp, aValue);
198 EditEngine* pEditP,
const OUString& rBaseURL,
const Size& aPageSizeP,
201 aPageSize( aPageSizeP ),
202 aBaseURL( rBaseURL ),
216 bTabInTabCell( false ),
236 for(
const auto& rEntry : *
pTables)
237 delete rEntry.second;
248 bool bLoading = pObjSh && pObjSh->
IsLoading();
258 const char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
261 OUString aContentType =
"text/html; charset=" +
262 OUString::createFromAscii( pCharSet );
266 pAttributes = xValues.
get();
270 ErrCode nErr =
pEdit->
Read( rStream, rBaseURL, EETextFormat::Html, pAttributes );
279 for ( sal_uInt16 j = 1; j < nCount; j++ )
321 OSL_FAIL(
"EntryEnd: EditEngine ESelection End < Start" );
337 SCCOL* pCol, sal_uInt16 nOffsetTol )
339 OSL_ENSURE( pOffset,
"ScHTMLLayoutParser::SeekOffset - illegal call" );
341 bool bFound = it != pOffset->
end();
343 *pCol =
static_cast<SCCOL>(nPos);
350 if ( nPos < nCount && (((*pOffset)[nPos] - nOffsetTol) <= nOffset) )
353 else if ( nPos && (((*pOffset)[nPos-1] + nOffsetTol) >= nOffset) )
362 sal_uInt16& nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
364 OSL_ENSURE( pOffset,
"ScHTMLLayoutParser::MakeCol - illegal call" );
366 if (
SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
367 nOffset =
static_cast<sal_uInt16
>((*pOffset)[nPos]);
369 pOffset->
insert( nOffset );
372 if (
SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
373 nWidth =
static_cast<sal_uInt16
>((*pOffset)[nPos]) - nOffset;
375 pOffset->
insert( nOffset + nWidth );
380 sal_uInt16 nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol )
382 OSL_ENSURE( pOffset,
"ScHTMLLayoutParser::MakeColNoRef - illegal call" );
384 if (
SeekOffset( pOffset, nOffset, &nPos, nOffsetTol ) )
385 nOffset =
static_cast<sal_uInt16
>((*pOffset)[nPos]);
387 pOffset->
insert( nOffset );
390 if ( !
SeekOffset( pOffset, nOffset + nWidth, &nPos, nWidthTol ) )
391 pOffset->
insert( nOffset + nWidth );
396 sal_uInt16& nNewOffset, sal_uInt16 nOffsetTol )
398 OSL_ENSURE( pOffset,
"ScHTMLLayoutParser::ModifyOffset - illegal call" );
400 if ( !
SeekOffset( pOffset, nOldOffset, &nPos, nOffsetTol ) )
402 if (
SeekOffset( pOffset, nNewOffset, &nPos, nOffsetTol ) )
403 nNewOffset =
static_cast<sal_uInt16
>((*pOffset)[nPos]);
405 pOffset->
insert( nNewOffset );
408 nOldOffset =
static_cast<sal_uInt16
>((*pOffset)[nPos]);
410 if (
SeekOffset( pOffset, nNewOffset, &nPos2, nOffsetTol ) )
412 nNewOffset =
static_cast<sal_uInt16
>((*pOffset)[nPos2]);
420 const_cast<sal_uLong&
>((*pOffset)[nPos]) += nDiff;
427 const_cast<sal_uLong&
>((*pOffset)[nPos]) += nDiff;
428 }
while ( ++nPos < static_cast<sal_uInt16>(pOffset->
size()) );
438 bool bBadCol =
false;
464 if ( bJoin && !bBadCol )
472 std::stack< std::unique_ptr<ScHTMLAdjustStackEntry> > aStack;
477 sal_uInt16 nPageWidth =
static_cast<sal_uInt16
>(
aPageSize.
Width());
481 if (
pE->nTab < nTab )
483 if ( !aStack.empty() )
485 std::unique_ptr<ScHTMLAdjustStackEntry>
pS = std::move(aStack.top());
488 nLastCol = pS->nLastCol;
489 nNextRow = pS->nNextRow;
490 nCurRow = pS->nCurRow;
495 OuterMap::const_iterator it =
pTables->find( nTab );
502 if (
pE->nCol <= nLastCol )
504 if (
pE->nRow < nNextRow )
505 pE->nRow = nCurRow = nNextRow;
507 nCurRow = nNextRow =
pE->nRow;
511 InnerMap::const_iterator it = pTab->find( nCurRow );
512 if ( it != pTab->end() )
523 if (
pE->nTab > nTab )
525 aStack.push( std::make_unique<ScHTMLAdjustStackEntry>(
526 nLastCol, nNextRow, nCurRow ) );
530 OuterMap::const_iterator it =
pTables->find( nTab );
538 InnerMap::const_iterator it = pTab->find( nCurRow );
539 if ( it != pTab->end() )
543 nNextRow = nCurRow + nR;
545 nNextRow = nCurRow + 1;
548 pE->nWidth = nPageWidth;
553 SCROW nRowSpan =
pE->nRowOverlap;
554 for (
SCROW j=0; j < nRowSpan; j++ )
557 InnerMap::const_iterator it = pTab->find( nRow+j );
558 if ( it != pTab->end() )
562 pE->nRowOverlap += nRows - 1;
565 SCROW nTmp = nCurRow + nRows;
566 if ( nNextRow < nTmp )
575 SCCOL nColBeforeSkip =
pE->nCol;
577 if (
pE->nCol != nColBeforeSkip )
580 if ( nCount <= pE->nCol )
582 pE->nOffset =
static_cast<sal_uInt16
>(
maColOffset[nCount-1]);
592 pE->nColOverlap = (nPos >
pE->nCol ? nPos -
pE->nCol : 1);
599 pE->nCol +
pE->nColOverlap - 1,
pE->nRow +
pE->nRowOverlap - 1, 0 ) );
601 SCCOL nColTmp =
pE->nCol +
pE->nColOverlap;
604 SCROW nRowTmp =
pE->nRow +
pE->nRowOverlap;
614 sal_Int32 nTmp = std::min( static_cast<sal_Int32>( pE->
nCol -
617 SCCOL nPos = (nTmp < 0 ? 0 : static_cast<SCCOL>(nTmp));
618 sal_uInt16 nOff2 =
static_cast<sal_uInt16
>((*pLocalColOffset)[nPos]);
630 if ( nColsPerRow <= 0 )
634 sal_uInt16 nWidth =
nTableWidth /
static_cast<sal_uInt16
>(nColsPerRow);
637 for ( nCol = 0; nCol <= nColsPerRow; ++nCol, nOff = nOff + nWidth )
647 pE->nOffset =
static_cast<sal_uInt16
>((*pLocalColOffset)[
pE->nCol -
nColCntStart]);
657 std::unique_ptr<sal_uInt16[]> pOffsets(
new sal_uInt16[ nColsPerRow+1 ]);
658 memset( pOffsets.get(), 0, (nColsPerRow+1) *
sizeof(sal_uInt16) );
659 std::unique_ptr<sal_uInt16[]> pWidths(
new sal_uInt16[ nColsPerRow ]);
660 memset( pWidths.get(), 0, nColsPerRow *
sizeof(sal_uInt16) );
668 if ( nCol < nColsPerRow )
670 if (
pE->nColOverlap == 1 )
672 if ( pWidths[nCol] <
pE->nWidth )
673 pWidths[nCol] =
pE->nWidth;
677 sal_uInt16 nTotal = 0;
680 SCCOL nStop = std::min( static_cast<SCCOL>(nCol +
pE->nColOverlap), nColsPerRow );
681 for ( ; nCol < nStop; nCol++ )
684 nTotal = nTotal + pWidths[nCol];
696 if ( bFound &&
pE->nWidth > nTotal )
697 pWidths[nHere] =
pE->nWidth - nTotal;
702 sal_uInt16 nWidths = 0;
703 sal_uInt16 nUnknown = 0;
704 for ( nCol = 0; nCol < nColsPerRow; nCol++ )
707 nWidths = nWidths + pWidths[nCol];
716 for ( nCol = 0; nCol < nColsPerRow; nCol++ )
718 if ( !pWidths[nCol] )
722 for ( nCol = 1; nCol <= nColsPerRow; nCol++ )
724 pOffsets[nCol] = pOffsets[nCol-1] + pWidths[nCol-1];
727 for ( nCol = 0; nCol <= nColsPerRow; nCol++ )
739 OSL_ENSURE( nCol < nColsPerRow,
"ScHTMLLayoutParser::SetWidths: column overflow" );
740 if ( nCol < nColsPerRow )
742 pE->nOffset = pOffsets[nCol];
743 nCol = nCol +
pE->nColOverlap;
744 if ( nCol > nColsPerRow )
746 pE->nWidth = pOffsets[nCol] -
pE->nOffset;
766 OSL_ENSURE(
pE->nWidth,
"SetWidths: pE->nWidth == 0" );
782 if ( nCol < pE->nCol )
787 nColOffset =
static_cast<sal_uInt16
>((*pLocalColOffset)[nCol]);
789 nColOffset =
static_cast<sal_uInt16
>((*pLocalColOffset)[nCount - 1]);
820 while ( rSel.nStartPara < rSel.nEndPara
825 while ( rSel.nEndPos == 0 && rSel.nEndPara > rSel.nStartPara )
830 if ( rSel.nStartPara > rSel.nEndPara )
832 OSL_FAIL(
"CloseEntry: EditEngine ESelection Start > End" );
833 rSel.nEndPara = rSel.nStartPara;
835 if ( rSel.HasRange() )
843 switch ( rInfo.eState )
845 case HtmlImportState::NextToken:
848 case HtmlImportState::Start:
850 case HtmlImportState::End:
851 if ( rInfo.aSelection.nEndPos )
860 CloseEntry( &rInfo );
862 while ( nTableLevel > 0 )
865 case HtmlImportState::SetAttr:
867 case HtmlImportState::InsertText:
869 case HtmlImportState::InsertPara:
870 if ( nTableLevel < 1 )
872 CloseEntry( &rInfo );
876 case HtmlImportState::InsertField:
879 OSL_FAIL(
"HTMLImportHdl: unknown ImportInfo.eState");
892 a -=
SCROW(a / b) * b;
894 b -=
SCROW(b / a) * a;
896 return ((a != 0) ? a : b);
914 OSL_FAIL(
"dumbo doc! <TH> or <TD> without previous <TABLE>" );
918 bool bHorJustifyCenterTH = (pInfo->
nToken == HtmlTokenId::TABLEHEADER_ON);
920 for (
const auto & rOption : rOptions)
922 switch( rOption.GetToken() )
924 case HtmlOptionId::COLSPAN:
926 mxActEntry->nColOverlap =
static_cast<SCCOL>(rOption.GetString().toInt32());
929 case HtmlOptionId::ROWSPAN:
931 mxActEntry->nRowOverlap =
static_cast<SCROW>(rOption.GetString().toInt32());
934 case HtmlOptionId::ALIGN:
936 bHorJustifyCenterTH =
false;
938 const OUString& rOptVal = rOption.GetString();
940 eVal = SvxCellHorJustify::Right;
942 eVal = SvxCellHorJustify::Center;
944 eVal = SvxCellHorJustify::Left;
946 eVal = SvxCellHorJustify::Standard;
947 if ( eVal != SvxCellHorJustify::Standard )
951 case HtmlOptionId::VALIGN:
954 const OUString& rOptVal = rOption.GetString();
956 eVal = SvxCellVerJustify::Top;
958 eVal = SvxCellVerJustify::Center;
960 eVal = SvxCellVerJustify::Bottom;
962 eVal = SvxCellVerJustify::Standard;
966 case HtmlOptionId::WIDTH:
971 case HtmlOptionId::BGCOLOR:
974 rOption.GetColor( aColor );
978 case HtmlOptionId::SDVAL:
983 case HtmlOptionId::SDNUM:
996 if ( bHorJustifyCenterTH )
1025 aTableStack.push( std::make_unique<ScHTMLTableStackEntry>(
1037 if ( pInfo->
nToken == HtmlTokenId::TABLE_ON )
1040 for (
const auto & rOption : rOptions)
1042 switch( rOption.GetToken() )
1044 case HtmlOptionId::WIDTH:
1049 case HtmlOptionId::BORDER:
1081 aTableStack.push( std::make_unique<ScHTMLTableStackEntry>(
1090 if ( pInfo->
nToken == HtmlTokenId::TABLE_ON )
1094 for (
const auto & rOption : rOptions)
1096 switch( rOption.GetToken() )
1098 case HtmlOptionId::WIDTH:
1103 case HtmlOptionId::BORDER:
1127 OSL_FAIL(
"dumbo doc! </TABLE> without opening <TABLE>" );
1134 std::unique_ptr<ScHTMLTableStackEntry>
pS = std::move(
aTableStack.top());
1137 auto&
pE = pS->xCellEntry;
1141 SCROW nRow = pS->nRowCnt;
1142 sal_uInt16 nTab = pS->nTable;
1146 OuterMap::const_iterator it =
pTables->find( nTab );
1151 (*pTables)[ nTab ] = pTab1;
1155 SCROW nRowSpan =
pE->nRowOverlap;
1161 nRowKGV =
lcl_KGV( nRowSpan, nRows );
1162 nRowsPerRow1 = nRowKGV / nRowSpan;
1163 nRowsPerRow2 = nRowKGV / nRows;
1167 nRowKGV = nRowsPerRow1 = nRows;
1171 if ( nRowsPerRow2 > 1 )
1174 (*pTables)[
nTable ] = pTab2;
1179 if ( nRowsPerRow1 > 1 )
1181 for (
SCROW j=0; j < nRowSpan; j++ )
1184 SCROW nR = (*pTab1)[ nRowKey ];
1186 (*pTab1)[ nRowKey ] = nRowsPerRow1;
1187 else if ( nRowsPerRow1 > nR )
1188 (*pTab1)[ nRowKey ] = nRowsPerRow1;
1190 else if ( nRowsPerRow1 < nR && nRowSpan == 1
1193 SCROW nAdd = nRowsPerRow1 - (nR % nRowsPerRow1);
1195 if ( (nR % nRows) == 0 )
1197 SCROW nR2 = (*pTab1)[ nRowKey+1 ];
1200 (*pTab1)[ nRowKey ] = nR;
1201 (*pTab1)[ nRowKey+1 ] = nR2 - nAdd;
1202 nRowsPerRow2 = nR / nRows;
1208 if ( nRowsPerRow2 > 1 )
1213 (*pTables)[
nTable ] = pTab2;
1215 for (
SCROW j=0; j < nRows; j++ )
1218 (*pTab2)[ nRowKey ] = nRowsPerRow2;
1230 sal_uInt16 nOldOffset =
pE->nOffset +
pE->nWidth;
1233 sal_uInt16 nTmp = nNewOffset -
pE->nOffset -
pE->nWidth;
1234 pE->nWidth = nNewOffset -
pE->nOffset;
1235 pS->nTableWidth = pS->nTableWidth + nTmp;
1236 if ( pS->nColOffset >= nOldOffset )
1237 pS->nColOffset = pS->nColOffset + nTmp;
1276 mxActEntry->maImageList.push_back(std::make_unique<ScHTMLImage>());
1279 for (
const auto & rOption : rOptions)
1281 switch( rOption.GetToken() )
1283 case HtmlOptionId::SRC:
1288 case HtmlOptionId::ALT:
1299 case HtmlOptionId::WIDTH:
1301 pImage->
aSize.
setWidth( static_cast<tools::Long>(rOption.GetNumber()) );
1304 case HtmlOptionId::HEIGHT:
1306 pImage->
aSize.
setHeight( static_cast<tools::Long>(rOption.GetNumber()) );
1309 case HtmlOptionId::HSPACE:
1311 pImage->
aSpace.setX( static_cast<tools::Long>(rOption.GetNumber()) );
1314 case HtmlOptionId::VSPACE:
1316 pImage->
aSpace.setY( static_cast<tools::Long>(rOption.GetNumber()) );
1322 if (pImage->
aURL.isEmpty())
1324 OSL_FAIL(
"Image: graphic without URL ?!?" );
1329 std::unique_ptr<Graphic> pGraphic(
new Graphic);
1332 *pGraphic, &rFilter, &nFormat ) )
1342 pImage->
pGraphic = std::move( pGraphic );
1347 pImage->
pGraphic->GetPrefMapMode() );
1353 for (
const std::unique_ptr<ScHTMLImage> & pI :
mxActEntry->maImageList)
1356 nWidth += pI->aSize.Width() + 2 * pI->aSpace.X();
1369 for (
const auto & rOption : rOptions)
1371 if( rOption.GetToken() == HtmlOptionId::WIDTH )
1382 const OUString& rOptVal = rOption.
GetString();
1383 if ( rOptVal.indexOf(
'%') != -1 )
1386 return static_cast<sal_uInt16
>((rOption.
GetNumber() * nW) / 100);
1390 if ( rOptVal.indexOf(
'*') != -1 )
1396 return static_cast<sal_uInt16
>(rOption.
GetNumber());
1403 for (
const auto & rOption : rOptions)
1405 if( rOption.GetToken() == HtmlOptionId::NAME )
1425 for (
const auto & rOption : rOptions)
1427 switch( rOption.GetToken() )
1429 case HtmlOptionId::FACE :
1431 const OUString& rFace = rOption.GetString();
1432 OUStringBuffer aFontName;
1438 OUString aFName = rFace.getToken( 0,
',', nPos );
1440 if( !aFontName.isEmpty() )
1441 aFontName.append(
";");
1442 aFontName.append(aFName);
1444 if ( !aFontName.isEmpty() )
1447 RTL_TEXTENCODING_DONTKNOW,
ATTR_FONT ) );
1450 case HtmlOptionId::SIZE :
1452 sal_uInt16 nSize =
static_cast<sal_uInt16
>(rOption.GetNumber());
1461 case HtmlOptionId::COLOR :
1464 rOption.GetColor( aColor );
1477 case HtmlTokenId::META:
1480 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1483 xDPS->getDocumentProperties(),
1487 case HtmlTokenId::TITLE_ON:
1493 case HtmlTokenId::TITLE_OFF:
1499 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1501 uno::UNO_QUERY_THROW);
1502 xDPS->getDocumentProperties()->setTitle(
aString);
1507 case HtmlTokenId::TABLE_ON:
1512 case HtmlTokenId::COL_ON:
1517 case HtmlTokenId::TABLEHEADER_ON:
1526 case HtmlTokenId::TABLEDATA_ON:
1531 case HtmlTokenId::TABLEHEADER_OFF:
1532 case HtmlTokenId::TABLEDATA_OFF:
1537 case HtmlTokenId::TABLEROW_ON:
1542 case HtmlTokenId::TABLEROW_OFF:
1547 case HtmlTokenId::TABLE_OFF:
1552 case HtmlTokenId::IMAGE:
1557 case HtmlTokenId::PARABREAK_OFF:
1563 case HtmlTokenId::ANCHOR_ON:
1568 case HtmlTokenId::FONT_ON :
1573 case HtmlTokenId::BIGPRINT_ON :
1581 case HtmlTokenId::SMALLPRINT_ON :
1589 case HtmlTokenId::BOLD_ON :
1590 case HtmlTokenId::STRONG_ON :
1597 case HtmlTokenId::ITALIC_ON :
1598 case HtmlTokenId::EMPHASIS_ON :
1599 case HtmlTokenId::ADDRESS_ON :
1600 case HtmlTokenId::BLOCKQUOTE_ON :
1601 case HtmlTokenId::BLOCKQUOTE30_ON :
1602 case HtmlTokenId::CITIATION_ON :
1603 case HtmlTokenId::VARIABLE_ON :
1610 case HtmlTokenId::DEFINSTANCE_ON :
1621 case HtmlTokenId::UNDERLINE_ON :
1628 case HtmlTokenId::TEXTTOKEN:
1640 template<
typename Type >
1642 {
return std::clamp( rValue, rMin, rMax ); }
1646 mbImportAlways( false )
1674 "ScHTMLQueryParser::AdjustEntryEnd - invalid end position" );
1721 const_iterator
begin()
const {
return maTables.begin(); }
1722 const_iterator
end()
const {
return maTables.end(); }
1736 {
if( pTable ) mpCurrTable = pTable; }
1740 mrParentTable(rParentTable),
1741 mpCurrTable(nullptr)
1754 pResult = aFind->second.get();
1758 if( !pResult && bDeep )
1782 class ScHTMLTableIterator
1789 bool is()
const {
return mpTableMap &&
maIter !=
maEnd; }
1801 ScHTMLTableIterator::ScHTMLTableIterator(
const ScHTMLTableMap* pTableMap ) :
1802 mpTableMap(pTableMap)
1812 mnTableId( rnUnusedId ),
1813 mrnUnusedId( rnUnusedId )
1819 mpParentTable( &rParentTable ),
1820 maTableId( rParentTable.maTableId.mrnUnusedId ),
1821 maTableItemSet( rParentTable.GetCurrItemSet() ),
1822 mrEditEngine( rParentTable.mrEditEngine ),
1823 mrEEParseList( rParentTable.mrEEParseList ),
1824 mpCurrEntryVector( nullptr ),
1826 mpParser(rParentTable.mpParser),
1827 mbBorderOn( false ),
1828 mbPreFormText( bPreFormText ),
1831 mbPushEmptyLine( false )
1842 for (
const auto& rOption : rOptions)
1844 switch( rOption.GetToken() )
1846 case HtmlOptionId::BORDER:
1847 mbBorderOn = rOption.GetString().isEmpty() || (rOption.GetNumber() != 0);
1849 case HtmlOptionId::ID:
1863 std::vector<std::shared_ptr<ScEEParseEntry>>& rEEParseList,
1866 mpParentTable( nullptr ),
1867 maTableId( rnUnusedId ),
1868 maTableItemSet( rPool ),
1869 mrEditEngine( rEditEngine ),
1870 mrEEParseList( rEEParseList ),
1871 mpCurrEntryVector( nullptr ),
1874 mbBorderOn( false ),
1875 mbPreFormText( false ),
1878 mbPushEmptyLine( false )
1914 OSL_ENSURE(
mxCurrEntry,
"ScHTMLTable::PutItem - no current entry" );
1921 OSL_ENSURE(
mxCurrEntry,
"ScHTMLTable::PutText - no current entry" );
1960 OSL_ENSURE(
mxCurrEntry,
"ScHTMLTable::AnchorOn - no current entry" );
2013 OUString decodeNumberFormat(
const OUString& rFmt)
2015 OUStringBuffer
aBuf;
2017 sal_Int32
n = rFmt.getLength();
2018 for (sal_Int32 i = 0;
i < n; ++
i, ++p)
2027 sal_Int32 nDigitCount = 0;
2029 for (;
i < n; ++
i, ++p, ++nDigitCount)
2031 if (*p <
'0' ||
'9' < *p)
2044 sal_uInt32 nVal = OUString(p1, nDigitCount).toUInt32(16);
2045 aBuf.append(static_cast<sal_Unicode>(nVal));
2051 return aBuf.makeStringAndClear();
2063 std::optional<OUString> pValStr, pNumStr;
2066 for (
const auto& rOption : rOptions)
2068 switch (rOption.GetToken())
2070 case HtmlOptionId::COLSPAN:
2071 aSpanSize.
mnCols =
static_cast<SCCOL>( getLimitedValue<sal_Int32>( rOption.GetString().toInt32(), 1, 256 ) );
2073 case HtmlOptionId::ROWSPAN:
2074 aSpanSize.
mnRows =
static_cast<SCROW>( getLimitedValue<sal_Int32>( rOption.GetString().toInt32(), 1, 256 ) );
2076 case HtmlOptionId::SDVAL:
2077 pValStr = rOption.GetString();
2079 case HtmlOptionId::SDNUM:
2080 pNumStr = rOption.GetString();
2082 case HtmlOptionId::CLASS:
2086 OUString aClass = rOption.GetString();
2088 const OUString& rVal = rStyles.
getPropertyValue(
"td", aClass,
"mso-number-format");
2089 if (!rVal.isEmpty())
2091 OUString aNumFmt = decodeNumberFormat(rVal);
2096 sal_Int32 nErrPos = 0;
2176 size_t nIndex =
static_cast< size_t >( nCellPos );
2177 if( nIndex >= rSizes.size() )
return 0;
2178 return (nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]);
2184 size_t nBeginIdx =
static_cast< size_t >( std::max< SCCOLROW >( nCellBegin, 0 ) );
2185 size_t nEndIdx =
static_cast< size_t >( std::min< SCCOLROW >( nCellEnd,
static_cast< SCCOLROW >( rSizes.size() ) ) );
2186 if (nBeginIdx >= nEndIdx )
return 0;
2187 return rSizes[ nEndIdx - 1 ] - ((nBeginIdx == 0) ? 0 : rSizes[ nBeginIdx - 1 ]);
2193 return rSizes.empty() ? 0 : rSizes.back();
2229 OSL_ENSURE( pDoc,
"ScHTMLTable::ApplyCellBorders - no document" );
2236 SvxBorderLine aOuterLine(
nullptr, nOuterLine, SvxBorderLineStyle::SOLID);
2237 SvxBorderLine aInnerLine(
nullptr, nInnerLine, SvxBorderLineStyle::SOLID);
2240 for(
SCCOL nCol = 0; nCol <= nLastCol; ++nCol )
2242 SvxBorderLine* pLeftLine = (nCol == 0) ? &aOuterLine : &aInnerLine;
2243 SvxBorderLine* pRightLine = (nCol == nLastCol) ? &aOuterLine : &aInnerLine;
2246 for(
SCROW nRow = 0; nRow <= nLastRow; ++nRow )
2248 SvxBorderLine* pTopLine = (nRow == 0) ? &aOuterLine : &aInnerLine;
2249 SvxBorderLine* pBottomLine = (nRow == nLastRow) ? &aOuterLine : &aInnerLine;
2252 for(
SCCOL nCellCol = nCellCol1; nCellCol <= nCellCol2; ++nCellCol )
2254 aBorderItem.
SetLine( (nCellCol == nCellCol1) ? pLeftLine :
nullptr, SvxBoxItemLine::LEFT );
2255 aBorderItem.
SetLine( (nCellCol == nCellCol2) ? pRightLine :
nullptr, SvxBoxItemLine::RIGHT );
2256 for(
SCROW nCellRow = nCellRow1; nCellRow <= nCellRow2; ++nCellRow )
2258 aBorderItem.
SetLine( (nCellRow == nCellRow1) ? pTopLine :
nullptr, SvxBoxItemLine::TOP );
2259 aBorderItem.
SetLine( (nCellRow == nCellRow2) ? pBottomLine :
nullptr, SvxBoxItemLine::BOTTOM );
2260 pDoc->
ApplyAttr( nCellCol, nCellRow, rFirstPos.
Tab(), aBorderItem );
2267 for( ScHTMLTableIterator aIter(
mxNestedTables.get() ); aIter.is(); ++aIter )
2268 aIter->ApplyCellBorders( pDoc, rFirstPos );
2283 return (rInfo.
nToken == HtmlTokenId::TEXTTOKEN) && (rInfo.
aText.getLength() == 1) && (rInfo.
aText[ 0 ] ==
' ');
2293 OSL_ENSURE( !
mxCurrEntry,
"ScHTMLTable::CreateNewEntry - old entry still present" );
2301 rEntryVector.push_back( rxEntry.get() );
2303 mrEEParseList.push_back(std::shared_ptr<ScEEParseEntry>(rxEntry.release()));
2308 bool bPushed =
false;
2309 if( rxEntry && rxEntry->HasContents() )
2328 OSL_FAIL(
"ScHTMLTable::PushEntry - cannot push entry, no parent found" );
2336 OSL_ENSURE(
mxCurrEntry,
"ScHTMLTable::PushEntry - no current entry" );
2337 bool bPushed =
false;
2360 OSL_ENSURE( nTableId !=
SC_HTML_GLOBAL_TABLE,
"ScHTMLTable::PushTableEntry - cannot push global table" );
2372 OSL_ENSURE( pTable || (nTableId ==
SC_HTML_GLOBAL_TABLE),
"ScHTMLTable::GetExistingTable - table not found" );
2413 if (!aNewRange.aEnd.Move( rSpanSize.
mnCols - 1, rSpanSize.
mnRows - 1, 0, aErrorPos))
2417 if( rSpanSize.
mnRows > 1 )
2426 if( rSpanSize.
mnCols > 1 )
2486 if( rInfo.
nToken == HtmlTokenId::TABLEHEADER_ON )
2493 for (
const auto& rOption : rOptions)
2495 switch( rOption.GetToken() )
2497 case HtmlOptionId::ALIGN:
2500 const OUString& rOptVal = rOption.GetString();
2502 eVal = SvxCellHorJustify::Right;
2504 eVal = SvxCellHorJustify::Center;
2506 eVal = SvxCellHorJustify::Left;
2507 if( eVal != SvxCellHorJustify::Standard )
2512 case HtmlOptionId::VALIGN:
2515 const OUString& rOptVal = rOption.GetString();
2517 eVal = SvxCellVerJustify::Top;
2519 eVal = SvxCellVerJustify::Center;
2521 eVal = SvxCellVerJustify::Bottom;
2522 if( eVal != SvxCellVerJustify::Standard )
2527 case HtmlOptionId::BGCOLOR:
2530 rOption.GetColor( aColor );
2541 OSL_ENSURE( nCellPos >= 0,
"ScHTMLTable::SetDocSize - unexpected negative position" );
2543 size_t nIndex =
static_cast< size_t >( nCellPos );
2545 while( nIndex >= rSizes.size() )
2546 rSizes.push_back( rSizes.empty() ? 1 : (rSizes.back() + 1) );
2549 SCCOLROW nDiff = nSize - ((nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]));
2551 std::for_each(rSizes.begin() + nIndex, rSizes.end(), [&nDiff](
SCCOLROW& rSize) { rSize += nDiff; });
2559 while( nCellSpan > 1 )
2561 nDiffSize +=
GetDocSize( eOrient, nCellPos );
2566 nRealDocSize -= std::min< SCCOLROW >( nRealDocSize - 1, nDiffSize );
2567 SetDocSize( eOrient, nCellPos, nRealDocSize );
2572 for( ScHTMLTableIterator aIter(
mxNestedTables.get() ); aIter.is(); ++aIter )
2573 aIter->FillEmptyCells();
2584 for( aAddr.SetCol( 0 ); aAddr.Col() <
maSize.
mnCols; aAddr.IncCol() )
2609 for( ScHTMLTableIterator aIter(
mxNestedTables.get() ); aIter.is(); ++aIter )
2610 aIter->RecalcDocSize();
2615 static const sal_uInt16 PASS_SINGLE = 0;
2616 static const sal_uInt16 PASS_SPANNED = 1;
2617 for( sal_uInt16 nPass = PASS_SINGLE; nPass <= PASS_SPANNED; ++nPass )
2620 for(
const auto& [rCellPos, rEntryVector] :
maEntryMap )
2626 bool bProcessColWidth = ((nPass == PASS_SINGLE) == (aCellSpan.
mnCols == 1));
2627 bool bProcessRowHeight = ((nPass == PASS_SINGLE) == (aCellSpan.
mnRows == 1));
2628 if( bProcessColWidth || bProcessRowHeight )
2633 for(
const auto& rpEntry : rEntryVector )
2637 if( bProcessColWidth && pTable )
2640 if( bProcessRowHeight )
2646 if( bProcessColWidth )
2648 if( bProcessRowHeight )
2661 for(
auto& [rCellPos, rEntryVector] :
maEntryMap )
2672 for(
const auto& rpEntry : rEntryVector )
2677 pTable->RecalcDocPos( aEntryDocPos );
2680 SCROW nTableRows =
static_cast< SCROW >( pTable->GetDocSize(
tdRow ) );
2687 if( nStartCol < nNextCol )
2689 pEntry->
nCol = nStartCol;
2695 aEntryDocPos.
mnRow += nTableRows;
2703 ++aEntryDocPos.
mnRow;
2719 while( aEntryDocPos.
mnRow < nFirstUnusedRow )
2722 xDummyEntry->nCol = aEntryDocPos.
mnCol;
2723 xDummyEntry->nRow = aEntryDocPos.
mnRow;
2724 xDummyEntry->nColOverlap = aCellDocSize.
mnCols;
2726 ++aEntryDocPos.
mnRow;
2736 std::vector<std::shared_ptr<ScEEParseEntry>>& rEEParseVector,
2740 ScHTMLTable( rPool, rEditEngine, rEEParseVector, rnUnusedId, pParser )
2786 const char* pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
2789 OUString aContentType =
"text/html; charset=" +
2790 OUString::createFromAscii( pCharSet );
2794 pAttributes = xValues.
get();
2800 ErrCode nErr =
pEdit->
Read( rStrm, rBaseURL, EETextFormat::Html, pAttributes );
2820 case HtmlTokenId::META:
MetaOn( rInfo );
break;
2823 case HtmlTokenId::TITLE_ON:
TitleOn();
break;
2824 case HtmlTokenId::TITLE_OFF:
TitleOff( rInfo );
break;
2826 case HtmlTokenId::STYLE_ON:
break;
2834 case HtmlTokenId::TEXTTOKEN:
InsertText( rInfo );
break;
2836 case HtmlTokenId::HEAD1_ON:
2837 case HtmlTokenId::HEAD2_ON:
2838 case HtmlTokenId::HEAD3_ON:
2839 case HtmlTokenId::HEAD4_ON:
2840 case HtmlTokenId::HEAD5_ON:
2841 case HtmlTokenId::HEAD6_ON:
2848 case HtmlTokenId::TABLE_ON:
TableOn( rInfo );
break;
2849 case HtmlTokenId::TABLE_OFF:
TableOff( rInfo );
break;
2852 case HtmlTokenId::TABLEHEADER_ON:
2854 case HtmlTokenId::TABLEHEADER_OFF:
2856 case HtmlTokenId::PREFORMTXT_ON:
PreOn( rInfo );
break;
2857 case HtmlTokenId::PREFORMTXT_OFF:
PreOff( rInfo );
break;
2860 case HtmlTokenId::FONT_ON:
FontOn( rInfo );
break;
2862 case HtmlTokenId::BIGPRINT_ON:
2866 case HtmlTokenId::SMALLPRINT_ON:
2871 case HtmlTokenId::BOLD_ON:
2872 case HtmlTokenId::STRONG_ON:
2876 case HtmlTokenId::ITALIC_ON:
2877 case HtmlTokenId::EMPHASIS_ON:
2878 case HtmlTokenId::ADDRESS_ON:
2879 case HtmlTokenId::BLOCKQUOTE_ON:
2880 case HtmlTokenId::BLOCKQUOTE30_ON:
2881 case HtmlTokenId::CITIATION_ON:
2882 case HtmlTokenId::VARIABLE_ON:
2886 case HtmlTokenId::DEFINSTANCE_ON:
2891 case HtmlTokenId::UNDERLINE_ON:
2908 for (
const auto& rOption : rOptions)
2910 switch( rOption.GetToken() )
2912 case HtmlOptionId::FACE :
2914 const OUString& rFace = rOption.GetString();
2923 if ( !aFontName.isEmpty() )
2926 RTL_TEXTENCODING_DONTKNOW,
ATTR_FONT ) );
2929 case HtmlOptionId::SIZE :
2931 sal_uInt32 nSize = getLimitedValue< sal_uInt32 >( rOption.GetNumber(), 1,
SC_HTML_FONTSIZES );
2935 case HtmlOptionId::COLOR :
2938 rOption.GetColor( aColor );
2953 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2956 xDPS->getDocumentProperties(),
2972 OUString aTitle =
maTitle.makeStringAndClear().trim();
2975 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
2978 xDPS->getDocumentProperties()->setTitle(aTitle);
3021 MemStr() : mp(nullptr), mn(0) {}
3022 MemStr(
const char* p,
size_t n) : mp(p), mn(n) {}
3023 MemStr& operator=(
const MemStr& r) =
default;
3030 explicit CSSHandler() {}
3032 static void at_rule_name(
const char* ,
size_t )
3037 void property_name(
const char* p,
size_t n)
3039 maPropName = MemStr(p, n);
3042 void value(
const char* p,
size_t n)
3044 maPropValue = MemStr(p, n);
3047 static void begin_parse() {}
3049 static void end_parse() {}
3051 static void begin_block() {}
3053 static void end_block() {}
3055 static void begin_property() {}
3059 maPropName = MemStr();
3060 maPropValue = MemStr();
3064 static void simple_selector_type(
const char* ,
size_t ) {}
3066 static void simple_selector_class(
const char* ,
size_t ) {}
3068 static void simple_selector_pseudo_element(orcus::css::pseudo_element_t ) {}
3070 static void simple_selector_pseudo_class(orcus::css::pseudo_class_t ) {}
3072 static void simple_selector_id(
const char* ,
size_t ) {}
3074 static void end_simple_selector() {}
3076 static void end_selector() {}
3078 static void combinator(orcus::css::combinator_t ) {}
3080 static void rgb(uint8_t , uint8_t , uint8_t ) {}
3082 static void rgba(uint8_t , uint8_t , uint8_t ,
double ) {}
3084 static void hsl(uint8_t , uint8_t , uint8_t ) {}
3086 static void hsla(uint8_t , uint8_t , uint8_t ,
double ) {}
3088 static void url(
const char* ,
size_t ) {}
3098 orcus::css_parser<CSSHandler> aParser(aStr.getStr(), aStr.getLength(), aHdl);
3103 catch (
const orcus::css::parse_error&)
3111 switch( rInfo.eState )
3113 case HtmlImportState::Start:
3116 case HtmlImportState::NextToken:
3117 ProcessToken( rInfo );
3120 case HtmlImportState::InsertPara:
3121 mpCurrTable->InsertPara( rInfo );
3124 case HtmlImportState::SetAttr:
3125 case HtmlImportState::InsertText:
3126 case HtmlImportState::InsertField:
3129 case HtmlImportState::End:
3131 CloseTable( rInfo );
3135 OSL_FAIL(
"ScHTMLQueryParser::HTMLImportHdl - unknown ImportInfo::eState" );
#define LINK(Instance, Class, Member)
std::unique_ptr< OuterMap > pTables
void RowOn(const HtmlImportInfo &rInfo)
Starts next row (tag).
EditEngine & mrEditEngine
List of all used cells.
ScHTMLStyles()
just a persistent empty string.
std::vector< std::shared_ptr< ScEEParseEntry > > & mrEEParseList
Edit engine (from ScEEParser).
ScHTMLTable * PreOn(const HtmlImportInfo &rInfo)
Starts a new table based on preformatted text (.
SvKeyValueIterator * GetHeaderAttributes()
const Value & back() const
void AnchorOn(HtmlImportInfo *)
SfxItemSet maTableItemSet
Unique identifier of this table.
const sal_uInt16 SC_HTML_OFFSET_TOLERANCE_LARGE
static void EntryEnd(ScEEParseEntry *, const ESelection &)
#define OOO_STRING_SVTOOLS_HTML_VA_bottom
ScHTMLSize maSize
Cumulated cell counts for each HTML table column/row.
static void MakeCol(ScHTMLColOffset *, sal_uInt16 &nOffset, sal_uInt16 &nWidth, sal_uInt16 nOffsetTol, sal_uInt16 nWidthTol)
void SetHtmlImportHdl(const Link< HtmlImportInfo &, void > &rLink)
ScHTMLTableAutoId(ScHTMLTableId &rnUnusedId)
Reference to global unused identifier variable.
static void ModifyOffset(ScHTMLColOffset *, sal_uInt16 &nOldOffset, sal_uInt16 &nNewOffset, sal_uInt16 nOffsetTol)
A map of ScHTMLTable objects.
constexpr TypedWhichId< SvxBoxItem > ATTR_BORDER(150)
virtual ~ScHTMLParser() override
void Strip(const EditEngine &rEditEngine)
Deletes leading and trailing empty paragraphs from the entry.
void setWidth(tools::Long nWidth)
A single entry containing a line of text or representing a table.
#define OOO_STRING_SVTOOLS_HTML_AL_center
bool PushEntry(ScHTMLEntryPtr &rxEntry)
Tries to insert the entry into the current cell.
void NewActEntry(const ScEEParseEntry *)
ScHTMLTableStdMap::const_iterator const_iterator
const sal_uInt32 SC_HTML_FONTSIZES
ScHTMLEntry(const SfxItemSet &rItemSet, ScHTMLTableId nTableId=SC_HTML_NO_TABLE)
void Colonize(ScEEParseEntry *)
::std::map< SCROW, SCROW > InnerMap
SC_DLLPUBLIC bool Intersects(const ScRange &rRange) const
bool IsEmptyCell() const
Returns true, if the current cell does not contain an entry yet.
void InsertNewCell(const ScHTMLSize &rSpanSize)
Inserts a new cell in an unused position, starting from current cell position.
::std::map< sal_uInt16, InnerMap * > OuterMap
OUString maTableName
Table of nested HTML tables.
ScRangeList maHMergedCells
Items for the current cell.
std::map< ScHTMLTableId, ScHTMLTablePtr > ScHTMLTableStdMap
void CloseEntry(const HtmlImportInfo *)
void AdjustEnd(const HtmlImportInfo &rInfo)
Sets end point of the entry selection to the end of the import info object.
bool IsAtBeginningOfText(const HtmlImportInfo *)
ScHTMLTable * TableOn(const HtmlImportInfo &rInfo)
Starts a new table nested in this table (.
OUString GetImportFormatName(sal_uInt16 nFormat)
ScHTMLTable * TableOff(const HtmlImportInfo &rInfo)
Closes this table (tag).
NamePropsType m_GlobalProps
bool mbPreFormText
true = Table borders on.
const OUString & GetString() const
ScSizeVec maCumSizes[2]
Working entry, not yet inserted in a list.
void InsertText(const HtmlImportInfo &rInfo)
Inserts a text portion into current entry.
const_iterator find(const Value &x) const
void CloseTable(const HtmlImportInfo &rInfo)
Closes the current table, regardless on opening tag.
SCCOLROW GetDocSize(ScHTMLOrient eOrient, SCCOLROW nCellPos) const
Returns the resulting document row/column count of the specified HTML row/column. ...
void ProcToken(HtmlImportInfo *)
constexpr TypedWhichId< SvxFontItem > ATTR_FONT(100)
css::uno::Reference< css::frame::XModel > GetModel() const
virtual ~ScHTMLGlobalTable() override
ScHTMLEntryPtr mxCurrEntry
Current entry vector from map for faster access.
ScHTMLTableId & mrnUnusedId
The created unique table identifier.
SC_DLLPUBLIC void ApplyAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem &rAttr)
ScHTMLParser * mpParser
Resulting base address in a Calc document.
static void ParseStyle(std::u16string_view rStrm)
void NextRow(const HtmlImportInfo *)
void BodyOff(const HtmlImportInfo &rInfo)
Closes the body of the HTML document (