Commit 22c64834 authored by Elen.Subbotina's avatar Elen.Subbotina Committed by Alexander Trofimov

XlsFormat - подчищена работа с внешними источниками данных

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@68120 954022d7-b5bf-4e40-9824-e11837661b57
parent 396ec996
......@@ -53,8 +53,6 @@ void BoundSheet8::readFields(CFRecord& record)
unsigned short flags;
record >> lbPlyPos >> flags >> stName;
record.getGlobalWorkbookInfo()->sheets_names.push_back(stName);
switch(GETBITS(flags, 0, 1))
{
case 0:
......@@ -64,11 +62,12 @@ void BoundSheet8::readFields(CFRecord& record)
hsState = std::wstring (L"hidden");
break;
case 2:
hsState = std::wstring (L"veryHidden");
hsState = std::wstring (L"hidden");//(L"veryHidden");
break;
default:
throw;// EXCEPT::RT::WrongBiffRecord("Unsupported value of hsState.", record.getTypeString());
}
record.getGlobalWorkbookInfo()->sheets_names.push_back(stName);
record.getGlobalWorkbookInfo()->sheets_state.push_back(hsState);
dt = GETBITS(flags, 8, 15);
}
......
......@@ -24,10 +24,10 @@ public:
static const ElementType type = typeBoundSheet8;
//-----------------------------
ForwardOnlyParam<_UINT32> lbPlyPos;
BIFF_BSTR hsState;
BIFF_BYTE dt;
ShortXLUnicodeString stName;
ForwardOnlyParam<_UINT32> lbPlyPos;
std::wstring hsState;
BIFF_BYTE dt;
ShortXLUnicodeString stName;
};
} // namespace XLS
......
#include "CF.h"
#include <utils.h>
namespace XLS
{
......@@ -96,9 +97,9 @@ int CF::serialize(std::wostream & stream)
CP_XML_NODE(L"formula")
{
if (!s1.empty())
CP_XML_STREAM() << s1;
CP_XML_STREAM() << xml::utils::replace_text_to_xml(s1);
else if(!s2.empty())
CP_XML_STREAM() << s2;
CP_XML_STREAM() << xml::utils::replace_text_to_xml(s2);
}
}
}
......
#include "CF12.h"
#include <Logic/Biff_structures/CFMultistate.h>
#include <utils.h>
namespace XLS
{
......@@ -130,9 +131,9 @@ int CF12::serialize(std::wostream & stream)
CP_XML_NODE(L"formula")
{
if (!s1.empty())
CP_XML_STREAM() << s1;
CP_XML_STREAM() << xml::utils::replace_text_to_xml(s1);
else if(!s2.empty())
CP_XML_STREAM() << s2;
CP_XML_STREAM() << xml::utils::replace_text_to_xml(s2);
}
}
}
......
......@@ -72,9 +72,40 @@ void ExternName::readFields(CFRecord& record)
{
body = BiffStructurePtr(new ExternDocName);
}
record.getGlobalWorkbookInfo()->AddinUdfs.push_back(L"");// This fills in the gaps between AddinUdfs if the body is not AddinUdf. The simplest way to maintain indexing from my point of view.
// This fills in the gaps between AddinUdfs if the body is not AddinUdf. The simplest way to maintain indexing from my point of view.
}
body->load(record);
if(0x3A01 != supbook_cch)
{
std::wstring name;
if(!fOle && !fOleLink)
{
ExternDocName* n = dynamic_cast<ExternDocName*>(body.get());
if (n->ixals > 0)
{
//from SupBook
}
else
{
name = n->nameDefinition.getAssembledFormula();
if (name.empty())
name = n->extName.value();
}
}
if(fOle && !fOleLink) // DDE data item
{
ExternDdeLinkNoOper* n = dynamic_cast<ExternDdeLinkNoOper*>(body.get());
name = n->linkName.value();
}
if(!fOle && fOleLink)
{
ExternOleDdeLink* n = dynamic_cast<ExternOleDdeLink*>(body.get());
name = n->linkName.value();
}
record.getGlobalWorkbookInfo()->arExternalNames.push_back(name);
}
}
} // namespace XLS
......
......@@ -22,12 +22,6 @@ public:
static const ElementType type = typeRRSort;
//-----------------------------
// BIFF_WORD userName;
public:
//BO_ATTRIB_MARKUP_BEGIN
// //BO_ATTRIB_MARKUP_ATTRIB(userName)
//BO_ATTRIB_MARKUP_END
};
......
......@@ -36,22 +36,6 @@ public:
XLUnicodeStringNoCch stKey1;
XLUnicodeStringNoCch stKey2;
XLUnicodeStringNoCch stKey3;
public:
//BO_ATTRIB_MARKUP_BEGIN
//BO_ATTRIB_MARKUP_ATTRIB(fCol)
//BO_ATTRIB_MARKUP_ATTRIB(fKey1Dsc)
//BO_ATTRIB_MARKUP_ATTRIB(fKey2Dsc)
//BO_ATTRIB_MARKUP_ATTRIB(fKey3Dsc)
//BO_ATTRIB_MARKUP_ATTRIB(fCaseSensitive)
//BO_ATTRIB_MARKUP_ATTRIB(iOrder)
//BO_ATTRIB_MARKUP_ATTRIB(fAltMethod)
//BO_ATTRIB_MARKUP_ATTRIB(stKey1)
//BO_ATTRIB_MARKUP_ATTRIB(stKey2)
//BO_ATTRIB_MARKUP_ATTRIB(stKey3)
//BO_ATTRIB_MARKUP_END
};
} // namespace XLS
......
......@@ -32,16 +32,21 @@ void SortData::readFields(CFRecord& record)
{
record.skipNunBytes(12);
#pragma message("############################ frtHeader skipped here")
unsigned short flags;
record >> flags;
fCol = GETBIT(flags, 0);
fCaseSensitive = GETBIT(flags, 1);
fAltMethod = GETBIT(flags, 2);
sfp = GETBITS(flags, 3, 5);
fCol = GETBIT(flags, 0);
fCaseSensitive = GETBIT(flags, 1);
fAltMethod = GETBIT(flags, 2);
sfp = GETBITS(flags, 3, 5);
RFX rfx_orig;
record >> rfx_orig >> cconditions;
rfx = static_cast<std::wstring >(rfx_orig);
record >> idParent;
std::list<CFRecordPtr>& recs = continue_records[rt_ContinueFrt12];
while(!recs.empty())
{
......@@ -49,6 +54,7 @@ void SortData::readFields(CFRecord& record)
record.appendRawData(recs.front()->getData() + 12, recs.front()->getDataSize() - 12);
recs.pop_front();
}
for(unsigned int i = 0; i < cconditions; ++i)
{
SortCond12Ptr sort_cond(new SortCond12);
......
......@@ -24,34 +24,18 @@ public:
static const ElementType type = typeSortData;
//-----------------------------
bool fCol;
bool fCaseSensitive;
bool fAltMethod;
BIFF_BYTE sfp;
bool fCol;
bool fCaseSensitive;
bool fAltMethod;
BIFF_BYTE sfp;
BIFF_BSTR rfx;
BIFF_DWORD cconditions;
BIFF_DWORD idParent;
BIFF_DWORD cconditions;
BIFF_DWORD idParent;
BiffStructurePtrVector sortCond12Array;
public:
//BO_ATTRIB_MARKUP_BEGIN
//BO_ATTRIB_MARKUP_ATTRIB(fCol)
//BO_ATTRIB_MARKUP_ATTRIB(fCaseSensitive)
//BO_ATTRIB_MARKUP_ATTRIB(fAltMethod)
//BO_ATTRIB_MARKUP_ATTRIB(sfp)
//BO_ATTRIB_MARKUP_ATTRIB(rfx)
//BO_ATTRIB_MARKUP_ATTRIB(cconditions)
//if(0x01 == sfp || 0x03 == sfp)
//{
// //BO_ATTRIB_MARKUP_ATTRIB(idParent)
//}
//BO_ATTRIB_MARKUP_VECTOR_COMPLEX(sortCond12Array, SortCond12)
//BO_ATTRIB_MARKUP_END
//-----------------------------
std::wstring rfx;
};
} // namespace XLS
......
......@@ -26,17 +26,11 @@ public:
static const ElementType type = typeSupBook;
//-----------------------------
BIFF_WORD ctab;
BIFF_WORD cch;
XLUnicodeStringNoCch virtPath;
XLUnicodeString rgst;
public:
//BO_ATTRIB_MARKUP_BEGIN
//BO_ATTRIB_MARKUP_ATTRIB(ctab)
//BO_ATTRIB_MARKUP_ATTRIB(cch)
//BO_ATTRIB_MARKUP_ATTRIB_NAME(virtPath/*.getEscapedW()*/, L"virtPath")
//BO_ATTRIB_MARKUP_ATTRIB(rgst)
//BO_ATTRIB_MARKUP_END
_UINT16 ctab;
_UINT16 cch;
XLUnicodeStringNoCch virtPath;
XLUnicodeString rgst;
};
......
......@@ -67,7 +67,7 @@ int DXFFntD::serialize(std::wostream & stream)
CP_XML_ATTR(L"val", stFontName.value());
}
}
if (stxp.twpHeight != 0)
if (stxp.twpHeight > 20)
{
CP_XML_NODE(L"sz")
{
......
......@@ -61,6 +61,18 @@ void ExtNameParsedFormula::load(CFRecord& record) // Maybe this class shouldn't
val->load(record);
rgce.addPtg(val);
}
if (record.getDataSize() > record.getRdPtr())
{
int sz = record.getDataSize() - record.getRdPtr();
if (sz < 100)
{
char *buf = new char[sz];
memcpy(buf, record.getCurData<char>(), sz);
record.skipNunBytes(sz);
delete []buf;
}
}
}
......
......@@ -20,9 +20,9 @@ public:
virtual void load(CFRecord& record);
virtual void store(CFRecord& record);
unsigned short ixals;
ShortXLUnicodeString extName;
ExtNameParsedFormula nameDefinition;
unsigned short ixals;
ShortXLUnicodeString extName;
ExtNameParsedFormula nameDefinition;
};
} // namespace XLS
......
......@@ -66,6 +66,11 @@ void PtgNameX::assemble(AssemblerStack& ptg_stack, PtgQueue& extra_data)
_Name = global_info->arDefineNames[nameindex - 1];
}
if (sheet.empty() && _Name.empty() && nameindex <= global_info->arExternalNames.size())
{
_Name = global_info->arExternalNames[nameindex - 1];
}
ptg_stack.push(sheet + _Name);
}
else
......
......@@ -21,9 +21,9 @@ public:
virtual void load(CFRecord& record);
virtual void store(CFRecord& record);
bool fSortDes;
unsigned short sortOn;
RFX rfx;
bool fSortDes;
unsigned short sortOn;
RFX rfx;
CondDataValue condDataValue;
CFFlag cfflag;
......
......@@ -250,7 +250,7 @@ int XFProp::serialize(std::wostream & stream)
case 0x0022: serialize_val_prop (stream, L"charset", xfPropDataBlob); break;
case 0x0023: serialize_val_prop (stream, L"family", xfPropDataBlob); break;
case 0x0024: serialize_val_prop (stream, L"sz", xfPropDataBlob); break;
case 0x0025: serialize_val_prop (stream, L"scheme", xfPropDataBlob); break;
//case 0x0025: serialize_val_prop (stream, L"scheme", xfPropDataBlob); break;
case 0x0026: serialize_val_prop (stream, L"formatCode", xfPropDataBlob); break;
case 0x0029: serialize_val_prop (stream, L"numFmtId", xfPropDataBlob); break;
case 0x002A: serialize_val_prop (stream, L"relativeIndent", xfPropDataBlob); break;
......
......@@ -11,22 +11,6 @@ BiffStructurePtr XTI::clone()
return BiffStructurePtr(new XTI(*this));
}
//void XTI::setXMLAttributes(MSXML2::IXMLDOMElementPtr xml_tag)
//{
// xml_tag->setAttribute(L"iSupBook", iSupBook);
// xml_tag->setAttribute(L"itabFirst", itabFirst);
// xml_tag->setAttribute(L"itabLast", itabLast);
//}
//
//void XTI::getXMLAttributes(MSXML2::IXMLDOMElementPtr xml_tag)
//{
// iSupBook = getStructAttribute(xml_tag, L"iSupBook");
// itabFirst = getStructAttribute(xml_tag, L"itabFirst");
// itabLast = getStructAttribute(xml_tag, L"itabLast");
//}
void XTI::store(CFRecord& record)
{
record << iSupBook << itabFirst << itabLast;
......@@ -37,8 +21,15 @@ void XTI::load(CFRecord& record)
{
record >> iSupBook >> itabFirst >> itabLast;
record.getGlobalWorkbookInfo()->xti_parsed.push_back(
XMLSTUFF::xti_indexes2sheet_name(itabFirst, itabLast, record.getGlobalWorkbookInfo()->sheets_names));
if (itabFirst < 0 && itabLast < 0)
{
record.getGlobalWorkbookInfo()->xti_parsed.push_back(L"");
}
else
{
record.getGlobalWorkbookInfo()->xti_parsed.push_back(
XMLSTUFF::xti_indexes2sheet_name(itabFirst, itabLast, record.getGlobalWorkbookInfo()->sheets_names));
}
}
......
......@@ -25,7 +25,6 @@ BaseObjectPtr BUNDLESHEET::clone()
// BUNDLESHEET = BoundSheet8
const bool BUNDLESHEET::loadContent(BinProcessor& proc)
{
if(!proc.mandatory<BoundSheet8>())
{
return false;
......
......@@ -159,7 +159,7 @@ int FORMATTING::serialize2(std::wostream & stream)
{
m_Styles->serialize(stream);
}
if (m_arDXF.size() > 0)
if (global_info->cellStyleDxfs_count > 0)
{
CP_XML_NODE(L"dxfs")
{
......
......@@ -74,9 +74,9 @@ const bool LBL::loadContent(BinProcessor& proc)
if (it != global_info_->mapDefineNames.end())
{
if (ind_sheet >= it->second.size())
while ( it->second.size() <= ind_sheet)
{
it->second.reserve(ind_sheet + 1);
it->second.push_back(L"");
}
it->second[ind_sheet] = value;
//it->second.push_back(value);
......
......@@ -19,7 +19,8 @@ public:
virtual const bool loadContent(BinProcessor& proc);
static const ElementType type = typeSORT;
BaseObjectPtr m_RRSort;
};
} // namespace XLS
......
......@@ -68,6 +68,10 @@ int SORTANDFILTER::serialize(std::wostream & stream)
{
m_AUTOFILTER->serialize(stream);
}
if (m_SORTDATA12)
{
m_SORTDATA12->serialize(stream);
}
return 0;
}
......
......@@ -30,10 +30,44 @@ const bool SORTDATA12::loadContent(BinProcessor& proc)
{
return false;
}
proc.repeated<ContinueFrt12>(0, 0); // processed inside of SortData
m_SortData = elements_.back();
elements_.pop_back();
int count = proc.repeated<ContinueFrt12>(0, 0); // processed inside of SortData
return true;
}
int SORTDATA12::serialize(std::wostream & stream)
{
if (m_SortData == NULL) return 0;
SortData *info = dynamic_cast<SortData*>(m_SortData.get());
std::wstring ref = info->rfx;
CP_XML_WRITER(stream)
{
CP_XML_NODE(L"sortState")
{
CP_XML_ATTR(L"ref", ref);
if (info->fCol) CP_XML_ATTR(L"columnSort", 1);
if (info->fCaseSensitive) CP_XML_ATTR(L"caseSensitive", 1);
if (info->fAltMethod) CP_XML_ATTR(L"sortMethod", L"stroke");
for (int i = 0 ; i < info->sortCond12Array.size(); i++)
{
SortCond12 * sortCond = dynamic_cast<SortCond12 *>(info->sortCond12Array[i].get());
if (sortCond == NULL) continue;
CP_XML_NODE(L"sortCondition")
{
CP_XML_ATTR(L"ref", sortCond->rfx.toString());
}
}
}
}
return 0;
}
} // namespace XLS
......@@ -20,6 +20,9 @@ public:
static const ElementType type = typeSORTDATA12;
int serialize(std::wostream & stream);
BaseObjectPtr m_SortData;
};
} // namespace XLS
......
......@@ -26,11 +26,13 @@ BaseObjectPtr SORT::clone()
// SORT = RRSort *Continue
const bool SORT::loadContent(BinProcessor& proc)
{
if(!proc.mandatory<RRSort>())
{
return false;
}
m_RRSort = elements_.back();
elements_.pop_back();
proc.repeated<Continue>(0, 0);
return true;
......
......@@ -19,6 +19,9 @@ public:
virtual const bool loadContent(BinProcessor& proc);
static const ElementType type = typeSUPBOOK;
BaseObjectPtr m_SupBook;
BaseObjectPtr m_ExternSheet;
};
......
......@@ -56,14 +56,15 @@ const bool SUPBOOK::loadContent(BinProcessor& proc)
{
return false;
}
/* The above is equal to:
m_SupBook = elements_.back();
elements_.pop_back();
if(!proc.mandatory<SupBook>())
if (supbook.cch != 0x0401 && supbook.cch != 0x3A01 )
{
return false;
proc.getGlobalWorkbookInfo()->arExternalNames.clear();
}
*/
for(;/*infinity*/;)
while(true)
{
ExternName extern_name(supbook.getSupportingLinkType());
if(!proc.optional(extern_name))
......@@ -71,11 +72,14 @@ const bool SUPBOOK::loadContent(BinProcessor& proc)
break;
}
}
//proc.repeated<ExternName>(0, 0);
proc.repeated<Parenthesis_SUPBOOK_1>(0, 0);
proc.optional<ExternSheet>();
int count = proc.repeated<Parenthesis_SUPBOOK_1>(0, 0);
if (proc.optional<ExternSheet>())
{
m_ExternSheet = elements_.back();
elements_.pop_back();
}
//proc.repeated<Continue>(0, 0);
return true;
}
......
......@@ -44,6 +44,7 @@ public:
unsigned short CodePage;
CRYPT::DecryptorPtr decryptor;
std::vector<std::wstring> sheets_state;
std::vector<std::wstring> sheets_names;
std::vector<std::wstring> xti_parsed;
std::vector<std::wstring> AddinUdfs;
......@@ -61,6 +62,7 @@ public:
std::map<std::wstring, std::vector<std::wstring>> mapDefineNames;
std::vector<std::wstring> arDefineNames;
std::vector<std::wstring> arExternalNames;
unsigned int startAddedSharedStrings;
std::vector<std::wstring> arAddedSharedStrings;
......
......@@ -134,6 +134,7 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
proc.mandatory<INTERFACE_T>();
proc.mandatory<WriteAccess>();
proc.optional<FileSharing>();
if (proc.mandatory<CodePage>())
{
m_CodePage = elements_.back();
......@@ -155,7 +156,7 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
proc.optional<CodeName>();
proc.optional<FNGROUPS>();
proc.repeated<Lbl>(0, 0);
count = proc.repeated<Lbl>(0, 0);
proc.optional<OleObjectSize>();
proc.mandatory<PROTECTION>();
......@@ -169,6 +170,7 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
}
proc.mandatory<Backup>();
proc.mandatory<HideObj>();
count = proc.repeated<Window1>(0, 0); // OpenOffice Calc stored files workaround
while(count > 0)
{
......@@ -232,7 +234,9 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
}
proc.optional<UsesELFs>();
proc.repeated<BUNDLESHEET>(1, 0);
count = proc.repeated<BUNDLESHEET>(1, 0);
proc.optional<METADATA>(); // Let it be optional
proc.optional<MTRSettings>();
proc.optional<ForceFullCalculation>();
......@@ -251,8 +255,14 @@ const bool GlobalsSubstream::loadContent(BinProcessor& proc)
proc.getGlobalWorkbookInfo()->CodePage;
}
}
proc.repeated<SUPBOOK>(0, 0);
count = proc.repeated<SUPBOOK>(0, 0);
while(count > 0)
{
m_arSUPBOOK.insert(m_arSUPBOOK.begin(), elements_.back());
elements_.pop_back();
count--;
}
count = proc.repeated<LBL>(0, 0);
while(count > 0)
{
......
......@@ -37,6 +37,7 @@ public:
std::vector<BaseObjectPtr> m_arMSODRAWINGGROUP;
std::vector<BaseObjectPtr> m_arWindow1;
std::vector<BaseObjectPtr> m_arUserBView;
std::vector<BaseObjectPtr> m_arSUPBOOK;
unsigned short code_page_;
};
......
......@@ -251,6 +251,7 @@ void XlsConverter::convert(XLS::WorkbookStreamObject* woorkbook)
{
xls_global_info->current_sheet = i + 1;
xlsx_context->start_table(xls_global_info->sheets_names.size() > i ? xls_global_info->sheets_names[i] : L"Sheet_" + boost::lexical_cast<std::wstring>(i+1));
xlsx_context->set_state(xls_global_info->sheets_state.size() > i ? xls_global_info->sheets_state[i] : L"visible");
if (woorkbook->m_arWorksheetSubstream[i]->get_type() == XLS::typeWorksheetSubstream)
{
......
......@@ -62,6 +62,13 @@ bool xlsx_conversion_context::start_table(const std::wstring & name)
return true;
}
void xlsx_conversion_context::set_state(const std::wstring & state)
{
if (state.empty()) return;
sheets_.back()->set_state(state);
}
void xlsx_conversion_context::start_chart()
{
charts_.push_back(oox_chart_context::create());
......@@ -141,10 +148,10 @@ void xlsx_conversion_context::end_document()
{
CP_XML_NODE(L"sheet")
{
CP_XML_ATTR(L"name", sheet->name());
CP_XML_ATTR(L"name", sheet->name());
CP_XML_ATTR(L"sheetId", count);
CP_XML_ATTR(L"state", L"visible");
CP_XML_ATTR(L"r:id", id);
CP_XML_ATTR(L"state", sheet->state() );
CP_XML_ATTR(L"r:id", id);
}
}
......
......@@ -30,6 +30,7 @@ public:
void end_document();
bool start_table(const std::wstring & name);
void set_state(const std::wstring & state);
void end_table();
void start_chart();
......
......@@ -10,8 +10,13 @@ namespace oox {
class xlsx_xml_worksheet::Impl
{
public:
Impl(std::wstring const & name) : name_(name){}
std::wstring name_;
Impl(std::wstring const & name) : name_(name)
{
state_ = L"visible";
}
std::wstring name_;
std::wstring state_;
std::wstringstream cols_;
std::wstringstream sheetPr_;
......@@ -44,7 +49,10 @@ std::wstring xlsx_xml_worksheet::name() const
{
return impl_->name_;
}
std::wstring xlsx_xml_worksheet::state() const
{
return impl_->state_;
}
xlsx_xml_worksheet_ptr xlsx_xml_worksheet::create(std::wstring const & name)
{
return boost::make_shared<xlsx_xml_worksheet>(name);
......@@ -148,16 +156,16 @@ void xlsx_xml_worksheet::write_to(std::wostream & strm)
}
// !!! ( office 2010)
// !!!
CP_XML_STREAM() << impl_->mergeCells_.str();
CP_XML_STREAM() << impl_->hyperlinks_.str();
CP_XML_STREAM() << impl_->sortAndFilters_.str();
CP_XML_STREAM() << impl_->customViews_.str();
CP_XML_STREAM() << impl_->mergeCells_.str();
CP_XML_STREAM() << impl_->conditionalFormatting_.str();
CP_XML_STREAM() << impl_->hyperlinks_.str();
CP_XML_STREAM() << impl_->pageProperties_.str();
......@@ -177,7 +185,10 @@ void xlsx_xml_worksheet::write_to(std::wostream & strm)
}
}
}
void xlsx_xml_worksheet::set_state (std::wstring const & state)
{
impl_->state_ = state;
}
void xlsx_xml_worksheet::set_drawing_link(std::wstring const & fileName, std::wstring const & id)
{
impl_->drawingName_ = fileName;
......
......@@ -21,6 +21,7 @@ public:
~xlsx_xml_worksheet();
public:
std::wstring name() const;
std::wstring state() const;
std::wostream & dimension();
std::wostream & sheetViews();
......@@ -44,6 +45,7 @@ public:
void set_drawing_link (std::wstring const & fileName, std::wstring const & id);
void set_vml_drawing_link (std::wstring const & fileName, std::wstring const & id);
void set_comments_link (std::wstring const & fileName, std::wstring const & id);
void set_state (std::wstring const & state);
std::pair<std::wstring, std::wstring> get_drawing_link() const;
std::pair<std::wstring, std::wstring> get_vml_drawing_link() const;
......
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