Commit 64213746 authored by ElenaSubbotina's avatar ElenaSubbotina

XlsFormat - query tables

parent 09941c67
......@@ -70,11 +70,19 @@ void DBQueryExt::readFields(CFRecord& record)
case 4: grbitDbt.reset(new ConnGrbitDbtWeb); break;
case 5: grbitDbt.reset(new ConnGrbitDbtOledb); break;
case 7: grbitDbt.reset(new ConnGrbitDbtAdo); break;
default:
record.skipNunBytes(2); break; //unused
}
record >> flags1 >> bVerDbqueryEdit >> bVerDbqueryRefreshed >> bVerDbqueryRefreshableMin;
if (grbitDbt)
{
grbitDbt->load(record);
}
record >> flags2 >> bVerDbqueryEdit >> bVerDbqueryRefreshed >> bVerDbqueryRefreshableMin;
fTxtWiz = GETBIT(flags1, 0);
fTableNames = GETBIT(flags1, 1);
fTxtWiz = GETBIT(flags2, 0);
fTableNames = GETBIT(flags2, 1);
record.skipNunBytes(3); //unused
......
......@@ -92,17 +92,10 @@ void DConn::readFields(CFRecord& record)
case 5: grbitDbt.reset(new ConnGrbitDbtOledb); break;
case 7: grbitDbt.reset(new ConnGrbitDbtAdo); break;
default:
break;
record.skipNunBytes(2); break; //unused
}
if (grbitDbt)
{
record >> *grbitDbt;
}
else
{
unsigned short unused;
record >> unused;
}
grbitDbt->load(record);
record >> bVerDbqueryEdit >> bVerDbqueryRefreshed >> bVerDbqueryRefreshableMin >> wRefreshInterval >> wHtmlFmt >> rcc >> credMethod >> reserved3;
......@@ -138,7 +131,9 @@ void DConn::readFields(CFRecord& record)
}
if (connection)
record >> *connection;
{
connection->load(record);
}
if (dbt == 1 || dbt == 5)
{
......
......@@ -74,6 +74,8 @@ void Qsi::readFields(CFRecord& record)
fibitAtrBdr = GETBIT(flags2, 3);
fibitAtrPat = GETBIT(flags2, 4);
fibitAtrProt = GETBIT(flags2, 5);
record.skipNunBytes(2); //unused
}
} // namespace XLS
......
......@@ -58,7 +58,7 @@ void TxtQry::readFields(CFRecord& record)
unsigned short reserved, flags1, unused1;
unsigned char unused2, flags2;
record >> rt >> flags1 >> unused1 >> rowStartAt >> flags2 >> chCustom >> unused2 >> itwf >> chDecimal >> chThousSep;
record >> rt >> reserved >> flags1 >> unused1 >> rowStartAt >> flags2 >> chCustom >> unused2 >> itwf >> chDecimal >> chThousSep;
fFile = GETBIT(flags1, 0);
fDelimited = GETBIT(flags1, 1);
......
......@@ -56,7 +56,7 @@ void DConnParamBindingValType::load(CFRecord& record)
}
if (rgbBindingValue)
{
record >> *rgbBindingValue;
rgbBindingValue->load(record);
}
}
//-----------------------------------------------------------------------------------
......
......@@ -75,7 +75,6 @@ void HyperlinkMoniker::load(XLS::CFRecord& record)
{
data.reset(new URLMoniker);
}
else if (FileMoniker_CLSID == clsid)
{
data.reset(new FileMoniker);
......@@ -94,10 +93,13 @@ void HyperlinkMoniker::load(XLS::CFRecord& record)
}
else
{
// EXCEPT::RT::WrongBiffRecord("Unsupported type of HyperlinkMoniker.", record.getTypeString());
//throw;
}
record >> *data;
if (data)
{
data->load(record);
}
}
......
......@@ -282,8 +282,8 @@ void XLUnicodeRichExtendedString::loadSymbols(CFRecord& record, const size_t cch
char* out_str_char = (char*) out_str;
for (int i = 0; i < inp_str_size; i++)
{
out_str_char[2*i+0] = inp_str.c_str()[i];
out_str_char[2*i+1] = 0;
out_str_char[2*i + 0] = inp_str.c_str()[i];
out_str_char[2*i + 1] = 0;
}
out_str[inp_str_size] = 0;
......
......@@ -31,34 +31,34 @@
*/
#include "CHARTFOMATS.h"
#include <Logic/Biff_records/Chart.h>
#include <Logic/Biff_records/Begin.h>
#include <Logic/Biff_records/Scl.h>
#include <Logic/Biff_records/PlotGrowth.h>
#include <Logic/Biff_records/ShtProps.h>
#include <Logic/Biff_records/AxesUsed.h>
#include <Logic/Biff_records/CrtLayout12A.h>
#include <Logic/Biff_records/DataLabExt.h>
#include <Logic/Biff_records/DataLabExtContents.h>
#include <Logic/Biff_records/StartObject.h>
#include <Logic/Biff_records/EndObject.h>
#include <Logic/Biff_records/End.h>
#include <Logic/Biff_records/ObjectLink.h>
#include <Logic/Biff_records/FrtWrapper.h>
#include <Logic/Biff_records/TextPropsStream.h>
#include <Logic/Biff_unions/FONTLIST.h>
#include <Logic/Biff_unions/FRAME.h>
#include <Logic/Biff_unions/SERIESFORMAT.h>
#include <Logic/Biff_unions/SS.h>
#include <Logic/Biff_unions/DFTTEXT.h>
#include <Logic/Biff_unions/AXISPARENT.h>
#include <Logic/Biff_unions/DAT.h>
#include <Logic/Biff_unions/ATTACHEDLABEL.h>
#include <Logic/Biff_unions/CRTMLFRT.h>
#include <Logic/Biff_unions/ATTACHEDLABEL.h>
#include <Logic/Biff_unions/TEXTPROPS.h>
#include <Logic/Biff_unions/SHAPEPROPS.h>
#include "FONTLIST.h"
#include "FRAME.h"
#include "SERIESFORMAT.h"
#include "SS.h"
#include "DFTTEXT.h"
#include "AXISPARENT.h"
#include "DAT.h"
#include "ATTACHEDLABEL.h"
#include "CRTMLFRT.h"
#include "ATTACHEDLABEL.h"
#include "TEXTPROPS.h"
#include "SHAPEPROPS.h"
#include "../Biff_records/Chart.h"
#include "../Biff_records/Begin.h"
#include "../Biff_records/Scl.h"
#include "../Biff_records/PlotGrowth.h"
#include "../Biff_records/ShtProps.h"
#include "../Biff_records/AxesUsed.h"
#include "../Biff_records/CrtLayout12A.h"
#include "../Biff_records/DataLabExt.h"
#include "../Biff_records/DataLabExtContents.h"
#include "../Biff_records/StartObject.h"
#include "../Biff_records/EndObject.h"
#include "../Biff_records/End.h"
#include "../Biff_records/ObjectLink.h"
#include "../Biff_records/FrtWrapper.h"
#include "../Biff_records/TextPropsStream.h"
namespace XLS
{
......
......@@ -35,9 +35,6 @@
namespace XLS
{
// Logical representation of CHARTFOMATS union of records
class CHARTFORMATS: public CompositeObject
{
BASE_OBJECT_DEFINE_CLASS_NAME(CHARTFORMATS)
......
......@@ -31,8 +31,8 @@
*/
#include "DBQUERY.h"
#include <Logic/Biff_records/DbOrParamQry.h>
#include <Logic/Biff_records/SXString.h>
#include "../Biff_records/DbOrParamQry.h"
#include "../Biff_records/SXString.h"
namespace XLS
{
......@@ -184,7 +184,8 @@ const bool DBQUERY::loadContent(BinProcessor& proc)
int DBQUERY::serialize(std::wostream & strm)
{
connectionId = ++global_info->connectionId;
int connectionId = serialize_connection();
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"cacheSource")
......@@ -193,16 +194,17 @@ int DBQUERY::serialize(std::wostream & strm)
CP_XML_ATTR(L"connectionId", connectionId); //connectionId in connections(root)
}
}
serialize_connection(global_info->connections_stream);
return 0;
}
int DBQUERY::serialize_connection(std::wostream & strm)
int DBQUERY::serialize_connection()
{
DbOrParamQry* queryOrParam = dynamic_cast<DbOrParamQry*>(m_DbQry.get());
if (!queryOrParam) return 0;
if (!queryOrParam) return -1;
CP_XML_WRITER(strm)
int connectionId = ++global_info->connectionId;
CP_XML_WRITER(global_info->connections_stream)
{
CP_XML_NODE(L"connection")
{
......@@ -212,7 +214,7 @@ int DBQUERY::serialize_connection(std::wostream & strm)
CP_XML_ATTR(L"type", queryOrParam->query.dbt);
//switch(queryOrParam->query.dbt)
//{
// case 0x1: CP_XML_ATTR(L"type", 1); break;
// case 0x1:
// case 0x2:
// case 0x3:
// case 0x4:
......@@ -243,7 +245,7 @@ int DBQUERY::serialize_connection(std::wostream & strm)
}
}
}
return 0;
return connectionId;
}
......
......@@ -53,7 +53,7 @@ public:
virtual const bool loadContent(BinProcessor& proc);
int serialize(std::wostream & stream);
int serialize_connection(std::wostream & strm);
int serialize_connection();
BaseObjectPtr m_DbQry;
......@@ -63,7 +63,6 @@ public:
std::vector<std::wstring> m_arSXString;
//------------------------------------------------------
GlobalWorkbookInfoPtr global_info;
int connectionId;
};
} // namespace XLS
......
......@@ -40,17 +40,14 @@
namespace XLS
{
DBQUERYEXT::DBQUERYEXT()
{
}
DBQUERYEXT::~DBQUERYEXT()
{
}
class Parenthesis_DBQUERYEXT_1: public ABNFParenthesis
{
BASE_OBJECT_DEFINE_CLASS_NAME(Parenthesis_DBQUERYEXT_1)
......
......@@ -31,50 +31,200 @@
*/
#include "QUERYTABLE.h"
#include <Logic/Biff_records/Qsi.h>
#include <Logic/Biff_records/QsiSXTag.h>
#include <Logic/Biff_unions/DBQUERY.h>
#include <Logic/Biff_unions/DBQUERYEXT.h>
#include <Logic/Biff_unions/SXADDLQSI.h>
#include <Logic/Biff_unions/QSIR.h>
#include <Logic/Biff_unions/SORTDATA12.h>
#include "DBQUERY.h"
#include "DBQUERYEXT.h"
#include "SXADDLQSI.h"
#include "QSIR.h"
#include "SORTDATA12.h"
#include "../Biff_records/Qsi.h"
#include "../Biff_records/QsiSXTag.h"
#include "../Biff_records/DbOrParamQry.h"
#include "../Biff_records/SXString.h"
#include "../Biff_records/TxtQry.h"
namespace XLS
{
QUERYTABLE::QUERYTABLE()
{
}
QUERYTABLE::~QUERYTABLE()
{
}
BaseObjectPtr QUERYTABLE::clone()
{
return BaseObjectPtr(new QUERYTABLE(*this));
}
// QUERYTABLE = Qsi DBQUERY QsiSXTag DBQUERYEXT [SXADDLQSI] [QSIR] [SORTDATA12]
const bool QUERYTABLE::loadContent(BinProcessor& proc)
{
if(!proc.mandatory<Qsi>())
if(!proc.mandatory<Qsi>()) return false;
global_info = proc.getGlobalWorkbookInfo();
m_Qsi = elements_.back(); elements_.pop_back();
if (proc.mandatory<DBQUERY>())
{
m_DBQUERY = elements_.back(); elements_.pop_back();
}
if (proc.mandatory<QsiSXTag>())
{
return false;
m_QsiSXTag = elements_.back(); elements_.pop_back();
}
if (proc.mandatory<DBQUERYEXT>())
{
m_DBQUERYEXT = elements_.back(); elements_.pop_back();
}
if (proc.optional<SXADDLQSI>())
{
m_SXADDLQSI = elements_.back(); elements_.pop_back();
}
if (proc.optional<QSIR>())
{
m_QSIR = elements_.back(); elements_.pop_back();
}
if (proc.optional<SORTDATA12>())
{
m_SORTDATA12 = elements_.back(); elements_.pop_back();
}
proc.mandatory<DBQUERY>();
proc.mandatory<QsiSXTag>();
proc.mandatory<DBQUERYEXT>();
proc.optional<SXADDLQSI>();
proc.optional<QSIR>();
proc.optional<SORTDATA12>();
return true;
}
int QUERYTABLE::serialize(std::wostream & strm)
{
Qsi *info = dynamic_cast<Qsi*>(m_Qsi.get());
if (!info) return 0;
int connectionId = serialize_connection();
if (connectionId < 1) return 0;
std::wstring name = info->rgchName.value();
if (name.empty())
name = L"Connection" + std::to_wstring(connectionId);
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"queryTable")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
CP_XML_ATTR(L"connectionId", connectionId);
CP_XML_ATTR(L"name", name);
if (info->fAutoFormat)
{
CP_XML_ATTR(L"autoFormatId", info->itblAutoFmt);
}
CP_XML_ATTR(L"applyNumberFormats", info->fibitAtrNum);//0"
CP_XML_ATTR(L"applyBorderFormats", info->fibitAtrBdr);//0"
CP_XML_ATTR(L"applyFontFormats", info->fibitAtrFnt);//1"
CP_XML_ATTR(L"applyPatternFormats", info->fibitAtrPat);//1"
CP_XML_ATTR(L"applyAlignmentFormats", info->fibitAtrAlc);//0"
//CP_XML_ATTR(L"applyWidthHeightFormats", info->);//0"/>
}
}
return 0;
}
int QUERYTABLE::serialize_connection()
{
Qsi *info = dynamic_cast<Qsi*>(m_Qsi.get());
if (!info) return -1;
DBQUERY *query = dynamic_cast<DBQUERY*>(m_DBQUERY.get());
if (!query) return -1;
DbOrParamQry* queryOrParam = dynamic_cast<DbOrParamQry*>(query->m_DbQry.get());
if (!queryOrParam) return -1;
DBQUERYEXT *query_ext = dynamic_cast<DBQUERYEXT*>(m_DBQUERYEXT.get());
int connectionId = ++global_info->connectionId;
std::wstring name = info->rgchName.value();
if (name.empty())
name = L"Connection" + std::to_wstring(connectionId);
CP_XML_WRITER(global_info->connections_stream)
{
CP_XML_NODE(L"connection")
{
CP_XML_ATTR(L"id", connectionId);
CP_XML_ATTR(L"name", name);
CP_XML_ATTR(L"type", queryOrParam->query.dbt);
//background="1"
//saveData="1"
if (queryOrParam->query.fSavePwd) CP_XML_ATTR(L"savePassword", 1);
CP_XML_ATTR(L"refreshedVersion", 1);
if (queryOrParam->query.dbt == 6)
{
TxtQry *query_txt = dynamic_cast<TxtQry*>(query_ext->m_TxtQry.get());
if (query_txt)
{
CP_XML_NODE(L"textPr")
{
CP_XML_ATTR(L"sourceFile", query_txt->rgchFile.value());
//delimited="0"
CP_XML_NODE(L"textFields")
{
for (size_t i = 0; i < query_txt->rgtxtwf.size(); i++)
{
CP_XML_NODE(L"textField")
{
switch(query_txt->rgtxtwf[i].fieldType)
{
case 0: CP_XML_ATTR(L"type", L"general"); break;
case 1: CP_XML_ATTR(L"type", L"text"); break;
case 2: CP_XML_ATTR(L"type", L"MDY"); break;
case 3: CP_XML_ATTR(L"type", L"DMY"); break;
case 4: CP_XML_ATTR(L"type", L"YMD"); break;
case 5: CP_XML_ATTR(L"type", L"MYD"); break;
case 6: CP_XML_ATTR(L"type", L"DYM"); break;
case 7: CP_XML_ATTR(L"type", L"YDM"); break;
case 8: CP_XML_ATTR(L"type", L"skip"); break;
case 9: CP_XML_ATTR(L"type", L"EMD"); break;
}
CP_XML_ATTR(L"position", query_txt->rgtxtwf[i].fieldStart);
}
}
}
}
}
}
else
{
int index = 0;
CP_XML_NODE(L"dbPr")
{
std::wstring command, connection;
for (index = 0; index < queryOrParam->query.cstQuery; index++)
{
command += query->m_arSXString[index];
}
for (; index < queryOrParam->query.cstQuery + queryOrParam->query.cstOdbcConn; index++)
{
connection += query->m_arSXString[index];
}
CP_XML_ATTR(L"connection", connection);
CP_XML_ATTR(L"command", command);
}
}
}
}
return connectionId;
}
} // namespace XLS
......@@ -36,8 +36,6 @@
namespace XLS
{
// Logical representation of QUERYTABLE union of records
class QUERYTABLE: public CompositeObject
{
BASE_OBJECT_DEFINE_CLASS_NAME(QUERYTABLE)
......@@ -48,8 +46,22 @@ public:
BaseObjectPtr clone();
virtual const bool loadContent(BinProcessor& proc);
int serialize(std::wostream & strm);
int serialize_connection();
static const ElementType type = typeQUERYTABLE;
BaseObjectPtr m_Qsi;
BaseObjectPtr m_DBQUERY;
BaseObjectPtr m_QsiSXTag;
BaseObjectPtr m_DBQUERYEXT;
BaseObjectPtr m_SXADDLQSI;
BaseObjectPtr m_QSIR;
BaseObjectPtr m_SORTDATA12;
static const ElementType type = typeQUERYTABLE;
//------------------------------------------------------
GlobalWorkbookInfoPtr global_info;
};
} // namespace XLS
......
......@@ -953,7 +953,7 @@ namespace NSCustomShapesConvert
LONG lValue;
bool bRes = true;
for (int nIndex = 0; nIndex < oArray.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oArray.size(); ++nIndex)
{
std::wstring str = oArray[nIndex];
lValue = NSCustomShapesConvert::GetValue(oArray[nIndex], eParamType, bRes);
......
......@@ -263,7 +263,8 @@ namespace NSCustomShapesConvert
{
m_eRuler = oSrc.m_eRuler;
m_arPoints.clear();
for (int nIndex = 0; nIndex < oSrc.m_arPoints.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oSrc.m_arPoints.size(); ++nIndex)
{
m_arPoints.push_back(oSrc.m_arPoints[nIndex]);
}
......@@ -547,7 +548,7 @@ namespace NSCustomShapesConvert
LONG lValue;
bool bRes = true;
for (int nIndex = 0; nIndex < oArray.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oArray.size(); ++nIndex)
{
lValue = GetValue(oArray[nIndex], eParamType, bRes);
if (bRes)
......@@ -595,7 +596,8 @@ namespace NSCustomShapesConvert
height = oSrc.height;
m_arSlices.clear();
for (int nIndex = 0; nIndex < oSrc.m_arSlices.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oSrc.m_arSlices.size(); ++nIndex)
{
m_arSlices.push_back(oSrc.m_arSlices[nIndex]);
}
......@@ -615,7 +617,7 @@ namespace NSCustomShapesConvert
NSStringUtils::ParseString(_T("e"), strPath, oArray);
for (int nIndex = 0; nIndex < oArray.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oArray.size(); ++nIndex)
{
CPartPath oPath;
m_arParts.push_back(oPath);
......@@ -626,7 +628,8 @@ namespace NSCustomShapesConvert
CPath& operator =(const CPath& oSrc)
{
m_arParts.clear();
for (int nIndex = 0; nIndex < oSrc.m_arParts.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < oSrc.m_arParts.size(); ++nIndex)
{
m_arParts.push_back(oSrc.m_arParts[nIndex]);
}
......@@ -635,7 +638,7 @@ namespace NSCustomShapesConvert
void SetCoordsize(LONG lWidth, LONG lHeight)
{
for (int nIndex = 0; nIndex < m_arParts.size(); ++nIndex)
for (size_t nIndex = 0; nIndex < m_arParts.size(); ++nIndex)
{
m_arParts[nIndex].width = lWidth;
m_arParts[nIndex].height = lHeight;
......
......@@ -61,6 +61,7 @@
#include "../XlsFormat/Logic/Biff_unions/PIVOTCACHE.h"
#include "../XlsFormat/Logic/Biff_unions/PIVOTCACHEDEFINITION.h"
#include "../XlsFormat/Logic/Biff_unions/SUPBOOK.h"
#include "../XlsFormat/Logic/Biff_unions/QUERYTABLE.h"
#include "../XlsFormat/Logic/Biff_records/BkHim.h"
#include "../XlsFormat/Logic/Biff_records/HLink.h"
......@@ -343,27 +344,27 @@ void XlsConverter::convert(XLS::BaseObject *xls_unknown)
{
case XLS::typeHLINK:
{
XLS::HLINK * hlink = dynamic_cast<XLS::HLINK *>(xls_unknown);
XLS::HLINK * hlink = dynamic_cast<XLS::HLINK*>(xls_unknown);
convert(hlink);
}break;
case XLS::typeLBL:
{
XLS::LBL * lbl = dynamic_cast<XLS::LBL *>(xls_unknown);
XLS::LBL * lbl = dynamic_cast<XLS::LBL*>(xls_unknown);
convert(lbl);
}break;
case XLS::typeOBJECTS:
{
XLS::OBJECTS * obj = dynamic_cast<XLS::OBJECTS *>(xls_unknown);
XLS::OBJECTS * obj = dynamic_cast<XLS::OBJECTS*>(xls_unknown);
convert(obj);
}break;
case XLS::typeTxO:
{
XLS::TxO * txo = dynamic_cast<XLS::TxO *>(xls_unknown);
XLS::TxO * txo = dynamic_cast<XLS::TxO*>(xls_unknown);
convert(txo);
}break;
case XLS::typeObj:
{
XLS::Obj * obj = dynamic_cast<XLS::Obj *>(xls_unknown);
XLS::Obj * obj = dynamic_cast<XLS::Obj*>(xls_unknown);
convert(obj);
}break;
case XLS::typeAnyObject:
......@@ -417,13 +418,15 @@ void XlsConverter::convert(XLS::WorkbookStreamObject* woorkbook)
{
convert(it->get());
}
xlsx_context->add_connections(xls_global_info->connections_stream.str());
}
void XlsConverter::convert (XLS::WorksheetSubstream* sheet)
{
if (sheet == NULL) return;
if (sheet->m_arWINDOW.size() > 0)
if (!sheet->m_arWINDOW.empty())
{
sheet->m_arWINDOW[0]->serialize(xlsx_context->current_sheet().sheetViews());
}
......@@ -488,6 +491,10 @@ void XlsConverter::convert (XLS::WorksheetSubstream* sheet)
sheet->m_DVAL->serialize(xlsx_context->current_sheet().dataValidations());
}
for (size_t i = 0; i < sheet->m_arQUERYTABLE.size(); i++)
{
convert(dynamic_cast<XLS::QUERYTABLE*>(sheet->m_arQUERYTABLE[i].get()));
}
for (size_t i = 0; i < sheet->m_arPIVOTVIEW.size(); i++)
{
convert((XLS::PIVOTVIEW*)sheet->m_arPIVOTVIEW[i].get());
......@@ -587,8 +594,6 @@ void XlsConverter::convert(XLS::GlobalsSubstream* global)
{
convert((XLS::PIVOTCACHEDEFINITION*)global->m_arPIVOTCACHEDEFINITION[i].get());
}
xlsx_context->get_pivots_context().add_connections(xls_global_info->connections_stream.str());
}
typedef boost::unordered_map<XLS::FillInfo, int> mapFillInfo;
......@@ -1349,7 +1354,7 @@ void XlsConverter::convert_fill_style(std::vector<ODRAW::OfficeArtFOPTEPtr> & pr
}break;
case NSOfficeDrawing::fillShadeColors:
{
ODRAW::fillShadeColors *shadeColors = (ODRAW::fillShadeColors *)(props[i].get());
ODRAW::fillShadeColors *shadeColors = dynamic_cast<ODRAW::fillShadeColors*>(props[i].get());
for (size_t i = 0 ; (shadeColors) && (i < shadeColors->fillShadeColors_complex.data.size()); i++)
{
......@@ -2022,7 +2027,7 @@ void XlsConverter::convert(XLS::Obj * obj)
}
}
void XlsConverter::convert_chart_sheet(XLS::ChartSheetSubstream * chart)
void XlsConverter::convert_chart_sheet(XLS::ChartSheetSubstream* chart)
{
if (chart == NULL) return;
......@@ -2034,7 +2039,7 @@ void XlsConverter::convert_chart_sheet(XLS::ChartSheetSubstream * chart)
xlsx_context->get_drawing_context().end_drawing();
}
}
void XlsConverter::convert(XLS::ChartSheetSubstream * chart)
void XlsConverter::convert(XLS::ChartSheetSubstream* chart)
{
if (chart == NULL) return;
......@@ -2042,7 +2047,7 @@ void XlsConverter::convert(XLS::ChartSheetSubstream * chart)
//convert(chart->m_OBJECTSCHART.get());непонятные какие то текстбоксы - пустые и бз привязок
}
void XlsConverter::convert(XLS::PIVOTVIEW * pivot_view)
void XlsConverter::convert(XLS::PIVOTVIEW* pivot_view)
{
if (pivot_view == NULL) return;
......@@ -2060,7 +2065,7 @@ void XlsConverter::convert(XLS::PIVOTVIEW * pivot_view)
}
}
void XlsConverter::convert(XLS::PIVOTCACHEDEFINITION * pivot_cached)
void XlsConverter::convert(XLS::PIVOTCACHEDEFINITION* pivot_cached)
{
if (pivot_cached == NULL) return;
......@@ -2077,7 +2082,7 @@ void XlsConverter::convert(XLS::PIVOTCACHEDEFINITION * pivot_cached)
}
}
void XlsConverter::convert(XLS::SUPBOOK * external)
void XlsConverter::convert(XLS::SUPBOOK* external)
{
if (external == NULL) return;
if (external->IsExternal() == false) return;
......@@ -2092,5 +2097,13 @@ void XlsConverter::convert(XLS::SUPBOOK * external)
}
xlsx_context->end_external();
}
void XlsConverter::convert(XLS::QUERYTABLE* query_table)
{
if (query_table == NULL) return;
std::wstringstream strm;
query_table->serialize(strm);
xlsx_context->add_query_table(strm.str());
}
......@@ -76,6 +76,7 @@ namespace XLS
class PIVOTVIEW;
class PIVOTCACHEDEFINITION;
class SUPBOOK;
class QUERYTABLE;
class Note;
class TxO;
......@@ -128,6 +129,7 @@ public:
void convert(XLS::PIVOTVIEW * pivot_view);
void convert(XLS::PIVOTCACHEDEFINITION * pivot_cached);
void convert(XLS::SUPBOOK * external);
void convert(XLS::QUERYTABLE * query_table);
void convert(ODRAW::OfficeArtRecord * art);
void convert(ODRAW::OfficeArtBStoreContainer* art_bstore, int start_id = 0);
......
......@@ -124,26 +124,20 @@ void content_types_file::set_media(external_items & _Mediaitems)
/////////////////////////////////////////////////////////////////////////
simple_element::simple_element(const std::wstring & FileName, const std::wstring & Content) : file_name_(FileName)
simple_element::simple_element(const std::wstring & fileName, const std::wstring & content) : filename_(fileName), content_(content)
{
//utf8::utf16to8(Content.begin(), Content.end(), std::back_inserter(content_utf8_));
//падает на спец символах
content = Content;
}
void simple_element::write(const std::wstring & RootPath)
{
std::wstring name_ = RootPath + FILE_SEPARATOR_STR + file_name_;
std::wstring name_ = RootPath + FILE_SEPARATOR_STR + filename_;
NSFile::CFileBinary file;
if ( file.CreateFileW(name_) == true)
{
std::string root = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
file.WriteFile((BYTE*)root.c_str(), root.length());
//file.WriteFile((BYTE*)content_utf8_.c_str(), content_utf8_.length());
file.WriteStringUTF8(content);
file.WriteStringUTF8(content_);
file.CloseFile();
}
}
......@@ -200,7 +194,7 @@ _CP_PTR(chart_content) chart_content::create()
return boost::make_shared<chart_content>();
}
//----------------------------------------------------------------------------------------
element_ptr simple_element::create(const std::wstring & FileName, const std::wstring & Content)
simple_element_ptr simple_element::create(const std::wstring & FileName, const std::wstring & Content)
{
return boost::make_shared<simple_element>(FileName, Content);
}
......
......@@ -92,19 +92,21 @@ private:
std::wstring filename_;
};
class simple_element;
typedef boost::shared_ptr<simple_element> simple_element_ptr;
class simple_element : public element
{
public:
simple_element(const std::wstring & FileName, const std::wstring & Content);
static element_ptr create(const std::wstring & FileName, const std::wstring & Content);
simple_element(const std::wstring & FileName, const std::wstring & content);
static simple_element_ptr create(const std::wstring & FileName, const std::wstring & content);
public:
virtual void write(const std::wstring & RootPath);
std::wstring get_filename() {return filename_;}
private:
std::wstring file_name_;
//std::string content_utf8_;
std::wstring content;
std::wstring filename_;
std::wstring content_;
};
......
......@@ -46,7 +46,7 @@ namespace oox {
xlsx_conversion_context::xlsx_conversion_context( package::xlsx_document * outputDocument) : output_document_(outputDocument),
next_vml_file_id_ ( 1 ),
xlsx_table_context_ ( *this ),
table_context_ ( *this ),
xlsx_drawing_context_handle_ ( next_vml_file_id_, get_mediaitems())
{
}
......@@ -186,6 +186,18 @@ xlsx_drawing_context_handle & xlsx_conversion_context::get_drawing_context_handl
return xlsx_drawing_context_handle_;
}
void xlsx_conversion_context::add_connections(std::wstring connections)
{
if (connections.empty()) return;
connections_ = connections;
}
void xlsx_conversion_context::add_query_table (std::wstring query_table)
{
if (query_table.empty()) return;
query_tables_.push_back(query_table);
}
void xlsx_conversion_context::end_document()
{
std::wstringstream workbook_content;
......@@ -273,7 +285,26 @@ void xlsx_conversion_context::end_document()
output_document_->get_xl_files().add_chart(content);
}
//workbook_content << L"<calcPr iterateCount=\"100\" refMode=\"A1\" iterate=\"false\" iterateDelta=\"0.0001\" />";
if (!connections_.empty())
{
std::wstringstream strm;
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"connections")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
CP_XML_STREAM() << connections_;
}
}
output_document_->get_xl_files().set_connections( package::simple_element::create(L"connections.xml", strm.str()) );
}
for (size_t i = 0; i < query_tables_.size(); i++)
{
std::wstring file_name = L"queryTable" + std::to_wstring(i+1) + L".xml";
output_document_->get_xl_files().add_query_table( package::simple_element::create(file_name, query_tables_[i]) );
}
//workbook_content << L"<calcPr iterateCount=\"100\" refMode=\"A1\" iterate=\"false\" iterateDelta=\"0.0001\" />";
output_document_->get_xl_files().set_sharedStrings( package::simple_element::create(L"sharedStrings.xml", xlsx_shared_strings_.str()) );
......@@ -336,7 +367,7 @@ void xlsx_conversion_context::end_document()
CP_XML_STREAM() << str_;
}
}
int pivot_cache_count = xlsx_pivots_context_.get_cache_count();
int pivot_cache_count = pivots_context_.get_cache_count();
if (pivot_cache_count > 0)
{
CP_XML_NODE(L"pivotCaches")
......@@ -355,36 +386,31 @@ void xlsx_conversion_context::end_document()
CP_XML_ATTR(L"r:id", rId);
}
xlsx_pivots_context_.dump_rels_cache(i, content->get_rels());
xlsx_pivots_context_.write_cache_definitions_to(i, content->definitions());
xlsx_pivots_context_.write_cache_records_to(i, content->records());
pivots_context_.dump_rels_cache(i, content->get_rels());
pivots_context_.write_cache_definitions_to(i, content->definitions());
pivots_context_.write_cache_records_to(i, content->records());
output_document_->get_xl_files().add_pivot_cache(content);
}
}
}
int pivot_view_count = xlsx_pivots_context_.get_view_count();
int pivot_view_count = pivots_context_.get_view_count();
if (pivot_view_count > 0)
{
for (int i = 0; i < pivot_view_count; i++)
{
package::pivot_table_content_ptr content = package::pivot_table_content::create();
xlsx_pivots_context_.dump_rels_view(i, content->get_rels());
xlsx_pivots_context_.write_table_view_to(i, content->content());
pivots_context_.dump_rels_view(i, content->get_rels());
pivots_context_.write_table_view_to(i, content->content());
output_document_->get_xl_files().add_pivot_table(content);
}
}
if (xlsx_pivots_context_.is_connections())
{
std::wstringstream strm;
xlsx_pivots_context_.write_connections_to(strm);
output_document_->get_xl_files().set_connections( package::simple_element::create(L"connections.xml", strm.str()) );
}
}
output_document_->get_xl_files().set_workbook( package::simple_element::create(L"workbook.xml", strm_workbook.str()) );
output_document_->get_xl_files().set_workbook( package::simple_element::create(L"workbook.xml", strm_workbook.str()) );
output_document_->content_type().set_media(get_mediaitems());
output_document_->get_xl_files().set_media(get_mediaitems());
......
......@@ -44,6 +44,7 @@
#include "xlsx_pivots_context.h"
#include "xlsx_external_context.h"
#include "xlsx_activeX_context.h"
#include "xlsx_query_table_context.h"
#include "xlsx_output_xml.h"
......@@ -86,15 +87,15 @@ public:
std::wostream & custom_views() { return xlsx_custom_views_; }
std::wostream & workbook_format() { return xlsx_workbook_pr_; }
xlsx_text_context & get_text_context() { return xlsx_text_context_; }
xlsx_table_context & get_table_context() { return xlsx_table_context_; }
xlsx_text_context & get_text_context() { return text_context_; }
xlsx_table_context & get_table_context() { return table_context_; }
xlsx_xml_worksheet & current_sheet();
oox_chart_context & current_chart();
oox_external_context & current_external();
oox_activeX_context & current_activeX();
xlsx_pivots_context & get_pivots_context() {return xlsx_pivots_context_;}
xlsx_pivots_context & get_pivots_context() {return pivots_context_;}
xlsx_drawing_context & get_drawing_context();
xlsx_drawing_context_handle & get_drawing_context_handle();
xlsx_comments_context & get_comments_context();
......@@ -102,7 +103,9 @@ public:
external_items & get_mediaitems() { return mediaitems_; }
void add_exteranal_content(std::wstring content);
void add_exteranal_content (std::wstring content);
void add_connections (std::wstring connections);
void add_query_table (std::wstring query_table);
private:
void create_new_sheet(std::wstring const & name);
......@@ -110,23 +113,20 @@ private:
package::xlsx_document *output_document_;
external_items mediaitems_;
xlsx_table_context
table_context_;
xlsx_text_context text_context_;
xlsx_pivots_context pivots_context_;
std::vector<xlsx_xml_worksheet_ptr> sheets_;
std::vector<oox_chart_context_ptr> charts_;
std::vector<oox_external_context_ptr> externals_;
std::vector<oox_activeX_context_ptr> activeXs_;
//std::wstringstream defaultOutput_;
//std::pair<float,float> maxDigitSize_;
//num_format_context num_format_context_;
//size_t default_style_;
std::vector<oox_chart_context_ptr> charts_;
std::vector<oox_external_context_ptr> externals_;
std::vector<oox_activeX_context_ptr> activeXs_;
size_t next_vml_file_id_; //используется для footer/header & comments
xlsx_pivots_context xlsx_pivots_context_;
xlsx_table_context xlsx_table_context_;
xlsx_text_context xlsx_text_context_;
std::vector<xlsx_xml_worksheet_ptr> sheets_;
std::wstring connections_;
std::vector<std::wstring> query_tables_;
std::wstringstream xlsx_shared_strings_;
std::wstringstream xlsx_defined_names_;
......
......@@ -131,7 +131,7 @@ void sheet_content::add_rel(relationship const & r)
void sheet_content::add_rels(rels & r)
{
for (int i = 0; i < r.relationships().size(); i++)
for (size_t i = 0; i < r.relationships().size(); i++)
{
rels_->get_rels().add(r.relationships()[i]);
}
......@@ -210,6 +210,10 @@ void xl_files::write(const std::wstring & RootPath)
sheets_files_.set_main_document( this->get_main_document() );
sheets_files_.write(path);
}
{
query_tables_files_.set_main_document( this->get_main_document() );
query_tables_files_.write(path);
}
if (sharedStrings_)
{
......@@ -360,6 +364,10 @@ void xl_files::add_pivot_table(pivot_table_content_ptr pivot_table)
{
pivot_table_files_.add_pivot_table(pivot_table);
}
void xl_files::add_query_table (simple_element_ptr element)
{
query_tables_files_.add_query_table(element);
}
//----------------------------------------------------------------------------------------
void xl_pivot_cache_files::add_pivot_cache(pivot_cache_content_ptr pivot_cache)
{
......@@ -367,6 +375,8 @@ void xl_pivot_cache_files::add_pivot_cache(pivot_cache_content_ptr pivot_cache)
}
void xl_pivot_cache_files::write(const std::wstring & RootPath)
{
if (pivot_caches_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"pivotCache";
NSDirectory::CreateDirectory(path.c_str());
......@@ -377,39 +387,38 @@ void xl_pivot_cache_files::write(const std::wstring & RootPath)
for (size_t i = 0; i < pivot_caches_.size(); i++)
{
if (pivot_caches_[i])
{
const std::wstring fileNameD = std::wstring(L"pivotCacheDefinition") + std::to_wstring(i + 1) + L".xml";
if (!pivot_caches_[i]) continue;
const std::wstring fileNameD = std::wstring(L"pivotCacheDefinition") + std::to_wstring(i + 1) + L".xml";
contentTypes.add_override(std::wstring(L"/xl/pivotCache/") + fileNameD, kWSConTypeD);
package::simple_element(fileNameD, pivot_caches_[i]->str_d()).write(path);
if (pivot_caches_[i]->get_rels().empty() == false)
{
rels_files relFiles;
pivot_caches_[i]->definitions_rels_file_->set_file_name(fileNameD + L".rels");
relFiles.add_rel_file(pivot_caches_[i]->definitions_rels_file_);
relFiles.write(path);
}
if (rels_) //for workbook
{
const std::wstring id = std::wstring(L"pcId") + std::to_wstring(i + 1);
static const std::wstring kWSRel = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition";
const std::wstring fileRef = std::wstring(L"pivotCache/") + fileNameD;
rels_->add(id, kWSRel, fileRef);
}
std::wstring content_records = pivot_caches_[i]->str_r();
if (!content_records.empty())
{
const std::wstring fileNameR = std::wstring(L"pivotCacheRecords") + std::to_wstring(i + 1) + L".xml";
contentTypes.add_override(std::wstring(L"/xl/pivotCache/") + fileNameR, kWSConTypeR);
package::simple_element(fileNameR, content_records).write(path);
}
}
contentTypes.add_override(std::wstring(L"/xl/pivotCache/") + fileNameD, kWSConTypeD);
package::simple_element(fileNameD, pivot_caches_[i]->str_d()).write(path);
if (pivot_caches_[i]->get_rels().empty() == false)
{
rels_files relFiles;
pivot_caches_[i]->definitions_rels_file_->set_file_name(fileNameD + L".rels");
relFiles.add_rel_file(pivot_caches_[i]->definitions_rels_file_);
relFiles.write(path);
}
if (rels_) //for workbook
{
const std::wstring id = std::wstring(L"pcId") + std::to_wstring(i + 1);
static const std::wstring kWSRel = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition";
const std::wstring fileRef = std::wstring(L"pivotCache/") + fileNameD;
rels_->add(id, kWSRel, fileRef);
}
std::wstring content_records = pivot_caches_[i]->str_r();
if (!content_records.empty())
{
const std::wstring fileNameR = std::wstring(L"pivotCacheRecords") + std::to_wstring(i + 1) + L".xml";
contentTypes.add_override(std::wstring(L"/xl/pivotCache/") + fileNameR, kWSConTypeR);
package::simple_element(fileNameR, content_records).write(path);
}
}
}
//----------------------------------------------------------------------------------------
......@@ -417,8 +426,11 @@ void xl_pivot_table_files::add_pivot_table(pivot_table_content_ptr pivot_table)
{
pivot_tables_.push_back(pivot_table);
}
void xl_pivot_table_files::write(const std::wstring & RootPath)
{
if (pivot_tables_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"pivotTables";
NSDirectory::CreateDirectory(path.c_str());
......@@ -428,23 +440,22 @@ void xl_pivot_table_files::write(const std::wstring & RootPath)
for (size_t i = 0; i < pivot_tables_.size(); i++)
{
if (pivot_tables_[i])
{
const std::wstring fileName = std::wstring(L"pivotTable") + std::to_wstring(i + 1) + L".xml";
contentTypes.add_override(std::wstring(L"/xl/pivotTables/") + fileName, kWSConType);
package::simple_element(fileName, pivot_tables_[i]->str()).write(path);
if (pivot_tables_[i]->get_rels().empty() == false)
{
rels_files relFiles;
pivot_tables_[i]->rels_file_->set_file_name(fileName + L".rels");
relFiles.add_rel_file(pivot_tables_[i]->rels_file_);
relFiles.write(path);
}
}
if (!pivot_tables_[i]) continue;
const std::wstring fileName = std::wstring(L"pivotTable") + std::to_wstring(i + 1) + L".xml";
contentTypes.add_override(std::wstring(L"/xl/pivotTables/") + fileName, kWSConType);
package::simple_element(fileName, pivot_tables_[i]->str()).write(path);
if (pivot_tables_[i]->get_rels().empty() == false)
{
rels_files relFiles;
pivot_tables_[i]->rels_file_->set_file_name(fileName + L".rels");
relFiles.add_rel_file(pivot_tables_[i]->rels_file_);
relFiles.write(path);
}
}
}
//----------------------------------------------------------------------------------------
......@@ -454,6 +465,8 @@ void xl_charts_files::add_chart(chart_content_ptr chart)
}
void xl_charts_files::write(const std::wstring & RootPath)
{
if (charts_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"charts";
NSDirectory::CreateDirectory(path.c_str());
......@@ -487,6 +500,8 @@ void xl_activeX_files::add_activeX(activeX_content_ptr activeX)
}
void xl_activeX_files::write(const std::wstring & RootPath)
{
if (activeXs_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"activeX";
content_type & contentTypes = this->get_main_document()->content_type().get_content_type();
......@@ -519,6 +534,8 @@ void xl_externals_files::add_external(external_content_ptr external)
}
void xl_externals_files::write(const std::wstring & RootPath)
{
if (externals_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"externalLinks";
NSDirectory::CreateDirectory(path.c_str());
......@@ -553,6 +570,34 @@ void xl_externals_files::write(const std::wstring & RootPath)
}
}
}
//----------------------------------------------------------------------------------------
void xl_query_table_files::add_query_table(simple_element_ptr query_table)
{
query_tables_.push_back(query_table);
}
void xl_query_table_files::write(const std::wstring & RootPath)
{
if (query_tables_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"queryTables";
NSDirectory::CreateDirectory(path);
content_type & contentTypes = this->get_main_document()->content_type().get_content_type();
static const std::wstring kWSConType = L"application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml";
for (size_t i = 0; i < query_tables_.size(); i++)
{
if (!query_tables_[i])continue;
const std::wstring fileName = query_tables_[i]->get_filename();
contentTypes.add_override(std::wstring(L"/xl/queryTables/") + fileName, kWSConType);
query_tables_[i]->write(path);
}
}
//----------------------------------------------------------------------------------------
xl_drawings_ptr xl_drawings::create(const std::vector<drawing_elm> & elms)
{
......@@ -561,6 +606,8 @@ xl_drawings_ptr xl_drawings::create(const std::vector<drawing_elm> & elms)
void xl_drawings::write(const std::wstring & RootPath)
{
if (drawings_.empty()) return;
std::wstring path = RootPath + FILE_SEPARATOR_STR + L"drawings";
NSDirectory::CreateDirectory(path.c_str());
......@@ -596,8 +643,10 @@ xl_comments_ptr xl_comments::create(const std::vector<comment_elm> & elms)
void xl_comments::write(const std::wstring & RootPath)
{
if (comments_.empty()) return;
std::wstring vml_path = RootPath + FILE_SEPARATOR_STR + L"drawings";
NSDirectory::CreateDirectory(vml_path.c_str());
NSDirectory::CreateDirectory(vml_path);
for (size_t i = 0; i < comments_.size(); i++)
{
......
......@@ -150,7 +150,7 @@ public:
std::vector<chart_content_ptr> charts_;
};
class xl_activeX_files : public element
class xl_activeX_files : public element
{
public:
xl_activeX_files(){}
......@@ -160,6 +160,16 @@ public:
std::vector<activeX_content_ptr> activeXs_;
};
class xl_query_table_files : public element
{
public:
xl_query_table_files(){}
void add_query_table(simple_element_ptr query_table);
virtual void write(const std::wstring & RootPath);
std::vector<simple_element_ptr> query_tables_;
};
class xl_externals_files : public element
{
public:
......@@ -272,6 +282,7 @@ public:
void add_external (external_content_ptr external);
void add_pivot_cache (pivot_cache_content_ptr cache);
void add_pivot_table (pivot_table_content_ptr table);
void add_query_table (simple_element_ptr element);
void add_vba_project ();
private:
......@@ -282,10 +293,12 @@ private:
xl_pivot_cache_files pivot_cache_files_;
xl_pivot_table_files pivot_table_files_;
xl_activeX_files activeXs_files_;
xl_query_table_files query_tables_files_;
element_ptr theme_;
element_ptr workbook_;
element_ptr connections_;
element_ptr styles_;
element_ptr sharedStrings_;
......
......@@ -60,7 +60,6 @@ public:
std::vector<_pivot_cache> caches_;
std::vector<_pivot_view> views_;
std::wstring connections_;
};
xlsx_pivots_context::xlsx_pivots_context() : impl_(new xlsx_pivots_context::Impl())
......@@ -83,10 +82,7 @@ int xlsx_pivots_context::get_cache_count()
{
return (int)impl_->caches_.size();
}
bool xlsx_pivots_context::is_connections()
{
return !impl_->connections_.empty();
}
void xlsx_pivots_context::dump_rels_cache(int index, rels & Rels)
{
if (impl_->caches_[index].records_.empty() == false)
......@@ -117,18 +113,6 @@ void xlsx_pivots_context::write_cache_definitions_to(int index, std::wostream &
{
strm << impl_->caches_[index].definitions_;
}
void xlsx_pivots_context::write_connections_to(std::wostream & strm)
{
CP_XML_WRITER(strm)
{
CP_XML_NODE(L"connections")
{
CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main");
CP_XML_STREAM() << impl_->connections_;
}
}
}
void xlsx_pivots_context::write_cache_records_to(int index, std::wostream & strm)
{
......@@ -148,13 +132,6 @@ int xlsx_pivots_context::add_view(std::wstring table_view, int indexCache)
return (int)impl_->views_.size();
}
void xlsx_pivots_context::add_connections(std::wstring connections)
{
if (connections.empty()) return;
impl_->connections_ = connections;
}
int xlsx_pivots_context::get_view_count()
{
return (int)impl_->views_.size();
......
......@@ -54,7 +54,6 @@ public:
void write_cache_definitions_to (int index, std::wostream & strm);
void write_cache_records_to (int index, std::wostream & strm);
void write_connections_to (std::wostream & strm);
void write_table_view_to (int index, std::wostream & strm);
......@@ -62,8 +61,6 @@ public:
void dump_rels_view (int index, rels & Rels);
void add_connections(std::wstring connections);
bool is_connections();
private:
class Impl;
_CP_PTR(Impl) impl_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment