/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#pragma once
#include "RtfTable.h"
#include "RtfDocument.h"
int RtfTable::GetType( )
{
return TYPE_RTF_TABLE;
}
RtfTable::RtfTable()
{
}
RtfTable::RtfTable(const RtfTable& oTabl)
{
}
RtfTable& RtfTable::operator=(const RtfTable& oTabl)
{
return *this;
}
std::wstring RtfTable::RenderToOOX(RenderParameter oRenderParameter)
{
bool bRowsBidi = false;
for (size_t i = 0; i < m_aArray.size(); i++)
{
RtfTableRowPtr &rowPr = m_aArray[i];
if ((rowPr) && (rowPr->m_oProperty.m_nRightToLeft == 1))
{
bRowsBidi = true;
break;
}
}
if (bRowsBidi && m_oProperty.m_bBidi == PROP_DEF)
m_oProperty.m_bBidi = 1;
std::wstring sResult = L"";
sResult += m_oProperty.RenderToOOX(oRenderParameter);
sResult += L"";
for (size_t i = 0; i < (int)m_aTableGrid.size(); i++)
{
if (m_aTableGrid[i] > 0)
sResult += L"";
else
sResult += L"";
}
sResult += L"";
for (size_t i = 0; i < m_aArray.size(); i++)
{
sResult += m_aArray[i]->RenderToOOX(oRenderParameter);
}
sResult += L"";
return sResult;
}
std::wstring RtfTable::RenderToRtf(RenderParameter oRenderParameter)
{
std::wstring result;
result += L"\n";
for (size_t i = 0; i < m_aArray.size(); i++)
{
result += m_aArray[i]->RenderToRtf(oRenderParameter);
}
result += L"\n";
return result;
}
void RtfTable::CalculateGridProp()
{
//массив всевозможных cellx
std::vector aCellx; // упорядочен по возрастанию
int nLastCellx = 0;
int maxCellxFirstRow = 0;
//m_aArray - строки
for (size_t nCurRow = 0; nCurRow < m_aArray.size(); nCurRow++)
{
nLastCellx = 0;
RtfTableRowPtr oCurRow = m_aArray[nCurRow];
int nWidthBefore = 0;
int nWidthAfter = 0;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthStartInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthStartInvCellUnit)
nWidthBefore = oCurRow->m_oProperty.m_nWidthStartInvCell;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthEndInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthEndInvCellUnit)
nWidthAfter = oCurRow->m_oProperty.m_nWidthEndInvCell;
int nDelta = 0;// поправка на margin и indent и spacing
if (PROP_DEF != oCurRow->m_oProperty.m_nLeft) //для каждого row свой
nDelta = -oCurRow->m_oProperty.m_nLeft;
else
{
if (PROP_DEF != m_oProperty.nTableIndent && 3 == m_oProperty.eTableIndentUnit)
nDelta -= m_oProperty.nTableIndent;
if (PROP_DEF != m_oProperty.m_nDefCellMarLeft && 3 == m_oProperty.m_eDefCellMarLeftUnit)
nDelta += m_oProperty.m_nDefCellMarLeft;
if (PROP_DEF != m_oProperty.m_nDefCellSpLeft && 3 == m_oProperty.m_eDefCellSpLeftUnit)
nDelta += 2 * m_oProperty.m_nDefCellSpLeft;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthStartInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthStartInvCellUnit)
nDelta -= oCurRow->m_oProperty.m_nWidthStartInvCell;
}
//добавляем widthBefore
if (0 != nWidthBefore)
{
AddToArray(aCellx, nWidthBefore);
nLastCellx = nWidthBefore + nDelta;
}
int nCellx = 0;
for (int nCurCell = 0; nCurCell < oCurRow->GetCount(); nCurCell++)
{
RtfTableCellPtr oCurCell = oCurRow->operator [](nCurCell);
int nCellx = nWidthBefore + nDelta + oCurCell->m_oProperty.m_nCellx;
if (nCellx > maxCellxFirstRow && maxCellxFirstRow > 0)
nCellx = maxCellxFirstRow;
AddToArray(aCellx, nCellx);
//те свойства, что остались в row не трогаем - они не важны для конвертации в oox
nLastCellx = nCellx;
}
//добавляем widthAfter
if (0 != nWidthAfter)
AddToArray(aCellx, nLastCellx + nWidthAfter);
if (maxCellxFirstRow == 0) maxCellxFirstRow = nLastCellx + nWidthAfter;
}
//вычисляем Span
for (size_t i = 0; i < m_aArray.size(); i++)
{
RtfTableRowPtr oCurRow = m_aArray[i];
//индекс последнего минимального элемента
int nLastIndex = 0;
int nLastCellx = 0;
int nWidthBefore = 0;
int nWidthAfter = 0;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthStartInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthStartInvCellUnit)
nWidthBefore = oCurRow->m_oProperty.m_nWidthStartInvCell;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthEndInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthEndInvCellUnit)
nWidthAfter = oCurRow->m_oProperty.m_nWidthEndInvCell;
int nDelta = 0;// поправка на margin и indent и spacing и border
if (PROP_DEF != oCurRow->m_oProperty.m_nLeft) //для каждого row свой
nDelta = -oCurRow->m_oProperty.m_nLeft;
else
{
if (PROP_DEF != m_oProperty.nTableIndent && 3 == m_oProperty.eTableIndentUnit)
nDelta -= m_oProperty.nTableIndent;
if (PROP_DEF != m_oProperty.m_nDefCellMarLeft && 3 == m_oProperty.m_eDefCellMarLeftUnit)
nDelta += m_oProperty.m_nDefCellMarLeft;
if (PROP_DEF != m_oProperty.m_nDefCellSpLeft && 3 == m_oProperty.m_eDefCellSpLeftUnit)
nDelta += 2 * m_oProperty.m_nDefCellSpLeft;
if (PROP_DEF != oCurRow->m_oProperty.m_nWidthStartInvCell && mu_Twips == oCurRow->m_oProperty.m_eWidthStartInvCellUnit)
nDelta -= oCurRow->m_oProperty.m_nWidthStartInvCell;
}
//добавляем gridBefore
if (0 != nWidthBefore)
{
for (int k = nLastIndex; k < (int)aCellx.size(); k++)
{
if (aCellx[k] == nWidthBefore)
{
oCurRow->m_oProperty.m_nGridBefore = k - nLastIndex + 1;
nLastIndex = k + 1;
break;
}
}
}
for (int j = 0; j < oCurRow->GetCount(); j++)
{
RtfTableCellPtr oCurCell = oCurRow->operator [](j);
int nCellx = nWidthBefore + nDelta + oCurCell->m_oProperty.m_nCellx;
for (int k = nLastIndex; k < (int)aCellx.size(); k++)
{
if (aCellx[k] == nCellx)
{
oCurCell->m_oProperty.m_nSpan = k - nLastIndex + 1;
int nWidth;
if (0 == nLastIndex)
nWidth = aCellx[k];
else
nWidth = aCellx[k] - aCellx[nLastIndex - 1];
oCurCell->m_oProperty.m_nWidth = nWidth;
oCurCell->m_oProperty.m_eWidthUnit = mu_Twips;
nLastIndex = k + 1;
break;
}
}
nLastCellx = nCellx;
}
//добавляем gridAfter
if (0 != nWidthAfter)
for (int k = nLastIndex; k < (int)aCellx.size(); k++)
{
if (aCellx[k] == nLastCellx + nWidthAfter)
{
m_aArray[i]->m_oProperty.m_nGridAfter = k - nLastIndex + 1;
nLastIndex = k + 1;
break;
}
}
}
//вычисляем gridTable
for (size_t i = 0; i < (int)aCellx.size(); i++)
{
if (i == 0)
m_aTableGrid.push_back(aCellx[0]);
else
m_aTableGrid.push_back(aCellx[i] - aCellx[i - 1]);
}
}
void RtfTable::CalculateCellx(RtfDocument& oDocument)//todo учитывать margin indent
{
if (m_aTableGrid.size() == 0 && m_aArray.size() > 0)
{
//если отсутствует делаем пропорционально
m_oProperty.m_nAutoFit = 1;
if ((PROP_DEF == m_oProperty.m_nWidth || m_oProperty.m_nWidth <= 0))
{
//если не задана ширина таблицы, считаем ее 100%
// Width = PageWidth - MarginLeft - MarginRight - Gutter
int nGutter = oDocument.m_oProperty.m_nGutterWidth;
if (1 == oDocument.m_oProperty.m_bGutterAtTop)//не учитываем если это Top gutter
nGutter = 0;
m_oProperty.m_nWidth = oDocument.m_oProperty.m_nPaperWidth - oDocument.m_oProperty.m_nMarginLeft - oDocument.m_oProperty.m_nMarginRight - nGutter;
m_oProperty.m_eWidthUnit = mu_Twips;
}
for (size_t i = 0; i < m_aArray.size(); i++)
{
RtfTableRowPtr oCurRow = m_aArray[i];
int nCellCount = oCurRow->GetCount();
if (oCurRow->m_oProperty.GetCount() < nCellCount)
nCellCount = oCurRow->m_oProperty.GetCount();
if (nCellCount > 0)
{
int nCellWidth = m_oProperty.m_nWidth / nCellCount;
int nCurCellX = 0;
for (int j = 0; j < nCellCount; j++)
{
nCurCellX += nCellWidth;
RtfTableCellPtr oCellPtr = (*oCurRow)[j];
oCellPtr->m_oProperty.m_nCellx = nCurCellX;
oCurRow->m_oProperty[j].m_nCellx = nCurCellX;
}
}
}
}
else
{
for (size_t i = 0; i < m_aArray.size(); i++)
{
RtfTableRowPtr oCurRow = m_aArray[i];
int nLeft = 0;
if (PROP_DEF != m_oProperty.nTableIndent && 3 == m_oProperty.eTableIndentUnit)
nLeft += m_oProperty.nTableIndent;
if (PROP_DEF != m_oProperty.m_nDefCellMarLeft && 3 == m_oProperty.m_eDefCellMarLeftUnit)
nLeft -= m_oProperty.m_nDefCellMarLeft;
if (PROP_DEF != m_oProperty.m_nDefCellSpLeft && 3 == m_oProperty.m_eDefCellSpLeftUnit)
nLeft += 2 * m_oProperty.m_nDefCellSpLeft;
int nDelta = nLeft;//в left учитывается GrindBefore
//if( PROP_DEF != oCurRow->m_oProperty.m_nGridBefore )
//{
// int nGridBefore = oCurRow->m_oProperty.m_nGridBefore;
// if( (int)m_aTableGrid.size() > nGridBefore - 1)
// {
// int nWidthBefore = 0;
// for (int k = 0; k < nGridBefore ; k++ )
// nWidthBefore += m_aTableGrid[k];
// oCurRow->m_oProperty.m_nWidthStartInvCell = nWidthBefore;
// oCurRow->m_oProperty.m_eMUStartInvCell = mu_Twips;
// nLeft += nWidthBefore;
// }
//}
//if( PROP_DEF != oCurRow->m_oProperty.m_nGridAfter )
//{
// int nGridAfter = oCurRow->m_oProperty.m_nGridAfter;
// if( (int)m_aTableGrid.size() > nGridAfter - 1)
// {
// int nWidthAfter = 0;
//
// for( int k = (int)m_aTableGrid.size() - 1; k >= (int)m_aTableGrid.size() - 1 - nGridAfter; k-- )
// nWidthAfter += m_aTableGrid[k];
// oCurRow->m_oProperty.m_nWidthEndInvCell = nWidthAfter;
// oCurRow->m_oProperty.m_eMUEndInvCell = mu_Twips;
// }
//}
if (0 != nLeft)
oCurRow->m_oProperty.m_nLeft = nLeft;
int nCurWidth = 0;
int nCurIndex = 0;
for (int j = 0; j < oCurRow->m_oProperty.GetCount(); j++)
{
RtfTableCellPtr oCurCell = oCurRow->operator [](j);
int nSpan = 1;
if (PROP_DEF != oCurCell->m_oProperty.m_nSpan)
nSpan = oCurCell->m_oProperty.m_nSpan;
if (j == 0 && PROP_DEF != oCurRow->m_oProperty.m_nGridBefore)
nCurIndex += oCurRow->m_oProperty.m_nGridBefore;
//if( j == oCurRow->m_oProperty.size() - 1 && PROP_DEF != oCurRow->m_oProperty.m_nGridAfter )
// nSpan += oCurRow->m_oProperty.m_nGridAfter;
for (int k = nCurIndex; k < nCurIndex + nSpan && k < (int)m_aTableGrid.size(); k++)
nCurWidth += m_aTableGrid[k];
nCurIndex = nCurIndex + nSpan;
//if( j == 0 )
oCurRow->m_oProperty[j].m_nCellx = nLeft + nCurWidth;
//else
// oCurRow->m_oProperty[j].m_nCellx = nCurWidth;
}
}
}
}
void RtfTable::AddToArray(std::vector& aArray, int nValue)//todo можно применить то что он упорядоченный
{
bool bNeedAdd = true;
for (size_t k = 0; k < aArray.size(); k++)
{
if (std::abs(aArray[k] - nValue) < 1)
{
bNeedAdd = false;
break;
}
else if (aArray[k] > nValue)
{
bNeedAdd = false;
aArray.insert(aArray.begin() + k, nValue);
break;
}
}
if (true == bNeedAdd)
{
aArray.push_back(nValue);
}
}