FCLT#81254 Native Excel XLSX v1.0 savepoint

svn path=/Slnkxlsx/trunk/; revision=63006
This commit is contained in:
Jos Groot Lipman
2023-12-19 09:55:45 +00:00
parent 3c8ff8bde7
commit 745fccbfbe
173 changed files with 89094 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
Debug
ipch
x64

22
SLNKXLSX.sln Normal file
View File

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SLNKXLSX", "SLNKXLSX\SLNKXLSX.vcxproj", "{A3B53DEB-39D4-4C35-A066-A48073FE92D9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A3B53DEB-39D4-4C35-A066-A48073FE92D9}.Debug|x64.ActiveCfg = Debug|x64
{A3B53DEB-39D4-4C35-A066-A48073FE92D9}.Debug|x64.Build.0 = Debug|x64
{A3B53DEB-39D4-4C35-A066-A48073FE92D9}.Release|x64.ActiveCfg = Release|x64
{A3B53DEB-39D4-4C35-A066-A48073FE92D9}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

21
SLNKXLSX/About.cpp Normal file
View File

@@ -0,0 +1,21 @@
// About.cpp : Implementation of CAbout
#include "stdafx.h"
#include "About.h"
// CAbout
extern HINSTANCE g_hInstance;
STDMETHODIMP CAbout::get_DLLPath(BSTR* pVal)
{
char module[_MAX_PATH]; // HMODULE
GetModuleFileName(g_hInstance, module, sizeof(module));
CString result;
result.Format("%s", module);
(*pVal) = result.AllocSysString();
return S_OK;
}

59
SLNKXLSX/About.h Normal file
View File

@@ -0,0 +1,59 @@
// About.h : Declaration of the CAbout
#pragma once
#include "resource.h" // main symbols
#include "SLNKXLSX_i.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CAbout
class ATL_NO_VTABLE CAbout :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CAbout, &CLSID_About>,
public IDispatchImpl<IAbout, &IID_IAbout, &LIBID_SLNKXLSXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CAbout()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_ABOUT)
BEGIN_COM_MAP(CAbout)
COM_INTERFACE_ENTRY(IAbout)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(get_DLLPath)(BSTR* pVal);
};
OBJECT_ENTRY_AUTO(__uuidof(About), CAbout)

26
SLNKXLSX/About.rgs Normal file
View File

@@ -0,0 +1,26 @@
HKCR
{
SLNKXLSX.About.1 = s 'About Class'
{
CLSID = s '{C7757185-F47E-4361-9EAD-B2979A6790F6}'
}
SLNKXLSX.About = s 'About Class'
{
CurVer = s 'SLNKXLSX.About.1'
}
NoRemove CLSID
{
ForceRemove {C7757185-F47E-4361-9EAD-B2979A6790F6} = s 'About Class'
{
ProgID = s 'SLNKXLSX.About.1'
VersionIndependentProgID = s 'SLNKXLSX.About'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{651B4313-8484-4456-AB33-A2C636F6CAB7}'
Version = s '1.0'
}
}
}

74
SLNKXLSX/ClassDiagram.cd Normal file
View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="CSLNKXLSXModule" Collapsed="true">
<Position X="4.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>dllmain.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="CAbout" Collapsed="true">
<Position X="3" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAgACAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAA=</HashCode>
<FileName>About.h</FileName>
</TypeIdentifier>
</Class>
<Struct Name="IAbout" Collapsed="true">
<Position X="4.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>SLNKXLSX_i.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="__unnamed_struct_0171_1" Collapsed="true">
<Position X="0.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAQAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>libxlsxwriter\third_party\minizip\iowin32.c</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="IAboutVtbl" Collapsed="true">
<Position X="3" Y="2.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAKAAAAJBAAAAAAAAAAAAQAAgAAAAAAAABAAAAA=</HashCode>
<FileName>SLNKXLSX_i.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="_IID" Collapsed="true">
<Position X="3" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAgAAAAACAQABAAAAAAAA=</HashCode>
<FileName>SLNKXLSX_i.c</FileName>
</TypeIdentifier>
</Struct>
<Typedef Name="WIN32FILE_IOWIN" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>libxlsxwriter\third_party\minizip\iowin32.c</FileName>
</TypeIdentifier>
</Typedef>
<Typedef Name="About" Collapsed="true">
<Position X="3" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>SLNKXLSX_i.h</FileName>
</TypeIdentifier>
</Typedef>
<Typedef Name="IID" Collapsed="true">
<Position X="3" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>c:\Program Files (x86)\Windows Kits\8.1\Include\shared\guiddef.h</FileName>
</TypeIdentifier>
</Typedef>
<Typedef Name="CLSID" Collapsed="true">
<Position X="4.75" Y="4" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>c:\Program Files (x86)\Windows Kits\8.1\Include\shared\guiddef.h</FileName>
</TypeIdentifier>
</Typedef>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

32
SLNKXLSX/Excel.cpp Normal file
View File

@@ -0,0 +1,32 @@
// Excel.cpp : Implementation of CExcel
#include "stdafx.h"
#include "Excel.h"
// CExcel
CExcel::CExcel()
{
}
CExcel::~CExcel()
{
}
STDMETHODIMP CExcel::workbook_new(BSTR filename, ULONG constant_memory, IWorkbook** pWorkbook)
{
CComObject<CWorkbook> *theWorkbook;
HRESULT hr = CComObject<CWorkbook>::CreateInstance(&theWorkbook);
if (FAILED(hr)) return hr;
theWorkbook->AddRef();
hr = theWorkbook->QueryInterface(IID_IWorkbook, (void **)pWorkbook);
theWorkbook->SetPath(filename, constant_memory);
theWorkbook->Release();
if (FAILED(hr)) return hr;
// TODO theWorkbook->SetImpl(pWorkbook); // Heel belangrijk: zet de implementatie waar we een interface op bieden
return S_OK;
}

58
SLNKXLSX/Excel.h Normal file
View File

@@ -0,0 +1,58 @@
// Excel.h : Declaration of the CExcel
#pragma once
#include "resource.h" // main symbols
#include "xlsxwriter.h"
#include "SLNKXLSX_i.h"
#include "SLNKWorkbook.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CExcel
class ATL_NO_VTABLE CExcel :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CExcel, &CLSID_Excel>,
public IDispatchImpl<IExcel, &IID_IExcel, &LIBID_SLNKXLSXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CExcel();
~CExcel();
DECLARE_REGISTRY_RESOURCEID(IDR_EXCEL)
BEGIN_COM_MAP(CExcel)
COM_INTERFACE_ENTRY(IExcel)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
private:
public:
STDMETHOD(workbook_new)(BSTR sPath, ULONG constant_memory, IWorkbook** pWorkbook);
};
OBJECT_ENTRY_AUTO(__uuidof(Excel), CExcel)

26
SLNKXLSX/Excel.rgs Normal file
View File

@@ -0,0 +1,26 @@
HKCR
{
SLNKXLSX.Excel.1 = s 'Excel Class'
{
CLSID = s '{326630EA-3016-4BD4-BDE6-A7666354DEB9}'
}
SLNKXLSX.Excel = s 'Excel Class'
{
CurVer = s 'SLNKXLSX.Excel.1'
}
NoRemove CLSID
{
ForceRemove {326630EA-3016-4BD4-BDE6-A7666354DEB9} = s 'Excel Class'
{
ProgID = s 'SLNKXLSX.Excel.1'
VersionIndependentProgID = s 'SLNKXLSX.Excel'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{651B4313-8484-4456-AB33-A2C636F6CAB7}'
Version = s '1.0'
}
}
}

86
SLNKXLSX/JglUtil.cpp Normal file
View File

@@ -0,0 +1,86 @@
#include "stdafx.h"
#include <math.h>
//#include "JglUtil.h"
HRESULT myAtlReportError(const CLSID & clsid, LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
CString s;
s.FormatV(lpszFormat, args);
if (errno)
{
CString s2;
s2.Format("%s\n(errno %d)", s, errno);
s = s2;
}
if (GetLastError())
{
CString s2;
s2.Format("%s\n(lasterror may not apply) %d: %s", s, GetLastError(), myGetLastErrorMsg());
s = s2;
}
va_end(args);
return AtlReportError(clsid, s);
}
const CString myCString(LPCTSTR lpszFormat, ...)
{
va_list args;
va_start(args, lpszFormat);
CString s;
s.FormatV(lpszFormat, args);
va_end(args);
return s;
}
const CString myGetLastErrorMsg()
{
LPSTR lpBuffer;
DWORD dwError = GetLastError();
int nResult = 0;
if (dwError >= 12000 && dwError <= 12174)
nResult = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
GetModuleHandle("wininet.dll"), dwError, 0,
(LPSTR)&lpBuffer, 0, NULL);
else
nResult = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPSTR)&lpBuffer, 0, NULL);
if (nResult)
{
CString s(lpBuffer);
LocalFree(lpBuffer);
return s;
}
return "Could not format errormessage";
}
long myRound(double const &x) {
ATLASSERT(x >= LONG_MIN-0.5);
ATLASSERT(x <= LONG_MAX+0.5);
if (x >= 0)
return (long) (x+0.5);
return (long) (x-0.5);
}
BOOL isDarkRGB(COLORREF const &clr)
{
return pow(255.0 - GetRValue(clr),2) +
pow(255.0 - GetGValue(clr),2) +
pow(255.0 - GetBValue(clr),2) >
pow(GetRValue(clr), 2.0) +
pow(GetGValue(clr), 2.0) +
pow(GetBValue(clr), 2.0);
}

8
SLNKXLSX/JglUtil.h Normal file
View File

@@ -0,0 +1,8 @@
#define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
long myRound(double const &x);
const CString myGetLastErrorMsg();
HRESULT myAtlReportError(const CLSID & clsid, LPCTSTR lpszFormat, ...);
const CString myCString(LPCTSTR lpszFormat, ...);

64
SLNKXLSX/ReadMe.txt Normal file
View File

@@ -0,0 +1,64 @@
========================================================================
ACTIVE TEMPLATE LIBRARY : SLNKXLSX Project Overview
========================================================================
AppWizard has created this SLNKXLSX project for you to use as the starting point for
writing your Dynamic Link Library (DLL).
This file contains a summary of what you will find in each of the files that
make up your project.
SLNKXLSX.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
SLNKXLSX.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
SLNKXLSX.idl
This file contains the IDL definitions of the type library, the interfaces
and co-classes defined in your project.
This file will be processed by the MIDL compiler to generate:
C++ interface definitions and GUID declarations (SLNKXLSX.h)
GUID definitions (SLNKXLSX_i.c)
A type library (SLNKXLSX.tlb)
Marshaling code (SLNKXLSX_p.c and dlldata.c)
SLNKXLSX.h
This file contains the C++ interface definitions and GUID declarations of the
items defined in SLNKXLSX.idl. It will be regenerated by MIDL during compilation.
SLNKXLSX.cpp
This file contains the object map and the implementation of your DLL's exports.
SLNKXLSX.rc
This is a listing of all of the Microsoft Windows resources that the
program uses.
SLNKXLSX.def
This module-definition file provides the linker with information about the exports
required by your DLL. It contains exports for:
DllGetClassObject
DllCanUnloadNow
DllRegisterServer
DllUnregisterServer
DllInstall
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named SLNKXLSX.pch and a precompiled types file named StdAfx.obj.
Resource.h
This is the standard header file that defines resource IDs.
/////////////////////////////////////////////////////////////////////////////

159
SLNKXLSX/SLNKWorkbook.cpp Normal file
View File

@@ -0,0 +1,159 @@
// Workbook.cpp : Implementation of CWorkbook
#include "stdafx.h"
#include "SLNKWorkbook.h"
// CWorkbook
STDMETHODIMP CWorkbook::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* const arr[] =
{
&IID_IWorkbook
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
CWorkbook::CWorkbook()
{
m_workbook = NULL;
m_doc_properties = {};
HDC tempDC = CreateDC("DISPLAY", NULL, NULL, NULL);
m_myDC = CreateCompatibleDC(tempDC);
DeleteDC(tempDC);
memset(&m_logfont, 0, sizeof(LOGFONT)); // clear out structure.
HFONT m_font;
strcpy_s(m_logfont.lfFaceName, LF_FACESIZE, CString(LXW_DEFAULT_FONT_NAME));
m_logfont.lfHeight = -22;
m_font = CreateFontIndirect(&m_logfont);
ATLASSERT(m_font);
HFONT oldfont = (HFONT)SelectObject(m_myDC, m_font);
ATLASSERT(oldfont);
DeleteObject(oldfont);
}
HRESULT CWorkbook::invalid()
{
return myAtlReportError(GetObjectCLSID(), "Must call SetPath first");
}
STDMETHODIMP CWorkbook::SetPath(BSTR filename, ULONG constant_memory)
{
if (constant_memory)
{
lxw_workbook_options options = {};
options.constant_memory = LXW_TRUE;
m_workbook = ::workbook_new_opt(CString(filename), &options);
}
else
m_workbook = ::workbook_new(CString(filename));
// Definieer een aantal default formats
m_format_bold = workbook_add_format(m_workbook);
format_set_bold(m_format_bold);
m_format_text_wrap = workbook_add_format(m_workbook);
format_set_text_wrap(m_format_text_wrap);
m_format_float2 = workbook_add_format(m_workbook);
format_set_num_format(m_format_float2, "0.00");
m_format_date = workbook_add_format(m_workbook);
format_set_num_format(m_format_date, "d-m-yyyy");
m_format_datetime = workbook_add_format(m_workbook);
format_set_num_format(m_format_datetime, "d-m-yyyy hh:mm");
m_format_time = workbook_add_format(m_workbook);
format_set_num_format(m_format_time, "hh:mm");
return S_OK;
}
STDMETHODIMP CWorkbook::add_worksheet(BSTR sheetname, IWorksheet** pWorksheet)
{
if (!m_workbook)
return invalid();
CComObject<CWorksheet> *theWorksheet;
HRESULT hr = CComObject<CWorksheet>::CreateInstance(&theWorksheet);
if (FAILED(hr)) return hr;
(*((CWorksheet*)(theWorksheet))).my_workbook = this;
theWorksheet->AddRef();
hr = theWorksheet->QueryInterface(IID_IWorksheet, (void **)pWorksheet);
theWorksheet->SetName(sheetname);
theWorksheet->Release();
if (FAILED(hr)) return hr;
// TODO theWorksheet->SetImpl(pWorksheet); // Heel belangrijk: zet de implementatie waar we een interface op bieden
return S_OK;
}
STDMETHODIMP CWorkbook::set_property(BSTR name, BSTR value)
{
if (!m_workbook)
return invalid();
CString nm(name);
CString v(value);
nm.MakeLower();
if (nm == "title")
m_doc_properties.title = lxw_strdup(v);
else if (nm == "subject")
m_doc_properties.subject = lxw_strdup(v);
else if (nm == "author")
m_doc_properties.author = lxw_strdup(v);
else if (nm == "manager")
m_doc_properties.manager = lxw_strdup(v);
else if (nm == "company")
m_doc_properties.company = lxw_strdup(v);
else if (nm == "category")
m_doc_properties.category = lxw_strdup(v);
else if (nm == "keywords")
m_doc_properties.keywords = lxw_strdup(v);
else if (nm == "comments")
m_doc_properties.comments = lxw_strdup(v);
else if (nm == "status")
m_doc_properties.status = lxw_strdup(v);
else
return E_FAIL; // TODO: unsupporty property of er gewoon custom property van maken?
return S_OK;
}
STDMETHODIMP CWorkbook::workbook_close()
{
if (!m_workbook)
return invalid();
::workbook_set_properties(m_workbook, &m_doc_properties);
free((void *)m_doc_properties.title);
free((void *)m_doc_properties.subject);
free((void *)m_doc_properties.author);
free((void *)m_doc_properties.manager);
free((void *)m_doc_properties.company);
free((void *)m_doc_properties.category);
free((void *)m_doc_properties.keywords);
free((void *)m_doc_properties.comments);
free((void *)m_doc_properties.status);
free((void *)m_doc_properties.hyperlink_base);
::workbook_close(m_workbook);
return S_OK;
}

78
SLNKXLSX/SLNKWorkbook.h Normal file
View File

@@ -0,0 +1,78 @@
// Workbook.h : Declaration of the CWorkbook
#pragma once
#include "resource.h" // main symbols
#include "SLNKXLSX_i.h"
#include "SLNKWorksheet.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CWorkbook
class ATL_NO_VTABLE CWorkbook :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CWorkbook, &CLSID_Workbook>,
public ISupportErrorInfo,
public IDispatchImpl<IWorkbook, &IID_IWorkbook, &LIBID_SLNKXLSXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CWorkbook();
DECLARE_REGISTRY_RESOURCEID(IDR_WORKBOOK)
BEGIN_COM_MAP(CWorkbook)
COM_INTERFACE_ENTRY(IWorkbook)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
private:
lxw_doc_properties m_doc_properties;
HRESULT invalid();
public:
lxw_workbook *m_workbook;
lxw_format *m_format_bold;
lxw_format *m_format_text_wrap;
lxw_format *m_format_float2;
lxw_format *m_format_date;
lxw_format *m_format_datetime;
lxw_format *m_format_time;
LOGFONT m_logfont;
HDC m_myDC;
STDMETHOD(SetPath)(BSTR filename, ULONG constant_memory);
STDMETHOD(add_worksheet)(BSTR sheetname, IWorksheet** pWorksheet);
STDMETHOD(set_property)(BSTR name, BSTR value);
STDMETHOD(workbook_close)();
};
OBJECT_ENTRY_AUTO(__uuidof(Workbook), CWorkbook)

211
SLNKXLSX/SLNKWorksheet.cpp Normal file
View File

@@ -0,0 +1,211 @@
// Worksheet.cpp : Implementation of CWorksheet
#include "stdafx.h"
#include "SLNKWorksheet.h"
#include "SLNKWorkbook.h"
// CWorksheet
STDMETHODIMP CWorksheet::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* const arr[] =
{
&IID_IWorksheet
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
CWorksheet::CWorksheet()
{
m_worksheet = NULL;
}
HRESULT CWorksheet::invalid()
{
return myAtlReportError(GetObjectCLSID(), "Worksheet must be created from workbook with add_worksheet");
}
STDMETHODIMP CWorksheet::SetName(BSTR sheetname)
{
m_worksheet = workbook_add_worksheet(my_workbook->m_workbook, CString(sheetname));
worksheet_ignore_errors(m_worksheet, LXW_IGNORE_NUMBER_STORED_AS_TEXT, "A1:XFD1048576");
return S_OK;
}
STDMETHODIMP CWorksheet::freeze_panes(USHORT row, USHORT col)
{
if (!m_worksheet)
return invalid();
worksheet_freeze_panes(m_worksheet, row, col);
return S_OK;
}
STDMETHODIMP CWorksheet::write_string(USHORT row, USHORT col, BSTR string, ULONG format, LONG *pVal)
{
if (!m_worksheet)
return invalid();
lxw_format *fmt = NULL;
switch (format)
{
case 0:
fmt = NULL;
break;
case 1:
fmt = my_workbook->m_format_bold;
break;
}
// Let op: Die string moet echt UTF-8 encoded zijn!
COLE2T pszUTF8(string, CP_UTF8);
::worksheet_write_string(m_worksheet, row, col, pszUTF8, fmt);
SIZE sz;
GetTextExtentPoint32(my_workbook->m_myDC, pszUTF8, (int)strlen(pszUTF8), &sz);
*pVal = sz.cx;
return S_OK;
}
STDMETHODIMP CWorksheet::write_number(USHORT row, USHORT col, DOUBLE number, ULONG format)
{
if (!m_worksheet)
return invalid();
lxw_format *fmt = NULL;
switch (format)
{
case 0:
fmt = NULL;
break;
case 1:
fmt = my_workbook->m_format_float2;
break;
}
::worksheet_write_number(m_worksheet, row, col, number, fmt);
return S_OK;
}
STDMETHODIMP CWorksheet::write_unixtime(USHORT row, USHORT col, LONG64 unixtime, ULONG format)
{
if (!m_worksheet)
return invalid();
lxw_format *fmt = NULL;
switch (format)
{
case 0:
fmt = my_workbook->m_format_date;
worksheet_set_column(m_worksheet, col, col, 10.0, NULL);
break;
case 1:
fmt = my_workbook->m_format_datetime;
worksheet_set_column(m_worksheet, col, col, 15.0, NULL);
break;
case 2:
fmt = my_workbook->m_format_time;
worksheet_set_column(m_worksheet, col, col, 5.0, NULL);
break;
}
::worksheet_write_unixtime(m_worksheet, row, col, unixtime, fmt);
return S_OK;
}
unsigned int unix_stamp_of_DATE(DATE date)
{
//convert DATE to SYSTEMTIME
SYSTEMTIME st;
VariantTimeToSystemTime(date, &st);
//convert SYSTEMTIME to FILETIME
FILETIME ft;
SystemTimeToFileTime(&st, &ft);
//convert FILETIME to ULARGE_INTEGER
//then QuadPart is 64bit timestamp
ULARGE_INTEGER ul{ ft.dwLowDateTime, ft.dwHighDateTime };
return (unsigned int)((ul.QuadPart - 116444736000000000ULL) / 10000000);
}
// In JavaScript gebruik je new Date().getVarDate();
STDMETHODIMP CWorksheet::write_vardate(USHORT row, USHORT col, DATE date, ULONG format)
{
if (!m_worksheet)
return invalid();
write_unixtime(row, col, unix_stamp_of_DATE(date), format);
return S_OK;
}
STDMETHODIMP CWorksheet::set_column_width(USHORT col, DOUBLE number, ULONG format)
{
if (!m_worksheet)
return invalid();
lxw_format *fmt = NULL;
switch (format)
{
case 1:
fmt = my_workbook->m_format_text_wrap;
break;
}
worksheet_set_column(m_worksheet, col, col, number, fmt);
return S_OK;
}
STDMETHODIMP CWorksheet::write_formula(USHORT row, USHORT col, BSTR string, ULONG format)
{
if (!m_worksheet)
return invalid();
lxw_format *fmt = NULL;
switch (format)
{
case 0:
fmt = NULL;
break;
case 1:
fmt = my_workbook->m_format_bold;
break;
}
// Let op: Die string moet echt UTF-8 encoded zijn!
COLE2T pszUTF8(string, CP_UTF8);
::worksheet_write_formula(m_worksheet, row, col, pszUTF8, fmt);
return S_OK;
}
STDMETHODIMP CWorksheet::insert_image(USHORT row, USHORT col, BSTR path, ULONG format)
{
if (!m_worksheet)
return invalid();
::worksheet_insert_image(m_worksheet, row, col, CString(path));
return S_OK;
}
STDMETHODIMP CWorksheet::write_comment(USHORT row, USHORT col, BSTR string)
{
if (!m_worksheet)
return invalid();
// Let op: Die string moet echt UTF-8 encoded zijn!
COLE2T pszUTF8(string, CP_UTF8);
::worksheet_write_comment(m_worksheet, row, col, pszUTF8);
return S_OK;
}

BIN
SLNKXLSX/SLNKXLSX.APS Normal file

Binary file not shown.

92
SLNKXLSX/SLNKXLSX.cpp Normal file
View File

@@ -0,0 +1,92 @@
fdllmain// SLNKXLSX.cpp : Implementation of DLL Exports.
#include "stdafx.h"
#include "resource.h"
#include "SLNKXLSX_i.h"
#include "dllmain.h"
#include "xdlldata.h"
using namespace ATL;
// Used to determine whether the DLL can be unloaded by OLE.
STDAPI DllCanUnloadNow(void)
{
#ifdef _MERGE_PROXYSTUB
HRESULT hr = PrxDllCanUnloadNow();
if (hr != S_OK)
return hr;
#endif
return _AtlModule.DllCanUnloadNow();
}
// Returns a class factory to create an object of the requested type.
_Check_return_
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
{
#ifdef _MERGE_PROXYSTUB
HRESULT hr = PrxDllGetClassObject(rclsid, riid, ppv);
if (hr != CLASS_E_CLASSNOTAVAILABLE)
return hr;
#endif
return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}
// DllRegisterServer - Adds entries to the system registry.
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
HRESULT hr = _AtlModule.DllRegisterServer();
#ifdef _MERGE_PROXYSTUB
if (FAILED(hr))
return hr;
hr = PrxDllRegisterServer();
#endif
return hr;
}
// DllUnregisterServer - Removes entries from the system registry.
STDAPI DllUnregisterServer(void)
{
HRESULT hr = _AtlModule.DllUnregisterServer();
#ifdef _MERGE_PROXYSTUB
if (FAILED(hr))
return hr;
hr = PrxDllRegisterServer();
if (FAILED(hr))
return hr;
hr = PrxDllUnregisterServer();
#endif
return hr;
}
// DllInstall - Adds/Removes entries to the system registry per user per machine.
STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine)
{
HRESULT hr = E_FAIL;
static const wchar_t szUserSwitch[] = L"user";
if (pszCmdLine != NULL)
{
if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
{
ATL::AtlSetPerUserRegistration(true);
}
}
if (bInstall)
{
hr = DllRegisterServer();
if (FAILED(hr))
{
DllUnregisterServer();
}
}
else
{
hr = DllUnregisterServer();
}
return hr;
}

10
SLNKXLSX/SLNKXLSX.def Normal file
View File

@@ -0,0 +1,10 @@
; SLNKXLSX.def : Declares the module parameters.
LIBRARY
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllInstall PRIVATE

99
SLNKXLSX/SLNKXLSX.idl Normal file
View File

@@ -0,0 +1,99 @@
// SLNKXLSX.idl : IDL source for SLNKXLSX
//
// This file will be processed by the MIDL tool to
// produce the type library (SLNKXLSX.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(D81F8688-134A-4035-89D0-DA4863C1672E),
dual,
nonextensible,
pointer_default(unique)
]
interface IAbout : IDispatch{
[propget, id(1)] HRESULT DLLPath([out, retval] BSTR* pVal);
};
[
object,
uuid(3B4C8629-5D20-44EC-88FA-85FC09985E6B),
dual,
nonextensible,
pointer_default(unique)
]
interface IWorksheet : IDispatch{
[id(1)] HRESULT SetName([in] BSTR sheetname);
[id(2), helpstring("method freeze_panes")] HRESULT freeze_panes(USHORT row, USHORT col);
[id(3), helpstring("method write_string")] HRESULT write_string(USHORT row, USHORT col, BSTR string, [in, defaultvalue(0)] ULONG format, [out, retval] LONG* pVal);
[id(4), helpstring("method write_number")] HRESULT write_number(USHORT row, USHORT col, DOUBLE number, [in, defaultvalue(0)] ULONG format);
[id(5), helpstring("method write_unixtime")] HRESULT write_unixtime(USHORT row, USHORT col, LONG64 unixtime, [in, defaultvalue(0)] ULONG format);
[id(6)] HRESULT write_vardate(USHORT row, USHORT col, DATE date, [in, defaultvalue(0)] ULONG format);
[id(7), helpstring("method set_column_width")] HRESULT set_column_width(USHORT col, DOUBLE number, [in, defaultvalue(0)] ULONG format);
[id(8), helpstring("method write_comment")] HRESULT write_comment(USHORT row, USHORT col, BSTR string);
[id(9), helpstring("method write_formula")] HRESULT write_formula(USHORT row, USHORT col, BSTR string, [in, defaultvalue(0)] ULONG format);
[id(10), helpstring("method insert_image")] HRESULT insert_image(USHORT row, USHORT col, [in] BSTR filename, [in, defaultvalue(0)] ULONG format);
};
[
object,
uuid(19C55709-EDFE-4E23-AEF1-9E3AFA073D5A),
dual,
nonextensible,
pointer_default(unique)
]
interface IWorkbook : IDispatch{
[id(1)] HRESULT SetPath([in] BSTR filename, [in, defaultvalue(0)] ULONG constant_memory);
[id(2)] HRESULT add_worksheet([in] BSTR sheetname, [out, retval] IWorksheet** pWorksheet);
[id(3)] HRESULT set_property(BSTR name, BSTR val);
[id(4), helpstring("method workbook_close")] HRESULT workbook_close();
};
[
object,
uuid(AA4E910B-EDA7-4933-8B11-DE558839EC46),
dual,
nonextensible,
pointer_default(unique)
]
interface IExcel : IDispatch{
[id(1)] HRESULT workbook_new([in] BSTR sPath, [in, defaultvalue(0)] ULONG constant_memory, [out, retval] IWorkbook** pWorkbook);
};
[
uuid(651B4313-8484-4456-AB33-A2C636F6CAB7),
version(1.0),
]
library SLNKXLSXLib
{
importlib("stdole2.tlb");
[
uuid(C7757185-F47E-4361-9EAD-B2979A6790F6)
]
coclass About
{
[default] interface IAbout;
};
[
uuid(326630EA-3016-4BD4-BDE6-A7666354DEB9)
]
coclass Excel
{
[default] interface IExcel;
};
[
uuid(7695B8CE-E648-4A5A-95E5-88CEB038817E)
]
coclass Workbook
{
[default] interface IWorkbook;
};
[
uuid(2B2F275D-7542-4E4A-A768-6E93BFA81CAB)
]
coclass Worksheet
{
[default] interface IWorksheet;
};
};
import "shobjidl.idl";

BIN
SLNKXLSX/SLNKXLSX.rc Normal file

Binary file not shown.

3
SLNKXLSX/SLNKXLSX.rgs Normal file
View File

@@ -0,0 +1,3 @@
HKCR
{
}

323
SLNKXLSX/SLNKXLSX.vcxproj Normal file
View File

@@ -0,0 +1,323 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{A3B53DEB-39D4-4C35-A066-A48073FE92D9}</ProjectGuid>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<Keyword>AtlProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IgnoreImportLibrary>true</IgnoreImportLibrary>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>./libxlsxwriter/include;./libxlsxwriter/zlib</AdditionalIncludeDirectories>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SLNKXLSX_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SLNKXLSX_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SLNKXLSX_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SLNKXLSX.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SLNKXLSX.def</ModuleDefinitionFile>
<RegisterOutput>false</RegisterOutput>
</Link>
<PostBuildEvent>
<Command>$(SolutionDir)/signDLL.bat cZqePYo7d0 $(OutDir)$(TargetName)$(TargetExt)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>./libxlsxwriter/include;./libxlsxwriter/zlib</AdditionalIncludeDirectories>
</ClCompile>
<Midl>
<MkTypLibCompatible>false</MkTypLibCompatible>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<HeaderFileName>SLNKXLSX_i.h</HeaderFileName>
<InterfaceIdentifierFileName>SLNKXLSX_i.c</InterfaceIdentifierFileName>
<ProxyFileName>SLNKXLSX_p.c</ProxyFileName>
<GenerateStublessProxies>true</GenerateStublessProxies>
<TypeLibraryName>$(IntDir)SLNKXLSX.tlb</TypeLibraryName>
<DllDataFileName />
<ValidateAllParameters>true</ValidateAllParameters>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ModuleDefinitionFile>.\SLNKXLSX.def</ModuleDefinitionFile>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<RegisterOutput>false</RegisterOutput>
</Link>
<PostBuildEvent>
<Command>$(SolutionDir)/signDLL.bat cZqePYo7d0 $(OutDir)$(TargetName)$(TargetExt)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="About.cpp" />
<ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Excel.cpp" />
<ClCompile Include="JglUtil.cpp" />
<ClCompile Include="libxlsxwriter\src\app.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\chart.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\chartsheet.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\comment.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\content_types.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\core.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\custom.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\drawing.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\format.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\hash_table.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\metadata.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\packager.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\relationships.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\shared_strings.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\styles.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\table.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\theme.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\utility.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\vml.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\workbook.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\worksheet.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\xmlwriter.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\md5\md5.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\ioapi.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\iowin32.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\mztools.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\zip.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\tmpfileplus\tmpfileplus.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\adler32.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\crc32.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\deflate.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\trees.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\zutil.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SLNKWorkbook.cpp" />
<ClCompile Include="SLNKWorksheet.cpp" />
<ClCompile Include="SLNKXLSX.cpp" />
<ClCompile Include="SLNKXLSX_i.c">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="xdlldata.c">
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PrecompiledHeader>
<CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="About.h" />
<ClInclude Include="dllmain.h" />
<ClInclude Include="Excel.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="SLNKXLSX_i.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Workbook.h" />
<ClInclude Include="worksheet.h" />
<ClInclude Include="xdlldata.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SLNKXLSX.rc" />
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<None Include="About.rgs" />
<None Include="ClassDiagram.cd" />
<None Include="Excel.rgs" />
<None Include="libxlsxwriter\src\Makefile" />
<None Include="SLNKXLSX.def" />
<None Include="SLNKXLSX.rgs" />
<None Include="Workbook.rgs" />
<None Include="worksheet.rgs" />
</ItemGroup>
<ItemGroup>
<Midl Include="SLNKXLSX.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{dbd6bc60-1d21-46b4-8f46-6bc6e235b732}</UniqueIdentifier>
<SourceControlFiles>False</SourceControlFiles>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SLNKXLSX.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="xdlldata.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SLNKXLSX_i.c">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="About.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\app.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\chart.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\chartsheet.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\comment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\content_types.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\core.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\custom.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\drawing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\format.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\hash_table.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\metadata.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\packager.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\relationships.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\shared_strings.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\styles.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\table.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\theme.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\utility.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\vml.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\workbook.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\worksheet.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\src\xmlwriter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\ioapi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\iowin32.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\mztools.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\md5\md5.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\tmpfileplus\tmpfileplus.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\third_party\minizip\zip.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\deflate.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\crc32.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\adler32.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\zutil.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libxlsxwriter\zlib\trees.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Excel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SLNKWorkbook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SLNKWorksheet.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JglUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dllmain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="xdlldata.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SLNKXLSX_i.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="About.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Excel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Workbook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="worksheet.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SLNKXLSX.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<None Include="SLNKXLSX.rgs">
<Filter>Resource Files</Filter>
</None>
<None Include="SLNKXLSX.def">
<Filter>Source Files</Filter>
</None>
<None Include="About.rgs">
<Filter>Resource Files</Filter>
</None>
<None Include="libxlsxwriter\src\Makefile">
<Filter>Source Files</Filter>
</None>
<None Include="ClassDiagram.cd" />
<None Include="Excel.rgs">
<Filter>Resource Files</Filter>
</None>
<None Include="Workbook.rgs">
<Filter>Resource Files</Filter>
</None>
<None Include="worksheet.rgs">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Midl Include="SLNKXLSX.idl">
<Filter>Source Files</Filter>
</Midl>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommand>CScript.exe</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>excel.js</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(SolutionDir)Testing</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

73
SLNKXLSX/SLNKworksheet.h Normal file
View File

@@ -0,0 +1,73 @@
// worksheet.h : Declaration of the Cworksheet
#pragma once
#include "resource.h" // main symbols
#include "xlsxwriter.h"
#include "SLNKXLSX_i.h"
class CWorkbook; // forward declaration
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// Cworksheet
class ATL_NO_VTABLE CWorksheet :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CWorksheet, &CLSID_Worksheet>,
public ISupportErrorInfo,
public IDispatchImpl<IWorksheet, &IID_IWorksheet, &LIBID_SLNKXLSXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CWorksheet();
DECLARE_REGISTRY_RESOURCEID(IDR_WORKSHEET)
BEGIN_COM_MAP(CWorksheet)
COM_INTERFACE_ENTRY(IWorksheet)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
private:
lxw_worksheet *m_worksheet; // self
HRESULT invalid();
public:
CWorkbook *my_workbook; // waar hij onder valt
STDMETHOD(SetName)(BSTR sheetname);
STDMETHOD(freeze_panes)(USHORT row, USHORT col);
STDMETHOD(write_string)(USHORT row, USHORT col, BSTR string, ULONG format, LONG *pVal);
STDMETHOD(write_number)(USHORT row, USHORT col, DOUBLE number, ULONG format);
STDMETHOD(write_unixtime)(USHORT row, USHORT col, LONG64 unixtime, ULONG format);
STDMETHOD(write_vardate)(USHORT row, USHORT col, DATE date, ULONG format);
STDMETHOD(set_column_width)(USHORT col, DOUBLE number, ULONG format);
STDMETHOD(write_comment)(USHORT row, USHORT col, BSTR string);
STDMETHOD(write_formula)(USHORT row, USHORT col, BSTR string, ULONG format);
STDMETHOD(insert_image)(USHORT row, USHORT col, BSTR path, ULONG format);
};
OBJECT_ENTRY_AUTO(__uuidof(Worksheet), CWorksheet)

24
SLNKXLSX/Workbook.rgs Normal file
View File

@@ -0,0 +1,24 @@
HKCR
{
SLNKXLSX.Workbook.1 = s 'Workbook Class'
{
CLSID = s '{7695B8CE-E648-4A5A-95E5-88CEB038817E}'
}
SLNKXLSX.Workbook = s 'Workbook Class'
{
CurVer = s 'SLNKXLSX.Workbook.1'
}
NoRemove CLSID
{
ForceRemove {7695B8CE-E648-4A5A-95E5-88CEB038817E} = s 'Workbook Class'
{
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{651B4313-8484-4456-AB33-A2C636F6CAB7}'
Version = s '1.0'
}
}
}

38
SLNKXLSX/dlldata.c Normal file
View File

@@ -0,0 +1,38 @@
/*********************************************************
DllData file -- generated by MIDL compiler
DO NOT ALTER THIS FILE
This file is regenerated by MIDL on every IDL file compile.
To completely reconstruct this file, delete it and rerun MIDL
on all the IDL files in this DLL, specifying this file for the
/dlldata command line option
*********************************************************/
#define PROXY_DELEGATION
#include <rpcproxy.h>
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_PROXY_FILE( SLNKXLSX )
PROXYFILE_LIST_START
/* Start of list */
REFERENCE_PROXY_FILE( SLNKXLSX ),
/* End of list */
PROXYFILE_LIST_END
DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
#ifdef __cplusplus
} /*extern "C" */
#endif
/* end of generated dlldata file */

25
SLNKXLSX/dllmain.cpp Normal file
View File

@@ -0,0 +1,25 @@
// dllmain.cpp : Implementation of DllMain.
#include "stdafx.h"
#include "resource.h"
#include "SLNKXLSX_i.h"
#include "dllmain.h"
#include "xdlldata.h"
CSLNKXLSXModule _AtlModule;
HINSTANCE g_hInstance;
// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
g_hInstance = hInstance;
#ifdef _MERGE_PROXYSTUB
if (!PrxDllMain(hInstance, dwReason, lpReserved))
return FALSE;
#endif
hInstance;
return _AtlModule.DllMain(dwReason, lpReserved);
}

10
SLNKXLSX/dllmain.h Normal file
View File

@@ -0,0 +1,10 @@
// dllmain.h : Declaration of module class.
class CSLNKXLSXModule : public ATL::CAtlDllModuleT< CSLNKXLSXModule >
{
public :
DECLARE_LIBID(LIBID_SLNKXLSXLib)
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SLNKXLSX, "{44BE9F2B-32AB-4BC2-B1CC-0A578A0E5C40}")
};
extern class CSLNKXLSXModule _AtlModule;

View File

@@ -0,0 +1,25 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @file xlsxwriter.h
*
* xlsxwriter - A library for creating Excel XLSX files.
*
*/
#ifndef __LXW_XLSXWRITER_H__
#define __LXW_XLSXWRITER_H__
#include "xlsxwriter/workbook.h"
#include "xlsxwriter/worksheet.h"
#include "xlsxwriter/format.h"
#include "xlsxwriter/utility.h"
#define LXW_VERSION "1.1.5"
#define LXW_VERSION_ID 115
#define LXW_SOVERSION "5"
#endif /* __LXW_XLSXWRITER_H__ */

View File

@@ -0,0 +1,80 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* app - A libxlsxwriter library for creating Excel XLSX app files.
*
*/
#ifndef __LXW_APP_H__
#define __LXW_APP_H__
#include <stdint.h>
#include <string.h>
#include "workbook.h"
#include "common.h"
/* Define the queue.h TAILQ structs for the App structs. */
STAILQ_HEAD(lxw_heading_pairs, lxw_heading_pair);
STAILQ_HEAD(lxw_part_names, lxw_part_name);
typedef struct lxw_heading_pair {
char *key;
char *value;
STAILQ_ENTRY (lxw_heading_pair) list_pointers;
} lxw_heading_pair;
typedef struct lxw_part_name {
char *name;
STAILQ_ENTRY (lxw_part_name) list_pointers;
} lxw_part_name;
/* Struct to represent an App object. */
typedef struct lxw_app {
FILE *file;
struct lxw_heading_pairs *heading_pairs;
struct lxw_part_names *part_names;
lxw_doc_properties *properties;
uint32_t num_heading_pairs;
uint32_t num_part_names;
uint8_t doc_security;
} lxw_app;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_app *lxw_app_new(void);
void lxw_app_free(lxw_app *app);
void lxw_app_assemble_xml_file(lxw_app *self);
void lxw_app_add_part_name(lxw_app *self, const char *name);
void lxw_app_add_heading_pair(lxw_app *self, const char *key,
const char *value);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _app_xml_declaration(lxw_app *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_APP_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,544 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* chartsheet - A libxlsxwriter library for creating Excel XLSX chartsheet files.
*
*/
/**
* @page chartsheet_page The Chartsheet object
*
* The Chartsheet object represents an Excel chartsheet, which is a type of
* worksheet that only contains a chart. The Chartsheet object handles
* operations such as adding a chart and setting the page layout.
*
* See @ref chartsheet.h for full details of the functionality.
*
* @file chartsheet.h
*
* @brief Functions related to adding data and formatting to a chartsheet.
*
* The Chartsheet object represents an Excel chartsheet. It handles operations
* such as adding a chart and setting the page layout.
*
* A Chartsheet object isn't created directly. Instead a chartsheet is created
* by calling the workbook_add_chartsheet() function from a Workbook object. A
* chartsheet object functions as a worksheet and not as a chart. In order to
* have it display data a #lxw_chart object must be created and added to the
* chartsheet:
*
* @code
* #include "xlsxwriter.h"
*
* int main() {
*
* lxw_workbook *workbook = new_workbook("chartsheet.xlsx");
* lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);
* lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL);
* lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_BAR);
*
* //... Set up the chart.
*
* // Add the chart to the chartsheet.
* return workbook_close(workbook);
*
* }
* @endcode
*
* @image html chartsheet.png
*
* The data for the chartsheet chart must be contained on a separate
* worksheet. That is why it is always created in conjunction with at least
* one data worksheet, as shown above.
*/
#ifndef __LXW_CHARTSHEET_H__
#define __LXW_CHARTSHEET_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
#include "drawing.h"
#include "utility.h"
/**
* @brief Struct to represent an Excel chartsheet.
*
* The members of the lxw_chartsheet struct aren't modified directly. Instead
* the chartsheet properties are set by calling the functions shown in
* chartsheet.h.
*/
typedef struct lxw_chartsheet {
FILE *file;
lxw_worksheet *worksheet;
lxw_chart *chart;
struct lxw_protection_obj protection;
uint8_t is_protected;
const char *name;
const char *quoted_name;
const char *tmpdir;
uint16_t index;
uint8_t active;
uint8_t selected;
uint8_t hidden;
uint16_t *active_sheet;
uint16_t *first_sheet;
uint16_t rel_count;
STAILQ_ENTRY (lxw_chartsheet) list_pointers;
} lxw_chartsheet;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @brief Insert a chart object into a chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param chart A #lxw_chart object created via workbook_add_chart().
*
* @return A #lxw_error code.
*
* The `%chartsheet_set_chart()` function can be used to insert a chart into a
* chartsheet. The chart object must be created first using the
* `workbook_add_chart()` function and configured using the @ref chart.h
* functions.
*
* @code
* // Create the chartsheet.
* lxw_chartsheet *chartsheet = workbook_add_chartsheet(workbook, NULL);
*
* // Create a chart object.
* lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_LINE);
*
* // Add a data series to the chart.
* chart_add_series(chart, NULL, "=Sheet1!$A$1:$A$6");
*
* // Insert the chart into the chartsheet.
* chartsheet_set_chart(chartsheet, chart);
* @endcode
*
* @image html chartsheet2.png
*
* **Note:**
*
* A chart may only be inserted once into a chartsheet or a worksheet. If
* several similar charts are required then each one must be created
* separately.
*
*/
lxw_error chartsheet_set_chart(lxw_chartsheet *chartsheet, lxw_chart *chart);
/* Not currently required since scale options aren't useful in a chartsheet. */
lxw_error chartsheet_set_chart_opt(lxw_chartsheet *chartsheet,
lxw_chart *chart,
lxw_chart_options *user_options);
/**
* @brief Make a chartsheet the active, i.e., visible chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_activate()` function is used to specify which chartsheet
* is initially visible in a multi-sheet workbook:
*
* @code
* lxw_worksheet *worksheet1 = workbook_add_worksheet(workbook, NULL);
* lxw_chartsheet *chartsheet1 = workbook_add_chartsheet(workbook, NULL);
* lxw_chartsheet *chartsheet2 = workbook_add_chartsheet(workbook, NULL);
* lxw_chartsheet *chartsheet3 = workbook_add_chartsheet(workbook, NULL);
*
* chartsheet_activate(chartsheet3);
* @endcode
*
* @image html chartsheet_activate.png
*
* More than one chartsheet can be selected via the `chartsheet_select()`
* function, see below, however only one chartsheet can be active.
*
* The default active chartsheet is the first chartsheet.
*
* See also `worksheet_activate()`.
*
*/
void chartsheet_activate(lxw_chartsheet *chartsheet);
/**
* @brief Set a chartsheet tab as selected.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_select()` function is used to indicate that a chartsheet
* is selected in a multi-sheet workbook:
*
* @code
* chartsheet_activate(chartsheet1);
* chartsheet_select(chartsheet2);
* chartsheet_select(chartsheet3);
*
* @endcode
*
* A selected chartsheet has its tab highlighted. Selecting chartsheets is a
* way of grouping them together so that, for example, several chartsheets
* could be printed in one go. A chartsheet that has been activated via the
* `chartsheet_activate()` function will also appear as selected.
*
* See also `worksheet_select()`.
*
*/
void chartsheet_select(lxw_chartsheet *chartsheet);
/**
* @brief Hide the current chartsheet.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `%chartsheet_hide()` function is used to hide a chartsheet:
*
* @code
* chartsheet_hide(chartsheet2);
* @endcode
*
* You may wish to hide a chartsheet in order to avoid confusing a user with
* intermediate data or calculations.
*
* @image html hide_sheet.png
*
* A hidden chartsheet can not be activated or selected so this function is
* mutually exclusive with the `chartsheet_activate()` and
* `chartsheet_select()` functions. In addition, since the first chartsheet
* will default to being the active chartsheet, you cannot hide the first
* chartsheet without activating another sheet:
*
* @code
* chartsheet_activate(chartsheet2);
* chartsheet_hide(chartsheet1);
* @endcode
*
* See also `worksheet_hide()`.
*
*/
void chartsheet_hide(lxw_chartsheet *chartsheet);
/**
* @brief Set current chartsheet as the first visible sheet tab.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* The `chartsheet_activate()` function determines which chartsheet is
* initially selected. However, if there are a large number of chartsheets the
* selected chartsheet may not appear on the screen. To avoid this you can
* select the leftmost visible chartsheet tab using
* `%chartsheet_set_first_sheet()`:
*
* @code
* chartsheet_set_first_sheet(chartsheet19); // First visible chartsheet tab.
* chartsheet_activate(chartsheet20); // First visible chartsheet.
* @endcode
*
* This function is not required very often. The default value is the first
* chartsheet.
*
* See also `worksheet_set_first_sheet()`.
*
*/
void chartsheet_set_first_sheet(lxw_chartsheet *chartsheet);
/**
* @brief Set the color of the chartsheet tab.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param color The tab color.
*
* The `%chartsheet_set_tab_color()` function is used to change the color of
* the chartsheet tab:
*
* @code
* chartsheet_set_tab_color(chartsheet1, LXW_COLOR_RED);
* chartsheet_set_tab_color(chartsheet2, LXW_COLOR_GREEN);
* chartsheet_set_tab_color(chartsheet3, 0xFF9900); // Orange.
* @endcode
*
* The color should be an RGB integer value, see @ref working_with_colors.
*
* See also `worksheet_set_tab_color()`.
*/
void chartsheet_set_tab_color(lxw_chartsheet *chartsheet, lxw_color_t color);
/**
* @brief Protect elements of a chartsheet from modification.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param password A chartsheet password.
* @param options Chartsheet elements to protect.
*
* The `%chartsheet_protect()` function protects chartsheet elements from
* modification:
*
* @code
* chartsheet_protect(chartsheet, "Some Password", options);
* @endcode
*
* The `password` and lxw_protection pointer are both optional:
*
* @code
* chartsheet_protect(chartsheet2, NULL, my_options);
* chartsheet_protect(chartsheet3, "password", NULL);
* chartsheet_protect(chartsheet4, "password", my_options);
* @endcode
*
* Passing a `NULL` password is the same as turning on protection without a
* password. Passing a `NULL` password and `NULL` options had no effect on
* chartsheets.
*
* You can specify which chartsheet elements you wish to protect by passing a
* lxw_protection pointer in the `options` argument. In Excel chartsheets only
* have two protection options:
*
* no_content
* no_objects
*
* All parameters are off by default. Individual elements can be protected as
* follows:
*
* @code
* lxw_protection options = {
* .no_content = 1,
* .no_objects = 1,
* };
*
* chartsheet_protect(chartsheet, NULL, &options);
*
* @endcode
*
* See also worksheet_protect().
*
* **Note:** Sheet level passwords in Excel offer **very** weak
* protection. They don't encrypt your data and are very easy to
* deactivate. Full workbook encryption is not supported by `libxlsxwriter`
* since it requires a completely different file format.
*/
void chartsheet_protect(lxw_chartsheet *chartsheet, const char *password,
lxw_protection *options);
/**
* @brief Set the chartsheet zoom factor.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param scale Chartsheet zoom factor.
*
* Set the chartsheet zoom factor in the range `10 <= zoom <= 400`:
*
* @code
* chartsheet_set_zoom(chartsheet, 75);
* @endcode
*
* The default zoom factor is 100. It isn't possible to set the zoom to
* "Selection" because it is calculated by Excel at run-time.
*
* See also `worksheet_set_zoom()`.
*/
void chartsheet_set_zoom(lxw_chartsheet *chartsheet, uint16_t scale);
/**
* @brief Set the page orientation as landscape.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* This function is used to set the orientation of a chartsheet's printed page
* to landscape. The default chartsheet orientation is landscape, so this
* function isn't generally required:
*
* @code
* chartsheet_set_landscape(chartsheet);
* @endcode
*/
void chartsheet_set_landscape(lxw_chartsheet *chartsheet);
/**
* @brief Set the page orientation as portrait.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
*
* This function is used to set the orientation of a chartsheet's printed page
* to portrait:
*
* @code
* chartsheet_set_portrait(chartsheet);
* @endcode
*/
void chartsheet_set_portrait(lxw_chartsheet *chartsheet);
/**
* @brief Set the paper type for printing.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param paper_type The Excel paper format type.
*
* This function is used to set the paper format for the printed output of a
* chartsheet:
*
* @code
* chartsheet_set_paper(chartsheet1, 1); // US Letter
* chartsheet_set_paper(chartsheet2, 9); // A4
* @endcode
*
* If you do not specify a paper type the chartsheet will print using the
* printer's default paper style.
*
* See `worksheet_set_paper()` for a full list of available paper sizes.
*/
void chartsheet_set_paper(lxw_chartsheet *chartsheet, uint8_t paper_type);
/**
* @brief Set the chartsheet margins for the printed page.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param left Left margin in inches. Excel default is 0.7.
* @param right Right margin in inches. Excel default is 0.7.
* @param top Top margin in inches. Excel default is 0.75.
* @param bottom Bottom margin in inches. Excel default is 0.75.
*
* The `%chartsheet_set_margins()` function is used to set the margins of the
* chartsheet when it is printed. The units are in inches. Specifying `-1` for
* any parameter will give the default Excel value as shown above.
*
* @code
* chartsheet_set_margins(chartsheet, 1.3, 1.2, -1, -1);
* @endcode
*
*/
void chartsheet_set_margins(lxw_chartsheet *chartsheet, double left,
double right, double top, double bottom);
/**
* @brief Set the printed page header caption.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The header string.
*
* @return A #lxw_error code.
*
* Headers and footers are generated using a string which is a combination of
* plain text and control characters
*
* @code
* chartsheet_set_header(chartsheet, "&LHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* chartsheet_set_header(chartsheet, "&CHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* chartsheet_set_header(chartsheet, "&RHello");
*
* // ---------------------------------------------------------------
* // | |
* // | Hello |
* // | |
*
*
* @endcode
*
* See `worksheet_set_header()` for a full explanation of the syntax of
* Excel's header formatting and control characters.
*
*/
lxw_error chartsheet_set_header(lxw_chartsheet *chartsheet,
const char *string);
/**
* @brief Set the printed page footer caption.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The footer string.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header().
*
*/
lxw_error chartsheet_set_footer(lxw_chartsheet *chartsheet,
const char *string);
/**
* @brief Set the printed page header caption with additional options.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The header string.
* @param options Header options.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header() with an
* additional parameter to specify options for the header.
*
* Currently, the only available option is the header margin:
*
* @code
*
* lxw_header_footer_options header_options = { 0.2 };
*
* chartsheet_set_header_opt(chartsheet, "Some text", &header_options);
*
* @endcode
*
*/
lxw_error chartsheet_set_header_opt(lxw_chartsheet *chartsheet,
const char *string,
lxw_header_footer_options *options);
/**
* @brief Set the printed page footer caption with additional options.
*
* @param chartsheet Pointer to a lxw_chartsheet instance to be updated.
* @param string The footer string.
* @param options Footer options.
*
* @return A #lxw_error code.
*
* The syntax of this function is the same as chartsheet_set_header_opt().
*
*/
lxw_error chartsheet_set_footer_opt(lxw_chartsheet *chartsheet,
const char *string,
lxw_header_footer_options *options);
lxw_chartsheet *lxw_chartsheet_new(lxw_worksheet_init_data *init_data);
void lxw_chartsheet_free(lxw_chartsheet *chartsheet);
void lxw_chartsheet_assemble_xml_file(lxw_chartsheet *chartsheet);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _chartsheet_xml_declaration(lxw_chartsheet *chartsheet);
STATIC void _chartsheet_write_sheet_protection(lxw_chartsheet *chartsheet);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CHARTSHEET_H__ */

View File

@@ -0,0 +1,76 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* comment - A libxlsxwriter library for creating Excel XLSX comment files.
*
*/
#ifndef __LXW_COMMENT_H__
#define __LXW_COMMENT_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
/* Define the tree.h RB structs for the red-black head types. */
RB_HEAD(lxw_author_ids, lxw_author_id);
/*
* Struct to represent a comment object.
*/
typedef struct lxw_comment {
FILE *file;
struct lxw_comment_objs *comment_objs;
struct lxw_author_ids *author_ids;
char *comment_author;
uint32_t author_id;
} lxw_comment;
/* Struct to an author id */
typedef struct lxw_author_id {
uint32_t id;
char *author;
RB_ENTRY (lxw_author_id) tree_pointers;
} lxw_author_id;
#define LXW_RB_GENERATE_AUTHOR_IDS(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_REMOVE_COLOR(name, type, field, static) \
RB_GENERATE_INSERT(name, type, field, cmp, static) \
RB_GENERATE_REMOVE(name, type, field, static) \
RB_GENERATE_FIND(name, type, field, cmp, static) \
RB_GENERATE_NEXT(name, type, field, static) \
RB_GENERATE_MINMAX(name, type, field, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_author_ids{int unused;}
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_comment *lxw_comment_new(void);
void lxw_comment_free(lxw_comment *comment);
void lxw_comment_assemble_xml_file(lxw_comment *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _comment_xml_declaration(lxw_comment *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_COMMENT_H__ */

View File

@@ -0,0 +1,462 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @file common.h
*
* @brief Common functions and defines for the libxlsxwriter library.
*
* <!-- Copyright 2014-2022, John McNamara, jmcnamara@cpan.org -->
*
*/
#ifndef __LXW_COMMON_H__
#define __LXW_COMMON_H__
#include <time.h>
#include "third_party/queue.h"
#include "third_party/tree.h"
#ifndef TESTING
#define STATIC static
#else
#define STATIC
#endif
#if __GNUC__ >= 5
#define DEPRECATED(func, msg) func __attribute__ ((deprecated(msg)))
#elif defined(_MSC_VER)
#define DEPRECATED(func, msg) __declspec(deprecated, msg) func
#else
#define DEPRECATED(func, msg) func
#endif
/** Integer data type to represent a row value. Equivalent to `uint32_t`.
*
* The maximum row in Excel is 1,048,576.
*/
typedef uint32_t lxw_row_t;
/** Integer data type to represent a column value. Equivalent to `uint16_t`.
*
* The maximum column in Excel is 16,384.
*/
typedef uint16_t lxw_col_t;
/** Boolean values used in libxlsxwriter. */
enum lxw_boolean {
/** False value. */
LXW_FALSE,
/** True value. */
LXW_TRUE,
/** False value. Used to turn off a property that is default on, in order
* to distinguish it from an uninitialized value. */
LXW_EXPLICIT_FALSE
};
/**
* @brief Error codes from libxlsxwriter functions.
*
* See the `lxw_strerror()` function for an example of how to convert the
* enum number to a descriptive error message string.
*/
typedef enum lxw_error {
/** No error. */
LXW_NO_ERROR = 0,
/** Memory error, failed to malloc() required memory. */
LXW_ERROR_MEMORY_MALLOC_FAILED,
/** Error creating output xlsx file. Usually a permissions error. */
LXW_ERROR_CREATING_XLSX_FILE,
/** Error encountered when creating a tmpfile during file assembly. */
LXW_ERROR_CREATING_TMPFILE,
/** Error reading a tmpfile. */
LXW_ERROR_READING_TMPFILE,
/** Zip generic error ZIP_ERRNO while creating the xlsx file. */
LXW_ERROR_ZIP_FILE_OPERATION,
/** Zip error ZIP_PARAMERROR while creating the xlsx file. */
LXW_ERROR_ZIP_PARAMETER_ERROR,
/** Zip error ZIP_BADZIPFILE (use_zip64 option may be required). */
LXW_ERROR_ZIP_BAD_ZIP_FILE,
/** Zip error ZIP_INTERNALERROR while creating the xlsx file. */
LXW_ERROR_ZIP_INTERNAL_ERROR,
/** File error or unknown zip error when adding sub file to xlsx file. */
LXW_ERROR_ZIP_FILE_ADD,
/** Unknown zip error when closing xlsx file. */
LXW_ERROR_ZIP_CLOSE,
/** Feature is not currently supported in this configuration. */
LXW_ERROR_FEATURE_NOT_SUPPORTED,
/** NULL function parameter ignored. */
LXW_ERROR_NULL_PARAMETER_IGNORED,
/** Function parameter validation error. */
LXW_ERROR_PARAMETER_VALIDATION,
/** Worksheet name exceeds Excel's limit of 31 characters. */
LXW_ERROR_SHEETNAME_LENGTH_EXCEEDED,
/** Worksheet name cannot contain invalid characters: '[ ] : * ? / \\' */
LXW_ERROR_INVALID_SHEETNAME_CHARACTER,
/** Worksheet name cannot start or end with an apostrophe. */
LXW_ERROR_SHEETNAME_START_END_APOSTROPHE,
/** Worksheet name is already in use. */
LXW_ERROR_SHEETNAME_ALREADY_USED,
/** Parameter exceeds Excel's limit of 32 characters. */
LXW_ERROR_32_STRING_LENGTH_EXCEEDED,
/** Parameter exceeds Excel's limit of 128 characters. */
LXW_ERROR_128_STRING_LENGTH_EXCEEDED,
/** Parameter exceeds Excel's limit of 255 characters. */
LXW_ERROR_255_STRING_LENGTH_EXCEEDED,
/** String exceeds Excel's limit of 32,767 characters. */
LXW_ERROR_MAX_STRING_LENGTH_EXCEEDED,
/** Error finding internal string index. */
LXW_ERROR_SHARED_STRING_INDEX_NOT_FOUND,
/** Worksheet row or column index out of range. */
LXW_ERROR_WORKSHEET_INDEX_OUT_OF_RANGE,
/** Maximum hyperlink length (2079) exceeded. */
LXW_ERROR_WORKSHEET_MAX_URL_LENGTH_EXCEEDED,
/** Maximum number of worksheet URLs (65530) exceeded. */
LXW_ERROR_WORKSHEET_MAX_NUMBER_URLS_EXCEEDED,
/** Couldn't read image dimensions or DPI. */
LXW_ERROR_IMAGE_DIMENSIONS,
LXW_MAX_ERRNO
} lxw_error;
/** @brief Struct to represent a date and time in Excel.
*
* Struct to represent a date and time in Excel. See @ref working_with_dates.
*/
typedef struct lxw_datetime {
/** Year : 1900 - 9999 */
int year;
/** Month : 1 - 12 */
int month;
/** Day : 1 - 31 */
int day;
/** Hour : 0 - 23 */
int hour;
/** Minute : 0 - 59 */
int min;
/** Seconds : 0 - 59.999 */
double sec;
} lxw_datetime;
enum lxw_custom_property_types {
LXW_CUSTOM_NONE,
LXW_CUSTOM_STRING,
LXW_CUSTOM_DOUBLE,
LXW_CUSTOM_INTEGER,
LXW_CUSTOM_BOOLEAN,
LXW_CUSTOM_DATETIME
};
/* Size of MD5 byte arrays. */
#define LXW_MD5_SIZE 16
/* Excel sheetname max of 31 chars. */
#define LXW_SHEETNAME_MAX 31
/* Max with all worksheet chars 4xUTF-8 bytes + start and end quotes + \0. */
#define LXW_MAX_SHEETNAME_LENGTH ((LXW_SHEETNAME_MAX * 4) + 2 + 1)
/* Max col string length. */
#define LXW_MAX_COL_NAME_LENGTH sizeof("$XFD")
/* Max row string length. */
#define LXW_MAX_ROW_NAME_LENGTH sizeof("$1048576")
/* Max cell string length. */
#define LXW_MAX_CELL_NAME_LENGTH sizeof("$XFWD$1048576")
/* Max range: $XFWD$1048576:$XFWD$1048576\0 */
#define LXW_MAX_CELL_RANGE_LENGTH (LXW_MAX_CELL_NAME_LENGTH * 2)
/* Max range formula Sheet1!$A$1:$C$5$ style. */
#define LXW_MAX_FORMULA_RANGE_LENGTH (LXW_MAX_SHEETNAME_LENGTH + LXW_MAX_CELL_RANGE_LENGTH)
/* Datetime string length. */
#define LXW_DATETIME_LENGTH sizeof("2016-12-12T23:00:00Z")
/* GUID string length. */
#define LXW_GUID_LENGTH sizeof("{12345678-1234-1234-1234-1234567890AB}\0")
#define LXW_EPOCH_1900 0
#define LXW_EPOCH_1904 1
#define LXW_UINT32_T_LENGTH sizeof("4294967296")
#define LXW_FILENAME_LENGTH 128
#define LXW_IGNORE 1
#define LXW_PORTRAIT 1
#define LXW_LANDSCAPE 0
#define LXW_SCHEMA_MS "http://schemas.microsoft.com/office/2006/relationships"
#define LXW_SCHEMA_ROOT "http://schemas.openxmlformats.org"
#define LXW_SCHEMA_DRAWING LXW_SCHEMA_ROOT "/drawingml/2006"
#define LXW_SCHEMA_OFFICEDOC LXW_SCHEMA_ROOT "/officeDocument/2006"
#define LXW_SCHEMA_PACKAGE LXW_SCHEMA_ROOT "/package/2006/relationships"
#define LXW_SCHEMA_DOCUMENT LXW_SCHEMA_ROOT "/officeDocument/2006/relationships"
#define LXW_SCHEMA_CONTENT LXW_SCHEMA_ROOT "/package/2006/content-types"
/* Use REprintf() for error handling when compiled as an R library. */
#ifdef USE_R_LANG
#include <R.h>
#define LXW_PRINTF REprintf
#define LXW_STDERR
#else
#define LXW_PRINTF fprintf
#define LXW_STDERR stderr,
#endif
#define LXW_ERROR(message) \
LXW_PRINTF(LXW_STDERR "[ERROR][%s:%d]: " message "\n", __FILE__, __LINE__)
#define LXW_MEM_ERROR() \
LXW_ERROR("Memory allocation failed.")
#define GOTO_LABEL_ON_MEM_ERROR(pointer, label) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
goto label; \
} \
} while (0)
#define RETURN_ON_MEM_ERROR(pointer, error) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
return error; \
} \
} while (0)
#define RETURN_VOID_ON_MEM_ERROR(pointer) \
do { \
if (!pointer) { \
LXW_MEM_ERROR(); \
return; \
} \
} while (0)
#define RETURN_ON_ERROR(error) \
do { \
if (error) \
return error; \
} while (0)
#define RETURN_AND_ZIPCLOSE_ON_ERROR(error) \
do { \
if (error) { \
zipClose(self->zipfile, NULL); \
return error; \
} \
} while (0)
#define LXW_WARN(message) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
/* We can't use variadic macros here since we support ANSI C. */
#define LXW_WARN_FORMAT(message) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n")
#define LXW_WARN_FORMAT1(message, var) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var)
#define LXW_WARN_FORMAT2(message, var1, var2) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2)
#define LXW_WARN_FORMAT3(message, var1, var2, var3) \
LXW_PRINTF(LXW_STDERR "[WARNING]: " message "\n", var1, var2, var3)
/* Chart axis type checks. */
#define LXW_WARN_CAT_AXIS_ONLY(function) \
do { \
if (!axis->is_category) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for category axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_VALUE_AXIS_ONLY(function) \
do { \
if (!axis->is_value) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for value axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for date axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_CAT_AND_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_category && !axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for category and date axes\n"); \
return; \
} \
} while (0)
#define LXW_WARN_VALUE_AND_DATE_AXIS_ONLY(function) \
do { \
if (!axis->is_value && !axis->is_date) { \
LXW_PRINTF(LXW_STDERR "[WARNING]: " \
function "() is only valid for value and date axes\n"); \
return; \
} \
} while (0)
#ifndef LXW_BIG_ENDIAN
#define LXW_UINT16_HOST(n) (n)
#define LXW_UINT32_HOST(n) (n)
#define LXW_UINT16_NETWORK(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
#define LXW_UINT32_NETWORK(n) ((((n) & 0xFF) << 24) | \
(((n) & 0xFF00) << 8) | \
(((n) & 0xFF0000) >> 8) | \
(((n) & 0xFF000000) >> 24))
#else
#define LXW_UINT16_NETWORK(n) (n)
#define LXW_UINT32_NETWORK(n) (n)
#define LXW_UINT16_HOST(n) ((((n) & 0x00FF) << 8) | (((n) & 0xFF00) >> 8))
#define LXW_UINT32_HOST(n) ((((n) & 0xFF) << 24) | \
(((n) & 0xFF00) << 8) | \
(((n) & 0xFF0000) >> 8) | \
(((n) & 0xFF000000) >> 24))
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Compilers that have a native snprintf() can use it directly. */
#ifdef _MSC_VER
#define LXW_HAS_SNPRINTF
#endif
#ifdef LXW_HAS_SNPRINTF
#define lxw_snprintf snprintf
#else
#define lxw_snprintf __builtin_snprintf
#endif
/* Define a snprintf for MSVC 2010. */
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdarg.h>
#define snprintf msvc2010_snprintf
#define vsnprintf msvc2010_vsnprintf
__inline int
msvc2010_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int count = -1;
if (size != 0)
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
__inline int
msvc2010_snprintf(char *str, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = msvc2010_vsnprintf(str, size, format, ap);
va_end(ap);
return count;
}
#endif
/* Safer strcpy for fixed width char arrays. */
#define lxw_strcpy(dest, src) \
lxw_snprintf(dest, sizeof(dest), "%s", src)
/* Define the queue.h structs for the formats list. */
STAILQ_HEAD(lxw_formats, lxw_format);
/* Define the queue.h structs for the generic data structs. */
STAILQ_HEAD(lxw_tuples, lxw_tuple);
STAILQ_HEAD(lxw_custom_properties, lxw_custom_property);
typedef struct lxw_tuple {
char *key;
char *value;
STAILQ_ENTRY (lxw_tuple) list_pointers;
} lxw_tuple;
/* Define custom property used in workbook.c and custom.c. */
typedef struct lxw_custom_property {
enum lxw_custom_property_types type;
char *name;
union {
char *string;
double number;
int32_t integer;
uint8_t boolean;
lxw_datetime datetime;
} u;
STAILQ_ENTRY (lxw_custom_property) list_pointers;
} lxw_custom_property;
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_COMMON_H__ */

View File

@@ -0,0 +1,84 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* content_types - A libxlsxwriter library for creating Excel XLSX
* content_types files.
*
*/
#ifndef __LXW_CONTENT_TYPES_H__
#define __LXW_CONTENT_TYPES_H__
#include <stdint.h>
#include <string.h>
#include "common.h"
#define LXW_APP_PACKAGE "application/vnd.openxmlformats-package."
#define LXW_APP_DOCUMENT "application/vnd.openxmlformats-officedocument."
#define LXW_APP_MSEXCEL "application/vnd.ms-excel."
/*
* Struct to represent a content_types.
*/
typedef struct lxw_content_types {
FILE *file;
struct lxw_tuples *default_types;
struct lxw_tuples *overrides;
} lxw_content_types;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_content_types *lxw_content_types_new(void);
void lxw_content_types_free(lxw_content_types *content_types);
void lxw_content_types_assemble_xml_file(lxw_content_types *content_types);
void lxw_ct_add_default(lxw_content_types *content_types, const char *key,
const char *value);
void lxw_ct_add_override(lxw_content_types *content_types, const char *key,
const char *value);
void lxw_ct_add_worksheet_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_chartsheet_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_chart_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_drawing_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_table_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_comment_name(lxw_content_types *content_types,
const char *name);
void lxw_ct_add_vml_name(lxw_content_types *content_types);
void lxw_ct_add_shared_strings(lxw_content_types *content_types);
void lxw_ct_add_calc_chain(lxw_content_types *content_types);
void lxw_ct_add_custom_properties(lxw_content_types *content_types);
void lxw_ct_add_metadata(lxw_content_types *content_types);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _content_types_xml_declaration(lxw_content_types *self);
STATIC void _write_default(lxw_content_types *self, const char *ext,
const char *type);
STATIC void _write_override(lxw_content_types *self, const char *part_name,
const char *type);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CONTENT_TYPES_H__ */

View File

@@ -0,0 +1,51 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* core - A libxlsxwriter library for creating Excel XLSX core files.
*
*/
#ifndef __LXW_CORE_H__
#define __LXW_CORE_H__
#include <stdint.h>
#include "workbook.h"
#include "common.h"
/*
* Struct to represent a core.
*/
typedef struct lxw_core {
FILE *file;
lxw_doc_properties *properties;
} lxw_core;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_core *lxw_core_new(void);
void lxw_core_free(lxw_core *core);
void lxw_core_assemble_xml_file(lxw_core *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _core_xml_declaration(lxw_core *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CORE_H__ */

View File

@@ -0,0 +1,52 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* custom - A libxlsxwriter library for creating Excel custom property files.
*
*/
#ifndef __LXW_CUSTOM_H__
#define __LXW_CUSTOM_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a custom property file object.
*/
typedef struct lxw_custom {
FILE *file;
struct lxw_custom_properties *custom_properties;
uint32_t pid;
} lxw_custom;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_custom *lxw_custom_new(void);
void lxw_custom_free(lxw_custom *custom);
void lxw_custom_assemble_xml_file(lxw_custom *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _custom_xml_declaration(lxw_custom *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_CUSTOM_H__ */

View File

@@ -0,0 +1,103 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* drawing - A libxlsxwriter library for creating Excel XLSX drawing files.
*
*/
#ifndef __LXW_DRAWING_H__
#define __LXW_DRAWING_H__
#include <stdint.h>
#include <string.h>
#include "common.h"
STAILQ_HEAD(lxw_drawing_objects, lxw_drawing_object);
enum lxw_drawing_types {
LXW_DRAWING_NONE = 0,
LXW_DRAWING_IMAGE,
LXW_DRAWING_CHART,
LXW_DRAWING_SHAPE
};
enum image_types {
LXW_IMAGE_UNKNOWN = 0,
LXW_IMAGE_PNG,
LXW_IMAGE_JPEG,
LXW_IMAGE_BMP,
LXW_IMAGE_GIF
};
/* Coordinates used in a drawing object. */
typedef struct lxw_drawing_coords {
uint32_t col;
uint32_t row;
double col_offset;
double row_offset;
} lxw_drawing_coords;
/* Object to represent the properties of a drawing. */
typedef struct lxw_drawing_object {
uint8_t type;
uint8_t anchor;
struct lxw_drawing_coords from;
struct lxw_drawing_coords to;
uint64_t col_absolute;
uint64_t row_absolute;
uint32_t width;
uint32_t height;
uint8_t shape;
uint32_t rel_index;
uint32_t url_rel_index;
char *description;
char *tip;
uint8_t decorative;
STAILQ_ENTRY (lxw_drawing_object) list_pointers;
} lxw_drawing_object;
/*
* Struct to represent a collection of drawings.
*/
typedef struct lxw_drawing {
FILE *file;
uint8_t embedded;
uint8_t orientation;
struct lxw_drawing_objects *drawing_objects;
} lxw_drawing;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_drawing *lxw_drawing_new(void);
void lxw_drawing_free(lxw_drawing *drawing);
void lxw_drawing_assemble_xml_file(lxw_drawing *self);
void lxw_free_drawing_object(struct lxw_drawing_object *drawing_object);
void lxw_add_drawing_object(lxw_drawing *drawing,
lxw_drawing_object *drawing_object);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _drawing_xml_declaration(lxw_drawing *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_DRAWING_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* hash_table - Hash table functions for libxlsxwriter.
*
*/
#ifndef __LXW_HASH_TABLE_H__
#define __LXW_HASH_TABLE_H__
#include "common.h"
/* Macro to loop over hash table elements in insertion order. */
#define LXW_FOREACH_ORDERED(elem, hash_table) \
STAILQ_FOREACH((elem), (hash_table)->order_list, lxw_hash_order_pointers)
/* List declarations. */
STAILQ_HEAD(lxw_hash_order_list, lxw_hash_element);
SLIST_HEAD(lxw_hash_bucket_list, lxw_hash_element);
/* LXW_HASH hash table struct. */
typedef struct lxw_hash_table {
uint32_t num_buckets;
uint32_t used_buckets;
uint32_t unique_count;
uint8_t free_key;
uint8_t free_value;
struct lxw_hash_order_list *order_list;
struct lxw_hash_bucket_list **buckets;
} lxw_hash_table;
/*
* LXW_HASH table element struct.
*
* The hash elements contain pointers to allow them to be stored in
* lists in the the hash table buckets and also pointers to track the
* insertion order in a separate list.
*/
typedef struct lxw_hash_element {
void *key;
void *value;
STAILQ_ENTRY (lxw_hash_element) lxw_hash_order_pointers;
SLIST_ENTRY (lxw_hash_element) lxw_hash_list_pointers;
} lxw_hash_element;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_hash_element *lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key,
size_t key_len);
lxw_hash_element *lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key,
void *value, size_t key_len);
lxw_hash_table *lxw_hash_new(uint32_t num_buckets, uint8_t free_key,
uint8_t free_value);
void lxw_hash_free(lxw_hash_table *lxw_hash);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_HASH_TABLE_H__ */

View File

@@ -0,0 +1,49 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* metadata - A libxlsxwriter library for creating Excel XLSX metadata files.
*
*/
#ifndef __LXW_METADATA_H__
#define __LXW_METADATA_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a metadata object.
*/
typedef struct lxw_metadata {
FILE *file;
} lxw_metadata;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_metadata *lxw_metadata_new(void);
void lxw_metadata_free(lxw_metadata *metadata);
void lxw_metadata_assemble_xml_file(lxw_metadata *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _metadata_xml_declaration(lxw_metadata *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_METADATA_H__ */

View File

@@ -0,0 +1,101 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* packager - A libxlsxwriter library for creating Excel XLSX packager files.
*
*/
#ifndef __LXW_PACKAGER_H__
#define __LXW_PACKAGER_H__
#include <stdint.h>
#ifdef USE_SYSTEM_MINIZIP
#ifdef __GNUC__
#pragma GCC system_header
#endif
#include "minizip/zip.h"
#else
#include "third_party/zip.h"
#endif
#include "common.h"
#include "workbook.h"
#include "worksheet.h"
#include "shared_strings.h"
#include "app.h"
#include "core.h"
#include "custom.h"
#include "table.h"
#include "theme.h"
#include "styles.h"
#include "format.h"
#include "content_types.h"
#include "relationships.h"
#include "vml.h"
#include "comment.h"
#include "metadata.h"
#define LXW_ZIP_BUFFER_SIZE (16384)
/* If zip returns a ZIP_XXX error then errno is set and we can trap that in
* workbook.c. Otherwise return a default libxlsxwriter error. */
#define RETURN_ON_ZIP_ERROR(err, default_err) \
do { \
if (err == ZIP_ERRNO) \
return LXW_ERROR_ZIP_FILE_OPERATION; \
else if (err == ZIP_PARAMERROR) \
return LXW_ERROR_ZIP_PARAMETER_ERROR; \
else if (err == ZIP_BADZIPFILE) \
return LXW_ERROR_ZIP_BAD_ZIP_FILE; \
else if (err == ZIP_INTERNALERROR) \
return LXW_ERROR_ZIP_INTERNAL_ERROR; \
else \
return default_err; \
} while (0)
/*
* Struct to represent a packager.
*/
typedef struct lxw_packager {
FILE *file;
lxw_workbook *workbook;
size_t buffer_size;
size_t output_buffer_size;
zipFile zipfile;
zip_fileinfo zipfile_info;
const char *filename;
const char *buffer;
char *output_buffer;
const char *tmpdir;
uint8_t use_zip64;
} lxw_packager;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_packager *lxw_packager_new(const char *filename, const char *tmpdir,
uint8_t use_zip64);
void lxw_packager_free(lxw_packager *packager);
lxw_error lxw_create_package(lxw_packager *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_PACKAGER_H__ */

View File

@@ -0,0 +1,77 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* relationships - A libxlsxwriter library for creating Excel XLSX
* relationships files.
*
*/
#ifndef __LXW_RELATIONSHIPS_H__
#define __LXW_RELATIONSHIPS_H__
#include <stdint.h>
#include "common.h"
/* Define the queue.h STAILQ structs for the generic data structs. */
STAILQ_HEAD(lxw_rel_tuples, lxw_rel_tuple);
typedef struct lxw_rel_tuple {
char *type;
char *target;
char *target_mode;
STAILQ_ENTRY (lxw_rel_tuple) list_pointers;
} lxw_rel_tuple;
/*
* Struct to represent a relationships.
*/
typedef struct lxw_relationships {
FILE *file;
uint32_t rel_id;
struct lxw_rel_tuples *relationships;
} lxw_relationships;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_relationships *lxw_relationships_new(void);
void lxw_free_relationships(lxw_relationships *relationships);
void lxw_relationships_assemble_xml_file(lxw_relationships *self);
void lxw_add_document_relationship(lxw_relationships *self, const char *type,
const char *target);
void lxw_add_package_relationship(lxw_relationships *self, const char *type,
const char *target);
void lxw_add_ms_package_relationship(lxw_relationships *self,
const char *type, const char *target);
void lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
const char *target,
const char *target_mode);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _relationships_xml_declaration(lxw_relationships *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_RELATIONSHIPS_H__ */

View File

@@ -0,0 +1,85 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* shared_strings - A libxlsxwriter library for creating Excel XLSX
* sst files.
*
*/
#ifndef __LXW_SST_H__
#define __LXW_SST_H__
#include <string.h>
#include <stdint.h>
#include "common.h"
/* Define a tree.h RB structure for storing shared strings. */
RB_HEAD(sst_rb_tree, sst_element);
/* Define a queue.h structure for storing shared strings in insertion order. */
STAILQ_HEAD(sst_order_list, sst_element);
/* Wrapper around RB_GENERATE_STATIC from tree.h to avoid unused function
* warnings and to avoid portability issues with the _unused attribute. */
#define LXW_RB_GENERATE_ELEMENT(name, type, field, cmp) \
RB_GENERATE_INSERT_COLOR(name, type, field, static) \
RB_GENERATE_INSERT(name, type, field, cmp, static) \
/* Add unused struct to allow adding a semicolon */ \
struct lxw_rb_generate_element{int unused;}
/*
* Elements of the SST table. They contain pointers to allow them to
* be stored in a RB tree and also pointers to track the insertion order
* in a separate list.
*/
struct sst_element {
uint32_t index;
char *string;
uint8_t is_rich_string;
STAILQ_ENTRY (sst_element) sst_order_pointers;
RB_ENTRY (sst_element) sst_tree_pointers;
};
/*
* Struct to represent a sst.
*/
typedef struct lxw_sst {
FILE *file;
uint32_t string_count;
uint32_t unique_count;
struct sst_order_list *order_list;
struct sst_rb_tree *rb_tree;
} lxw_sst;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_sst *lxw_sst_new(void);
void lxw_sst_free(lxw_sst *sst);
struct sst_element *lxw_get_sst_index(lxw_sst *sst, const char *string,
uint8_t is_rich_string);
void lxw_sst_assemble_xml_file(lxw_sst *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _sst_xml_declaration(lxw_sst *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_SST_H__ */

View File

@@ -0,0 +1,88 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* styles - A libxlsxwriter library for creating Excel XLSX styles files.
*
*/
#ifndef __LXW_STYLES_H__
#define __LXW_STYLES_H__
#include <stdint.h>
#include <ctype.h>
#include "format.h"
/*
* Struct to represent a styles.
*/
typedef struct lxw_styles {
FILE *file;
uint32_t font_count;
uint32_t xf_count;
uint32_t dxf_count;
uint32_t num_format_count;
uint32_t border_count;
uint32_t fill_count;
struct lxw_formats *xf_formats;
struct lxw_formats *dxf_formats;
uint8_t has_hyperlink;
uint16_t hyperlink_font_id;
uint8_t has_comments;
} lxw_styles;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_styles *lxw_styles_new(void);
void lxw_styles_free(lxw_styles *styles);
void lxw_styles_assemble_xml_file(lxw_styles *self);
void lxw_styles_write_string_fragment(lxw_styles *self, const char *string);
void lxw_styles_write_rich_font(lxw_styles *styles, lxw_format *format);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _styles_xml_declaration(lxw_styles *self);
STATIC void _write_style_sheet(lxw_styles *self);
STATIC void _write_font_size(lxw_styles *self, double font_size);
STATIC void _write_font_color_theme(lxw_styles *self, uint8_t theme);
STATIC void _write_font_name(lxw_styles *self, const char *font_name,
uint8_t is_rich_string);
STATIC void _write_font_family(lxw_styles *self, uint8_t font_family);
STATIC void _write_font_scheme(lxw_styles *self, const char *font_scheme);
STATIC void _write_font(lxw_styles *self, lxw_format *format, uint8_t is_dxf,
uint8_t is_rich_string);
STATIC void _write_fonts(lxw_styles *self);
STATIC void _write_default_fill(lxw_styles *self, const char *pattern);
STATIC void _write_fills(lxw_styles *self);
STATIC void _write_border(lxw_styles *self, lxw_format *format,
uint8_t is_dxf);
STATIC void _write_borders(lxw_styles *self);
STATIC void _write_style_xf(lxw_styles *self, uint8_t has_hyperlink,
uint16_t font_id);
STATIC void _write_cell_style_xfs(lxw_styles *self);
STATIC void _write_xf(lxw_styles *self, lxw_format *format);
STATIC void _write_cell_xfs(lxw_styles *self);
STATIC void _write_cell_style(lxw_styles *self, char *name, uint8_t xf_id,
uint8_t builtin_id);
STATIC void _write_cell_styles(lxw_styles *self);
STATIC void _write_dxfs(lxw_styles *self);
STATIC void _write_table_styles(lxw_styles *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_STYLES_H__ */

View File

@@ -0,0 +1,51 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* table - A libxlsxwriter library for creating Excel XLSX table files.
*
*/
#ifndef __LXW_TABLE_H__
#define __LXW_TABLE_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a table object.
*/
typedef struct lxw_table {
FILE *file;
struct lxw_table_obj *table_obj;
} lxw_table;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_table *lxw_table_new(void);
void lxw_table_free(lxw_table *table);
void lxw_table_assemble_xml_file(lxw_table *self);
/* Declarations required for unit testing. */
#ifdef TESTING
STATIC void _table_xml_declaration(lxw_table *self);
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_TABLE_H__ */

View File

@@ -0,0 +1,47 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* theme - A libxlsxwriter library for creating Excel XLSX theme files.
*
*/
#ifndef __LXW_THEME_H__
#define __LXW_THEME_H__
#include <stdint.h>
#include "common.h"
/*
* Struct to represent a theme.
*/
typedef struct lxw_theme {
FILE *file;
} lxw_theme;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_theme *lxw_theme_new(void);
void lxw_theme_free(lxw_theme *theme);
void lxw_theme_xml_declaration(lxw_theme *self);
void lxw_theme_assemble_xml_file(lxw_theme *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_THEME_H__ */

View File

@@ -0,0 +1,26 @@
/* emyg_dtoa.h
** Copyright (C) 2015 Doug Currie
** based on dtoa_milo.h
** Copyright (C) 2014 Milo Yip
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
*/
/* Source from https://github.com/miloyip/dtoa-benchmark */
void emyg_dtoa (double value, char* buffer);

View File

@@ -0,0 +1,216 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
Changes
Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
More if/def section may be needed to support other platforms
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
(but you should use iowin32.c for windows instead)
*/
/* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
#ifndef _WIN32
#pragma GCC system_header
#endif
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
/* Linux needs this to support file operation on files larger then 4+GB
* But might need better if/def to select just the platforms that needs them. */
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
#define fopen64 fopen
#define ftello64 ftello
#define fseeko64 fseeko
#endif
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#else // old MSC
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif
#endif
/*
#ifndef ZPOS64_T
#ifdef _WIN32
#define ZPOS64_T fpos_t
#else
#include <stdint.h>
#define ZPOS64_T uint64_t
#endif
#endif
*/
#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif
/* a type chosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif
/* Maximum unsigned 32-bit value used as placeholder for zip64 */
#ifndef MAXU32
#define MAXU32 (0xffffffff)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
/* here is the "old" 32 bits structure structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin);
typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode);
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc64_def;
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
zlib_filefunc64_def zfile_func64;
open_file_func zopen32_file;
tell_file_func ztell32_file;
seek_file_func zseek32_file;
} zlib_filefunc64_32_def;
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
/*#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))*/
/*#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))*/
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode);
long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin);
ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream);
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

View File

@@ -0,0 +1,694 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD$
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/* #include <sys/cdefs.h> */
/*
* This file defines four types of data structures: singly-linked lists,
* singly-linked tail queues, lists and tail queues.
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may be traversed in either direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ
* _HEAD + + + +
* _HEAD_INITIALIZER + + + +
* _ENTRY + + + +
* _INIT + + + +
* _EMPTY + + + +
* _FIRST + + + +
* _NEXT + + + +
* _PREV - + - +
* _LAST - - + +
* _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + +
* _INSERT_TAIL - - + +
* _CONCAT - - + +
* _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + -
* _REMOVE + + + +
* _SWAP + + + +
*
*/
#ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */
struct qm_trace {
unsigned long lastline;
unsigned long prevline;
const char *lastfile;
const char *prevfile;
};
#define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \
(head)->trace.prevfile = (head)->trace.lastfile; \
(head)->trace.lastline = __LINE__; \
(head)->trace.lastfile = __FILE__; \
} while (0)
#define QMD_TRACE_ELEM(elem) do { \
(elem)->trace.prevline = (elem)->trace.lastline; \
(elem)->trace.prevfile = (elem)->trace.lastfile; \
(elem)->trace.lastline = __LINE__; \
(elem)->trace.lastfile = __FILE__; \
} while (0)
#else
#define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */
/*
* Singly-linked List declarations.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_FOREACH(var, head, field) \
for ((var) = SLIST_FIRST((head)); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \
(varp) = &SLIST_NEXT((var), field))
#define SLIST_INIT(head) do { \
SLIST_FIRST((head)) = NULL; \
} while (0)
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
SLIST_NEXT((slistelm), field) = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
SLIST_FIRST((head)) = (elm); \
} while (0)
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = SLIST_FIRST((head)); \
while (SLIST_NEXT(curelm, field) != (elm)) \
curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
SLIST_NEXT(elm, field) = \
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first;/* first element */ \
struct type **stqh_last;/* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_CONCAT(head1, head2) do { \
if (!STAILQ_EMPTY((head2))) { \
*(head1)->stqh_last = (head2)->stqh_first; \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_INIT((head2)); \
} \
} while (0)
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_NEXT((tqelm), field) = (elm); \
} while (0)
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
STAILQ_FIRST((head)) = (elm); \
} while (0)
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
STAILQ_NEXT((elm), field) = NULL; \
*(head)->stqh_last = (elm); \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? NULL : \
__containerof((head)->stqh_last, struct type, field.stqe_next))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = STAILQ_FIRST((head)); \
while (STAILQ_NEXT(curelm, field) != (elm)) \
curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \
} \
TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
if ((STAILQ_NEXT(elm, field) = \
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
(head1)->stqh_last = (head2)->stqh_last; \
STAILQ_FIRST(head2) = swap_first; \
(head2)->stqh_last = swap_last; \
if (STAILQ_EMPTY(head1)) \
(head1)->stqh_last = &STAILQ_FIRST(head1); \
if (STAILQ_EMPTY(head2)) \
(head2)->stqh_last = &STAILQ_FIRST(head2); \
} while (0)
/*
* List declarations.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_LIST_CHECK_HEAD(head, field) do { \
if (LIST_FIRST((head)) != NULL && \
LIST_FIRST((head))->field.le_prev != \
&LIST_FIRST((head))) \
panic("Bad list head %p first->prev != head", (head)); \
} while (0)
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
if (LIST_NEXT((elm), field) != NULL && \
LIST_NEXT((elm), field)->field.le_prev != \
&((elm)->field.le_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_LIST_CHECK_PREV(elm, field) do { \
if (*(elm)->field.le_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_LIST_CHECK_HEAD(head, field)
#define QMD_LIST_CHECK_NEXT(elm, field)
#define QMD_LIST_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_FOREACH(var, head, field) \
for ((var) = LIST_FIRST((head)); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QMD_LIST_CHECK_NEXT(listelm, field); \
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
LIST_NEXT((listelm), field)->field.le_prev = \
&LIST_NEXT((elm), field); \
LIST_NEXT((listelm), field) = (elm); \
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QMD_LIST_CHECK_PREV(listelm, field); \
(elm)->field.le_prev = (listelm)->field.le_prev; \
LIST_NEXT((elm), field) = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
QMD_LIST_CHECK_HEAD((head), field); \
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
LIST_FIRST((head)) = (elm); \
(elm)->field.le_prev = &LIST_FIRST((head)); \
} while (0)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
} while (0)
#define LIST_SWAP(head1, head2, type, field) do { \
struct type *swap_tmp = LIST_FIRST((head1)); \
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
LIST_FIRST((head2)) = swap_tmp; \
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
} while (0)
/*
* Tail queue declarations.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
TRACEBUF \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
}
/*
* Tail queue functions.
*/
#if (defined(_KERNEL) && defined(INVARIANTS))
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
if (!TAILQ_EMPTY(head) && \
TAILQ_FIRST((head))->field.tqe_prev != \
&TAILQ_FIRST((head))) \
panic("Bad tailq head %p first->prev != head", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
if (*(head)->tqh_last != NULL) \
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
} while (0)
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
if (TAILQ_NEXT((elm), field) != NULL && \
TAILQ_NEXT((elm), field)->field.tqe_prev != \
&((elm)->field.tqe_next)) \
panic("Bad link elm %p next->prev != elm", (elm)); \
} while (0)
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
if (*(elm)->field.tqe_prev != (elm)) \
panic("Bad link elm %p prev->next != elm", (elm)); \
} while (0)
#else
#define QMD_TAILQ_CHECK_HEAD(head, field)
#define QMD_TAILQ_CHECK_TAIL(head, headname)
#define QMD_TAILQ_CHECK_NEXT(elm, field)
#define QMD_TAILQ_CHECK_PREV(elm, field)
#endif /* (_KERNEL && INVARIANTS) */
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
QMD_TRACE_HEAD(head1); \
QMD_TRACE_HEAD(head2); \
} \
} while (0)
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QMD_TAILQ_CHECK_NEXT(listelm, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
TAILQ_NEXT((elm), field)->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else { \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
} \
TAILQ_NEXT((listelm), field) = (elm); \
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QMD_TAILQ_CHECK_PREV(listelm, field); \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
TAILQ_NEXT((elm), field) = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
QMD_TRACE_ELEM(&(elm)->field); \
QMD_TRACE_ELEM(&listelm->field); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QMD_TAILQ_CHECK_HEAD(head, field); \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = \
&TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QMD_TAILQ_CHECK_TAIL(head, field); \
TAILQ_NEXT((elm), field) = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
QMD_TRACE_HEAD(head); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = \
(elm)->field.tqe_prev; \
else { \
(head)->tqh_last = (elm)->field.tqe_prev; \
QMD_TRACE_HEAD(head); \
} \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT(*oldnext); \
TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \
} while (0)
#define TAILQ_SWAP(head1, head2, type, field) do { \
struct type *swap_first = (head1)->tqh_first; \
struct type **swap_last = (head1)->tqh_last; \
(head1)->tqh_first = (head2)->tqh_first; \
(head1)->tqh_last = (head2)->tqh_last; \
(head2)->tqh_first = swap_first; \
(head2)->tqh_last = swap_last; \
if ((swap_first = (head1)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head1)->tqh_first; \
else \
(head1)->tqh_last = &(head1)->tqh_first; \
if ((swap_first = (head2)->tqh_first) != NULL) \
swap_first->field.tqe_prev = &(head2)->tqh_first; \
else \
(head2)->tqh_last = &(head2)->tqh_first; \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

View File

@@ -0,0 +1,53 @@
/* $Id: tmpfileplus.h $ */
/*
* $Date: 2016-06-01 03:31Z $
* $Revision: 2.0.0 $
* $Author: dai $
*/
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2012-16 David Ireland, DI Management Services Pty Ltd
* <http://www.di-mgt.com.au/contact/>.
*/
#if _MSC_VER > 1000
#pragma once
#endif
#ifndef TMPFILEPLUS_H_
#define TMPFILEPLUS_H_
#include <stdio.h>
/** Create a unique temporary file.
@param dir (optional) directory to create file. If NULL use default TMP directory.
@param prefix (optional) prefix for file name. If NULL use "tmp.".
@param pathname (optional) pointer to a buffer to receive the temp filename.
Allocated using `malloc()`; user to free. Ignored if NULL.
@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
Otherwise file is automatically deleted when closed.
@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
@exception ENOMEM Not enough memory to allocate filename.
*/
FILE *tmpfileplus(const char *dir, const char *prefix, char **pathname, int keep);
/** Create a unique temporary file with filename stored in a fixed-length buffer.
@param dir (optional) directory to create file. If NULL use default directory.
@param prefix (optional) prefix for file name. If NULL use "tmp.".
@param pathnamebuf (optional) buffer to receive full pathname of temporary file. Ignored if NULL.
@param pathsize Size of buffer to receive filename and its terminating null character.
@param keep If `keep` is nonzero and `pathname` is not NULL, then keep the file after closing.
Otherwise file is automatically deleted when closed.
@return Pointer to stream opened in binary read/write (w+b) mode, or a null pointer on error.
@exception E2BIG Resulting filename is too big for the buffer `pathnamebuf`.
*/
FILE *tmpfileplus_f(const char *dir, const char *prefix, char *pathnamebuf, size_t pathsize, int keep);
#define TMPFILE_KEEP 1
#endif /* end TMPFILEPLUS_H_ */

View File

@@ -0,0 +1,801 @@
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD$ */
/*-
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
/* #include <sys/cdefs.h> */
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
*
* A splay tree is a self-organizing data structure. Every operation
* on the tree causes a splay to happen. The splay moves the requested
* node to the root of the tree and partly rebalances it.
*
* This has the benefit that request locality causes faster lookups as
* the requested nodes move to the top of the tree. On the other hand,
* every lookup causes memory writes.
*
* The Balance Theorem bounds the total access time for m operations
* and n inserts on an initially empty tree as O((m + n)lg n). The
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
*
* A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the
* same number of black nodes,
* - each red node (except for the root) has a black parent,
* - each leaf node is black.
*
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{ NULL }
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
static __inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return(NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
static __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
static __inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
/* Main splay operation.
* Moves node close to the key of elm to top
*/
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type * \
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void \
name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
/* Splay with either the minimum or the maximum element \
* Used to find minimum or maximum element in tree. \
*/ \
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
}
#define RB_INITIALIZER(root) \
{ NULL }
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#define RB_LEFT(elm, field) (elm)->field.rbe_left
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
#define RB_COLOR(elm, field) (elm)->field.rbe_color
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
RB_PROTOTYPE_INSERT(name, type, attr); \
RB_PROTOTYPE_REMOVE(name, type, attr); \
RB_PROTOTYPE_FIND(name, type, attr); \
RB_PROTOTYPE_NFIND(name, type, attr); \
RB_PROTOTYPE_NEXT(name, type, attr); \
RB_PROTOTYPE_PREV(name, type, attr); \
RB_PROTOTYPE_MINMAX(name, type, attr);
#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
#define RB_PROTOTYPE_REMOVE(name, type, attr) \
attr struct type *name##_RB_REMOVE(struct name *, struct type *)
#define RB_PROTOTYPE_INSERT(name, type, attr) \
attr struct type *name##_RB_INSERT(struct name *, struct type *)
#define RB_PROTOTYPE_FIND(name, type, attr) \
attr struct type *name##_RB_FIND(struct name *, struct type *)
#define RB_PROTOTYPE_NFIND(name, type, attr) \
attr struct type *name##_RB_NFIND(struct name *, struct type *)
#define RB_PROTOTYPE_NEXT(name, type, attr) \
attr struct type *name##_RB_NEXT(struct type *)
#define RB_PROTOTYPE_PREV(name, type, attr) \
attr struct type *name##_RB_PREV(struct type *)
#define RB_PROTOTYPE_MINMAX(name, type, attr) \
attr struct type *name##_RB_MINMAX(struct name *, int)
/* Main rb operation.
* Moves node close to the key of elm to top
*/
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
RB_GENERATE_REMOVE(name, type, field, attr) \
RB_GENERATE_FIND(name, type, field, cmp, attr) \
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
RB_GENERATE_NEXT(name, type, field, attr) \
RB_GENERATE_PREV(name, type, field, attr) \
RB_GENERATE_MINMAX(name, type, field, attr)
#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_LEFT(head, gparent, tmp, field); \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
}
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
if (RB_LEFT(parent, field) == elm) { \
tmp = RB_RIGHT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = RB_RIGHT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
tmp = RB_RIGHT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_RIGHT(tmp, field)) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_LEFT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} else { \
tmp = RB_LEFT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = RB_LEFT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
tmp = RB_LEFT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_LEFT(tmp, field)) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_RIGHT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} \
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
}
#define RB_GENERATE_REMOVE(name, type, field, attr) \
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
int color; \
if (RB_LEFT(elm, field) == NULL) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
RB_LEFT(RB_PARENT(old, field), field) = elm;\
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
/* Inserts a node into the RB tree */ \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
}
#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
/* Finds the node with the same key as elm */ \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (NULL); \
}
#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
}
#define RB_GENERATE_NEXT(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
}
#define RB_GENERATE_PREV(name, type, field, attr) \
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
}
#define RB_GENERATE_MINMAX(name, type, field, attr) \
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \
else \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
}
#define RB_NEGINF -1
#define RB_INF 1
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_FROM(x, name, y) \
for ((x) = (y); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
(x) = (y))
#endif /* _SYS_TREE_H_ */

View File

@@ -0,0 +1,377 @@
/* zip.h -- IO on .zip files using zlib
Version 1.1, February 14h, 2010
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
---------------------------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
---------------------------------------------------------------------------
Changes
See header of zip.h
*/
/* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
#ifndef _WIN32
#pragma GCC system_header
#endif
#ifndef _zip12_H
#define _zip12_H
#ifdef __cplusplus
extern "C" {
#endif
/*#define HAVE_BZIP2*/
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
/* Encryption not required by libxlsxwriter. */
#ifndef NOCRYPT
#define NOCRYPT
#endif
#ifndef NOUNCRYPT
#define NOUNCRYPT
#endif
#ifdef HAVE_BZIP2
#include "bzlib.h"
#endif
#define Z_BZIP2ED 12
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
int tm_sec; /* seconds after the minute - [0,59] */
int tm_min; /* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen(const char *pathname, int append);
extern zipFile ZEXPORT zipOpen64(const void *pathname, int append);
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of course, you can use RAW reading and writing to copy the file you did not want delete
*/
extern zipFile ZEXPORT zipOpen2(const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def);
extern zipFile ZEXPORT zipOpen2_64(const void *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc64_def* pzlib_filefunc_def);
extern zipFile ZEXPORT zipOpen3(const void *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc64_32_def* pzlib_filefunc64_32_def);
extern int ZEXPORT zipOpenNewFileInZip(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level);
extern int ZEXPORT zipOpenNewFileInZip64(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int zip64);
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
zip64 is set to 1 if a zip64 extended information block should be added to the local file header.
this MUST be '1' if the uncompressed size is >= 0xffffffff.
*/
extern int ZEXPORT zipOpenNewFileInZip2(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw);
extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int zip64);
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting);
extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
int zip64);
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCrypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipOpenNewFileInZip4(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase);
extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCrypting,
uLong versionMadeBy,
uLong flagBase,
int zip64);
/*
Same than zipOpenNewFileInZip4, except
versionMadeBy : value for Version made by field
flag : value for flag field (compression level info will be added)
*/
extern int ZEXPORT zipWriteInFileInZip(zipFile file,
const void* buf,
unsigned len);
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip(zipFile file);
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw(zipFile file,
uLong uncompressed_size,
uLong crc32);
extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file,
ZPOS64_T uncompressed_size,
uLong crc32);
/*
Close the current file in the zipfile, for file opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose(zipFile file,
const char* global_comment);
/*
Close the zipfile
*/
extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader);
/*
zipRemoveExtraInfoBlock - Added by Mathias Svensson
Remove extra information block from a extra information data for the local file header or central directory header
It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.
0x0001 is the signature header for the ZIP64 extra information blocks
usage.
Remove ZIP64 Extra information from a central director extra field data
zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);
Remove ZIP64 Extra information from a Local File Header extra field data
zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip64_H */

View File

@@ -0,0 +1,258 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*/
/**
* @file utility.h
*
* @brief Utility functions for libxlsxwriter.
*
* <!-- Copyright 2014-2022, John McNamara, jmcnamara@cpan.org -->
*
*/
#ifndef __LXW_UTILITY_H__
#define __LXW_UTILITY_H__
#include <stdint.h>
#ifndef _MSC_VER
#include <strings.h>
#endif
#include "common.h"
#include "xmlwriter.h"
/**
* @brief Convert an Excel `A1` cell string into a `(row, col)` pair.
*
* Convert an Excel `A1` cell string into a `(row, col)` pair.
*
* This is a little syntactic shortcut to help with worksheet layout:
*
* @code
* worksheet_write_string(worksheet, CELL("A1"), "Foo", NULL);
*
* //Same as:
* worksheet_write_string(worksheet, 0, 0, "Foo", NULL);
* @endcode
*
* @note
*
* This macro shouldn't be used in performance critical situations since it
* expands to two function calls.
*/
#define CELL(cell) \
lxw_name_to_row(cell), lxw_name_to_col(cell)
/**
* @brief Convert an Excel `A:B` column range into a `(col1, col2)` pair.
*
* Convert an Excel `A:B` column range into a `(col1, col2)` pair.
*
* This is a little syntactic shortcut to help with worksheet layout:
*
* @code
* worksheet_set_column(worksheet, COLS("B:D"), 20, NULL, NULL);
*
* // Same as:
* worksheet_set_column(worksheet, 1, 3, 20, NULL, NULL);
* @endcode
*
*/
#define COLS(cols) \
lxw_name_to_col(cols), lxw_name_to_col_2(cols)
/**
* @brief Convert an Excel `A1:B2` range into a `(first_row, first_col,
* last_row, last_col)` sequence.
*
* Convert an Excel `A1:B2` range into a `(first_row, first_col, last_row,
* last_col)` sequence.
*
* This is a little syntactic shortcut to help with worksheet layout.
*
* @code
* worksheet_print_area(worksheet, 0, 0, 41, 10); // A1:K42.
*
* // Same as:
* worksheet_print_area(worksheet, RANGE("A1:K42"));
* @endcode
*/
#define RANGE(range) \
lxw_name_to_row(range), lxw_name_to_col(range), \
lxw_name_to_row_2(range), lxw_name_to_col_2(range)
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/**
* @brief Retrieve the library version.
*
* @return The "X.Y.Z" version string.
*
* Get the library version as a "X.Y.Z" version string
*
* @code
* printf("Libxlsxwriter version = %s\n", lxw_version());
* @endcode
*
*/
const char *lxw_version(void);
/**
* @brief Retrieve the library version ID.
*
* @return The version ID.
*
* Get the library version such as "X.Y.Z" as a XYZ integer.
*
* @code
* printf("Libxlsxwriter version id = %d\n", lxw_version_id());
* @endcode
*
*/
uint16_t lxw_version_id(void);
/**
* @brief Converts a libxlsxwriter error number to a string.
*
* The `%lxw_strerror` function converts a libxlsxwriter error number defined
* by #lxw_error to a pointer to a string description of the error.
* Similar to the standard library strerror(3) function.
*
* For example:
*
* @code
* lxw_error error = workbook_close(workbook);
*
* if (error)
* printf("Error in workbook_close().\n"
* "Error %d = %s\n", error, lxw_strerror(error));
* @endcode
*
* This would produce output like the following if the target file wasn't
* writable:
*
* Error in workbook_close().
* Error 2 = Error creating output xlsx file. Usually a permissions error.
*
* @param error_num The error number returned by a libxlsxwriter function.
*
* @return A pointer to a statically allocated string. Do not free.
*/
char *lxw_strerror(lxw_error error_num);
/* Create a quoted version of the worksheet name */
char *lxw_quote_sheetname(const char *str);
void lxw_col_to_name(char *col_name, lxw_col_t col_num, uint8_t absolute);
void lxw_rowcol_to_cell(char *cell_name, lxw_row_t row, lxw_col_t col);
void lxw_rowcol_to_cell_abs(char *cell_name,
lxw_row_t row,
lxw_col_t col, uint8_t abs_row, uint8_t abs_col);
void lxw_rowcol_to_range(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
void lxw_rowcol_to_range_abs(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
void lxw_rowcol_to_formula_abs(char *formula, const char *sheetname,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col);
uint32_t lxw_name_to_row(const char *row_str);
uint16_t lxw_name_to_col(const char *col_str);
uint32_t lxw_name_to_row_2(const char *row_str);
uint16_t lxw_name_to_col_2(const char *col_str);
/**
* @brief Converts a #lxw_datetime to an Excel datetime number.
*
* @param datetime A pointer to a #lxw_datetime struct.
*
* @return A double representing an Excel datetime.
*
* The `%lxw_datetime_to_excel_datetime()` function converts a datetime in
* #lxw_datetime to an Excel datetime number:
*
* @code
* lxw_datetime datetime = {2013, 2, 28, 12, 0, 0.0};
*
* double excel_datetime = lxw_datetime_to_excel_date(&datetime);
* @endcode
*
* See @ref working_with_dates for more details on the Excel datetime format.
*/
double lxw_datetime_to_excel_datetime(lxw_datetime *datetime);
double lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime,
uint8_t date_1904);
/**
* @brief Converts a unix datetime to an Excel datetime number.
*
* @param unixtime Unix time (seconds since 1970-01-01)
*
* @return A double representing an Excel datetime.
*
* The `%lxw_unixtime_to_excel_date()` function converts a unix datetime to
* an Excel datetime number:
*
* @code
* double excel_datetime = lxw_unixtime_to_excel_date(946684800);
* @endcode
*
* See @ref working_with_dates for more details.
*/
double lxw_unixtime_to_excel_date(int64_t unixtime);
double lxw_unixtime_to_excel_date_epoch(int64_t unixtime, uint8_t date_1904);
char *lxw_strdup(const char *str);
char *lxw_strdup_formula(const char *formula);
size_t lxw_utf8_strlen(const char *str);
void lxw_str_tolower(char *str);
/* Define a portable version of strcasecmp(). */
#ifdef _MSC_VER
#define lxw_strcasecmp _stricmp
#else
#define lxw_strcasecmp strcasecmp
#endif
FILE *lxw_tmpfile(const char *tmpdir);
FILE *lxw_get_filehandle(char **buf, size_t *size, const char *tmpdir);
FILE *lxw_fopen(const char *filename, const char *mode);
/* Use the third party dtoa function to avoid locale issues with sprintf
* double formatting. Otherwise we use a simple macro that falls back to the
* default c-lib sprintf.
*/
#ifdef USE_DTOA_LIBRARY
int lxw_sprintf_dbl(char *data, double number);
#else
#define lxw_sprintf_dbl(data, number) \
lxw_snprintf(data, LXW_ATTR_32, "%.16G", number)
#endif
uint16_t lxw_hash_password(const char *password);
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_UTILITY_H__ */

View File

@@ -0,0 +1,55 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* vml - A libxlsxwriter library for creating Excel XLSX vml files.
*
*/
#ifndef __LXW_VML_H__
#define __LXW_VML_H__
#include <stdint.h>
#include "common.h"
#include "worksheet.h"
/*
* Struct to represent a vml object.
*/
typedef struct lxw_vml {
FILE *file;
uint8_t type;
struct lxw_comment_objs *button_objs;
struct lxw_comment_objs *comment_objs;
struct lxw_comment_objs *image_objs;
char *vml_data_id_str;
uint32_t vml_shape_id;
uint8_t comment_display_default;
} lxw_vml;
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
lxw_vml *lxw_vml_new(void);
void lxw_vml_free(lxw_vml *vml);
void lxw_vml_assemble_xml_file(lxw_vml *self);
/* Declarations required for unit testing. */
#ifdef TESTING
#endif /* TESTING */
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __LXW_VML_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/*
* libxlsxwriter
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
* xmlwriter - A libxlsxwriter library for creating Excel XLSX
* XML files.
*
* The xmlwriter library is used to create the XML sub-components files
* in the Excel XLSX file format.
*
* This library is used in preference to a more generic XML library to allow
* for customization and optimization for the XLSX file format.
*
* The xmlwriter functions are only used internally and do not need to be
* called directly by the end user.
*
*/
#ifndef __XMLWRITER_H__
#define __XMLWRITER_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "utility.h"
#define LXW_MAX_ATTRIBUTE_LENGTH 2080 /* Max URL length. */
#define LXW_ATTR_32 32
#define LXW_ATTRIBUTE_COPY(dst, src) \
do{ \
strncpy(dst, src, LXW_MAX_ATTRIBUTE_LENGTH -1); \
dst[LXW_MAX_ATTRIBUTE_LENGTH - 1] = '\0'; \
} while (0)
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/* Attribute used in XML elements. */
struct xml_attribute {
char key[LXW_MAX_ATTRIBUTE_LENGTH];
char value[LXW_MAX_ATTRIBUTE_LENGTH];
/* Make the struct a queue.h list element. */
STAILQ_ENTRY (xml_attribute) list_entries;
};
/* Use queue.h macros to define the xml_attribute_list type. */
STAILQ_HEAD(xml_attribute_list, xml_attribute);
/* Create a new attribute struct to add to a xml_attribute_list. */
struct xml_attribute *lxw_new_attribute_str(const char *key,
const char *value);
struct xml_attribute *lxw_new_attribute_int(const char *key, uint64_t value);
struct xml_attribute *lxw_new_attribute_dbl(const char *key, double value);
/* Macro to initialize the xml_attribute_list pointers. */
#define LXW_INIT_ATTRIBUTES() \
STAILQ_INIT(&attributes)
/* Macro to add attribute string elements to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_STR(key, value) \
do { \
attribute = lxw_new_attribute_str((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to add attribute int values to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_INT(key, value) \
do { \
attribute = lxw_new_attribute_int((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to add attribute double values to xml_attribute_list. */
#define LXW_PUSH_ATTRIBUTES_DBL(key, value) \
do { \
attribute = lxw_new_attribute_dbl((key), (value)); \
STAILQ_INSERT_TAIL(&attributes, attribute, list_entries); \
} while (0)
/* Macro to free xml_attribute_list and attribute. */
#define LXW_FREE_ATTRIBUTES() \
do { \
while (!STAILQ_EMPTY(&attributes)) { \
attribute = STAILQ_FIRST(&attributes); \
STAILQ_REMOVE_HEAD(&attributes, list_entries); \
free(attribute); \
} \
} while (0)
/**
* Create the XML declaration in an XML file.
*
* @param xmlfile A FILE pointer to the output XML file.
*/
void lxw_xml_declaration(FILE * xmlfile);
/**
* Write an XML start tag with optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_start_tag(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML start tag with optional un-encoded attributes.
* This is a minor optimization for attributes that don't need encoding.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_start_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML end tag.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
*/
void lxw_xml_end_tag(FILE * xmlfile, const char *tag);
/**
* Write an XML empty tag with optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_empty_tag(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML empty tag with optional un-encoded attributes.
* This is a minor optimization for attributes that don't need encoding.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_empty_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes);
/**
* Write an XML element containing data and optional attributes.
*
* @param xmlfile A FILE pointer to the output XML file.
* @param tag The XML tag to write.
* @param data The data section of the XML element.
* @param attributes An optional list of attributes to add to the tag.
*/
void lxw_xml_data_element(FILE * xmlfile,
const char *tag,
const char *data,
struct xml_attribute_list *attributes);
void lxw_xml_rich_si_element(FILE * xmlfile, const char *string);
uint8_t lxw_has_control_characters(const char *string);
char *lxw_escape_control_characters(const char *string);
char *lxw_escape_url_characters(const char *string, uint8_t escape_hash);
char *lxw_escape_data(const char *data);
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* __XMLWRITER_H__ */

0
SLNKXLSX/libxlsxwriter/lib/.gitignore vendored Normal file
View File

View File

@@ -0,0 +1,192 @@
###############################################################################
#
# Makefile for libxlsxwriter library.
#
# Copyright 2014-2022, John McNamara, jmcnamara@cpan.org
#
# Keep the output quiet by default.
Q=@
ifdef V
Q=
endif
DESTDIR ?=
PREFIX ?= /usr/local
OPT_LEVEL ?= -O3
SOVERSION = $(shell sed -n -e 's/.*LXW_SOVERSION \"\(.*\)\"/\1/p' ../include/xlsxwriter.h)
# Directory variables.
OBJS_DIR = .
INC_DIR = ../include
LIBS = -lz
ifdef USE_SYSTEM_MINIZIP
LIBS += -lminizip
CFLAGS += -DUSE_SYSTEM_MINIZIP
else
# Use the local copy of minizip.
MINIZIP_DIR = ../third_party/minizip
MINIZIP_OBJ = $(MINIZIP_DIR)/ioapi.o $(MINIZIP_DIR)/zip.o
MINIZIP_SO = $(MINIZIP_DIR)/ioapi.so $(MINIZIP_DIR)/zip.so
endif
ifdef USE_STANDARD_TMPFILE
# Use standard/C tmpfile().
CFLAGS += -DUSE_STANDARD_TMPFILE
else
# Use tmpfileplus (the default).
TMPFILEPLUS_DIR = ../third_party/tmpfileplus
TMPFILEPLUS_OBJ = $(TMPFILEPLUS_DIR)/tmpfileplus.o
TMPFILEPLUS_SO = $(TMPFILEPLUS_DIR)/tmpfileplus.so
endif
ifdef USE_NO_MD5
# Don't use MD5 to avoid duplicate image files.
CFLAGS += -DUSE_NO_MD5
else
ifdef USE_OPENSSL_MD5
CFLAGS += -DUSE_OPENSSL_MD5 -Wno-deprecated-declarations
LIBS += -lcrypto
else
# Use md5 (the default).
MD5_DIR = ../third_party/md5
MD5_OBJ = $(MD5_DIR)/md5.o
MD5_SO = $(MD5_DIR)/md5.so
endif
endif
# Set flag for big endian architecture.
ifdef USE_BIG_ENDIAN
CFLAGS += -DLXW_BIG_ENDIAN
endif
# Use a third party double number formatting function.
ifdef USE_DTOA_LIBRARY
CFLAGS += -DUSE_DTOA_LIBRARY
DTOA_LIB_DIR = ../third_party/dtoa
DTOA_LIB_OBJ = $(DTOA_LIB_DIR)/emyg_dtoa.o
DTOA_LIB_SO = $(DTOA_LIB_DIR)/emyg_dtoa.so
endif
# Use fmemopen()/open_memstream() to avoid creating temporary files
ifdef USE_MEM_FILE
USE_FMEMOPEN = 1
endif
ifdef USE_FMEMOPEN
CFLAGS += -DUSE_FMEMOPEN
endif
# Flags passed to compiler.
CFLAGS += -g $(OPT_LEVEL) -Wall -Wextra -Wstrict-prototypes -pedantic -ansi
# Ignore icc remarks about inlining limits.
ifeq ($(CC),icc)
CFLAGS +=-diag-disable=11074,11076
endif
# Library names.
LIBXLSXWRITER_A = libxlsxwriter.a
LIBXLSXWRITER_SO = libxlsxwriter.so.$(SOVERSION)
# Library with additional non-static functions for testing.
LIBXLSXWRITER_TO = libxlsxwriter_test.a
# Flags passed to static linker.
ARFLAGS = rc
# Flags passed to dynamic linker.
FPIC = -fPIC
SOFLAGS = -shared $(FPIC) -Wl,-soname,$(LIBXLSXWRITER_SO)
# Get Env/OS name.
UNAME := $(shell uname)
# Change make options on OS X.
ifeq ($(UNAME), Darwin)
LIBXLSXWRITER_SO = libxlsxwriter.$(SOVERSION).dylib
SOFLAGS = -dynamiclib $(FPIC) -compatibility_version $(SOVERSION) -install_name $(PREFIX)/lib/$(LIBXLSXWRITER_SO) $(GCOV)
endif
# Check for MinGW/MinGW64/Cygwin environments.
ifneq (,$(findstring MINGW, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring MSYS, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring CYGWIN, $(UNAME)))
MING_LIKE = y
endif
# Change make options on MinGW/MinGW64/Cygwin.
ifdef MING_LIKE
LIBXLSXWRITER_SO = libxlsxwriter.dll
FPIC =
CC = gcc
CFLAGS += -Wno-char-subscripts -Wno-long-long
endif
# Headers as dependecies.
HDRS = $(wildcard ../include/xlsxwriter/*.h)
# Ojects to compile.
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
SOBJS = $(patsubst %.c,%.so,$(SRCS))
TOBJS = $(patsubst %.c,%.to,$(SRCS))
# End of OBJS
# Build the object files and the libraries.
all : $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO)
$(Q)cp $(LIBXLSXWRITER_A) $(LIBXLSXWRITER_SO) ../lib
ifeq ($(UNAME), Darwin)
$(Q)rm -f ../lib/libxlsxwriter.dylib
$(Q)ln -s $(LIBXLSXWRITER_SO) ../lib/libxlsxwriter.dylib
endif
ifneq ($(UNAME), Darwin)
$(Q)rm -f ../lib/libxlsxwriter.so
$(Q)ln -s $(LIBXLSXWRITER_SO) ../lib/libxlsxwriter.so
endif
test_lib : libxlsxwriter_test.a
# The static library.
$(LIBXLSXWRITER_A) : $(OBJS)
$(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_OBJ) $(TMPFILEPLUS_OBJ) $(DTOA_LIB_OBJ) $(MD5_OBJ) $^
# The dynamic library.
ifeq ($(findstring m32,$(CFLAGS)),m32)
ARCH = -m32
endif
$(LIBXLSXWRITER_SO) : $(SOBJS)
$(Q)$(CC) $(LDFLAGS) $(SOFLAGS) $(ARCH) $(TARGET_ARCH) -o $@ $(MINIZIP_SO) $(TMPFILEPLUS_SO) $(MD5_SO) $(DTOA_LIB_SO) $^ $(LIBS)
# The test library.
$(LIBXLSXWRITER_TO) : $(TOBJS)
$(Q)$(AR) $(ARFLAGS) $@ $(MINIZIP_OBJ) $(TMPFILEPLUS_OBJ) $(DTOA_LIB_SO) $(MD5_OBJ) $^
# Minimal target for quick compile without creating the libs.
test_compile : $(OBJS)
# Targets for the object files.
%.o : %.c $(HDRS)
$(Q)$(CC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(TARGET_ARCH) $(GCOV) -c $<
%.so : %.c $(HDRS)
$(Q)$(CC) $(FPIC) -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(TARGET_ARCH) $(GCOV) -c $< -o $@
%.to : %.c $(HDRS)
$(Q)$(CC) -g $(OPT_LEVEL) -DTESTING -I$(INC_DIR) $(CFLAGS) $(CXXFLAGS) $(GCOV) -c $< -o $@
# Clean up any temp/build files.
clean :
$(Q)rm -f *.o *.a *.so *.so.* *.to *.dylib *.dll *.gcno *.gcda

View File

@@ -0,0 +1,446 @@
/*****************************************************************************
* app - A library for creating Excel XLSX app files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/app.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new app object.
*/
lxw_app *
lxw_app_new(void)
{
lxw_app *app = calloc(1, sizeof(lxw_app));
GOTO_LABEL_ON_MEM_ERROR(app, mem_error);
app->heading_pairs = calloc(1, sizeof(struct lxw_heading_pairs));
GOTO_LABEL_ON_MEM_ERROR(app->heading_pairs, mem_error);
STAILQ_INIT(app->heading_pairs);
app->part_names = calloc(1, sizeof(struct lxw_part_names));
GOTO_LABEL_ON_MEM_ERROR(app->part_names, mem_error);
STAILQ_INIT(app->part_names);
return app;
mem_error:
lxw_app_free(app);
return NULL;
}
/*
* Free a app object.
*/
void
lxw_app_free(lxw_app *app)
{
lxw_heading_pair *heading_pair;
lxw_part_name *part_name;
if (!app)
return;
/* Free the lists in the App object. */
if (app->heading_pairs) {
while (!STAILQ_EMPTY(app->heading_pairs)) {
heading_pair = STAILQ_FIRST(app->heading_pairs);
STAILQ_REMOVE_HEAD(app->heading_pairs, list_pointers);
free(heading_pair->key);
free(heading_pair->value);
free(heading_pair);
}
free(app->heading_pairs);
}
if (app->part_names) {
while (!STAILQ_EMPTY(app->part_names)) {
part_name = STAILQ_FIRST(app->part_names);
STAILQ_REMOVE_HEAD(app->part_names, list_pointers);
free(part_name->name);
free(part_name);
}
free(app->part_names);
}
free(app);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_app_xml_declaration(lxw_app *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <Properties> element.
*/
STATIC void
_write_properties(lxw_app *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] = LXW_SCHEMA_OFFICEDOC "/extended-properties";
char xmlns_vt[] = LXW_SCHEMA_OFFICEDOC "/docPropsVTypes";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_STR("xmlns:vt", xmlns_vt);
lxw_xml_start_tag(self->file, "Properties", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <Application> element.
*/
STATIC void
_write_application(lxw_app *self)
{
lxw_xml_data_element(self->file, "Application", "Microsoft Excel", NULL);
}
/*
* Write the <DocSecurity> element.
*/
STATIC void
_write_doc_security(lxw_app *self)
{
if (self->doc_security == 2)
lxw_xml_data_element(self->file, "DocSecurity", "2", NULL);
else
lxw_xml_data_element(self->file, "DocSecurity", "0", NULL);
}
/*
* Write the <ScaleCrop> element.
*/
STATIC void
_write_scale_crop(lxw_app *self)
{
lxw_xml_data_element(self->file, "ScaleCrop", "false", NULL);
}
/*
* Write the <vt:lpstr> element.
*/
STATIC void
_write_vt_lpstr(lxw_app *self, const char *str)
{
lxw_xml_data_element(self->file, "vt:lpstr", str, NULL);
}
/*
* Write the <vt:i4> element.
*/
STATIC void
_write_vt_i4(lxw_app *self, const char *value)
{
lxw_xml_data_element(self->file, "vt:i4", value, NULL);
}
/*
* Write the <vt:variant> element.
*/
STATIC void
_write_vt_variant(lxw_app *self, const char *key, const char *value)
{
/* Write the vt:lpstr element. */
lxw_xml_start_tag(self->file, "vt:variant", NULL);
_write_vt_lpstr(self, key);
lxw_xml_end_tag(self->file, "vt:variant");
/* Write the vt:i4 element. */
lxw_xml_start_tag(self->file, "vt:variant", NULL);
_write_vt_i4(self, value);
lxw_xml_end_tag(self->file, "vt:variant");
}
/*
* Write the <vt:vector> element for the heading pairs.
*/
STATIC void
_write_vt_vector_heading_pairs(lxw_app *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
lxw_heading_pair *heading_pair;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("size", self->num_heading_pairs * 2);
LXW_PUSH_ATTRIBUTES_STR("baseType", "variant");
lxw_xml_start_tag(self->file, "vt:vector", &attributes);
STAILQ_FOREACH(heading_pair, self->heading_pairs, list_pointers) {
_write_vt_variant(self, heading_pair->key, heading_pair->value);
}
lxw_xml_end_tag(self->file, "vt:vector");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <vt:vector> element for the named parts.
*/
STATIC void
_write_vt_vector_lpstr_named_parts(lxw_app *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
lxw_part_name *part_name;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("size", self->num_part_names);
LXW_PUSH_ATTRIBUTES_STR("baseType", "lpstr");
lxw_xml_start_tag(self->file, "vt:vector", &attributes);
STAILQ_FOREACH(part_name, self->part_names, list_pointers) {
_write_vt_lpstr(self, part_name->name);
}
lxw_xml_end_tag(self->file, "vt:vector");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <HeadingPairs> element.
*/
STATIC void
_write_heading_pairs(lxw_app *self)
{
lxw_xml_start_tag(self->file, "HeadingPairs", NULL);
/* Write the vt:vector element. */
_write_vt_vector_heading_pairs(self);
lxw_xml_end_tag(self->file, "HeadingPairs");
}
/*
* Write the <TitlesOfParts> element.
*/
STATIC void
_write_titles_of_parts(lxw_app *self)
{
lxw_xml_start_tag(self->file, "TitlesOfParts", NULL);
/* Write the vt:vector element. */
_write_vt_vector_lpstr_named_parts(self);
lxw_xml_end_tag(self->file, "TitlesOfParts");
}
/*
* Write the <Manager> element.
*/
STATIC void
_write_manager(lxw_app *self)
{
lxw_doc_properties *properties = self->properties;
if (!properties)
return;
if (properties->manager)
lxw_xml_data_element(self->file, "Manager", properties->manager,
NULL);
}
/*
* Write the <Company> element.
*/
STATIC void
_write_company(lxw_app *self)
{
lxw_doc_properties *properties = self->properties;
if (properties && properties->company)
lxw_xml_data_element(self->file, "Company", properties->company,
NULL);
else
lxw_xml_data_element(self->file, "Company", "", NULL);
}
/*
* Write the <LinksUpToDate> element.
*/
STATIC void
_write_links_up_to_date(lxw_app *self)
{
lxw_xml_data_element(self->file, "LinksUpToDate", "false", NULL);
}
/*
* Write the <SharedDoc> element.
*/
STATIC void
_write_shared_doc(lxw_app *self)
{
lxw_xml_data_element(self->file, "SharedDoc", "false", NULL);
}
/*
* Write the <HyperlinkBase> element.
*/
STATIC void
_write_hyperlink_base(lxw_app *self)
{
lxw_doc_properties *properties = self->properties;
if (!properties)
return;
if (properties->hyperlink_base)
lxw_xml_data_element(self->file, "HyperlinkBase",
properties->hyperlink_base, NULL);
}
/*
* Write the <HyperlinksChanged> element.
*/
STATIC void
_write_hyperlinks_changed(lxw_app *self)
{
lxw_xml_data_element(self->file, "HyperlinksChanged", "false", NULL);
}
/*
* Write the <AppVersion> element.
*/
STATIC void
_write_app_version(lxw_app *self)
{
lxw_xml_data_element(self->file, "AppVersion", "12.0000", NULL);
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_app_assemble_xml_file(lxw_app *self)
{
/* Write the XML declaration. */
_app_xml_declaration(self);
_write_properties(self);
_write_application(self);
_write_doc_security(self);
_write_scale_crop(self);
_write_heading_pairs(self);
_write_titles_of_parts(self);
_write_manager(self);
_write_company(self);
_write_links_up_to_date(self);
_write_shared_doc(self);
_write_hyperlink_base(self);
_write_hyperlinks_changed(self);
_write_app_version(self);
lxw_xml_end_tag(self->file, "Properties");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Add the name of a workbook Part such as 'Sheet1' or 'Print_Titles'.
*/
void
lxw_app_add_part_name(lxw_app *self, const char *name)
{
lxw_part_name *part_name;
if (!name)
return;
part_name = calloc(1, sizeof(lxw_part_name));
GOTO_LABEL_ON_MEM_ERROR(part_name, mem_error);
part_name->name = lxw_strdup(name);
GOTO_LABEL_ON_MEM_ERROR(part_name->name, mem_error);
STAILQ_INSERT_TAIL(self->part_names, part_name, list_pointers);
self->num_part_names++;
return;
mem_error:
if (part_name) {
free(part_name->name);
free(part_name);
}
}
/*
* Add the name of a workbook Heading Pair such as 'Worksheets', 'Charts' or
* 'Named Ranges'.
*/
void
lxw_app_add_heading_pair(lxw_app *self, const char *key, const char *value)
{
lxw_heading_pair *heading_pair;
if (!key || !value)
return;
heading_pair = calloc(1, sizeof(lxw_heading_pair));
GOTO_LABEL_ON_MEM_ERROR(heading_pair, mem_error);
heading_pair->key = lxw_strdup(key);
GOTO_LABEL_ON_MEM_ERROR(heading_pair->key, mem_error);
heading_pair->value = lxw_strdup(value);
GOTO_LABEL_ON_MEM_ERROR(heading_pair->value, mem_error);
STAILQ_INSERT_TAIL(self->heading_pairs, heading_pair, list_pointers);
self->num_heading_pairs++;
return;
mem_error:
if (heading_pair) {
free(heading_pair->key);
free(heading_pair->value);
free(heading_pair);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,508 @@
/*****************************************************************************
* chartsheet - A library for creating Excel XLSX chartsheet files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/chartsheet.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new chartsheet object.
*/
lxw_chartsheet *
lxw_chartsheet_new(lxw_worksheet_init_data *init_data)
{
lxw_chartsheet *chartsheet = calloc(1, sizeof(lxw_chartsheet));
GOTO_LABEL_ON_MEM_ERROR(chartsheet, mem_error);
/* Use an embedded worksheet instance to write XML records that are
* shared with worksheet.c. */
chartsheet->worksheet = lxw_worksheet_new(NULL);
GOTO_LABEL_ON_MEM_ERROR(chartsheet->worksheet, mem_error);
if (init_data) {
chartsheet->name = init_data->name;
chartsheet->quoted_name = init_data->quoted_name;
chartsheet->tmpdir = init_data->tmpdir;
chartsheet->index = init_data->index;
chartsheet->hidden = init_data->hidden;
chartsheet->active_sheet = init_data->active_sheet;
chartsheet->first_sheet = init_data->first_sheet;
}
chartsheet->worksheet->is_chartsheet = LXW_TRUE;
chartsheet->worksheet->zoom_scale_normal = LXW_FALSE;
chartsheet->worksheet->orientation = LXW_LANDSCAPE;
return chartsheet;
mem_error:
lxw_chartsheet_free(chartsheet);
return NULL;
}
/*
* Free a chartsheet object.
*/
void
lxw_chartsheet_free(lxw_chartsheet *chartsheet)
{
if (!chartsheet)
return;
lxw_worksheet_free(chartsheet->worksheet);
free((void *) chartsheet->name);
free((void *) chartsheet->quoted_name);
free(chartsheet);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_chartsheet_xml_declaration(lxw_chartsheet *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <chartsheet> element.
*/
STATIC void
_chartsheet_write_chartsheet(lxw_chartsheet *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] = "http://schemas.openxmlformats.org/"
"spreadsheetml/2006/main";
char xmlns_r[] = "http://schemas.openxmlformats.org/"
"officeDocument/2006/relationships";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
lxw_xml_start_tag(self->file, "chartsheet", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <sheetPr> element.
*/
STATIC void
_chartsheet_write_sheet_pr(lxw_chartsheet *self)
{
lxw_worksheet_write_sheet_pr(self->worksheet);
}
/*
* Write the <sheetViews> element.
*/
STATIC void
_chartsheet_write_sheet_views(lxw_chartsheet *self)
{
lxw_worksheet_write_sheet_views(self->worksheet);
}
/*
* Write the <pageMargins> element.
*/
STATIC void
_chartsheet_write_page_margins(lxw_chartsheet *self)
{
lxw_worksheet_write_page_margins(self->worksheet);
}
/*
* Write the <drawing> elements.
*/
STATIC void
_chartsheet_write_drawings(lxw_chartsheet *self)
{
lxw_worksheet_write_drawings(self->worksheet);
}
/*
* Write the <sheetProtection> element.
*/
STATIC void
_chartsheet_write_sheet_protection(lxw_chartsheet *self)
{
lxw_worksheet_write_sheet_protection(self->worksheet, &self->protection);
}
/*
* Write the <pageSetup> element.
*/
STATIC void
_chartsheet_write_page_setup(lxw_chartsheet *self)
{
lxw_worksheet_write_page_setup(self->worksheet);
}
/*
* Write the <headerFooter> element.
*/
STATIC void
_chartsheet_write_header_footer(lxw_chartsheet *self)
{
lxw_worksheet_write_header_footer(self->worksheet);
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_chartsheet_assemble_xml_file(lxw_chartsheet *self)
{
/* Set the embedded worksheet filehandle to the same as the chartsheet. */
self->worksheet->file = self->file;
/* Write the XML declaration. */
_chartsheet_xml_declaration(self);
/* Write the chartsheet element. */
_chartsheet_write_chartsheet(self);
/* Write the sheetPr element. */
_chartsheet_write_sheet_pr(self);
/* Write the sheetViews element. */
_chartsheet_write_sheet_views(self);
/* Write the sheetProtection element. */
_chartsheet_write_sheet_protection(self);
/* Write the pageMargins element. */
_chartsheet_write_page_margins(self);
/* Write the chartsheet page setup. */
_chartsheet_write_page_setup(self);
/* Write the headerFooter element. */
_chartsheet_write_header_footer(self);
/* Write the drawing element. */
_chartsheet_write_drawings(self);
lxw_xml_end_tag(self->file, "chartsheet");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Set a chartsheet chart, with options.
*/
lxw_error
chartsheet_set_chart_opt(lxw_chartsheet *self,
lxw_chart *chart, lxw_chart_options *user_options)
{
lxw_object_properties *object_props;
lxw_chart_series *series;
if (!chart) {
LXW_WARN("chartsheet_set_chart()/_opt(): chart must be non-NULL.");
return LXW_ERROR_NULL_PARAMETER_IGNORED;
}
/* Check that the chart isn't being used more than once. */
if (chart->in_use) {
LXW_WARN("chartsheet_set_chart()/_opt(): the same chart object "
"cannot be set for a chartsheet more than once.");
return LXW_ERROR_PARAMETER_VALIDATION;
}
/* Check that the chart has a data series. */
if (STAILQ_EMPTY(chart->series_list)) {
LXW_WARN("chartsheet_set_chart()/_opt(): chart must have a series.");
return LXW_ERROR_PARAMETER_VALIDATION;
}
/* Check that the chart has a 'values' series. */
STAILQ_FOREACH(series, chart->series_list, list_pointers) {
if (!series->values->formula && !series->values->sheetname) {
LXW_WARN("chartsheet_set_chart()/_opt(): chart must have a "
"'values' series.");
return LXW_ERROR_PARAMETER_VALIDATION;
}
}
/* Create a new object to hold the chart image properties. */
object_props = calloc(1, sizeof(lxw_object_properties));
RETURN_ON_MEM_ERROR(object_props, LXW_ERROR_MEMORY_MALLOC_FAILED);
if (user_options) {
object_props->x_offset = user_options->x_offset;
object_props->y_offset = user_options->y_offset;
object_props->x_scale = user_options->x_scale;
object_props->y_scale = user_options->y_scale;
}
object_props->width = 480;
object_props->height = 288;
if (object_props->x_scale == 0.0)
object_props->x_scale = 1;
if (object_props->y_scale == 0.0)
object_props->y_scale = 1;
/* Store chart references so they can be ordered in the workbook. */
object_props->chart = chart;
/* Store the chart data in the embedded worksheet. */
STAILQ_INSERT_TAIL(self->worksheet->chart_data, object_props,
list_pointers);
chart->in_use = LXW_TRUE;
chart->is_chartsheet = LXW_TRUE;
chart->is_protected = self->is_protected;
self->chart = chart;
return LXW_NO_ERROR;
}
/*
* Set a chartsheet charts.
*/
lxw_error
chartsheet_set_chart(lxw_chartsheet *self, lxw_chart *chart)
{
return chartsheet_set_chart_opt(self, chart, NULL);
}
/*
* Set this chartsheet as a selected worksheet, i.e. the worksheet has its tab
* highlighted.
*/
void
chartsheet_select(lxw_chartsheet *self)
{
self->selected = LXW_TRUE;
/* Selected worksheet can't be hidden. */
self->hidden = LXW_FALSE;
}
/*
* Set this chartsheet as the active worksheet, i.e. the worksheet that is
* displayed when the workbook is opened. Also set it as selected.
*/
void
chartsheet_activate(lxw_chartsheet *self)
{
self->worksheet->selected = LXW_TRUE;
self->worksheet->active = LXW_TRUE;
/* Active worksheet can't be hidden. */
self->worksheet->hidden = LXW_FALSE;
*self->active_sheet = self->index;
}
/*
* Set this chartsheet as the first visible sheet. This is necessary
* when there are a large number of worksheets and the activated
* worksheet is not visible on the screen.
*/
void
chartsheet_set_first_sheet(lxw_chartsheet *self)
{
/* Active worksheet can't be hidden. */
self->hidden = LXW_FALSE;
*self->first_sheet = self->index;
}
/*
* Hide this chartsheet.
*/
void
chartsheet_hide(lxw_chartsheet *self)
{
self->hidden = LXW_TRUE;
/* A hidden worksheet shouldn't be active or selected. */
self->selected = LXW_FALSE;
/* If this is active_sheet or first_sheet reset the workbook value. */
if (*self->first_sheet == self->index)
*self->first_sheet = 0;
if (*self->active_sheet == self->index)
*self->active_sheet = 0;
}
/*
* Set the color of the chartsheet tab.
*/
void
chartsheet_set_tab_color(lxw_chartsheet *self, lxw_color_t color)
{
self->worksheet->tab_color = color;
}
/*
* Set the chartsheet protection flags to prevent modification of chartsheet
* objects.
*/
void
chartsheet_protect(lxw_chartsheet *self, const char *password,
lxw_protection *options)
{
struct lxw_protection_obj *protect = &self->protection;
/* Copy any user parameters to the internal structure. */
if (options) {
protect->objects = options->no_objects;
protect->no_content = options->no_content;
}
else {
protect->objects = LXW_FALSE;
protect->no_content = LXW_FALSE;
}
if (password) {
uint16_t hash = lxw_hash_password(password);
lxw_snprintf(protect->hash, 5, "%X", hash);
}
else {
if (protect->objects && protect->no_content)
return;
}
protect->no_sheet = LXW_TRUE;
protect->scenarios = LXW_TRUE;
protect->is_configured = LXW_TRUE;
if (self->chart)
self->chart->is_protected = LXW_TRUE;
else
self->is_protected = LXW_TRUE;
}
/*
* Set the chartsheet zoom factor.
*/
void
chartsheet_set_zoom(lxw_chartsheet *self, uint16_t scale)
{
/* Confine the scale to Excel"s range */
if (scale < 10 || scale > 400) {
LXW_WARN("chartsheet_set_zoom(): "
"Zoom factor scale outside range: 10 <= zoom <= 400.");
return;
}
self->worksheet->zoom = scale;
}
/*
* Set the page orientation as portrait.
*/
void
chartsheet_set_portrait(lxw_chartsheet *self)
{
worksheet_set_portrait(self->worksheet);
}
/*
* Set the page orientation as landscape.
*/
void
chartsheet_set_landscape(lxw_chartsheet *self)
{
worksheet_set_landscape(self->worksheet);
}
/*
* Set the paper type. Example. 1 = US Letter, 9 = A4
*/
void
chartsheet_set_paper(lxw_chartsheet *self, uint8_t paper_size)
{
worksheet_set_paper(self->worksheet, paper_size);
}
/*
* Set all the page margins in inches.
*/
void
chartsheet_set_margins(lxw_chartsheet *self, double left, double right,
double top, double bottom)
{
worksheet_set_margins(self->worksheet, left, right, top, bottom);
}
/*
* Set the page header caption and options.
*/
lxw_error
chartsheet_set_header_opt(lxw_chartsheet *self, const char *string,
lxw_header_footer_options *options)
{
return worksheet_set_header_opt(self->worksheet, string, options);
}
/*
* Set the page footer caption and options.
*/
lxw_error
chartsheet_set_footer_opt(lxw_chartsheet *self, const char *string,
lxw_header_footer_options *options)
{
return worksheet_set_footer_opt(self->worksheet, string, options);
}
/*
* Set the page header caption.
*/
lxw_error
chartsheet_set_header(lxw_chartsheet *self, const char *string)
{
return chartsheet_set_header_opt(self, string, NULL);
}
/*
* Set the page footer caption.
*/
lxw_error
chartsheet_set_footer(lxw_chartsheet *self, const char *string)
{
return chartsheet_set_footer_opt(self, string, NULL);
}

View File

@@ -0,0 +1,443 @@
/*****************************************************************************
* comment - A library for creating Excel XLSX comment files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/comment.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
STATIC int _author_id_cmp(lxw_author_id *tuple1, lxw_author_id *tuple2);
#ifndef __clang_analyzer__
LXW_RB_GENERATE_AUTHOR_IDS(lxw_author_ids, lxw_author_id,
tree_pointers, _author_id_cmp);
#endif
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Comparator for the author ids.
*/
STATIC int
_author_id_cmp(lxw_author_id *author_id1, lxw_author_id *author_id2)
{
return strcmp(author_id1->author, author_id2->author);
}
/*
* Check if an author already existing in the author/id table.
*/
STATIC uint8_t
_check_author(lxw_comment *self, char *author)
{
lxw_author_id tmp_author_id;
lxw_author_id *existing_author = NULL;
if (!author)
return LXW_TRUE;
tmp_author_id.author = author;
existing_author = RB_FIND(lxw_author_ids,
self->author_ids, &tmp_author_id);
if (existing_author)
return LXW_TRUE;
else
return LXW_FALSE;
}
/*
* Get the index used for an author name.
*/
STATIC uint32_t
_get_author_index(lxw_comment *self, char *author)
{
lxw_author_id tmp_author_id;
lxw_author_id *existing_author = NULL;
lxw_author_id *new_author_id = NULL;
if (!author)
return 0;
tmp_author_id.author = author;
existing_author = RB_FIND(lxw_author_ids,
self->author_ids, &tmp_author_id);
if (existing_author) {
return existing_author->id;
}
else {
new_author_id = calloc(1, sizeof(lxw_author_id));
if (new_author_id) {
new_author_id->id = self->author_id;
new_author_id->author = lxw_strdup(author);
self->author_id++;
RB_INSERT(lxw_author_ids, self->author_ids, new_author_id);
return new_author_id->id;
}
else {
return 0;
}
}
}
/*
* Create a new comment object.
*/
lxw_comment *
lxw_comment_new(void)
{
lxw_comment *comment = calloc(1, sizeof(lxw_comment));
GOTO_LABEL_ON_MEM_ERROR(comment, mem_error);
comment->author_ids = calloc(1, sizeof(struct lxw_author_ids));
GOTO_LABEL_ON_MEM_ERROR(comment->author_ids, mem_error);
RB_INIT(comment->author_ids);
return comment;
mem_error:
lxw_comment_free(comment);
return NULL;
}
/*
* Free a comment object.
*/
void
lxw_comment_free(lxw_comment *comment)
{
struct lxw_author_id *author_id;
struct lxw_author_id *next_author_id;
if (!comment)
return;
if (comment->author_ids) {
for (author_id =
RB_MIN(lxw_author_ids, comment->author_ids);
author_id; author_id = next_author_id) {
next_author_id =
RB_NEXT(lxw_author_ids, worksheet->author_id, author_id);
RB_REMOVE(lxw_author_ids, comment->author_ids, author_id);
free(author_id->author);
free(author_id);
}
free(comment->author_ids);
}
free(comment);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_comment_xml_declaration(lxw_comment *self)
{
lxw_xml_declaration(self->file);
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Write the <t> element.
*/
STATIC void
_comment_write_text_t(lxw_comment *self, lxw_vml_obj *comment_obj)
{
lxw_xml_data_element(self->file, "t", comment_obj->text, NULL);
}
/*
* Write the <family> element.
*/
STATIC void
_comment_write_family(lxw_comment *self, lxw_vml_obj *comment_obj)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("val", comment_obj->font_family);
lxw_xml_empty_tag(self->file, "family", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <rFont> element.
*/
STATIC void
_comment_write_r_font(lxw_comment *self, lxw_vml_obj *comment_obj)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char font_name[LXW_ATTR_32];
if (comment_obj->font_name)
lxw_snprintf(font_name, LXW_ATTR_32, "%s", comment_obj->font_name);
else
lxw_snprintf(font_name, LXW_ATTR_32, "Tahoma");
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("val", font_name);
lxw_xml_empty_tag(self->file, "rFont", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <color> element.
*/
STATIC void
_comment_write_color(lxw_comment *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char indexed[] = "81";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("indexed", indexed);
lxw_xml_empty_tag(self->file, "color", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <sz> element.
*/
STATIC void
_comment_write_sz(lxw_comment *self, lxw_vml_obj *comment_obj)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_DBL("val", comment_obj->font_size);
lxw_xml_empty_tag(self->file, "sz", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <rPr> element.
*/
STATIC void
_comment_write_r_pr(lxw_comment *self, lxw_vml_obj *comment_obj)
{
lxw_xml_start_tag(self->file, "rPr", NULL);
/* Write the sz element. */
_comment_write_sz(self, comment_obj);
/* Write the color element. */
_comment_write_color(self);
/* Write the rFont element. */
_comment_write_r_font(self, comment_obj);
/* Write the family element. */
_comment_write_family(self, comment_obj);
lxw_xml_end_tag(self->file, "rPr");
}
/*
* Write the <r> element.
*/
STATIC void
_comment_write_r(lxw_comment *self, lxw_vml_obj *comment_obj)
{
lxw_xml_start_tag(self->file, "r", NULL);
/* Write the rPr element. */
_comment_write_r_pr(self, comment_obj);
/* Write the t element. */
_comment_write_text_t(self, comment_obj);
lxw_xml_end_tag(self->file, "r");
}
/*
* Write the <text> element.
*/
STATIC void
_comment_write_text(lxw_comment *self, lxw_vml_obj *comment_obj)
{
lxw_xml_start_tag(self->file, "text", NULL);
/* Write the r element. */
_comment_write_r(self, comment_obj);
lxw_xml_end_tag(self->file, "text");
}
/*
* Write the <comment> element.
*/
STATIC void
_comment_write_comment(lxw_comment *self, lxw_vml_obj *comment_obj)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char ref[LXW_MAX_CELL_NAME_LENGTH];
lxw_rowcol_to_cell(ref, comment_obj->row, comment_obj->col);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("ref", ref);
LXW_PUSH_ATTRIBUTES_INT("authorId", comment_obj->author_id);
lxw_xml_start_tag(self->file, "comment", &attributes);
/* Write the text element. */
_comment_write_text(self, comment_obj);
lxw_xml_end_tag(self->file, "comment");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <commentList> element.
*/
STATIC void
_comment_write_comment_list(lxw_comment *self)
{
lxw_vml_obj *comment_obj;
lxw_xml_start_tag(self->file, "commentList", NULL);
STAILQ_FOREACH(comment_obj, self->comment_objs, list_pointers) {
/* Write the comment element. */
_comment_write_comment(self, comment_obj);
}
lxw_xml_end_tag(self->file, "commentList");
}
/*
* Write the <author> element.
*/
STATIC void
_comment_write_author(lxw_comment *self, char *author)
{
lxw_xml_data_element(self->file, "author", author, NULL);
}
/*
* Write the <authors> element.
*/
STATIC void
_comment_write_authors(lxw_comment *self)
{
lxw_vml_obj *comment_obj;
char *author;
lxw_xml_start_tag(self->file, "authors", NULL);
/* Set the default author (from worksheet_set_comments_author()). */
if (self->comment_author) {
_get_author_index(self, self->comment_author);
_comment_write_author(self, self->comment_author);
}
else {
_get_author_index(self, "");
_comment_write_author(self, "");
}
STAILQ_FOREACH(comment_obj, self->comment_objs, list_pointers) {
author = comment_obj->author;
if (author) {
if (!_check_author(self, author))
_comment_write_author(self, author);
comment_obj->author_id = _get_author_index(self, author);
}
}
lxw_xml_end_tag(self->file, "authors");
}
/*
* Write the <comments> element.
*/
STATIC void
_comment_write_comments(lxw_comment *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] =
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
lxw_xml_start_tag(self->file, "comments", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Assemble and write the XML file.
*/
void
lxw_comment_assemble_xml_file(lxw_comment *self)
{
/* Write the XML declaration. */
_comment_xml_declaration(self);
/* Write the comments element. */
_comment_write_comments(self);
/* Write the authors element. */
_comment_write_authors(self);
/* Write the commentList element. */
_comment_write_comment_list(self);
lxw_xml_end_tag(self->file, "comments");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,392 @@
/*****************************************************************************
* content_types - A library for creating Excel XLSX content_types files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/content_types.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new content_types object.
*/
lxw_content_types *
lxw_content_types_new(void)
{
lxw_content_types *content_types = calloc(1, sizeof(lxw_content_types));
GOTO_LABEL_ON_MEM_ERROR(content_types, mem_error);
content_types->default_types = calloc(1, sizeof(struct lxw_tuples));
GOTO_LABEL_ON_MEM_ERROR(content_types->default_types, mem_error);
STAILQ_INIT(content_types->default_types);
content_types->overrides = calloc(1, sizeof(struct lxw_tuples));
GOTO_LABEL_ON_MEM_ERROR(content_types->overrides, mem_error);
STAILQ_INIT(content_types->overrides);
lxw_ct_add_default(content_types, "rels",
LXW_APP_PACKAGE "relationships+xml");
lxw_ct_add_default(content_types, "xml", "application/xml");
lxw_ct_add_override(content_types, "/docProps/app.xml",
LXW_APP_DOCUMENT "extended-properties+xml");
lxw_ct_add_override(content_types, "/docProps/core.xml",
LXW_APP_PACKAGE "core-properties+xml");
lxw_ct_add_override(content_types, "/xl/styles.xml",
LXW_APP_DOCUMENT "spreadsheetml.styles+xml");
lxw_ct_add_override(content_types, "/xl/theme/theme1.xml",
LXW_APP_DOCUMENT "theme+xml");
return content_types;
mem_error:
lxw_content_types_free(content_types);
return NULL;
}
/*
* Free a content_types object.
*/
void
lxw_content_types_free(lxw_content_types *content_types)
{
lxw_tuple *default_type;
lxw_tuple *override;
if (!content_types)
return;
if (content_types->default_types) {
while (!STAILQ_EMPTY(content_types->default_types)) {
default_type = STAILQ_FIRST(content_types->default_types);
STAILQ_REMOVE_HEAD(content_types->default_types, list_pointers);
free(default_type->key);
free(default_type->value);
free(default_type);
}
free(content_types->default_types);
}
if (content_types->overrides) {
while (!STAILQ_EMPTY(content_types->overrides)) {
override = STAILQ_FIRST(content_types->overrides);
STAILQ_REMOVE_HEAD(content_types->overrides, list_pointers);
free(override->key);
free(override->value);
free(override);
}
free(content_types->overrides);
}
free(content_types);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_content_types_xml_declaration(lxw_content_types *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <Types> element.
*/
STATIC void
_write_types(lxw_content_types *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", LXW_SCHEMA_CONTENT);
lxw_xml_start_tag(self->file, "Types", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <Default> element.
*/
STATIC void
_write_default(lxw_content_types *self, const char *ext, const char *type)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("Extension", ext);
LXW_PUSH_ATTRIBUTES_STR("ContentType", type);
lxw_xml_empty_tag(self->file, "Default", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <Override> element.
*/
STATIC void
_write_override(lxw_content_types *self, const char *part_name,
const char *type)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("PartName", part_name);
LXW_PUSH_ATTRIBUTES_STR("ContentType", type);
lxw_xml_empty_tag(self->file, "Override", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Write out all of the <Default> types.
*/
STATIC void
_write_defaults(lxw_content_types *self)
{
lxw_tuple *tuple;
STAILQ_FOREACH(tuple, self->default_types, list_pointers) {
_write_default(self, tuple->key, tuple->value);
}
}
/*
* Write out all of the <Override> types.
*/
STATIC void
_write_overrides(lxw_content_types *self)
{
lxw_tuple *tuple;
STAILQ_FOREACH(tuple, self->overrides, list_pointers) {
_write_override(self, tuple->key, tuple->value);
}
}
/*
* Assemble and write the XML file.
*/
void
lxw_content_types_assemble_xml_file(lxw_content_types *self)
{
/* Write the XML declaration. */
_content_types_xml_declaration(self);
_write_types(self);
_write_defaults(self);
_write_overrides(self);
/* Close the content_types tag. */
lxw_xml_end_tag(self->file, "Types");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Add elements to the ContentTypes defaults.
*/
void
lxw_ct_add_default(lxw_content_types *self, const char *key,
const char *value)
{
lxw_tuple *tuple;
if (!key || !value)
return;
tuple = calloc(1, sizeof(lxw_tuple));
GOTO_LABEL_ON_MEM_ERROR(tuple, mem_error);
tuple->key = lxw_strdup(key);
GOTO_LABEL_ON_MEM_ERROR(tuple->key, mem_error);
tuple->value = lxw_strdup(value);
GOTO_LABEL_ON_MEM_ERROR(tuple->value, mem_error);
STAILQ_INSERT_TAIL(self->default_types, tuple, list_pointers);
return;
mem_error:
if (tuple) {
free(tuple->key);
free(tuple->value);
free(tuple);
}
}
/*
* Add elements to the ContentTypes overrides.
*/
void
lxw_ct_add_override(lxw_content_types *self, const char *key,
const char *value)
{
lxw_tuple *tuple;
if (!key || !value)
return;
tuple = calloc(1, sizeof(lxw_tuple));
GOTO_LABEL_ON_MEM_ERROR(tuple, mem_error);
tuple->key = lxw_strdup(key);
GOTO_LABEL_ON_MEM_ERROR(tuple->key, mem_error);
tuple->value = lxw_strdup(value);
GOTO_LABEL_ON_MEM_ERROR(tuple->value, mem_error);
STAILQ_INSERT_TAIL(self->overrides, tuple, list_pointers);
return;
mem_error:
if (tuple) {
free(tuple->key);
free(tuple->value);
free(tuple);
}
}
/*
* Add the name of a worksheet to the ContentTypes overrides.
*/
void
lxw_ct_add_worksheet_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name,
LXW_APP_DOCUMENT "spreadsheetml.worksheet+xml");
}
/*
* Add the name of a chartsheet to the ContentTypes overrides.
*/
void
lxw_ct_add_chartsheet_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name,
LXW_APP_DOCUMENT "spreadsheetml.chartsheet+xml");
}
/*
* Add the name of a chart to the ContentTypes overrides.
*/
void
lxw_ct_add_chart_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name, LXW_APP_DOCUMENT "drawingml.chart+xml");
}
/*
* Add the name of a drawing to the ContentTypes overrides.
*/
void
lxw_ct_add_drawing_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name, LXW_APP_DOCUMENT "drawing+xml");
}
/*
* Add the name of a table to the ContentTypes overrides.
*/
void
lxw_ct_add_table_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name,
LXW_APP_DOCUMENT "spreadsheetml.table+xml");
}
/*
* Add the name of a VML drawing to the ContentTypes overrides.
*/
void
lxw_ct_add_vml_name(lxw_content_types *self)
{
lxw_ct_add_default(self, "vml", LXW_APP_DOCUMENT "vmlDrawing");
}
/*
* Add the name of a comment to the ContentTypes overrides.
*/
void
lxw_ct_add_comment_name(lxw_content_types *self, const char *name)
{
lxw_ct_add_override(self, name,
LXW_APP_DOCUMENT "spreadsheetml.comments+xml");
}
/*
* Add the sharedStrings link to the ContentTypes overrides.
*/
void
lxw_ct_add_shared_strings(lxw_content_types *self)
{
lxw_ct_add_override(self, "/xl/sharedStrings.xml",
LXW_APP_DOCUMENT "spreadsheetml.sharedStrings+xml");
}
/*
* Add the calcChain link to the ContentTypes overrides.
*/
void
lxw_ct_add_calc_chain(lxw_content_types *self)
{
lxw_ct_add_override(self, "/xl/calcChain.xml",
LXW_APP_DOCUMENT "spreadsheetml.calcChain+xml");
}
/*
* Add the custom properties to the ContentTypes overrides.
*/
void
lxw_ct_add_custom_properties(lxw_content_types *self)
{
lxw_ct_add_override(self, "/docProps/custom.xml",
LXW_APP_DOCUMENT "custom-properties+xml");
}
/*
* Add the metadata file to the ContentTypes overrides.
*/
void
lxw_ct_add_metadata(lxw_content_types *self)
{
lxw_ct_add_override(self, "/xl/metadata.xml",
LXW_APP_DOCUMENT "spreadsheetml.sheetMetadata+xml");
}

View File

@@ -0,0 +1,293 @@
/*****************************************************************************
* core - A library for creating Excel XLSX core files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/core.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new core object.
*/
lxw_core *
lxw_core_new(void)
{
lxw_core *core = calloc(1, sizeof(lxw_core));
GOTO_LABEL_ON_MEM_ERROR(core, mem_error);
return core;
mem_error:
lxw_core_free(core);
return NULL;
}
/*
* Free a core object.
*/
void
lxw_core_free(lxw_core *core)
{
if (!core)
return;
free(core);
}
/*
* Convert a time_t to a ISO 8601 style "2010-01-01T00:00:00Z" date.
*/
static void
_datetime_to_iso8601_date(time_t *timer, char *str, size_t size)
{
struct tm *tmp_datetime;
time_t current_time = time(NULL);
if (*timer)
tmp_datetime = gmtime(timer);
else
tmp_datetime = gmtime(&current_time);
strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ", tmp_datetime);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_core_xml_declaration(lxw_core *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <cp:coreProperties> element.
*/
STATIC void
_write_cp_core_properties(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:cp",
"http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dc", "http://purl.org/dc/elements/1.1/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dcterms", "http://purl.org/dc/terms/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dcmitype", "http://purl.org/dc/dcmitype/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
lxw_xml_start_tag(self->file, "cp:coreProperties", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dc:creator> element.
*/
STATIC void
_write_dc_creator(lxw_core *self)
{
if (self->properties->author) {
lxw_xml_data_element(self->file, "dc:creator",
self->properties->author, NULL);
}
else {
lxw_xml_data_element(self->file, "dc:creator", "", NULL);
}
}
/*
* Write the <cp:lastModifiedBy> element.
*/
STATIC void
_write_cp_last_modified_by(lxw_core *self)
{
if (self->properties->author) {
lxw_xml_data_element(self->file, "cp:lastModifiedBy",
self->properties->author, NULL);
}
else {
lxw_xml_data_element(self->file, "cp:lastModifiedBy", "", NULL);
}
}
/*
* Write the <dcterms:created> element.
*/
STATIC void
_write_dcterms_created(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char datetime[LXW_ATTR_32];
_datetime_to_iso8601_date(&self->properties->created, datetime,
LXW_ATTR_32);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
lxw_xml_data_element(self->file, "dcterms:created", datetime,
&attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dcterms:modified> element.
*/
STATIC void
_write_dcterms_modified(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char datetime[LXW_ATTR_32];
_datetime_to_iso8601_date(&self->properties->created, datetime,
LXW_ATTR_32);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
lxw_xml_data_element(self->file, "dcterms:modified", datetime,
&attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dc:title> element.
*/
STATIC void
_write_dc_title(lxw_core *self)
{
if (!self->properties->title)
return;
lxw_xml_data_element(self->file, "dc:title", self->properties->title,
NULL);
}
/*
* Write the <dc:subject> element.
*/
STATIC void
_write_dc_subject(lxw_core *self)
{
if (!self->properties->subject)
return;
lxw_xml_data_element(self->file, "dc:subject", self->properties->subject,
NULL);
}
/*
* Write the <cp:keywords> element.
*/
STATIC void
_write_cp_keywords(lxw_core *self)
{
if (!self->properties->keywords)
return;
lxw_xml_data_element(self->file, "cp:keywords",
self->properties->keywords, NULL);
}
/*
* Write the <dc:description> element.
*/
STATIC void
_write_dc_description(lxw_core *self)
{
if (!self->properties->comments)
return;
lxw_xml_data_element(self->file, "dc:description",
self->properties->comments, NULL);
}
/*
* Write the <cp:category> element.
*/
STATIC void
_write_cp_category(lxw_core *self)
{
if (!self->properties->category)
return;
lxw_xml_data_element(self->file, "cp:category",
self->properties->category, NULL);
}
/*
* Write the <cp:contentStatus> element.
*/
STATIC void
_write_cp_content_status(lxw_core *self)
{
if (!self->properties->status)
return;
lxw_xml_data_element(self->file, "cp:contentStatus",
self->properties->status, NULL);
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_core_assemble_xml_file(lxw_core *self)
{
/* Write the XML declaration. */
_core_xml_declaration(self);
_write_cp_core_properties(self);
_write_dc_title(self);
_write_dc_subject(self);
_write_dc_creator(self);
_write_cp_keywords(self);
_write_dc_description(self);
_write_cp_last_modified_by(self);
_write_dcterms_created(self);
_write_dcterms_modified(self);
_write_cp_category(self);
_write_cp_content_status(self);
lxw_xml_end_tag(self->file, "cp:coreProperties");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,224 @@
/*****************************************************************************
* custom - A library for creating Excel custom property files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/custom.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new custom object.
*/
lxw_custom *
lxw_custom_new(void)
{
lxw_custom *custom = calloc(1, sizeof(lxw_custom));
GOTO_LABEL_ON_MEM_ERROR(custom, mem_error);
return custom;
mem_error:
lxw_custom_free(custom);
return NULL;
}
/*
* Free a custom object.
*/
void
lxw_custom_free(lxw_custom *custom)
{
if (!custom)
return;
free(custom);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_custom_xml_declaration(lxw_custom *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <vt:lpwstr> element.
*/
STATIC void
_chart_write_vt_lpwstr(lxw_custom *self, char *value)
{
lxw_xml_data_element(self->file, "vt:lpwstr", value, NULL);
}
/*
* Write the <vt:r8> element.
*/
STATIC void
_chart_write_vt_r_8(lxw_custom *self, double value)
{
char data[LXW_ATTR_32];
lxw_sprintf_dbl(data, value);
lxw_xml_data_element(self->file, "vt:r8", data, NULL);
}
/*
* Write the <vt:i4> element.
*/
STATIC void
_custom_write_vt_i_4(lxw_custom *self, int32_t value)
{
char data[LXW_ATTR_32];
lxw_snprintf(data, LXW_ATTR_32, "%d", value);
lxw_xml_data_element(self->file, "vt:i4", data, NULL);
}
/*
* Write the <vt:bool> element.
*/
STATIC void
_custom_write_vt_bool(lxw_custom *self, uint8_t value)
{
if (value)
lxw_xml_data_element(self->file, "vt:bool", "true", NULL);
else
lxw_xml_data_element(self->file, "vt:bool", "false", NULL);
}
/*
* Write the <vt:filetime> element.
*/
STATIC void
_custom_write_vt_filetime(lxw_custom *self, lxw_datetime *datetime)
{
char data[LXW_DATETIME_LENGTH];
lxw_snprintf(data, LXW_DATETIME_LENGTH, "%4d-%02d-%02dT%02d:%02d:%02dZ",
datetime->year, datetime->month, datetime->day,
datetime->hour, datetime->min, (int) datetime->sec);
lxw_xml_data_element(self->file, "vt:filetime", data, NULL);
}
/*
* Write the <property> element.
*/
STATIC void
_chart_write_custom_property(lxw_custom *self,
lxw_custom_property *custom_property)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char fmtid[] = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
self->pid++;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("fmtid", fmtid);
LXW_PUSH_ATTRIBUTES_INT("pid", self->pid + 1);
LXW_PUSH_ATTRIBUTES_STR("name", custom_property->name);
lxw_xml_start_tag(self->file, "property", &attributes);
if (custom_property->type == LXW_CUSTOM_STRING) {
/* Write the vt:lpwstr element. */
_chart_write_vt_lpwstr(self, custom_property->u.string);
}
else if (custom_property->type == LXW_CUSTOM_DOUBLE) {
/* Write the vt:r8 element. */
_chart_write_vt_r_8(self, custom_property->u.number);
}
else if (custom_property->type == LXW_CUSTOM_INTEGER) {
/* Write the vt:i4 element. */
_custom_write_vt_i_4(self, custom_property->u.integer);
}
else if (custom_property->type == LXW_CUSTOM_BOOLEAN) {
/* Write the vt:bool element. */
_custom_write_vt_bool(self, custom_property->u.boolean);
}
else if (custom_property->type == LXW_CUSTOM_DATETIME) {
/* Write the vt:filetime element. */
_custom_write_vt_filetime(self, &custom_property->u.datetime);
}
lxw_xml_end_tag(self->file, "property");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <Properties> element.
*/
STATIC void
_write_custom_properties(lxw_custom *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] = LXW_SCHEMA_OFFICEDOC "/custom-properties";
char xmlns_vt[] = LXW_SCHEMA_OFFICEDOC "/docPropsVTypes";
lxw_custom_property *custom_property;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_STR("xmlns:vt", xmlns_vt);
lxw_xml_start_tag(self->file, "Properties", &attributes);
STAILQ_FOREACH(custom_property, self->custom_properties, list_pointers) {
_chart_write_custom_property(self, custom_property);
}
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_custom_assemble_xml_file(lxw_custom *self)
{
/* Write the XML declaration. */
_custom_xml_declaration(self);
_write_custom_properties(self);
lxw_xml_end_tag(self->file, "Properties");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,963 @@
/*****************************************************************************
* drawing - A library for creating Excel XLSX drawing files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/common.h"
#include "xlsxwriter/drawing.h"
#include "xlsxwriter/worksheet.h"
#include "xlsxwriter/utility.h"
#define LXW_OBJ_NAME_LENGTH 14 /* "Picture 65536", or "Chart 65536" */
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new drawing collection.
*/
lxw_drawing *
lxw_drawing_new(void)
{
lxw_drawing *drawing = calloc(1, sizeof(lxw_drawing));
GOTO_LABEL_ON_MEM_ERROR(drawing, mem_error);
drawing->drawing_objects = calloc(1, sizeof(struct lxw_drawing_objects));
GOTO_LABEL_ON_MEM_ERROR(drawing->drawing_objects, mem_error);
STAILQ_INIT(drawing->drawing_objects);
return drawing;
mem_error:
lxw_drawing_free(drawing);
return NULL;
}
/*
* Free a drawing object.
*/
void
lxw_free_drawing_object(lxw_drawing_object *drawing_object)
{
if (!drawing_object)
return;
free(drawing_object->description);
free(drawing_object->tip);
free(drawing_object);
}
/*
* Free a drawing collection.
*/
void
lxw_drawing_free(lxw_drawing *drawing)
{
lxw_drawing_object *drawing_object;
if (!drawing)
return;
if (drawing->drawing_objects) {
while (!STAILQ_EMPTY(drawing->drawing_objects)) {
drawing_object = STAILQ_FIRST(drawing->drawing_objects);
STAILQ_REMOVE_HEAD(drawing->drawing_objects, list_pointers);
lxw_free_drawing_object(drawing_object);
}
free(drawing->drawing_objects);
}
free(drawing);
}
/*
* Add a drawing object to the drawing collection.
*/
void
lxw_add_drawing_object(lxw_drawing *drawing,
lxw_drawing_object *drawing_object)
{
STAILQ_INSERT_TAIL(drawing->drawing_objects, drawing_object,
list_pointers);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_drawing_xml_declaration(lxw_drawing *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <xdr:wsDr> element.
*/
STATIC void
_write_drawing_workspace(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns_xdr[] = LXW_SCHEMA_DRAWING "/spreadsheetDrawing";
char xmlns_a[] = LXW_SCHEMA_DRAWING "/main";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:xdr", xmlns_xdr);
LXW_PUSH_ATTRIBUTES_STR("xmlns:a", xmlns_a);
lxw_xml_start_tag(self->file, "xdr:wsDr", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:col> element.
*/
STATIC void
_drawing_write_col(lxw_drawing *self, char *data)
{
lxw_xml_data_element(self->file, "xdr:col", data, NULL);
}
/*
* Write the <xdr:colOff> element.
*/
STATIC void
_drawing_write_col_off(lxw_drawing *self, char *data)
{
lxw_xml_data_element(self->file, "xdr:colOff", data, NULL);
}
/*
* Write the <xdr:row> element.
*/
STATIC void
_drawing_write_row(lxw_drawing *self, char *data)
{
lxw_xml_data_element(self->file, "xdr:row", data, NULL);
}
/*
* Write the <xdr:rowOff> element.
*/
STATIC void
_drawing_write_row_off(lxw_drawing *self, char *data)
{
lxw_xml_data_element(self->file, "xdr:rowOff", data, NULL);
}
/*
* Write the main part of the <xdr:from> and <xdr:to> elements.
*/
STATIC void
_drawing_write_coords(lxw_drawing *self, lxw_drawing_coords *coords)
{
char data[LXW_UINT32_T_LENGTH];
lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", coords->col);
_drawing_write_col(self, data);
lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u",
(uint32_t) coords->col_offset);
_drawing_write_col_off(self, data);
lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u", coords->row);
_drawing_write_row(self, data);
lxw_snprintf(data, LXW_UINT32_T_LENGTH, "%u",
(uint32_t) coords->row_offset);
_drawing_write_row_off(self, data);
}
/*
* Write the <xdr:from> element.
*/
STATIC void
_drawing_write_from(lxw_drawing *self, lxw_drawing_coords *coords)
{
lxw_xml_start_tag(self->file, "xdr:from", NULL);
_drawing_write_coords(self, coords);
lxw_xml_end_tag(self->file, "xdr:from");
}
/*
* Write the <xdr:to> element.
*/
STATIC void
_drawing_write_to(lxw_drawing *self, lxw_drawing_coords *coords)
{
lxw_xml_start_tag(self->file, "xdr:to", NULL);
_drawing_write_coords(self, coords);
lxw_xml_end_tag(self->file, "xdr:to");
}
/*
* Write the <a:hlinkClick> element.
*/
STATIC void
_drawing_write_a_hlink_click(lxw_drawing *self, uint32_t rel_index, char *tip)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns_r[] = "http://schemas.openxmlformats.org/"
"officeDocument/2006/relationships";
char r_id[LXW_MAX_ATTRIBUTE_LENGTH];
lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", rel_index);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
LXW_PUSH_ATTRIBUTES_STR("r:id", r_id);
if (tip)
LXW_PUSH_ATTRIBUTES_STR("tooltip", tip);
lxw_xml_empty_tag(self->file, "a:hlinkClick", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a16:creationId> element.
*/
STATIC void
_drawing_write_a16_creation_id(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] = "http://schemas.microsoft.com/office/drawing/2014/main";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:a16", xmlns);
LXW_PUSH_ATTRIBUTES_STR("id", "{00000000-0008-0000-0000-000002000000}");
lxw_xml_empty_tag(self->file, "a16:creationId", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <adec:decorative> element.
*/
STATIC void
_workbook_write_adec_decorative(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] =
"http://schemas.microsoft.com/office/drawing/2017/decorative";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:adec", xmlns);
LXW_PUSH_ATTRIBUTES_STR("val", "1");
lxw_xml_empty_tag(self->file, "adec:decorative", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:ext> element.
*/
STATIC void
_drawing_write_uri_ext(lxw_drawing *self, char *uri)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("uri", uri);
lxw_xml_start_tag(self->file, "a:ext", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the decorative elements.
*/
STATIC void
_workbook_write_decorative(lxw_drawing *self)
{
lxw_xml_start_tag(self->file, "a:extLst", NULL);
_drawing_write_uri_ext(self, "{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}");
_drawing_write_a16_creation_id(self);
lxw_xml_end_tag(self->file, "a:ext");
_drawing_write_uri_ext(self, "{C183D7F6-B498-43B3-948B-1728B52AA6E4}");
_workbook_write_adec_decorative(self);
lxw_xml_end_tag(self->file, "a:ext");
lxw_xml_end_tag(self->file, "a:extLst");
}
/*
* Write the <xdr:cNvPr> element.
*/
STATIC void
_drawing_write_c_nv_pr(lxw_drawing *self, char *object_name, uint32_t index,
lxw_drawing_object *drawing_object)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char name[LXW_OBJ_NAME_LENGTH];
lxw_snprintf(name, LXW_OBJ_NAME_LENGTH, "%s %d", object_name, index);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("id", index + 1);
LXW_PUSH_ATTRIBUTES_STR("name", name);
if (drawing_object && drawing_object->description
&& strlen(drawing_object->description)
&& !drawing_object->decorative) {
LXW_PUSH_ATTRIBUTES_STR("descr", drawing_object->description);
}
if (drawing_object
&& (drawing_object->url_rel_index || drawing_object->decorative)) {
lxw_xml_start_tag(self->file, "xdr:cNvPr", &attributes);
if (drawing_object->url_rel_index) {
/* Write the a:hlinkClick element. */
_drawing_write_a_hlink_click(self,
drawing_object->url_rel_index,
drawing_object->tip);
}
if (drawing_object->decorative) {
_workbook_write_decorative(self);
}
lxw_xml_end_tag(self->file, "xdr:cNvPr");
}
else {
lxw_xml_empty_tag(self->file, "xdr:cNvPr", &attributes);
}
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:picLocks> element.
*/
STATIC void
_drawing_write_a_pic_locks(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("noChangeAspect", "1");
lxw_xml_empty_tag(self->file, "a:picLocks", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:cNvPicPr> element.
*/
STATIC void
_drawing_write_c_nv_pic_pr(lxw_drawing *self)
{
lxw_xml_start_tag(self->file, "xdr:cNvPicPr", NULL);
/* Write the a:picLocks element. */
_drawing_write_a_pic_locks(self);
lxw_xml_end_tag(self->file, "xdr:cNvPicPr");
}
/*
* Write the <xdr:nvPicPr> element.
*/
STATIC void
_drawing_write_nv_pic_pr(lxw_drawing *self, uint32_t index,
lxw_drawing_object *drawing_object)
{
lxw_xml_start_tag(self->file, "xdr:nvPicPr", NULL);
/* Write the xdr:cNvPr element. */
_drawing_write_c_nv_pr(self, "Picture", index, drawing_object);
/* Write the xdr:cNvPicPr element. */
_drawing_write_c_nv_pic_pr(self);
lxw_xml_end_tag(self->file, "xdr:nvPicPr");
}
/*
* Write the <a:blip> element.
*/
STATIC void
_drawing_write_a_blip(lxw_drawing *self, uint32_t index)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns_r[] = LXW_SCHEMA_OFFICEDOC "/relationships";
char r_id[LXW_MAX_ATTRIBUTE_LENGTH];
lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", index);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
LXW_PUSH_ATTRIBUTES_STR("r:embed", r_id);
lxw_xml_empty_tag(self->file, "a:blip", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:fillRect> element.
*/
STATIC void
_drawing_write_a_fill_rect(lxw_drawing *self)
{
lxw_xml_empty_tag(self->file, "a:fillRect", NULL);
}
/*
* Write the <a:stretch> element.
*/
STATIC void
_drawing_write_a_stretch(lxw_drawing *self)
{
lxw_xml_start_tag(self->file, "a:stretch", NULL);
/* Write the a:fillRect element. */
_drawing_write_a_fill_rect(self);
lxw_xml_end_tag(self->file, "a:stretch");
}
/*
* Write the <xdr:blipFill> element.
*/
STATIC void
_drawing_write_blip_fill(lxw_drawing *self, uint32_t index)
{
lxw_xml_start_tag(self->file, "xdr:blipFill", NULL);
/* Write the a:blip element. */
_drawing_write_a_blip(self, index);
/* Write the a:stretch element. */
_drawing_write_a_stretch(self);
lxw_xml_end_tag(self->file, "xdr:blipFill");
}
/*
* Write the <a:ext> element.
*/
STATIC void
_drawing_write_a_ext(lxw_drawing *self, lxw_drawing_object *drawing_object)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("cx", drawing_object->width);
LXW_PUSH_ATTRIBUTES_INT("cy", drawing_object->height);
lxw_xml_empty_tag(self->file, "a:ext", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:off> element.
*/
STATIC void
_drawing_write_a_off(lxw_drawing *self, lxw_drawing_object *drawing_object)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("x", drawing_object->col_absolute);
LXW_PUSH_ATTRIBUTES_INT("y", drawing_object->row_absolute);
lxw_xml_empty_tag(self->file, "a:off", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:xfrm> element.
*/
STATIC void
_drawing_write_a_xfrm(lxw_drawing *self, lxw_drawing_object *drawing_object)
{
lxw_xml_start_tag(self->file, "a:xfrm", NULL);
/* Write the a:off element. */
_drawing_write_a_off(self, drawing_object);
/* Write the a:ext element. */
_drawing_write_a_ext(self, drawing_object);
lxw_xml_end_tag(self->file, "a:xfrm");
}
/*
* Write the <a:avLst> element.
*/
STATIC void
_drawing_write_a_av_lst(lxw_drawing *self)
{
lxw_xml_empty_tag(self->file, "a:avLst", NULL);
}
/*
* Write the <a:prstGeom> element.
*/
STATIC void
_drawing_write_a_prst_geom(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("prst", "rect");
lxw_xml_start_tag(self->file, "a:prstGeom", &attributes);
/* Write the a:avLst element. */
_drawing_write_a_av_lst(self);
lxw_xml_end_tag(self->file, "a:prstGeom");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:spPr> element.
*/
STATIC void
_drawing_write_sp_pr(lxw_drawing *self, lxw_drawing_object *drawing_object)
{
lxw_xml_start_tag(self->file, "xdr:spPr", NULL);
/* Write the a:xfrm element. */
_drawing_write_a_xfrm(self, drawing_object);
/* Write the a:prstGeom element. */
_drawing_write_a_prst_geom(self);
lxw_xml_end_tag(self->file, "xdr:spPr");
}
/*
* Write the <xdr:pic> element.
*/
STATIC void
_drawing_write_pic(lxw_drawing *self, uint32_t index,
lxw_drawing_object *drawing_object)
{
lxw_xml_start_tag(self->file, "xdr:pic", NULL);
/* Write the xdr:nvPicPr element. */
_drawing_write_nv_pic_pr(self, index, drawing_object);
/* Write the xdr:blipFill element. */
_drawing_write_blip_fill(self, drawing_object->rel_index);
/* Write the xdr:spPr element. */
_drawing_write_sp_pr(self, drawing_object);
lxw_xml_end_tag(self->file, "xdr:pic");
}
/*
* Write the <xdr:clientData> element.
*/
STATIC void
_drawing_write_client_data(lxw_drawing *self)
{
lxw_xml_empty_tag(self->file, "xdr:clientData", NULL);
}
/*
* Write the <a:graphicFrameLocks> element.
*/
STATIC void
_drawing_write_a_graphic_frame_locks(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("noGrp", 1);
lxw_xml_empty_tag(self->file, "a:graphicFrameLocks", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:cNvGraphicFramePr> element.
*/
STATIC void
_drawing_write_c_nv_graphic_frame_pr(lxw_drawing *self)
{
if (self->embedded) {
lxw_xml_empty_tag(self->file, "xdr:cNvGraphicFramePr", NULL);
}
else {
lxw_xml_start_tag(self->file, "xdr:cNvGraphicFramePr", NULL);
/* Write the a:graphicFrameLocks element. */
_drawing_write_a_graphic_frame_locks(self);
lxw_xml_end_tag(self->file, "xdr:cNvGraphicFramePr");
}
}
/*
* Write the <xdr:nvGraphicFramePr> element.
*/
STATIC void
_drawing_write_nv_graphic_frame_pr(lxw_drawing *self, uint32_t index,
lxw_drawing_object *drawing_object)
{
lxw_xml_start_tag(self->file, "xdr:nvGraphicFramePr", NULL);
/* Write the xdr:cNvPr element. */
_drawing_write_c_nv_pr(self, "Chart", index, drawing_object);
/* Write the xdr:cNvGraphicFramePr element. */
_drawing_write_c_nv_graphic_frame_pr(self);
lxw_xml_end_tag(self->file, "xdr:nvGraphicFramePr");
}
/*
* Write the <a:off> element.
*/
STATIC void
_drawing_write_xfrm_offset(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("x", "0");
LXW_PUSH_ATTRIBUTES_STR("y", "0");
lxw_xml_empty_tag(self->file, "a:off", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:ext> element.
*/
STATIC void
_drawing_write_xfrm_extension(lxw_drawing *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("cx", "0");
LXW_PUSH_ATTRIBUTES_STR("cy", "0");
lxw_xml_empty_tag(self->file, "a:ext", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:xfrm> element.
*/
STATIC void
_drawing_write_xfrm(lxw_drawing *self)
{
lxw_xml_start_tag(self->file, "xdr:xfrm", NULL);
/* Write the a:off element. */
_drawing_write_xfrm_offset(self);
/* Write the a:ext element. */
_drawing_write_xfrm_extension(self);
lxw_xml_end_tag(self->file, "xdr:xfrm");
}
/*
* Write the <c:chart> element.
*/
STATIC void
_drawing_write_chart(lxw_drawing *self, uint32_t index)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns_c[] = LXW_SCHEMA_DRAWING "/chart";
char xmlns_r[] = LXW_SCHEMA_OFFICEDOC "/relationships";
char r_id[LXW_MAX_ATTRIBUTE_LENGTH];
lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", index);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:c", xmlns_c);
LXW_PUSH_ATTRIBUTES_STR("xmlns:r", xmlns_r);
LXW_PUSH_ATTRIBUTES_STR("r:id", r_id);
lxw_xml_empty_tag(self->file, "c:chart", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:graphicData> element.
*/
STATIC void
_drawing_write_a_graphic_data(lxw_drawing *self, uint32_t index)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char uri[] = LXW_SCHEMA_DRAWING "/chart";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("uri", uri);
lxw_xml_start_tag(self->file, "a:graphicData", &attributes);
/* Write the c:chart element. */
_drawing_write_chart(self, index);
lxw_xml_end_tag(self->file, "a:graphicData");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <a:graphic> element.
*/
STATIC void
_drawing_write_a_graphic(lxw_drawing *self, uint32_t index)
{
lxw_xml_start_tag(self->file, "a:graphic", NULL);
/* Write the a:graphicData element. */
_drawing_write_a_graphic_data(self, index);
lxw_xml_end_tag(self->file, "a:graphic");
}
/*
* Write the <xdr:graphicFrame> element.
*/
STATIC void
_drawing_write_graphic_frame(lxw_drawing *self, uint32_t index,
uint32_t rel_index,
lxw_drawing_object *drawing_object)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("macro", "");
lxw_xml_start_tag(self->file, "xdr:graphicFrame", &attributes);
/* Write the xdr:nvGraphicFramePr element. */
_drawing_write_nv_graphic_frame_pr(self, index, drawing_object);
/* Write the xdr:xfrm element. */
_drawing_write_xfrm(self);
/* Write the a:graphic element. */
_drawing_write_a_graphic(self, rel_index);
lxw_xml_end_tag(self->file, "xdr:graphicFrame");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:twoCellAnchor> element.
*/
STATIC void
_drawing_write_two_cell_anchor(lxw_drawing *self, uint32_t index,
lxw_drawing_object *drawing_object)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
if (drawing_object->anchor == LXW_OBJECT_MOVE_DONT_SIZE)
LXW_PUSH_ATTRIBUTES_STR("editAs", "oneCell");
else if (drawing_object->anchor == LXW_OBJECT_DONT_MOVE_DONT_SIZE)
LXW_PUSH_ATTRIBUTES_STR("editAs", "absolute");
lxw_xml_start_tag(self->file, "xdr:twoCellAnchor", &attributes);
_drawing_write_from(self, &drawing_object->from);
_drawing_write_to(self, &drawing_object->to);
if (drawing_object->type == LXW_DRAWING_CHART) {
/* Write the xdr:graphicFrame element for charts. */
_drawing_write_graphic_frame(self, index, drawing_object->rel_index,
drawing_object);
}
else if (drawing_object->type == LXW_DRAWING_IMAGE) {
/* Write the xdr:pic element. */
_drawing_write_pic(self, index, drawing_object);
}
else {
/* Write the xdr:sp element for shapes. */
/* _drawing_write_sp(self, index, col_absolute, row_absolute, width,
height, shape); */
}
/* Write the xdr:clientData element. */
_drawing_write_client_data(self);
lxw_xml_end_tag(self->file, "xdr:twoCellAnchor");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:ext> element.
*/
STATIC void
_drawing_write_ext(lxw_drawing *self, uint32_t cx, uint32_t cy)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("cx", cx);
LXW_PUSH_ATTRIBUTES_INT("cy", cy);
lxw_xml_empty_tag(self->file, "xdr:ext", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:pos> element.
*/
STATIC void
_drawing_write_pos(lxw_drawing *self, int32_t x, int32_t y)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("x", x);
LXW_PUSH_ATTRIBUTES_INT("y", y);
lxw_xml_empty_tag(self->file, "xdr:pos", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xdr:absoluteAnchor> element.
*/
STATIC void
_drawing_write_absolute_anchor(lxw_drawing *self, uint32_t frame_index)
{
lxw_xml_start_tag(self->file, "xdr:absoluteAnchor", NULL);
if (self->orientation == LXW_LANDSCAPE) {
/* Write the xdr:pos element. */
_drawing_write_pos(self, 0, 0);
/* Write the xdr:ext element. */
_drawing_write_ext(self, 9308969, 6078325);
}
else {
/* Write the xdr:pos element. */
_drawing_write_pos(self, 0, -47625);
/* Write the xdr:ext element. */
_drawing_write_ext(self, 6162675, 6124575);
}
_drawing_write_graphic_frame(self, frame_index, frame_index, NULL);
/* Write the xdr:clientData element. */
_drawing_write_client_data(self);
lxw_xml_end_tag(self->file, "xdr:absoluteAnchor");
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_drawing_assemble_xml_file(lxw_drawing *self)
{
uint32_t index;
lxw_drawing_object *drawing_object;
/* Write the XML declaration. */
_drawing_xml_declaration(self);
/* Write the xdr:wsDr element. */
_write_drawing_workspace(self);
if (self->embedded) {
index = 1;
STAILQ_FOREACH(drawing_object, self->drawing_objects, list_pointers) {
_drawing_write_two_cell_anchor(self, index, drawing_object);
index++;
}
}
else {
/* Write the xdr:absoluteAnchor element. Mainly for chartsheets. */
_drawing_write_absolute_anchor(self, 1);
}
lxw_xml_end_tag(self->file, "xdr:wsDr");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,812 @@
/*****************************************************************************
* format - A library for creating Excel XLSX format files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/format.h"
#include "xlsxwriter/utility.h"
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new format object.
*/
lxw_format *
lxw_format_new(void)
{
lxw_format *format = calloc(1, sizeof(lxw_format));
GOTO_LABEL_ON_MEM_ERROR(format, mem_error);
format->xf_format_indices = NULL;
format->dxf_format_indices = NULL;
format->xf_index = LXW_PROPERTY_UNSET;
format->dxf_index = LXW_PROPERTY_UNSET;
format->xf_id = 0;
format->font_name[0] = '\0';
format->font_scheme[0] = '\0';
format->num_format[0] = '\0';
format->num_format_index = 0;
format->font_index = 0;
format->has_font = LXW_FALSE;
format->has_dxf_font = LXW_FALSE;
format->font_size = 11.0;
format->bold = LXW_FALSE;
format->italic = LXW_FALSE;
format->font_color = LXW_COLOR_UNSET;
format->underline = LXW_UNDERLINE_NONE;
format->font_strikeout = LXW_FALSE;
format->font_outline = LXW_FALSE;
format->font_shadow = LXW_FALSE;
format->font_script = LXW_FALSE;
format->font_family = LXW_DEFAULT_FONT_FAMILY;
format->font_charset = LXW_FALSE;
format->font_condense = LXW_FALSE;
format->font_extend = LXW_FALSE;
format->theme = 0;
format->hyperlink = LXW_FALSE;
format->hidden = LXW_FALSE;
format->locked = LXW_TRUE;
format->text_h_align = LXW_ALIGN_NONE;
format->text_wrap = LXW_FALSE;
format->text_v_align = LXW_ALIGN_NONE;
format->text_justlast = LXW_FALSE;
format->rotation = 0;
format->fg_color = LXW_COLOR_UNSET;
format->bg_color = LXW_COLOR_UNSET;
format->pattern = LXW_PATTERN_NONE;
format->has_fill = LXW_FALSE;
format->has_dxf_fill = LXW_FALSE;
format->fill_index = 0;
format->fill_count = 0;
format->border_index = 0;
format->has_border = LXW_FALSE;
format->has_dxf_border = LXW_FALSE;
format->border_count = 0;
format->bottom = LXW_BORDER_NONE;
format->left = LXW_BORDER_NONE;
format->right = LXW_BORDER_NONE;
format->top = LXW_BORDER_NONE;
format->diag_border = LXW_BORDER_NONE;
format->diag_type = LXW_BORDER_NONE;
format->bottom_color = LXW_COLOR_UNSET;
format->left_color = LXW_COLOR_UNSET;
format->right_color = LXW_COLOR_UNSET;
format->top_color = LXW_COLOR_UNSET;
format->diag_color = LXW_COLOR_UNSET;
format->indent = 0;
format->shrink = LXW_FALSE;
format->merge_range = LXW_FALSE;
format->reading_order = 0;
format->just_distrib = LXW_FALSE;
format->color_indexed = LXW_FALSE;
format->font_only = LXW_FALSE;
format->quote_prefix = LXW_FALSE;
return format;
mem_error:
lxw_format_free(format);
return NULL;
}
/*
* Free a format object.
*/
void
lxw_format_free(lxw_format *format)
{
if (!format)
return;
free(format);
format = NULL;
}
/*
* Check a user input border.
*/
STATIC uint8_t
_check_border(uint8_t border)
{
if (border >= LXW_BORDER_THIN && border <= LXW_BORDER_SLANT_DASH_DOT)
return border;
else
return LXW_BORDER_NONE;
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Returns a format struct suitable for hashing as a lookup key. This is
* mainly a memcpy with any pointer members set to NULL.
*/
STATIC lxw_format *
_get_format_key(lxw_format *self)
{
lxw_format *key = calloc(1, sizeof(lxw_format));
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
memcpy(key, self, sizeof(lxw_format));
/* Set pointer members to NULL since they aren't part of the comparison. */
key->xf_format_indices = NULL;
key->dxf_format_indices = NULL;
key->num_xf_formats = NULL;
key->num_dxf_formats = NULL;
key->list_pointers.stqe_next = NULL;
return key;
mem_error:
return NULL;
}
/*
* Returns a font struct suitable for hashing as a lookup key.
*/
lxw_font *
lxw_format_get_font_key(lxw_format *self)
{
lxw_font *key = calloc(1, sizeof(lxw_font));
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
LXW_FORMAT_FIELD_COPY(key->font_name, self->font_name);
key->font_size = self->font_size;
key->bold = self->bold;
key->italic = self->italic;
key->underline = self->underline;
key->theme = self->theme;
key->font_color = self->font_color;
key->font_strikeout = self->font_strikeout;
key->font_outline = self->font_outline;
key->font_shadow = self->font_shadow;
key->font_script = self->font_script;
key->font_family = self->font_family;
key->font_charset = self->font_charset;
key->font_condense = self->font_condense;
key->font_extend = self->font_extend;
return key;
mem_error:
return NULL;
}
/*
* Returns a border struct suitable for hashing as a lookup key.
*/
lxw_border *
lxw_format_get_border_key(lxw_format *self)
{
lxw_border *key = calloc(1, sizeof(lxw_border));
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
key->bottom = self->bottom;
key->left = self->left;
key->right = self->right;
key->top = self->top;
key->diag_border = self->diag_border;
key->diag_type = self->diag_type;
key->bottom_color = self->bottom_color;
key->left_color = self->left_color;
key->right_color = self->right_color;
key->top_color = self->top_color;
key->diag_color = self->diag_color;
return key;
mem_error:
return NULL;
}
/*
* Returns a pattern fill struct suitable for hashing as a lookup key.
*/
lxw_fill *
lxw_format_get_fill_key(lxw_format *self)
{
lxw_fill *key = calloc(1, sizeof(lxw_fill));
GOTO_LABEL_ON_MEM_ERROR(key, mem_error);
key->fg_color = self->fg_color;
key->bg_color = self->bg_color;
key->pattern = self->pattern;
return key;
mem_error:
return NULL;
}
/*
* Returns the XF index number used by Excel to identify a format.
*/
int32_t
lxw_format_get_xf_index(lxw_format *self)
{
lxw_format *format_key;
lxw_format *existing_format;
lxw_hash_element *hash_element;
lxw_hash_table *formats_hash_table = self->xf_format_indices;
int32_t index;
/* Note: The formats_hash_table/xf_format_indices contains the unique and
* more importantly the *used* formats in the workbook.
*/
/* Format already has an index number so return it. */
if (self->xf_index != LXW_PROPERTY_UNSET) {
return self->xf_index;
}
/* Otherwise, the format doesn't have an index number so we assign one.
* First generate a unique key to identify the format in the hash table.
*/
format_key = _get_format_key(self);
/* Return the default format index if the key generation failed. */
if (!format_key)
return 0;
/* Look up the format in the hash table. */
hash_element =
lxw_hash_key_exists(formats_hash_table, format_key,
sizeof(lxw_format));
if (hash_element) {
/* Format matches existing format with an index. */
free(format_key);
existing_format = hash_element->value;
return existing_format->xf_index;
}
else {
/* New format requiring an index. */
index = formats_hash_table->unique_count;
self->xf_index = index;
lxw_insert_hash_element(formats_hash_table, format_key, self,
sizeof(lxw_format));
return index;
}
}
/*
* Returns the DXF index number used by Excel to identify a format.
*/
int32_t
lxw_format_get_dxf_index(lxw_format *self)
{
lxw_format *format_key;
lxw_format *existing_format;
lxw_hash_element *hash_element;
lxw_hash_table *formats_hash_table = self->dxf_format_indices;
int32_t index;
/* Note: The formats_hash_table/dxf_format_indices contains the unique and
* more importantly the *used* formats in the workbook.
*/
/* Format already has an index number so return it. */
if (self->dxf_index != LXW_PROPERTY_UNSET) {
return self->dxf_index;
}
/* Otherwise, the format doesn't have an index number so we assign one.
* First generate a unique key to identify the format in the hash table.
*/
format_key = _get_format_key(self);
/* Return the default format index if the key generation failed. */
if (!format_key)
return 0;
/* Look up the format in the hash table. */
hash_element =
lxw_hash_key_exists(formats_hash_table, format_key,
sizeof(lxw_format));
if (hash_element) {
/* Format matches existing format with an index. */
free(format_key);
existing_format = hash_element->value;
return existing_format->dxf_index;
}
else {
/* New format requiring an index. */
index = formats_hash_table->unique_count;
self->dxf_index = index;
lxw_insert_hash_element(formats_hash_table, format_key, self,
sizeof(lxw_format));
return index;
}
}
/*
* Set the font_name property.
*/
void
format_set_font_name(lxw_format *self, const char *font_name)
{
LXW_FORMAT_FIELD_COPY(self->font_name, font_name);
}
/*
* Set the font_size property.
*/
void
format_set_font_size(lxw_format *self, double size)
{
if (size >= LXW_MIN_FONT_SIZE && size <= LXW_MAX_FONT_SIZE)
self->font_size = size;
}
/*
* Set the font_color property.
*/
void
format_set_font_color(lxw_format *self, lxw_color_t color)
{
self->font_color = color;
}
/*
* Set the bold property.
*/
void
format_set_bold(lxw_format *self)
{
self->bold = LXW_TRUE;
}
/*
* Set the italic property.
*/
void
format_set_italic(lxw_format *self)
{
self->italic = LXW_TRUE;
}
/*
* Set the underline property.
*/
void
format_set_underline(lxw_format *self, uint8_t style)
{
if (style >= LXW_UNDERLINE_SINGLE
&& style <= LXW_UNDERLINE_DOUBLE_ACCOUNTING)
self->underline = style;
}
/*
* Set the font_strikeout property.
*/
void
format_set_font_strikeout(lxw_format *self)
{
self->font_strikeout = LXW_TRUE;
}
/*
* Set the font_script property.
*/
void
format_set_font_script(lxw_format *self, uint8_t style)
{
if (style >= LXW_FONT_SUPERSCRIPT && style <= LXW_FONT_SUBSCRIPT)
self->font_script = style;
}
/*
* Set the font_outline property.
*/
void
format_set_font_outline(lxw_format *self)
{
self->font_outline = LXW_TRUE;
}
/*
* Set the font_shadow property.
*/
void
format_set_font_shadow(lxw_format *self)
{
self->font_shadow = LXW_TRUE;
}
/*
* Set the num_format property.
*/
void
format_set_num_format(lxw_format *self, const char *num_format)
{
LXW_FORMAT_FIELD_COPY(self->num_format, num_format);
}
/*
* Set the unlocked property.
*/
void
format_set_unlocked(lxw_format *self)
{
self->locked = LXW_FALSE;
}
/*
* Set the hidden property.
*/
void
format_set_hidden(lxw_format *self)
{
self->hidden = LXW_TRUE;
}
/*
* Set the align property.
*/
void
format_set_align(lxw_format *self, uint8_t value)
{
if (value >= LXW_ALIGN_LEFT && value <= LXW_ALIGN_DISTRIBUTED) {
self->text_h_align = value;
}
if (value >= LXW_ALIGN_VERTICAL_TOP
&& value <= LXW_ALIGN_VERTICAL_DISTRIBUTED) {
self->text_v_align = value;
}
}
/*
* Set the text_wrap property.
*/
void
format_set_text_wrap(lxw_format *self)
{
self->text_wrap = LXW_TRUE;
}
/*
* Set the rotation property.
*/
void
format_set_rotation(lxw_format *self, int16_t angle)
{
/* Convert user angle to Excel angle. */
if (angle == 270) {
self->rotation = 255;
}
else if (angle >= -90 && angle <= 90) {
if (angle < 0)
angle = -angle + 90;
self->rotation = angle;
}
else {
LXW_WARN("Rotation rotation outside range: -90 <= angle <= 90.");
self->rotation = 0;
}
}
/*
* Set the indent property.
*/
void
format_set_indent(lxw_format *self, uint8_t value)
{
self->indent = value;
}
/*
* Set the shrink property.
*/
void
format_set_shrink(lxw_format *self)
{
self->shrink = LXW_TRUE;
}
/*
* Set the text_justlast property.
*/
void
format_set_text_justlast(lxw_format *self)
{
self->text_justlast = LXW_TRUE;
}
/*
* Set the pattern property.
*/
void
format_set_pattern(lxw_format *self, uint8_t value)
{
self->pattern = value;
}
/*
* Set the bg_color property.
*/
void
format_set_bg_color(lxw_format *self, lxw_color_t color)
{
self->bg_color = color;
}
/*
* Set the fg_color property.
*/
void
format_set_fg_color(lxw_format *self, lxw_color_t color)
{
self->fg_color = color;
}
/*
* Set the border property.
*/
void
format_set_border(lxw_format *self, uint8_t style)
{
style = _check_border(style);
self->bottom = style;
self->top = style;
self->left = style;
self->right = style;
}
/*
* Set the border_color property.
*/
void
format_set_border_color(lxw_format *self, lxw_color_t color)
{
self->bottom_color = color;
self->top_color = color;
self->left_color = color;
self->right_color = color;
}
/*
* Set the bottom property.
*/
void
format_set_bottom(lxw_format *self, uint8_t style)
{
self->bottom = _check_border(style);
}
/*
* Set the bottom_color property.
*/
void
format_set_bottom_color(lxw_format *self, lxw_color_t color)
{
self->bottom_color = color;
}
/*
* Set the left property.
*/
void
format_set_left(lxw_format *self, uint8_t style)
{
self->left = _check_border(style);
}
/*
* Set the left_color property.
*/
void
format_set_left_color(lxw_format *self, lxw_color_t color)
{
self->left_color = color;
}
/*
* Set the right property.
*/
void
format_set_right(lxw_format *self, uint8_t style)
{
self->right = _check_border(style);
}
/*
* Set the right_color property.
*/
void
format_set_right_color(lxw_format *self, lxw_color_t color)
{
self->right_color = color;
}
/*
* Set the top property.
*/
void
format_set_top(lxw_format *self, uint8_t style)
{
self->top = _check_border(style);
}
/*
* Set the top_color property.
*/
void
format_set_top_color(lxw_format *self, lxw_color_t color)
{
self->top_color = color;
}
/*
* Set the diag_type property.
*/
void
format_set_diag_type(lxw_format *self, uint8_t type)
{
if (type >= LXW_DIAGONAL_BORDER_UP && type <= LXW_DIAGONAL_BORDER_UP_DOWN)
self->diag_type = type;
}
/*
* Set the diag_color property.
*/
void
format_set_diag_color(lxw_format *self, lxw_color_t color)
{
self->diag_color = color;
}
/*
* Set the diag_border property.
*/
void
format_set_diag_border(lxw_format *self, uint8_t style)
{
self->diag_border = style;
}
/*
* Set the num_format_index property.
*/
void
format_set_num_format_index(lxw_format *self, uint8_t value)
{
self->num_format_index = value;
}
/*
* Set the valign property.
*/
void
format_set_valign(lxw_format *self, uint8_t value)
{
self->text_v_align = value;
}
/*
* Set the reading_order property.
*/
void
format_set_reading_order(lxw_format *self, uint8_t value)
{
self->reading_order = value;
}
/*
* Set the font_family property.
*/
void
format_set_font_family(lxw_format *self, uint8_t value)
{
self->font_family = value;
}
/*
* Set the font_charset property.
*/
void
format_set_font_charset(lxw_format *self, uint8_t value)
{
self->font_charset = value;
}
/*
* Set the font_scheme property.
*/
void
format_set_font_scheme(lxw_format *self, const char *font_scheme)
{
LXW_FORMAT_FIELD_COPY(self->font_scheme, font_scheme);
}
/*
* Set the font_condense property.
*/
void
format_set_font_condense(lxw_format *self)
{
self->font_condense = LXW_TRUE;
}
/*
* Set the font_extend property.
*/
void
format_set_font_extend(lxw_format *self)
{
self->font_extend = LXW_TRUE;
}
/*
* Set the theme property.
*/
void
format_set_theme(lxw_format *self, uint8_t value)
{
self->theme = value;
}
/*
* Set the color_indexed property.
*/
void
format_set_color_indexed(lxw_format *self, uint8_t value)
{
self->color_indexed = value;
}
/*
* Set the font_only property.
*/
void
format_set_font_only(lxw_format *self)
{
self->font_only = LXW_TRUE;
}
/*
* Set the theme property.
*/
void
format_set_hyperlink(lxw_format *self)
{
self->hyperlink = LXW_TRUE;
self->xf_id = 1;
self->underline = LXW_UNDERLINE_SINGLE;
self->theme = 10;
}
/*
* Set the quote_prefix property.
*/
void
format_set_quote_prefix(lxw_format *self)
{
self->quote_prefix = LXW_TRUE;
}

View File

@@ -0,0 +1,223 @@
/*****************************************************************************
* hash_table - Hash table functions for libxlsxwriter.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "xlsxwriter/hash_table.h"
/*
* Calculate the hash key using the FNV function. See:
* http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
*/
STATIC size_t
_generate_hash_key(void *data, size_t data_len, size_t num_buckets)
{
unsigned char *p = data;
size_t hash = 2166136261U;
size_t i;
for (i = 0; i < data_len; i++)
hash = (hash * 16777619) ^ p[i];
return hash % num_buckets;
}
/*
* Check if an element exists in the hash table and return a pointer
* to it if it does.
*/
lxw_hash_element *
lxw_hash_key_exists(lxw_hash_table *lxw_hash, void *key, size_t key_len)
{
size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
struct lxw_hash_bucket_list *list;
lxw_hash_element *element;
if (!lxw_hash->buckets[hash_key]) {
/* The key isn't in the LXW_HASH hash table. */
return NULL;
}
else {
/* The key is already in the table or there is a hash collision. */
list = lxw_hash->buckets[hash_key];
/* Iterate over the keys in the bucket's linked list. */
SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
if (memcmp(element->key, key, key_len) == 0) {
/* The key already exists in the table. */
return element;
}
}
/* Key doesn't exist in the list so this is a hash collision. */
return NULL;
}
}
/*
* Insert or update a value in the LXW_HASH table based on a key
* and return a pointer to the new or updated element.
*/
lxw_hash_element *
lxw_insert_hash_element(lxw_hash_table *lxw_hash, void *key, void *value,
size_t key_len)
{
size_t hash_key = _generate_hash_key(key, key_len, lxw_hash->num_buckets);
struct lxw_hash_bucket_list *list = NULL;
lxw_hash_element *element = NULL;
if (!lxw_hash->buckets[hash_key]) {
/* The key isn't in the LXW_HASH hash table. */
/* Create a linked list in the bucket to hold the lxw_hash keys. */
list = calloc(1, sizeof(struct lxw_hash_bucket_list));
GOTO_LABEL_ON_MEM_ERROR(list, mem_error1);
/* Initialize the bucket linked list. */
SLIST_INIT(list);
/* Create an lxw_hash element to add to the linked list. */
element = calloc(1, sizeof(lxw_hash_element));
GOTO_LABEL_ON_MEM_ERROR(element, mem_error1);
/* Store the key and value. */
element->key = key;
element->value = value;
/* Add the lxw_hash element to the bucket's linked list. */
SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
/* Also add it to the insertion order linked list. */
STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
lxw_hash_order_pointers);
/* Store the bucket list at the hash index. */
lxw_hash->buckets[hash_key] = list;
lxw_hash->used_buckets++;
lxw_hash->unique_count++;
return element;
}
else {
/* The key is already in the table or there is a hash collision. */
list = lxw_hash->buckets[hash_key];
/* Iterate over the keys in the bucket's linked list. */
SLIST_FOREACH(element, list, lxw_hash_list_pointers) {
if (memcmp(element->key, key, key_len) == 0) {
/* The key already exists in the table. Update the value. */
if (lxw_hash->free_value)
free(element->value);
element->value = value;
return element;
}
}
/* Key doesn't exist in the list so this is a hash collision.
* Create an lxw_hash element to add to the linked list. */
element = calloc(1, sizeof(lxw_hash_element));
GOTO_LABEL_ON_MEM_ERROR(element, mem_error2);
/* Store the key and value. */
element->key = key;
element->value = value;
/* Add the lxw_hash element to the bucket linked list. */
SLIST_INSERT_HEAD(list, element, lxw_hash_list_pointers);
/* Also add it to the insertion order linked list. */
STAILQ_INSERT_TAIL(lxw_hash->order_list, element,
lxw_hash_order_pointers);
lxw_hash->unique_count++;
return element;
}
mem_error1:
free(list);
mem_error2:
free(element);
return NULL;
}
/*
* Create a new LXW_HASH hash table object.
*/
lxw_hash_table *
lxw_hash_new(uint32_t num_buckets, uint8_t free_key, uint8_t free_value)
{
/* Create the new hash table. */
lxw_hash_table *lxw_hash = calloc(1, sizeof(lxw_hash_table));
RETURN_ON_MEM_ERROR(lxw_hash, NULL);
lxw_hash->free_key = free_key;
lxw_hash->free_value = free_value;
/* Add the lxw_hash element buckets. */
lxw_hash->buckets =
calloc(num_buckets, sizeof(struct lxw_hash_bucket_list *));
GOTO_LABEL_ON_MEM_ERROR(lxw_hash->buckets, mem_error);
/* Add a list for tracking the insertion order. */
lxw_hash->order_list = calloc(1, sizeof(struct lxw_hash_order_list));
GOTO_LABEL_ON_MEM_ERROR(lxw_hash->order_list, mem_error);
/* Initialize the order list. */
STAILQ_INIT(lxw_hash->order_list);
/* Store the number of buckets to calculate the load factor. */
lxw_hash->num_buckets = num_buckets;
return lxw_hash;
mem_error:
lxw_hash_free(lxw_hash);
return NULL;
}
/*
* Free the LXW_HASH hash table object.
*/
void
lxw_hash_free(lxw_hash_table *lxw_hash)
{
size_t i;
lxw_hash_element *element;
lxw_hash_element *element_temp;
if (!lxw_hash)
return;
/* Free the lxw_hash_elements and data using the ordered linked list. */
if (lxw_hash->order_list) {
STAILQ_FOREACH_SAFE(element, lxw_hash->order_list,
lxw_hash_order_pointers, element_temp) {
if (lxw_hash->free_key)
free(element->key);
if (lxw_hash->free_value)
free(element->value);
free(element);
}
}
/* Free the buckets from the hash table. */
for (i = 0; i < lxw_hash->num_buckets; i++) {
free(lxw_hash->buckets[i]);
}
free(lxw_hash->order_list);
free(lxw_hash->buckets);
free(lxw_hash);
}

View File

@@ -0,0 +1,283 @@
/*****************************************************************************
* metadata - A library for creating Excel XLSX metadata files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/metadata.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new metadata object.
*/
lxw_metadata *
lxw_metadata_new(void)
{
lxw_metadata *metadata = calloc(1, sizeof(lxw_metadata));
GOTO_LABEL_ON_MEM_ERROR(metadata, mem_error);
return metadata;
mem_error:
lxw_metadata_free(metadata);
return NULL;
}
/*
* Free a metadata object.
*/
void
lxw_metadata_free(lxw_metadata *metadata)
{
if (!metadata)
return;
free(metadata);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_metadata_xml_declaration(lxw_metadata *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <metadata> element.
*/
STATIC void
_metadata_write_metadata(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] = "http://schemas.openxmlformats.org/"
"spreadsheetml/2006/main";
char xmlns_xda[] = "http://schemas.microsoft.com/office/"
"spreadsheetml/2017/dynamicarray";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_STR("xmlns:xda", xmlns_xda);
lxw_xml_start_tag(self->file, "metadata", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <metadataType> element.
*/
STATIC void
_metadata_write_metadata_type(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("name", "XLDAPR");
LXW_PUSH_ATTRIBUTES_INT("minSupportedVersion", 120000);
LXW_PUSH_ATTRIBUTES_INT("copy", 1);
LXW_PUSH_ATTRIBUTES_INT("pasteAll", 1);
LXW_PUSH_ATTRIBUTES_INT("pasteValues", 1);
LXW_PUSH_ATTRIBUTES_INT("merge", 1);
LXW_PUSH_ATTRIBUTES_INT("splitFirst", 1);
LXW_PUSH_ATTRIBUTES_INT("rowColShift", 1);
LXW_PUSH_ATTRIBUTES_INT("clearFormats", 1);
LXW_PUSH_ATTRIBUTES_INT("clearComments", 1);
LXW_PUSH_ATTRIBUTES_INT("assign", 1);
LXW_PUSH_ATTRIBUTES_INT("coerce", 1);
LXW_PUSH_ATTRIBUTES_INT("cellMeta", 1);
lxw_xml_empty_tag(self->file, "metadataType", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <metadataTypes> element.
*/
STATIC void
_metadata_write_metadata_types(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("count", 1);
lxw_xml_start_tag(self->file, "metadataTypes", &attributes);
/* Write the metadataType element. */
_metadata_write_metadata_type(self);
lxw_xml_end_tag(self->file, "metadataTypes");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <xda:dynamicArrayProperties> element.
*/
STATIC void
_metadata_write_xda_dynamic_array_properties(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("fDynamic", "1");
LXW_PUSH_ATTRIBUTES_STR("fCollapsed", "0");
lxw_xml_empty_tag(self->file, "xda:dynamicArrayProperties", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <ext> element.
*/
STATIC void
_metadata_write_ext(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("uri", "{bdbb8cdc-fa1e-496e-a857-3c3f30c029c3}");
lxw_xml_start_tag(self->file, "ext", &attributes);
/* Write the xda:dynamicArrayProperties element. */
_metadata_write_xda_dynamic_array_properties(self);
lxw_xml_end_tag(self->file, "ext");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <futureMetadata> element.
*/
STATIC void
_metadata_write_future_metadata(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("name", "XLDAPR");
LXW_PUSH_ATTRIBUTES_INT("count", 1);
lxw_xml_start_tag(self->file, "futureMetadata", &attributes);
lxw_xml_start_tag(self->file, "bk", NULL);
lxw_xml_start_tag(self->file, "extLst", NULL);
/* Write the ext element. */
_metadata_write_ext(self);
lxw_xml_end_tag(self->file, "extLst");
lxw_xml_end_tag(self->file, "bk");
lxw_xml_end_tag(self->file, "futureMetadata");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <rc> element.
*/
STATIC void
_metadata_write_rc(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("t", "1");
LXW_PUSH_ATTRIBUTES_STR("v", "0");
lxw_xml_empty_tag(self->file, "rc", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <cellMetadata> element.
*/
STATIC void
_metadata_write_cell_metadata(lxw_metadata *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("count", "1");
lxw_xml_start_tag(self->file, "cellMetadata", &attributes);
lxw_xml_start_tag(self->file, "bk", NULL);
/* Write the rc element. */
_metadata_write_rc(self);
lxw_xml_end_tag(self->file, "bk");
lxw_xml_end_tag(self->file, "cellMetadata");
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_metadata_assemble_xml_file(lxw_metadata *self)
{
/* Write the XML declaration. */
_metadata_xml_declaration(self);
/* Write the metadata element. */
_metadata_write_metadata(self);
/* Write the metadataTypes element. */
_metadata_write_metadata_types(self);
/* Write the futureMetadata element. */
_metadata_write_future_metadata(self);
/* Write the cellMetadata element. */
_metadata_write_cell_metadata(self);
lxw_xml_end_tag(self->file, "metadata");
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
/*****************************************************************************
* relationships - A library for creating Excel XLSX relationships files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include <string.h>
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/relationships.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new relationships object.
*/
lxw_relationships *
lxw_relationships_new(void)
{
lxw_relationships *rels = calloc(1, sizeof(lxw_relationships));
GOTO_LABEL_ON_MEM_ERROR(rels, mem_error);
rels->relationships = calloc(1, sizeof(struct lxw_rel_tuples));
GOTO_LABEL_ON_MEM_ERROR(rels->relationships, mem_error);
STAILQ_INIT(rels->relationships);
return rels;
mem_error:
lxw_free_relationships(rels);
return NULL;
}
/*
* Free a relationships object.
*/
void
lxw_free_relationships(lxw_relationships *rels)
{
lxw_rel_tuple *relationship;
if (!rels)
return;
if (rels->relationships) {
while (!STAILQ_EMPTY(rels->relationships)) {
relationship = STAILQ_FIRST(rels->relationships);
STAILQ_REMOVE_HEAD(rels->relationships, list_pointers);
free(relationship->type);
free(relationship->target);
free(relationship->target_mode);
free(relationship);
}
free(rels->relationships);
}
free(rels);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_relationships_xml_declaration(lxw_relationships *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <Relationship> element.
*/
STATIC void
_write_relationship(lxw_relationships *self, const char *type,
const char *target, const char *target_mode)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char r_id[LXW_MAX_ATTRIBUTE_LENGTH] = { 0 };
self->rel_id++;
lxw_snprintf(r_id, LXW_ATTR_32, "rId%d", self->rel_id);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("Id", r_id);
LXW_PUSH_ATTRIBUTES_STR("Type", type);
LXW_PUSH_ATTRIBUTES_STR("Target", target);
if (target_mode)
LXW_PUSH_ATTRIBUTES_STR("TargetMode", target_mode);
lxw_xml_empty_tag(self->file, "Relationship", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <Relationships> element.
*/
STATIC void
_write_relationships(lxw_relationships *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
lxw_rel_tuple *rel;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", LXW_SCHEMA_PACKAGE);
lxw_xml_start_tag(self->file, "Relationships", &attributes);
STAILQ_FOREACH(rel, self->relationships, list_pointers) {
_write_relationship(self, rel->type, rel->target, rel->target_mode);
}
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_relationships_assemble_xml_file(lxw_relationships *self)
{
/* Write the XML declaration. */
_relationships_xml_declaration(self);
_write_relationships(self);
/* Close the relationships tag. */
lxw_xml_end_tag(self->file, "Relationships");
}
/*
* Add a generic container relationship to XLSX .rels xml files.
*/
STATIC void
_add_relationship(lxw_relationships *self, const char *schema,
const char *type, const char *target,
const char *target_mode)
{
lxw_rel_tuple *relationship;
if (!schema || !type || !target)
return;
relationship = calloc(1, sizeof(lxw_rel_tuple));
GOTO_LABEL_ON_MEM_ERROR(relationship, mem_error);
relationship->type = calloc(1, LXW_MAX_ATTRIBUTE_LENGTH);
GOTO_LABEL_ON_MEM_ERROR(relationship->type, mem_error);
/* Add the schema to the relationship type. */
lxw_snprintf(relationship->type, LXW_MAX_ATTRIBUTE_LENGTH, "%s%s",
schema, type);
relationship->target = lxw_strdup(target);
GOTO_LABEL_ON_MEM_ERROR(relationship->target, mem_error);
if (target_mode) {
relationship->target_mode = lxw_strdup(target_mode);
GOTO_LABEL_ON_MEM_ERROR(relationship->target_mode, mem_error);
}
STAILQ_INSERT_TAIL(self->relationships, relationship, list_pointers);
return;
mem_error:
if (relationship) {
free(relationship->type);
free(relationship->target);
free(relationship->target_mode);
free(relationship);
}
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Add a document relationship to XLSX .rels xml files.
*/
void
lxw_add_document_relationship(lxw_relationships *self, const char *type,
const char *target)
{
_add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, NULL);
}
/*
* Add a package relationship to XLSX .rels xml files.
*/
void
lxw_add_package_relationship(lxw_relationships *self, const char *type,
const char *target)
{
_add_relationship(self, LXW_SCHEMA_PACKAGE, type, target, NULL);
}
/*
* Add a MS schema package relationship to XLSX .rels xml files.
*/
void
lxw_add_ms_package_relationship(lxw_relationships *self, const char *type,
const char *target)
{
_add_relationship(self, LXW_SCHEMA_MS, type, target, NULL);
}
/*
* Add a worksheet relationship to sheet .rels xml files.
*/
void
lxw_add_worksheet_relationship(lxw_relationships *self, const char *type,
const char *target, const char *target_mode)
{
_add_relationship(self, LXW_SCHEMA_DOCUMENT, type, target, target_mode);
}

View File

@@ -0,0 +1,278 @@
/*****************************************************************************
* shared_strings - A library for creating Excel XLSX sst files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/shared_strings.h"
#include "xlsxwriter/utility.h"
#include <ctype.h>
/*
* Forward declarations.
*/
STATIC int _element_cmp(struct sst_element *element1,
struct sst_element *element2);
#ifndef __clang_analyzer__
LXW_RB_GENERATE_ELEMENT(sst_rb_tree, sst_element, sst_tree_pointers,
_element_cmp);
#endif
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new SST SharedString object.
*/
lxw_sst *
lxw_sst_new(void)
{
/* Create the new shared string table. */
lxw_sst *sst = calloc(1, sizeof(lxw_sst));
RETURN_ON_MEM_ERROR(sst, NULL);
/* Add the sst RB tree. */
sst->rb_tree = calloc(1, sizeof(struct sst_rb_tree));
GOTO_LABEL_ON_MEM_ERROR(sst->rb_tree, mem_error);
/* Add a list for tracking the insertion order. */
sst->order_list = calloc(1, sizeof(struct sst_order_list));
GOTO_LABEL_ON_MEM_ERROR(sst->order_list, mem_error);
/* Initialize the order list. */
STAILQ_INIT(sst->order_list);
/* Initialize the RB tree. */
RB_INIT(sst->rb_tree);
return sst;
mem_error:
lxw_sst_free(sst);
return NULL;
}
/*
* Free a SST SharedString table object.
*/
void
lxw_sst_free(lxw_sst *sst)
{
struct sst_element *sst_element;
struct sst_element *sst_element_temp;
if (!sst)
return;
/* Free the sst_elements and their data using the ordered linked list. */
if (sst->order_list) {
STAILQ_FOREACH_SAFE(sst_element, sst->order_list, sst_order_pointers,
sst_element_temp) {
if (sst_element && sst_element->string)
free(sst_element->string);
if (sst_element)
free(sst_element);
}
}
free(sst->order_list);
free(sst->rb_tree);
free(sst);
}
/*
* Comparator for the element structure
*/
STATIC int
_element_cmp(struct sst_element *element1, struct sst_element *element2)
{
return strcmp(element1->string, element2->string);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_sst_xml_declaration(lxw_sst *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <t> element.
*/
STATIC void
_write_t(lxw_sst *self, char *string)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
/* Add attribute to preserve leading or trailing whitespace. */
if (isspace((unsigned char) string[0])
|| isspace((unsigned char) string[strlen(string) - 1]))
LXW_PUSH_ATTRIBUTES_STR("xml:space", "preserve");
lxw_xml_data_element(self->file, "t", string, &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <si> element.
*/
STATIC void
_write_si(lxw_sst *self, char *string)
{
uint8_t escaped_string = LXW_FALSE;
lxw_xml_start_tag(self->file, "si", NULL);
/* Look for and escape control chars in the string. */
if (lxw_has_control_characters(string)) {
string = lxw_escape_control_characters(string);
escaped_string = LXW_TRUE;
}
/* Write the t element. */
_write_t(self, string);
lxw_xml_end_tag(self->file, "si");
if (escaped_string)
free(string);
}
/*
* Write the <si> element for rich strings.
*/
STATIC void
_write_rich_si(lxw_sst *self, char *string)
{
lxw_xml_rich_si_element(self->file, string);
}
/*
* Write the <sst> element.
*/
STATIC void
_write_sst(lxw_sst *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] =
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_INT("count", self->string_count);
LXW_PUSH_ATTRIBUTES_INT("uniqueCount", self->unique_count);
lxw_xml_start_tag(self->file, "sst", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
STATIC void
_write_sst_strings(lxw_sst *self)
{
struct sst_element *sst_element;
STAILQ_FOREACH(sst_element, self->order_list, sst_order_pointers) {
/* Write the si element. */
if (sst_element->is_rich_string)
_write_rich_si(self, sst_element->string);
else
_write_si(self, sst_element->string);
}
}
/*
* Assemble and write the XML file.
*/
void
lxw_sst_assemble_xml_file(lxw_sst *self)
{
/* Write the XML declaration. */
_sst_xml_declaration(self);
/* Write the sst element. */
_write_sst(self);
/* Write the sst strings. */
_write_sst_strings(self);
/* Close the sst tag. */
lxw_xml_end_tag(self->file, "sst");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/
/*
* Add to or find a string in the SST SharedString table and return it's index.
*/
struct sst_element *
lxw_get_sst_index(lxw_sst *sst, const char *string, uint8_t is_rich_string)
{
struct sst_element *element;
struct sst_element *existing_element;
/* Create an sst element to potentially add to the table. */
element = calloc(1, sizeof(struct sst_element));
if (!element)
return NULL;
/* Create potential new element with the string and its index. */
element->index = sst->unique_count;
element->string = lxw_strdup(string);
element->is_rich_string = is_rich_string;
/* Try to insert it and see whether we already have that string. */
existing_element = RB_INSERT(sst_rb_tree, sst->rb_tree, element);
/* If existing_element is not NULL, then it already existed. */
/* Free new created element. */
if (existing_element) {
free(element->string);
free(element);
sst->string_count++;
return existing_element;
}
/* If it didn't exist, also add it to the insertion order linked list. */
STAILQ_INSERT_TAIL(sst->order_list, element, sst_order_pointers);
/* Update SST string counts. */
sst->string_count++;
sst->unique_count++;
return element;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,304 @@
/*****************************************************************************
* table - A library for creating Excel XLSX table files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/worksheet.h"
#include "xlsxwriter/table.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new table object.
*/
lxw_table *
lxw_table_new(void)
{
lxw_table *table = calloc(1, sizeof(lxw_table));
GOTO_LABEL_ON_MEM_ERROR(table, mem_error);
return table;
mem_error:
lxw_table_free(table);
return NULL;
}
/*
* Free a table object.
*/
void
lxw_table_free(lxw_table *table)
{
if (!table)
return;
free(table);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_table_xml_declaration(lxw_table *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <table> element.
*/
STATIC void
_table_write_table(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char xmlns[] =
"http://schemas.openxmlformats.org/spreadsheetml/2006/main";
lxw_table_obj *table_obj = self->table_obj;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns", xmlns);
LXW_PUSH_ATTRIBUTES_INT("id", table_obj->id);
if (table_obj->name)
LXW_PUSH_ATTRIBUTES_STR("name", table_obj->name);
else
LXW_PUSH_ATTRIBUTES_STR("name", "Table1");
if (table_obj->name)
LXW_PUSH_ATTRIBUTES_STR("displayName", table_obj->name);
else
LXW_PUSH_ATTRIBUTES_STR("displayName", "Table1");
LXW_PUSH_ATTRIBUTES_STR("ref", table_obj->sqref);
if (table_obj->no_header_row)
LXW_PUSH_ATTRIBUTES_STR("headerRowCount", "0");
if (table_obj->total_row)
LXW_PUSH_ATTRIBUTES_STR("totalsRowCount", "1");
else
LXW_PUSH_ATTRIBUTES_STR("totalsRowShown", "0");
lxw_xml_start_tag(self->file, "table", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <autoFilter> element.
*/
STATIC void
_table_write_auto_filter(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
if (self->table_obj->no_autofilter)
return;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("ref", self->table_obj->filter_sqref);
lxw_xml_empty_tag(self->file, "autoFilter", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <tableColumn> element.
*/
STATIC void
_table_write_table_column(lxw_table *self, uint16_t id,
lxw_table_column *column)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
int32_t dfx_id;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("id", id);
LXW_PUSH_ATTRIBUTES_STR("name", column->header);
if (column->total_string) {
LXW_PUSH_ATTRIBUTES_STR("totalsRowLabel", column->total_string);
}
else if (column->total_function) {
if (column->total_function == LXW_TABLE_FUNCTION_AVERAGE)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "average");
if (column->total_function == LXW_TABLE_FUNCTION_COUNT_NUMS)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "countNums");
if (column->total_function == LXW_TABLE_FUNCTION_COUNT)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "count");
if (column->total_function == LXW_TABLE_FUNCTION_MAX)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "max");
if (column->total_function == LXW_TABLE_FUNCTION_MIN)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "min");
if (column->total_function == LXW_TABLE_FUNCTION_STD_DEV)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "stdDev");
if (column->total_function == LXW_TABLE_FUNCTION_SUM)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "sum");
if (column->total_function == LXW_TABLE_FUNCTION_VAR)
LXW_PUSH_ATTRIBUTES_STR("totalsRowFunction", "var");
}
if (column->format) {
dfx_id = lxw_format_get_dxf_index(column->format);
LXW_PUSH_ATTRIBUTES_INT("dataDxfId", dfx_id);
}
if (column->formula) {
lxw_xml_start_tag(self->file, "tableColumn", &attributes);
lxw_xml_data_element(self->file, "calculatedColumnFormula",
column->formula, NULL);
lxw_xml_end_tag(self->file, "tableColumn");
}
else {
lxw_xml_empty_tag(self->file, "tableColumn", &attributes);
}
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <tableColumns> element.
*/
STATIC void
_table_write_table_columns(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
uint16_t i;
uint16_t num_cols = self->table_obj->num_cols;
lxw_table_column **columns = self->table_obj->columns;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_INT("count", num_cols);
lxw_xml_start_tag(self->file, "tableColumns", &attributes);
for (i = 0; i < num_cols; i++)
_table_write_table_column(self, i + 1, columns[i]);
lxw_xml_end_tag(self->file, "tableColumns");
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <tableStyleInfo> element.
*/
STATIC void
_table_write_table_style_info(lxw_table *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char name[LXW_ATTR_32];
lxw_table_obj *table_obj = self->table_obj;
LXW_INIT_ATTRIBUTES();
if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_LIGHT) {
if (table_obj->style_type_number != 0) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleLight%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
}
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_MEDIUM) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleMedium%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
else if (table_obj->style_type == LXW_TABLE_STYLE_TYPE_DARK) {
lxw_snprintf(name, LXW_ATTR_32, "TableStyleDark%d",
table_obj->style_type_number);
LXW_PUSH_ATTRIBUTES_STR("name", name);
}
else {
LXW_PUSH_ATTRIBUTES_STR("name", "TableStyleMedium9");
}
if (table_obj->first_column)
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showFirstColumn", "0");
if (table_obj->last_column)
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showLastColumn", "0");
if (table_obj->no_banded_rows)
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "0");
else
LXW_PUSH_ATTRIBUTES_STR("showRowStripes", "1");
if (table_obj->banded_columns)
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "1");
else
LXW_PUSH_ATTRIBUTES_STR("showColumnStripes", "0");
lxw_xml_empty_tag(self->file, "tableStyleInfo", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_table_assemble_xml_file(lxw_table *self)
{
/* Write the XML declaration. */
_table_xml_declaration(self);
/* Write the table element. */
_table_write_table(self);
/* Write the autoFilter element. */
_table_write_auto_filter(self);
/* Write the tableColumns element. */
_table_write_table_columns(self);
/* Write the tableStyleInfo element. */
_table_write_table_style_info(self);
lxw_xml_end_tag(self->file, "table");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,348 @@
/*****************************************************************************
* theme - A library for creating Excel XLSX theme files.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include <string.h>
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/theme.h"
#include "xlsxwriter/utility.h"
const char *theme_strs[] = {
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n",
"<a:theme xmlns:a=\"http://schemas.openxmlformats.org/",
"drawingml/2006/main\" name=\"Office Theme\">",
"<a:themeElements>",
"<a:clrScheme name=\"Office\"><a:dk1>",
"<a:sysClr val=\"windowText\" lastClr=\"000000\"/>",
"</a:dk1><a:lt1>",
"<a:sysClr val=\"window\" lastClr=\"FFFFFF\"/></a:lt1><a:dk2>",
"<a:srgbClr val=\"1F497D\"/></a:dk2><a:lt2>",
"<a:srgbClr val=\"EEECE1\"/></a:lt2><a:accent1>",
"<a:srgbClr val=\"4F81BD\"/></a:accent1><a:accent2>",
"<a:srgbClr val=\"C0504D\"/></a:accent2><a:accent3>",
"<a:srgbClr val=\"9BBB59\"/></a:accent3><a:accent4>",
"<a:srgbClr val=\"8064A2\"/></a:accent4><a:accent5>",
"<a:srgbClr val=\"4BACC6\"/></a:accent5><a:accent6>",
"<a:srgbClr val=\"F79646\"/></a:accent6><a:hlink>",
"<a:srgbClr val=\"0000FF\"/></a:hlink><a:folHlink>",
"<a:srgbClr val=\"800080\"/></a:folHlink></a:clrScheme>",
"<a:fontScheme name=\"Office\"><a:majorFont>",
"<a:latin typeface=\"Cambria\"/><a:ea typeface=\"\"/>",
"<a:cs typeface=\"\"/>",
"<a:font script=\"Jpan\" typeface=\" Pゴシック\"/>",
"<a:font script=\"Hang\" typeface=\"맑은 고딕\"/>",
"<a:font script=\"Hans\" typeface=\"宋体\"/>",
"<a:font script=\"Hant\" typeface=\"新細明體\"/>",
"<a:font script=\"Arab\" typeface=\"Times New Roman\"/>",
"<a:font script=\"Hebr\" typeface=\"Times New Roman\"/>",
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>",
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>",
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>",
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>",
"<a:font script=\"Khmr\" typeface=\"MoolBoran\"/>",
"<a:font script=\"Knda\" typeface=\"Tunga\"/>",
"<a:font script=\"Guru\" typeface=\"Raavi\"/>",
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>",
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>",
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>",
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>",
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>",
"<a:font script=\"Deva\" typeface=\"Mangal\"/>",
"<a:font script=\"Telu\" typeface=\"Gautami\"/>",
"<a:font script=\"Taml\" typeface=\"Latha\"/>",
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>",
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>",
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>",
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>",
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>",
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>",
"<a:font script=\"Viet\" typeface=\"Times New Roman\"/>",
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>",
"</a:majorFont>",
"<a:minorFont>",
"<a:latin typeface=\"Calibri\"/>",
"<a:ea typeface=\"\"/>",
"<a:cs typeface=\"\"/>",
"<a:font script=\"Jpan\" typeface=\" Pゴシック\"/>",
"<a:font script=\"Hang\" typeface=\"맑은 고딕\"/>",
"<a:font script=\"Hans\" typeface=\"宋体\"/>",
"<a:font script=\"Hant\" typeface=\"新細明體\"/>",
"<a:font script=\"Arab\" typeface=\"Arial\"/>",
"<a:font script=\"Hebr\" typeface=\"Arial\"/>",
"<a:font script=\"Thai\" typeface=\"Tahoma\"/>",
"<a:font script=\"Ethi\" typeface=\"Nyala\"/>",
"<a:font script=\"Beng\" typeface=\"Vrinda\"/>",
"<a:font script=\"Gujr\" typeface=\"Shruti\"/>",
"<a:font script=\"Khmr\" typeface=\"DaunPenh\"/>",
"<a:font script=\"Knda\" typeface=\"Tunga\"/>",
"<a:font script=\"Guru\" typeface=\"Raavi\"/>",
"<a:font script=\"Cans\" typeface=\"Euphemia\"/>",
"<a:font script=\"Cher\" typeface=\"Plantagenet Cherokee\"/>",
"<a:font script=\"Yiii\" typeface=\"Microsoft Yi Baiti\"/>",
"<a:font script=\"Tibt\" typeface=\"Microsoft Himalaya\"/>",
"<a:font script=\"Thaa\" typeface=\"MV Boli\"/>",
"<a:font script=\"Deva\" typeface=\"Mangal\"/>",
"<a:font script=\"Telu\" typeface=\"Gautami\"/>",
"<a:font script=\"Taml\" typeface=\"Latha\"/>",
"<a:font script=\"Syrc\" typeface=\"Estrangelo Edessa\"/>",
"<a:font script=\"Orya\" typeface=\"Kalinga\"/>",
"<a:font script=\"Mlym\" typeface=\"Kartika\"/>",
"<a:font script=\"Laoo\" typeface=\"DokChampa\"/>",
"<a:font script=\"Sinh\" typeface=\"Iskoola Pota\"/>",
"<a:font script=\"Mong\" typeface=\"Mongolian Baiti\"/>",
"<a:font script=\"Viet\" typeface=\"Arial\"/>",
"<a:font script=\"Uigh\" typeface=\"Microsoft Uighur\"/>",
"</a:minorFont>",
"</a:fontScheme><a:fmtScheme name=\"Office\">",
"<a:fillStyleLst>",
"<a:solidFill>",
"<a:schemeClr val=\"phClr\"/>",
"</a:solidFill>",
"<a:gradFill rotWithShape=\"1\">",
"<a:gsLst>",
"<a:gs pos=\"0\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"50000\"/>",
"<a:satMod val=\"300000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"35000\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"37000\"/>",
"<a:satMod val=\"300000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"100000\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"15000\"/>",
"<a:satMod val=\"350000\"/>",
"</a:schemeClr>",
"</a:gs>",
"</a:gsLst>",
"<a:lin ang=\"16200000\" scaled=\"1\"/>",
"</a:gradFill>",
"<a:gradFill rotWithShape=\"1\">",
"<a:gsLst>",
"<a:gs pos=\"0\">",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"51000\"/>",
"<a:satMod val=\"130000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"80000\">",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"93000\"/>",
"<a:satMod val=\"130000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"100000\">",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"94000\"/>",
"<a:satMod val=\"135000\"/>",
"</a:schemeClr>",
"</a:gs>",
"</a:gsLst>",
"<a:lin ang=\"16200000\" scaled=\"0\"/>",
"</a:gradFill>",
"</a:fillStyleLst>",
"<a:lnStyleLst>",
"<a:ln w=\"9525\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">",
"<a:solidFill>",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"95000\"/>",
"<a:satMod val=\"105000\"/>",
"</a:schemeClr>",
"</a:solidFill>",
"<a:prstDash val=\"solid\"/>",
"</a:ln>",
"<a:ln w=\"25400\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">",
"<a:solidFill>",
"<a:schemeClr val=\"phClr\"/>",
"</a:solidFill>",
"<a:prstDash val=\"solid\"/>",
"</a:ln>",
"<a:ln w=\"38100\" cap=\"flat\" cmpd=\"sng\" algn=\"ctr\">",
"<a:solidFill>",
"<a:schemeClr val=\"phClr\"/>",
"</a:solidFill>",
"<a:prstDash val=\"solid\"/>",
"</a:ln>",
"</a:lnStyleLst>",
"<a:effectStyleLst>",
"<a:effectStyle>",
"<a:effectLst>",
"<a:outerShdw blurRad=\"40000\" dist=\"20000\" ",
"dir=\"5400000\" rotWithShape=\"0\">",
"<a:srgbClr val=\"000000\">",
"<a:alpha val=\"38000\"/>",
"</a:srgbClr>",
"</a:outerShdw>",
"</a:effectLst>",
"</a:effectStyle>",
"<a:effectStyle>",
"<a:effectLst>",
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" ",
"dir=\"5400000\" rotWithShape=\"0\">",
"<a:srgbClr val=\"000000\">",
"<a:alpha val=\"35000\"/>",
"</a:srgbClr>",
"</a:outerShdw>",
"</a:effectLst>",
"</a:effectStyle>",
"<a:effectStyle>",
"<a:effectLst>",
"<a:outerShdw blurRad=\"40000\" dist=\"23000\" ",
"dir=\"5400000\" rotWithShape=\"0\">",
"<a:srgbClr val=\"000000\">",
"<a:alpha val=\"35000\"/>",
"</a:srgbClr>",
"</a:outerShdw>",
"</a:effectLst>",
"<a:scene3d>",
"<a:camera prst=\"orthographicFront\">",
"<a:rot lat=\"0\" lon=\"0\" rev=\"0\"/>",
"</a:camera>",
"<a:lightRig rig=\"threePt\" dir=\"t\">",
"<a:rot lat=\"0\" lon=\"0\" rev=\"1200000\"/>",
"</a:lightRig>",
"</a:scene3d>",
"<a:sp3d>",
"<a:bevelT w=\"63500\" h=\"25400\"/>",
"</a:sp3d>",
"</a:effectStyle>",
"</a:effectStyleLst>",
"<a:bgFillStyleLst>",
"<a:solidFill>",
"<a:schemeClr val=\"phClr\"/>",
"</a:solidFill>",
"<a:gradFill rotWithShape=\"1\">",
"<a:gsLst>",
"<a:gs pos=\"0\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"40000\"/>",
"<a:satMod val=\"350000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"40000\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"45000\"/>",
"<a:shade val=\"99000\"/>",
"<a:satMod val=\"350000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"100000\">",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"20000\"/>",
"<a:satMod val=\"255000\"/>",
"</a:schemeClr>",
"</a:gs>",
"</a:gsLst>",
"<a:path path=\"circle\">",
"<a:fillToRect l=\"50000\" t=\"-80000\" r=\"50000\" b=\"180000\"/>",
"</a:path>",
"</a:gradFill>",
"<a:gradFill rotWithShape=\"1\">",
"<a:gsLst>",
"<a:gs pos=\"0\">",
"<a:schemeClr val=\"phClr\">",
"<a:tint val=\"80000\"/>",
"<a:satMod val=\"300000\"/>",
"</a:schemeClr>",
"</a:gs>",
"<a:gs pos=\"100000\">",
"<a:schemeClr val=\"phClr\">",
"<a:shade val=\"30000\"/>",
"<a:satMod val=\"200000\"/>",
"</a:schemeClr>",
"</a:gs>",
"</a:gsLst>",
"<a:path path=\"circle\">",
"<a:fillToRect l=\"50000\" t=\"50000\" r=\"50000\" b=\"50000\"/>",
"</a:path>",
"</a:gradFill>",
"</a:bgFillStyleLst>",
"</a:fmtScheme>",
"</a:themeElements>",
"<a:objectDefaults/>",
"<a:extraClrSchemeLst/>",
"</a:theme>\n",
""
};
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new theme object.
*/
lxw_theme *
lxw_theme_new(void)
{
lxw_theme *theme = calloc(1, sizeof(lxw_theme));
GOTO_LABEL_ON_MEM_ERROR(theme, mem_error);
return theme;
mem_error:
lxw_theme_free(theme);
return NULL;
}
/*
* Free a theme object.
*/
void
lxw_theme_free(lxw_theme *theme)
{
if (!theme)
return;
free(theme);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/* This library isn't a xmlwriter. */
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_theme_assemble_xml_file(lxw_theme *self)
{
int i = 0;
while (strlen(theme_strs[i])) {
fprintf(self->file, "%s", theme_strs[i]);
i++;
}
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/

View File

@@ -0,0 +1,702 @@
/*****************************************************************************
* utility - Utility functions for libxlsxwriter.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#ifdef USE_FMEMOPEN
#define _POSIX_C_SOURCE 200809L
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "xlsxwriter.h"
#include "xlsxwriter/common.h"
#include "xlsxwriter/third_party/tmpfileplus.h"
#ifdef USE_DTOA_LIBRARY
#include "xlsxwriter/third_party/emyg_dtoa.h"
#endif
char *error_strings[LXW_MAX_ERRNO + 1] = {
"No error.",
"Memory error, failed to malloc() required memory.",
"Error creating output xlsx file. Usually a permissions error.",
"Error encountered when creating a tmpfile during file assembly.",
"Error reading a tmpfile.",
"Zip generic error ZIP_ERRNO while creating the xlsx file.",
"Zip error ZIP_PARAMERROR while creating the xlsx file.",
"Zip error ZIP_BADZIPFILE (use_zip64 option may be required).",
"Zip error ZIP_INTERNALERROR while creating the xlsx file.",
"File error or unknown zip error when adding sub file to xlsx file.",
"Unknown zip error when closing xlsx file.",
"Feature is not currently supported in this configuration.",
"NULL function parameter ignored.",
"Function parameter validation error.",
"Worksheet name exceeds Excel's limit of 31 characters.",
"Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'",
"Worksheet name cannot start or end with an apostrophe.",
"Worksheet name is already in use.",
"Parameter exceeds Excel's limit of 32 characters.",
"Parameter exceeds Excel's limit of 128 characters.",
"Parameter exceeds Excel's limit of 255 characters.",
"String exceeds Excel's limit of 32,767 characters.",
"Error finding internal string index.",
"Worksheet row or column index out of range.",
"Maximum hyperlink length (2079) exceeded.",
"Maximum number of worksheet URLs (65530) exceeded.",
"Couldn't read image dimensions or DPI.",
"Unknown error number."
};
char *
lxw_strerror(lxw_error error_num)
{
if (error_num > LXW_MAX_ERRNO)
error_num = LXW_MAX_ERRNO;
return error_strings[error_num];
}
/*
* Convert Excel A-XFD style column name to zero based number.
*/
void
lxw_col_to_name(char *col_name, lxw_col_t col_num, uint8_t absolute)
{
uint8_t pos = 0;
size_t len;
size_t i;
/* Change from 0 index to 1 index. */
col_num++;
/* Convert the column number to a string in reverse order. */
while (col_num) {
/* Get the remainder in base 26. */
int remainder = col_num % 26;
if (remainder == 0)
remainder = 26;
/* Convert the remainder value to a character. */
col_name[pos++] = 'A' + remainder - 1;
col_name[pos] = '\0';
/* Get the next order of magnitude. */
col_num = (col_num - 1) / 26;
}
if (absolute) {
col_name[pos] = '$';
col_name[pos + 1] = '\0';
}
/* Reverse the column name string. */
len = strlen(col_name);
for (i = 0; i < (len / 2); i++) {
char tmp = col_name[i];
col_name[i] = col_name[len - i - 1];
col_name[len - i - 1] = tmp;
}
}
/*
* Convert zero indexed row and column to an Excel style A1 cell reference.
*/
void
lxw_rowcol_to_cell(char *cell_name, lxw_row_t row, lxw_col_t col)
{
size_t pos;
/* Add the column to the cell. */
lxw_col_to_name(cell_name, col, 0);
/* Get the end of the cell. */
pos = strlen(cell_name);
/* Add the row to the cell. */
lxw_snprintf(&cell_name[pos], LXW_MAX_ROW_NAME_LENGTH, "%d", ++row);
}
/*
* Convert zero indexed row and column to an Excel style $A$1 cell with
* an absolute reference.
*/
void
lxw_rowcol_to_cell_abs(char *cell_name, lxw_row_t row, lxw_col_t col,
uint8_t abs_row, uint8_t abs_col)
{
size_t pos;
/* Add the column to the cell. */
lxw_col_to_name(cell_name, col, abs_col);
/* Get the end of the cell. */
pos = strlen(cell_name);
if (abs_row)
cell_name[pos++] = '$';
/* Add the row to the cell. */
lxw_snprintf(&cell_name[pos], LXW_MAX_ROW_NAME_LENGTH, "%d", ++row);
}
/*
* Convert zero indexed row and column pair to an Excel style A1:C5
* range reference.
*/
void
lxw_rowcol_to_range(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col)
{
size_t pos;
/* Add the first cell to the range. */
lxw_rowcol_to_cell(range, first_row, first_col);
/* If the start and end cells are the same just return a single cell. */
if (first_row == last_row && first_col == last_col)
return;
/* Get the end of the cell. */
pos = strlen(range);
/* Add the range separator. */
range[pos++] = ':';
/* Add the first cell to the range. */
lxw_rowcol_to_cell(&range[pos], last_row, last_col);
}
/*
* Convert zero indexed row and column pairs to an Excel style $A$1:$C$5
* range reference with absolute values.
*/
void
lxw_rowcol_to_range_abs(char *range,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col)
{
size_t pos;
/* Add the first cell to the range. */
lxw_rowcol_to_cell_abs(range, first_row, first_col, 1, 1);
/* If the start and end cells are the same just return a single cell. */
if (first_row == last_row && first_col == last_col)
return;
/* Get the end of the cell. */
pos = strlen(range);
/* Add the range separator. */
range[pos++] = ':';
/* Add the first cell to the range. */
lxw_rowcol_to_cell_abs(&range[pos], last_row, last_col, 1, 1);
}
/*
* Convert sheetname and zero indexed row and column pairs to an Excel style
* Sheet1!$A$1:$C$5 formula reference with absolute values.
*/
void
lxw_rowcol_to_formula_abs(char *formula, const char *sheetname,
lxw_row_t first_row, lxw_col_t first_col,
lxw_row_t last_row, lxw_col_t last_col)
{
size_t pos;
char *quoted_name = lxw_quote_sheetname(sheetname);
strncpy(formula, quoted_name, LXW_MAX_FORMULA_RANGE_LENGTH - 1);
free(quoted_name);
/* Get the end of the sheetname. */
pos = strlen(formula);
/* Add the range separator. */
formula[pos++] = '!';
/* Add the first cell to the range. */
lxw_rowcol_to_cell_abs(&formula[pos], first_row, first_col, 1, 1);
/* If the start and end cells are the same just return a single cell. */
if (first_row == last_row && first_col == last_col)
return;
/* Get the end of the cell. */
pos = strlen(formula);
/* Add the range separator. */
formula[pos++] = ':';
/* Add the first cell to the range. */
lxw_rowcol_to_cell_abs(&formula[pos], last_row, last_col, 1, 1);
}
/*
* Convert an Excel style A1 cell reference to a zero indexed row number.
*/
lxw_row_t
lxw_name_to_row(const char *row_str)
{
lxw_row_t row_num = 0;
const char *p = row_str;
/* Skip the column letters and absolute symbol of the A1 cell. */
while (p && !isdigit((unsigned char) *p))
p++;
/* Convert the row part of the A1 cell to a number. */
if (p)
row_num = atoi(p);
if (row_num)
return row_num - 1;
else
return 0;
}
/*
* Convert an Excel style A1 cell reference to a zero indexed column number.
*/
lxw_col_t
lxw_name_to_col(const char *col_str)
{
lxw_col_t col_num = 0;
const char *p = col_str;
/* Convert leading column letters of A1 cell. Ignore absolute $ marker. */
while (p && (isupper((unsigned char) *p) || *p == '$')) {
if (*p != '$')
col_num = (col_num * 26) + (*p - 'A' + 1);
p++;
}
return col_num - 1;
}
/*
* Convert the second row of an Excel range ref to a zero indexed number.
*/
uint32_t
lxw_name_to_row_2(const char *row_str)
{
const char *p = row_str;
/* Find the : separator in the range. */
while (p && *p != ':')
p++;
if (p)
return lxw_name_to_row(++p);
else
return -1;
}
/*
* Convert the second column of an Excel range ref to a zero indexed number.
*/
uint16_t
lxw_name_to_col_2(const char *col_str)
{
const char *p = col_str;
/* Find the : separator in the range. */
while (p && *p != ':')
p++;
if (p)
return lxw_name_to_col(++p);
else
return -1;
}
/*
* Convert a lxw_datetime struct to an Excel serial date, with a 1900
* or 1904 epoch.
*/
double
lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
{
int year = datetime->year;
int month = datetime->month;
int day = datetime->day;
int hour = datetime->hour;
int min = datetime->min;
double sec = datetime->sec;
double seconds;
int epoch = date_1904 ? 1904 : 1900;
int offset = date_1904 ? 4 : 0;
int norm = 300;
int range;
/* Set month days and check for leap year. */
int mdays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int leap = 0;
int days = 0;
int i;
/* For times without dates set the default date for the epoch. */
if (!year) {
if (!date_1904) {
year = 1899;
month = 12;
day = 31;
}
else {
year = 1904;
month = 1;
day = 1;
}
}
/* Convert the Excel seconds to a fraction of the seconds in 24 hours. */
seconds = (hour * 60 * 60 + min * 60 + sec) / (24 * 60 * 60.0);
/* Special cases for Excel dates in the 1900 epoch. */
if (!date_1904) {
/* Excel 1900 epoch. */
if (year == 1899 && month == 12 && day == 31)
return seconds;
/* Excel 1900 epoch. */
if (year == 1900 && month == 1 && day == 0)
return seconds;
/* Excel false leapday */
if (year == 1900 && month == 2 && day == 29)
return 60 + seconds;
}
/* We calculate the date by calculating the number of days since the */
/* epoch and adjust for the number of leap days. We calculate the */
/* number of leap days by normalizing the year in relation to the */
/* epoch. Thus the year 2000 becomes 100 for 4-year and 100-year */
/* leapdays and 400 for 400-year leapdays. */
range = year - epoch;
if (year % 4 == 0 && (year % 100 > 0 || year % 400 == 0)) {
leap = 1;
mdays[2] = 29;
}
/*
* Calculate the serial date by accumulating the number of days
* since the epoch.
*/
/* Add days for previous months. */
for (i = 0; i < month; i++) {
days += mdays[i];
}
/* Add days for current month. */
days += day;
/* Add days for all previous years. */
days += range * 365;
/* Add 4 year leapdays. */
days += range / 4;
/* Remove 100 year leapdays. */
days -= (range + offset) / 100;
/* Add 400 year leapdays. */
days += (range + offset + norm) / 400;
/* Remove leap days already counted. */
days -= leap;
/* Adjust for Excel erroneously treating 1900 as a leap year. */
if (!date_1904 && days > 59)
days++;
return days + seconds;
}
/*
* Convert a lxw_datetime struct to an Excel serial date, for the 1900 epoch.
*/
double
lxw_datetime_to_excel_datetime(lxw_datetime *datetime)
{
return lxw_datetime_to_excel_date_epoch(datetime, LXW_FALSE);
}
/*
* Convert a unix datetime (1970/01/01 epoch) to an Excel serial date, with a
* 1900 epoch.
*/
double
lxw_unixtime_to_excel_date(int64_t unixtime)
{
return lxw_unixtime_to_excel_date_epoch(unixtime, LXW_FALSE);
}
/*
* Convert a unix datetime (1970/01/01 epoch) to an Excel serial date, with a
* 1900 or 1904 epoch.
*/
double
lxw_unixtime_to_excel_date_epoch(int64_t unixtime, uint8_t date_1904)
{
double excel_datetime = 0.0;
double epoch = date_1904 ? 24107.0 : 25568.0;
excel_datetime = epoch + (unixtime / (24 * 60 * 60.0));
if (!date_1904 && excel_datetime >= 60.0)
excel_datetime = excel_datetime + 1.0;
return excel_datetime;
}
/* Simple strdup() implementation since it isn't ANSI C. */
char *
lxw_strdup(const char *str)
{
size_t len;
char *copy;
if (!str)
return NULL;
len = strlen(str) + 1;
copy = malloc(len);
if (copy)
memcpy(copy, str, len);
return copy;
}
/* Simple function to strdup() a formula string without the leading "=". */
char *
lxw_strdup_formula(const char *formula)
{
if (!formula)
return NULL;
if (formula[0] == '=')
return lxw_strdup(formula + 1);
else
return lxw_strdup(formula);
}
/* Simple strlen that counts UTF-8 characters. Assumes well formed UTF-8. */
size_t
lxw_utf8_strlen(const char *str)
{
size_t byte_count = 0;
size_t char_count = 0;
while (str[byte_count]) {
if ((str[byte_count] & 0xc0) != 0x80)
char_count++;
byte_count++;
}
return char_count;
}
/* Simple tolower() for strings. */
void
lxw_str_tolower(char *str)
{
int i;
for (i = 0; str[i]; i++)
str[i] = tolower(str[i]);
}
/* Create a quoted version of the worksheet name, or return an unmodified
* copy if it doesn't required quoting. */
char *
lxw_quote_sheetname(const char *str)
{
uint8_t needs_quoting = 0;
size_t number_of_quotes = 2;
size_t i, j;
size_t len = strlen(str);
/* Don't quote the sheetname if it is already quoted. */
if (str[0] == '\'')
return lxw_strdup(str);
/* Check if the sheetname contains any characters that require it
* to be quoted. Also check for single quotes within the string. */
for (i = 0; i < len; i++) {
if (!isalnum((unsigned char) str[i]) && str[i] != '_'
&& str[i] != '.')
needs_quoting = 1;
if (str[i] == '\'') {
needs_quoting = 1;
number_of_quotes++;
}
}
if (!needs_quoting) {
return lxw_strdup(str);
}
else {
/* Add single quotes to the start and end of the string. */
char *quoted_name = calloc(1, len + number_of_quotes + 1);
RETURN_ON_MEM_ERROR(quoted_name, NULL);
quoted_name[0] = '\'';
for (i = 0, j = 1; i < len; i++, j++) {
quoted_name[j] = str[i];
/* Double quote inline single quotes. */
if (str[i] == '\'') {
quoted_name[++j] = '\'';
}
}
quoted_name[j++] = '\'';
quoted_name[j++] = '\0';
return quoted_name;
}
}
/*
* Thin wrapper for tmpfile() so it can be over-ridden with a user defined
* version if required for safety or portability.
*/
FILE *
lxw_tmpfile(const char *tmpdir)
{
#ifndef USE_STANDARD_TMPFILE
return tmpfileplus(tmpdir, NULL, NULL, 0);
#else
(void) tmpdir;
return tmpfile();
#endif
}
/**
* Return a memory-backed file if supported, otherwise a temporary one
*/
FILE *
lxw_get_filehandle(char **buf, size_t *size, const char *tmpdir)
{
static size_t s;
if (!size)
size = &s;
*buf = NULL;
*size = 0;
#ifdef USE_FMEMOPEN
(void) tmpdir;
return open_memstream(buf, size);
#else
return lxw_tmpfile(tmpdir);
#endif
}
/*
* Use third party function to handle sprintf of doubles for locale portable
* code.
*/
#ifdef USE_DTOA_LIBRARY
int
lxw_sprintf_dbl(char *data, double number)
{
emyg_dtoa(number, data);
return 0;
}
#endif
/*
* Retrieve runtime library version.
*/
const char *
lxw_version(void)
{
return LXW_VERSION;
}
/*
* Retrieve runtime library version ID.
*/
uint16_t
lxw_version_id(void)
{
return LXW_VERSION_ID;
}
/*
* Hash a worksheet password. Based on the algorithm in ECMA-376-4:2016,
* Office Open XML File Formats - Transitional Migration Features,
* Additional attributes for workbookProtection element (Part 1, §18.2.29).
*/
uint16_t
lxw_hash_password(const char *password)
{
uint16_t byte_count = (uint16_t) strlen(password);
uint16_t hash = 0;
const char *p = &password[byte_count];
if (!byte_count)
return hash;
while (p-- != password) {
hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
hash ^= *p & 0xFF;
}
hash = ((hash >> 14) & 0x01) | ((hash << 1) & 0x7fff);
hash ^= byte_count;
hash ^= 0xCE4B;
return hash;
}
/* Make a simple portable version of fopen() for Windows. */
#ifdef __MINGW32__
#undef _WIN32
#endif
#ifdef _WIN32
#include <windows.h>
FILE *
lxw_fopen(const char *filename, const char *mode)
{
int n;
wchar_t wide_filename[_MAX_PATH + 1] = L"";
wchar_t wide_mode[_MAX_PATH + 1] = L"";
n = MultiByteToWideChar(CP_UTF8, 0, filename, (int) strlen(filename),
wide_filename, _MAX_PATH);
if (n == 0) {
LXW_ERROR("MultiByteToWideChar error: filename");
return NULL;
}
n = MultiByteToWideChar(CP_UTF8, 0, mode, (int) strlen(mode),
wide_mode, _MAX_PATH);
if (n == 0) {
LXW_ERROR("MultiByteToWideChar error: mode");
return NULL;
}
return _wfopen(wide_filename, wide_mode);
}
#else
FILE *
lxw_fopen(const char *filename, const char *mode)
{
return fopen(filename, mode);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,454 @@
/*****************************************************************************
* xmlwriter - A base library for libxlsxwriter libraries.
*
* Used in conjunction with the libxlsxwriter library.
*
* Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "xlsxwriter/xmlwriter.h"
#define LXW_AMP "&amp;"
#define LXW_LT "&lt;"
#define LXW_GT "&gt;"
#define LXW_QUOT "&quot;"
#define LXW_NL "&#xA;"
/* Defines. */
#define LXW_MAX_ENCODED_ATTRIBUTE_LENGTH (LXW_MAX_ATTRIBUTE_LENGTH*6)
/* Forward declarations. */
STATIC char *_escape_attributes(struct xml_attribute *attribute);
char *lxw_escape_data(const char *data);
STATIC void _fprint_escaped_attributes(FILE * xmlfile,
struct xml_attribute_list *attributes);
STATIC void _fprint_escaped_data(FILE * xmlfile, const char *data);
/*
* Write the XML declaration.
*/
void
lxw_xml_declaration(FILE * xmlfile)
{
fprintf(xmlfile, "<?xml version=\"1.0\" "
"encoding=\"UTF-8\" standalone=\"yes\"?>\n");
}
/*
* Write an XML start tag with optional attributes.
*/
void
lxw_xml_start_tag(FILE * xmlfile,
const char *tag, struct xml_attribute_list *attributes)
{
fprintf(xmlfile, "<%s", tag);
_fprint_escaped_attributes(xmlfile, attributes);
fprintf(xmlfile, ">");
}
/*
* Write an XML start tag with optional, unencoded, attributes.
* This is a minor speed optimization for elements that don't need encoding.
*/
void
lxw_xml_start_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes)
{
struct xml_attribute *attribute;
fprintf(xmlfile, "<%s", tag);
if (attributes) {
STAILQ_FOREACH(attribute, attributes, list_entries) {
fprintf(xmlfile, " %s=\"%s\"", attribute->key, attribute->value);
}
}
fprintf(xmlfile, ">");
}
/*
* Write an XML end tag.
*/
void
lxw_xml_end_tag(FILE * xmlfile, const char *tag)
{
fprintf(xmlfile, "</%s>", tag);
}
/*
* Write an empty XML tag with optional attributes.
*/
void
lxw_xml_empty_tag(FILE * xmlfile,
const char *tag, struct xml_attribute_list *attributes)
{
fprintf(xmlfile, "<%s", tag);
_fprint_escaped_attributes(xmlfile, attributes);
fprintf(xmlfile, "/>");
}
/*
* Write an XML start tag with optional, unencoded, attributes.
* This is a minor speed optimization for elements that don't need encoding.
*/
void
lxw_xml_empty_tag_unencoded(FILE * xmlfile,
const char *tag,
struct xml_attribute_list *attributes)
{
struct xml_attribute *attribute;
fprintf(xmlfile, "<%s", tag);
if (attributes) {
STAILQ_FOREACH(attribute, attributes, list_entries) {
fprintf(xmlfile, " %s=\"%s\"", attribute->key, attribute->value);
}
}
fprintf(xmlfile, "/>");
}
/*
* Write an XML element containing data with optional attributes.
*/
void
lxw_xml_data_element(FILE * xmlfile,
const char *tag,
const char *data, struct xml_attribute_list *attributes)
{
fprintf(xmlfile, "<%s", tag);
_fprint_escaped_attributes(xmlfile, attributes);
fprintf(xmlfile, ">");
_fprint_escaped_data(xmlfile, data);
fprintf(xmlfile, "</%s>", tag);
}
/*
* Write an XML <si> element for rich strings, without encoding.
*/
void
lxw_xml_rich_si_element(FILE * xmlfile, const char *string)
{
fprintf(xmlfile, "<si>%s</si>", string);
}
/*
* Escape XML characters in attributes.
*/
STATIC char *
_escape_attributes(struct xml_attribute *attribute)
{
char *encoded = (char *) calloc(LXW_MAX_ENCODED_ATTRIBUTE_LENGTH, 1);
char *p_encoded = encoded;
char *p_attr = attribute->value;
while (*p_attr) {
switch (*p_attr) {
case '&':
memcpy(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
p_encoded += sizeof(LXW_AMP) - 1;
break;
case '<':
memcpy(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
p_encoded += sizeof(LXW_LT) - 1;
break;
case '>':
memcpy(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
p_encoded += sizeof(LXW_GT) - 1;
break;
case '"':
memcpy(p_encoded, LXW_QUOT, sizeof(LXW_QUOT) - 1);
p_encoded += sizeof(LXW_QUOT) - 1;
break;
case '\n':
memcpy(p_encoded, LXW_NL, sizeof(LXW_NL) - 1);
p_encoded += sizeof(LXW_NL) - 1;
break;
default:
*p_encoded = *p_attr;
p_encoded++;
break;
}
p_attr++;
}
return encoded;
}
/*
* Escape XML characters in data sections of tags.
* Note, this is different from _escape_attributes()
* in that double quotes are not escaped by Excel.
*/
char *
lxw_escape_data(const char *data)
{
size_t encoded_len = (strlen(data) * 5 + 1);
char *encoded = (char *) calloc(encoded_len, 1);
char *p_encoded = encoded;
while (*data) {
switch (*data) {
case '&':
memcpy(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
p_encoded += sizeof(LXW_AMP) - 1;
break;
case '<':
memcpy(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
p_encoded += sizeof(LXW_LT) - 1;
break;
case '>':
memcpy(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
p_encoded += sizeof(LXW_GT) - 1;
break;
default:
*p_encoded = *data;
p_encoded++;
break;
}
data++;
}
return encoded;
}
/*
* Check for control characters in strings.
*/
uint8_t
lxw_has_control_characters(const char *string)
{
while (string) {
/* 0xE0 == 0b11100000 masks values > 0x19 == 0b00011111. */
if (!(*string & 0xE0) && *string != 0x0A && *string != 0x09)
return LXW_TRUE;
string++;
}
return LXW_FALSE;
}
/*
* Escape control characters in strings with _xHHHH_.
*/
char *
lxw_escape_control_characters(const char *string)
{
size_t escape_len = sizeof("_xHHHH_") - 1;
size_t encoded_len = (strlen(string) * escape_len + 1);
char *encoded = (char *) calloc(encoded_len, 1);
char *p_encoded = encoded;
while (*string) {
switch (*string) {
case '\x01':
case '\x02':
case '\x03':
case '\x04':
case '\x05':
case '\x06':
case '\x07':
case '\x08':
case '\x0B':
case '\x0C':
case '\x0D':
case '\x0E':
case '\x0F':
case '\x10':
case '\x11':
case '\x12':
case '\x13':
case '\x14':
case '\x15':
case '\x16':
case '\x17':
case '\x18':
case '\x19':
case '\x1A':
case '\x1B':
case '\x1C':
case '\x1D':
case '\x1E':
case '\x1F':
lxw_snprintf(p_encoded, escape_len + 1, "_x%04X_", *string);
p_encoded += escape_len;
break;
default:
*p_encoded = *string;
p_encoded++;
break;
}
string++;
}
return encoded;
}
/*
* Escape special characters in URL strings with with %XX.
*/
char *
lxw_escape_url_characters(const char *string, uint8_t escape_hash)
{
size_t escape_len = sizeof("%XX") - 1;
size_t encoded_len = (strlen(string) * escape_len + 1);
char *encoded = (char *) calloc(encoded_len, 1);
char *p_encoded = encoded;
while (*string) {
switch (*string) {
case ' ':
case '"':
case '<':
case '>':
case '[':
case ']':
case '`':
case '^':
case '{':
case '}':
lxw_snprintf(p_encoded, escape_len + 1, "%%%2x", *string);
p_encoded += escape_len;
break;
case '#':
/* This is only escaped for "external:" style links. */
if (escape_hash) {
lxw_snprintf(p_encoded, escape_len + 1, "%%%2x", *string);
p_encoded += escape_len;
}
else {
*p_encoded = *string;
p_encoded++;
}
break;
case '%':
/* Only escape % if it isn't already an escape. */
if (!isxdigit(*(string + 1)) || !isxdigit(*(string + 2))) {
lxw_snprintf(p_encoded, escape_len + 1, "%%%2x", *string);
p_encoded += escape_len;
}
else {
*p_encoded = *string;
p_encoded++;
}
break;
default:
*p_encoded = *string;
p_encoded++;
break;
}
string++;
}
return encoded;
}
/* Write out escaped attributes. */
STATIC void
_fprint_escaped_attributes(FILE * xmlfile,
struct xml_attribute_list *attributes)
{
struct xml_attribute *attribute;
if (attributes) {
STAILQ_FOREACH(attribute, attributes, list_entries) {
fprintf(xmlfile, " %s=", attribute->key);
if (!strpbrk(attribute->value, "&<>\"\n")) {
fprintf(xmlfile, "\"%s\"", attribute->value);
}
else {
char *encoded = _escape_attributes(attribute);
if (encoded) {
fprintf(xmlfile, "\"%s\"", encoded);
free(encoded);
}
}
}
}
}
/* Write out escaped XML data. */
STATIC void
_fprint_escaped_data(FILE * xmlfile, const char *data)
{
/* Escape the data section of the XML element. */
if (!strpbrk(data, "&<>")) {
fprintf(xmlfile, "%s", data);
}
else {
char *encoded = lxw_escape_data(data);
if (encoded) {
fprintf(xmlfile, "%s", encoded);
free(encoded);
}
}
}
/* Create a new string XML attribute. */
struct xml_attribute *
lxw_new_attribute_str(const char *key, const char *value)
{
struct xml_attribute *attribute = malloc(sizeof(struct xml_attribute));
LXW_ATTRIBUTE_COPY(attribute->key, key);
LXW_ATTRIBUTE_COPY(attribute->value, value);
return attribute;
}
/* Create a new integer XML attribute. */
struct xml_attribute *
lxw_new_attribute_int(const char *key, uint64_t value)
{
struct xml_attribute *attribute = malloc(sizeof(struct xml_attribute));
LXW_ATTRIBUTE_COPY(attribute->key, key);
#if defined(_MSC_VER)
lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%lld", value);
#else
lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%ld",
(long) value);
#endif
return attribute;
}
/* Create a new double XML attribute. */
struct xml_attribute *
lxw_new_attribute_dbl(const char *key, double value)
{
struct xml_attribute *attribute = malloc(sizeof(struct xml_attribute));
LXW_ATTRIBUTE_COPY(attribute->key, key);
lxw_sprintf_dbl(attribute->value, value);
return attribute;
}

View File

@@ -0,0 +1,42 @@
###############################################################################
#
# Simplied Makefile to build the emyg_dtoa library for libxlsxwriter.
#
# Keep the output quiet by default.
Q=@
ifdef V
Q=
endif
UNAME := $(shell uname)
# Check for MinGW/MinGW64/Cygwin environments.
ifneq (,$(findstring MINGW, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring MSYS, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring CYGWIN, $(UNAME)))
MING_LIKE = y
endif
FPIC = -fPIC
# Change make options on MinGW/MinGW64/Cygwin.
ifdef MING_LIKE
FPIC =
CC = gcc
endif
all: emyg_dtoa.o emyg_dtoa.so
%.o : %.c
$(Q)$(CC) -c $(CFLAGS) $<
%.so : %.c
$(Q)$(CC) $(FPIC) -c $(CFLAGS) $< -o $@
clean:
$(Q)/bin/rm -f *.o *.so

View File

@@ -0,0 +1,461 @@
/* emyg_dtoa.c
** Copyright (C) 2015 Doug Currie
** based on dtoa_milo.h
** Copyright (C) 2014 Milo Yip
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
*/
/* This code is a mostly mechanical translation of Milo Yip's C++ version of
** Grisu2 to C. For algorithm information, see Loitsch, Florian. "Printing
** floating-point numbers quickly and accurately with integers." ACM Sigplan
** Notices 45.6 (2010): 233-243.
*/
/* Source from https://github.com/miloyip/dtoa-benchmark */
#include <assert.h>
#include <math.h>
#if defined(_MSC_VER)
#include <stdint.h>
#include <intrin.h>
#include <float.h>
#else
#include <stdint.h>
#endif
#include <string.h>
#include "emyg_dtoa.h"
#define UINT64_C2(h, l) (((uint64_t )(h) << 32) | (uint64_t )(l))
typedef struct DiyFp_s {
uint64_t f;
int e;
} DiyFp;
static const int kDiySignificandSize = 64;
static const int kDpSignificandSize = 52;
static const int kDpExponentBias = 0x3FF + 52;
static const int kDpMinExponent = -0x3FF - 52;
static const uint64_t kDpExponentMask = UINT64_C2(0x7FF00000, 0x00000000);
static const uint64_t kDpSignificandMask = UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
static const uint64_t kDpHiddenBit = UINT64_C2(0x00100000, 0x00000000);
static __inline DiyFp DiyFp_from_parts (uint64_t f, int e) {
DiyFp fp;
fp.f = f;
fp.e = e;
return fp;
}
DiyFp DiyFp_from_double (double d) {
DiyFp res;
int biased_e;
uint64_t significand;
union {
double d;
uint64_t u64;
} u;
u.d = d;
biased_e = (u.u64 & kDpExponentMask) >> kDpSignificandSize;
significand = (u.u64 & kDpSignificandMask);
if (biased_e != 0) {
res.f = significand + kDpHiddenBit;
res.e = biased_e - kDpExponentBias;
}
else {
res.f = significand;
res.e = kDpMinExponent + 1;
}
return res;
}
static __inline DiyFp DiyFp_subtract (const DiyFp lhs, const DiyFp rhs) {
assert(lhs.e == rhs.e);
assert(lhs.f >= rhs.f);
return DiyFp_from_parts(lhs.f - rhs.f, lhs.e);
}
static __inline DiyFp DiyFp_multiply (const DiyFp lhs, const DiyFp rhs) {
#if defined(_MSC_VER) && defined(_M_AMD64)
uint64_t h;
uint64_t l = _umul128(lhs.f, rhs.f, &h);
/* Handle rounding. */
if (l & ((uint64_t)1u << 63))
h++;
return DiyFp_from_parts(h, lhs.e + rhs.e + 64);
#elif ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __clang_major__ >= 9) && defined(__x86_64__))
unsigned __int128 p = (unsigned __int128 )(lhs.f) * (unsigned __int128 )(rhs.f);
uint64_t h = p >> 64;
uint64_t l = (uint64_t )(p);
/* Handle rounding. */
if (l & ((uint64_t)1u << 63))
h++;
return DiyFp_from_parts(h, lhs.e + rhs.e + 64);
#else
const uint64_t M32 = 0xFFFFFFFF;
const uint64_t a = lhs.f >> 32;
const uint64_t b = lhs.f & M32;
const uint64_t c = rhs.f >> 32;
const uint64_t d = rhs.f & M32;
const uint64_t ac = a * c;
const uint64_t bc = b * c;
const uint64_t ad = a * d;
const uint64_t bd = b * d;
uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
tmp += 1U << 31; /* mult_round */
return DiyFp_from_parts(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), lhs.e + rhs.e + 64);
#endif
}
static __inline DiyFp Normalize (const DiyFp lhs) {
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, lhs.f);
return DiyFp_from_parts(lhs.f << (63 - index), lhs.e - (63 - index));
#elif defined(__GNUC__)
int s = __builtin_clzll(lhs.f);
return DiyFp_from_parts(lhs.f << s, lhs.e - s);
#else
DiyFp res = lhs;
while (!(res.f & kDpHiddenBit)) {
res.f <<= 1;
res.e--;
}
res.f <<= (kDiySignificandSize - kDpSignificandSize - 1);
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 1);
return res;
#endif
}
static __inline DiyFp NormalizeBoundary (const DiyFp lhs) {
#if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index;
_BitScanReverse64(&index, lhs.f);
return DiyFp_from_parts(lhs.f << (63 - index), lhs.e - (63 - index));
#else
DiyFp res = lhs;
while (!(res.f & (kDpHiddenBit << 1))) {
res.f <<= 1;
res.e--;
}
res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
return res;
#endif
}
static __inline void NormalizedBoundaries (DiyFp lhs, DiyFp* minus, DiyFp* plus) {
DiyFp pl = NormalizeBoundary(DiyFp_from_parts((lhs.f << 1) + 1, lhs.e - 1));
DiyFp mi = (lhs.f == kDpHiddenBit)
? DiyFp_from_parts((lhs.f << 2) - 1, lhs.e - 2)
: DiyFp_from_parts((lhs.f << 1) - 1, lhs.e - 1);
mi.f <<= mi.e - pl.e;
mi.e = pl.e;
*plus = pl;
*minus = mi;
}
static __inline DiyFp GetCachedPower (int e, int* K) {
unsigned index;
/* 10^-348, 10^-340, ..., 10^340 */
static const uint64_t kCachedPowers_F[] = {
UINT64_C2(0xfa8fd5a0, 0x081c0288), UINT64_C2(0xbaaee17f, 0xa23ebf76),
UINT64_C2(0x8b16fb20, 0x3055ac76), UINT64_C2(0xcf42894a, 0x5dce35ea),
UINT64_C2(0x9a6bb0aa, 0x55653b2d), UINT64_C2(0xe61acf03, 0x3d1a45df),
UINT64_C2(0xab70fe17, 0xc79ac6ca), UINT64_C2(0xff77b1fc, 0xbebcdc4f),
UINT64_C2(0xbe5691ef, 0x416bd60c), UINT64_C2(0x8dd01fad, 0x907ffc3c),
UINT64_C2(0xd3515c28, 0x31559a83), UINT64_C2(0x9d71ac8f, 0xada6c9b5),
UINT64_C2(0xea9c2277, 0x23ee8bcb), UINT64_C2(0xaecc4991, 0x4078536d),
UINT64_C2(0x823c1279, 0x5db6ce57), UINT64_C2(0xc2109436, 0x4dfb5637),
UINT64_C2(0x9096ea6f, 0x3848984f), UINT64_C2(0xd77485cb, 0x25823ac7),
UINT64_C2(0xa086cfcd, 0x97bf97f4), UINT64_C2(0xef340a98, 0x172aace5),
UINT64_C2(0xb23867fb, 0x2a35b28e), UINT64_C2(0x84c8d4df, 0xd2c63f3b),
UINT64_C2(0xc5dd4427, 0x1ad3cdba), UINT64_C2(0x936b9fce, 0xbb25c996),
UINT64_C2(0xdbac6c24, 0x7d62a584), UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
UINT64_C2(0xf3e2f893, 0xdec3f126), UINT64_C2(0xb5b5ada8, 0xaaff80b8),
UINT64_C2(0x87625f05, 0x6c7c4a8b), UINT64_C2(0xc9bcff60, 0x34c13053),
UINT64_C2(0x964e858c, 0x91ba2655), UINT64_C2(0xdff97724, 0x70297ebd),
UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), UINT64_C2(0xf8a95fcf, 0x88747d94),
UINT64_C2(0xb9447093, 0x8fa89bcf), UINT64_C2(0x8a08f0f8, 0xbf0f156b),
UINT64_C2(0xcdb02555, 0x653131b6), UINT64_C2(0x993fe2c6, 0xd07b7fac),
UINT64_C2(0xe45c10c4, 0x2a2b3b06), UINT64_C2(0xaa242499, 0x697392d3),
UINT64_C2(0xfd87b5f2, 0x8300ca0e), UINT64_C2(0xbce50864, 0x92111aeb),
UINT64_C2(0x8cbccc09, 0x6f5088cc), UINT64_C2(0xd1b71758, 0xe219652c),
UINT64_C2(0x9c400000, 0x00000000), UINT64_C2(0xe8d4a510, 0x00000000),
UINT64_C2(0xad78ebc5, 0xac620000), UINT64_C2(0x813f3978, 0xf8940984),
UINT64_C2(0xc097ce7b, 0xc90715b3), UINT64_C2(0x8f7e32ce, 0x7bea5c70),
UINT64_C2(0xd5d238a4, 0xabe98068), UINT64_C2(0x9f4f2726, 0x179a2245),
UINT64_C2(0xed63a231, 0xd4c4fb27), UINT64_C2(0xb0de6538, 0x8cc8ada8),
UINT64_C2(0x83c7088e, 0x1aab65db), UINT64_C2(0xc45d1df9, 0x42711d9a),
UINT64_C2(0x924d692c, 0xa61be758), UINT64_C2(0xda01ee64, 0x1a708dea),
UINT64_C2(0xa26da399, 0x9aef774a), UINT64_C2(0xf209787b, 0xb47d6b85),
UINT64_C2(0xb454e4a1, 0x79dd1877), UINT64_C2(0x865b8692, 0x5b9bc5c2),
UINT64_C2(0xc83553c5, 0xc8965d3d), UINT64_C2(0x952ab45c, 0xfa97a0b3),
UINT64_C2(0xde469fbd, 0x99a05fe3), UINT64_C2(0xa59bc234, 0xdb398c25),
UINT64_C2(0xf6c69a72, 0xa3989f5c), UINT64_C2(0xb7dcbf53, 0x54e9bece),
UINT64_C2(0x88fcf317, 0xf22241e2), UINT64_C2(0xcc20ce9b, 0xd35c78a5),
UINT64_C2(0x98165af3, 0x7b2153df), UINT64_C2(0xe2a0b5dc, 0x971f303a),
UINT64_C2(0xa8d9d153, 0x5ce3b396), UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
UINT64_C2(0xbb764c4c, 0xa7a44410), UINT64_C2(0x8bab8eef, 0xb6409c1a),
UINT64_C2(0xd01fef10, 0xa657842c), UINT64_C2(0x9b10a4e5, 0xe9913129),
UINT64_C2(0xe7109bfb, 0xa19c0c9d), UINT64_C2(0xac2820d9, 0x623bf429),
UINT64_C2(0x80444b5e, 0x7aa7cf85), UINT64_C2(0xbf21e440, 0x03acdd2d),
UINT64_C2(0x8e679c2f, 0x5e44ff8f), UINT64_C2(0xd433179d, 0x9c8cb841),
UINT64_C2(0x9e19db92, 0xb4e31ba9), UINT64_C2(0xeb96bf6e, 0xbadf77d9),
UINT64_C2(0xaf87023b, 0x9bf0ee6b)
};
static const int16_t kCachedPowers_E[] = {
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
-954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
-688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
-422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
-157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
907, 933, 960, 986, 1013, 1039, 1066
};
/* dk must be positive, so can do ceiling in positive */
double dk = (-61 - e) * 0.30102999566398114 + 347;
int k = (int )(dk);
if (k != dk)
k++;
index = (unsigned )((k >> 3) + 1);
/* decimal exponent no need lookup table */
*K = -(-348 + (int )(index << 3));
assert(index < sizeof(kCachedPowers_F) / sizeof(kCachedPowers_F[0]));
return DiyFp_from_parts(kCachedPowers_F[index], kCachedPowers_E[index]);
}
static __inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
while (rest < wp_w && delta - rest >= ten_kappa &&
(rest + ten_kappa < wp_w || /* closer */
wp_w - rest > rest + ten_kappa - wp_w)) {
buffer[len - 1]--;
rest += ten_kappa;
}
}
static __inline unsigned CountDecimalDigit32(uint32_t n) {
/* Simple pure C++ implementation was faster than __builtin_clz version in this situation. */
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
return 10;
}
static __inline void DigitGen(const DiyFp W, const DiyFp Mp, uint64_t delta, char* buffer, int* len, int* K) {
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
const DiyFp one = DiyFp_from_parts((uint64_t )(1) << -Mp.e, Mp.e);
const DiyFp wp_w = DiyFp_subtract(Mp, W);
uint32_t p1 = (uint32_t )(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1);
int kappa = (int )(CountDecimalDigit32(p1));
*len = 0;
while (kappa > 0) {
uint32_t d;
uint64_t tmp;
switch (kappa) {
case 10: d = p1 / 1000000000; p1 %= 1000000000; break;
case 9: d = p1 / 100000000; p1 %= 100000000; break;
case 8: d = p1 / 10000000; p1 %= 10000000; break;
case 7: d = p1 / 1000000; p1 %= 1000000; break;
case 6: d = p1 / 100000; p1 %= 100000; break;
case 5: d = p1 / 10000; p1 %= 10000; break;
case 4: d = p1 / 1000; p1 %= 1000; break;
case 3: d = p1 / 100; p1 %= 100; break;
case 2: d = p1 / 10; p1 %= 10; break;
case 1: d = p1; p1 = 0; break;
default:
#if defined(_MSC_VER)
__assume(0);
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
__builtin_unreachable();
#else
d = 0;
#endif
}
if (d || *len)
buffer[(*len)++] = '0' + (char )(d);
kappa--;
tmp = ((uint64_t )(p1) << -one.e) + p2;
if (tmp <= delta) {
*K += kappa;
GrisuRound(buffer, *len, delta, tmp, (uint64_t )(kPow10[kappa]) << -one.e, wp_w.f);
return;
}
}
/* kappa = 0 */
for (;;) {
char d;
p2 *= 10;
delta *= 10;
d = (char )(p2 >> -one.e);
if (d || *len)
buffer[(*len)++] = '0' + d;
p2 &= one.f - 1;
kappa--;
if (p2 < delta) {
*K += kappa;
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]);
return;
}
}
}
static __inline void Grisu2(double value, char* buffer, int* length, int* K) {
const DiyFp v = DiyFp_from_double(value);
DiyFp c_mk;
DiyFp W;
DiyFp w_m, w_p;
DiyFp Wp;
DiyFp Wm;
NormalizedBoundaries(v, &w_m, &w_p);
c_mk = GetCachedPower(w_p.e, K);
W = DiyFp_multiply(Normalize(v), c_mk);
Wp = DiyFp_multiply(w_p, c_mk);
Wm = DiyFp_multiply(w_m, c_mk);
Wm.f++;
Wp.f--;
DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
}
static __inline const char* GetDigitsLut(void) {
static const char cDigitsLut[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
'2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '3', '8', '3', '9',
'4', '0', '4', '1', '4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8', '4', '9',
'5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7', '7', '8', '7', '9',
'8', '0', '8', '1', '8', '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7', '9', '8', '9', '9'
};
return cDigitsLut;
}
static __inline void WriteExponent(int K, char* buffer) {
if (K < 0) {
*buffer++ = '-';
K = -K;
}
else {
*buffer++ = '+';
}
if (K >= 100) {
char* d;
*buffer++ = '0' + (char )(K / 100);
K %= 100;
d = (char*)GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else if (K >= 10) {
const char* d = GetDigitsLut() + K * 2;
*buffer++ = d[0];
*buffer++ = d[1];
}
else
*buffer++ = '0' + (char )(K);
*buffer = '\0';
}
static __inline void Prettify(char* buffer, int length, int k) {
int i;
const int kk = length + k; /* 10^(kk-1) <= v < 10^kk */
if (length <= kk && kk <= 17) {
/* 1234e7 -> 12340000000 */
for (i = length; i < kk; i++)
buffer[i] = '0';
buffer[kk] = '\0';
}
else if (0 < kk && kk <= 17) {
/* 1234e-2 -> 12.34 */
memmove(&buffer[kk + 1], &buffer[kk], length - kk);
buffer[kk] = '.';
buffer[length + 1] = '\0';
}
else if (-6 < kk && kk <= 0) {
/* 1234e-6 -> 0.001234 */
const int offset = 2 - kk;
memmove(&buffer[offset], &buffer[0], length);
buffer[0] = '0';
buffer[1] = '.';
for (i = 2; i < offset; i++)
buffer[i] = '0';
buffer[length + offset] = '\0';
}
else if (length == 1) {
/* 1E30 */
buffer[1] = 'E';
WriteExponent(kk - 1, &buffer[2]);
}
else {
/* 1234E30 -> 1.234E33 */
memmove(&buffer[2], &buffer[1], length - 1);
buffer[1] = '.';
buffer[length + 1] = 'E';
WriteExponent(kk - 1, &buffer[0 + length + 2]);
}
}
void emyg_dtoa (double value, char* buffer) {
int length, K;
/* Not handling NaN and inf */
assert(!isnan(value));
assert(!isinf(value));
if (value == 0) {
buffer[0] = '0';
buffer[1] = '\0';
}
else {
if (value < 0) {
*buffer++ = '-';
value = -value;
}
Grisu2(value, buffer, &length, &K);
Prettify(buffer, length, K);
}
}

View File

@@ -0,0 +1,26 @@
/* emyg_dtoa.h
** Copyright (C) 2015 Doug Currie
** based on dtoa_milo.h
** Copyright (C) 2014 Milo Yip
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
*/
/* Source from https://github.com/miloyip/dtoa-benchmark */
void emyg_dtoa (double value, char* buffer);

View File

@@ -0,0 +1,42 @@
###############################################################################
#
# Simplied Makefile to build the openwall md5 library for libxlsxwriter.
#
# Keep the output quiet by default.
Q=@
ifdef V
Q=
endif
UNAME := $(shell uname)
# Check for MinGW/MinGW64/Cygwin environments.
ifneq (,$(findstring MINGW, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring MSYS, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring CYGWIN, $(UNAME)))
MING_LIKE = y
endif
FPIC = -fPIC
# Change make options on MinGW/MinGW64/Cygwin.
ifdef MING_LIKE
FPIC =
CC = gcc
endif
all: md5.o md5.so
%.o : %.c
$(Q)$(CC) -c $(CFLAGS) $(TARGET_ARCH) $<
%.so : %.c
$(Q)$(CC) $(FPIC) -c $(CFLAGS) $(TARGET_ARCH) $< -o $@
clean:
$(Q)/bin/rm -f *.o *.so

View File

@@ -0,0 +1,291 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* (This is a heavily cut-down "BSD license".)
*
* This differs from Colin Plumb's older public domain implementation in that
* no exactly 32-bit integer data type is required (any 32-bit or wider
* unsigned integer data type will do), there's no compile-time endianness
* configuration, and the function prototypes match OpenSSL's. No code from
* Colin Plumb's implementation has been reused; this comment merely compares
* the properties of the two independent implementations.
*
* The primary goals of this implementation are portability and ease of use.
* It is meant to be fast, but not as fast as possible. Some known
* optimizations are not included to reduce source code size and avoid
* compile-time configuration.
*/
#ifndef HAVE_OPENSSL
#include <string.h>
#include "md5.h"
/*
* The basic MD5 functions.
*
* F and G are optimized compared to their RFC 1321 definitions for
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
* implementation.
*/
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
/*
* The MD5 transformation for all four rounds.
*/
#define STEP(f, a, b, c, d, x, t, s) \
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
*
* The check for little-endian architectures that tolerate unaligned memory
* accesses is just an optimization. Nothing will break if it fails to detect
* a suitable architecture.
*
* Unfortunately, this optimization may be a C strict aliasing rules violation
* if the caller's data buffer has effective type that cannot be aliased by
* MD5_u32plus. In practice, this problem may occur if these MD5 routines are
* inlined into a calling function, or with future and dangerously advanced
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
(*(MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
#define SET(n) \
(ctx->block[(n)] = \
(MD5_u32plus)ptr[(n) * 4] | \
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
(ctx->block[(n)])
#endif
/*
* This processes one or more 64-byte data blocks, but does NOT update the bit
* counters. There are no alignment requirements.
*/
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
{
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
ptr = (const unsigned char *)data;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
ptr += 64;
} while (size -= 64);
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
return ptr;
}
void MD5_Init(MD5_CTX *ctx)
{
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
ctx->lo = 0;
ctx->hi = 0;
}
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used) {
available = 64 - used;
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
#define OUT(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
used = ctx->lo & 0x3f;
ctx->buffer[used++] = 0x80;
available = 64 - used;
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
memset(&ctx->buffer[used], 0, available - 8);
ctx->lo <<= 3;
OUT(&ctx->buffer[56], ctx->lo)
OUT(&ctx->buffer[60], ctx->hi)
body(ctx, ctx->buffer, 64);
OUT(&result[0], ctx->a)
OUT(&result[4], ctx->b)
OUT(&result[8], ctx->c)
OUT(&result[12], ctx->d)
memset(ctx, 0, sizeof(*ctx));
}
#endif

View File

@@ -0,0 +1,45 @@
/*
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
* MD5 Message-Digest Algorithm (RFC 1321).
*
* Homepage:
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
*
* Author:
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
* This software was written by Alexander Peslyak in 2001. No copyright is
* claimed, and the software is hereby placed in the public domain.
* In case this attempt to disclaim copyright and place the software in the
* public domain is deemed null and void, then the software is
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
* general public under the following terms:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* There's ABSOLUTELY NO WARRANTY, express or implied.
*
* See md5.c for more information.
*/
#ifdef HAVE_OPENSSL
#include <openssl/md5.h>
#elif !defined(_MD5_H)
#define _MD5_H
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
typedef struct {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
} MD5_CTX;
extern void MD5_Init(MD5_CTX *ctx);
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
#endif

View File

@@ -0,0 +1,44 @@
###############################################################################
#
# Simplied Makefile to build the minizip objects for the libxlsxwriter library.
#
# Keep the output quiet by default.
Q=@
ifdef V
Q=
endif
UNAME := $(shell uname -sr)
# Check for MinGW/MinGW64/Cygwin environments.
ifneq (,$(findstring MINGW, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring MSYS, $(UNAME)))
MING_LIKE = y
endif
ifneq (,$(findstring CYGWIN, $(UNAME)))
MING_LIKE = y
endif
FPIC = -fPIC
CFLAGS += -O3 -DNOCRYPT -DNOUNCRYPT
# Change make options on MinGW/MinGW64/Cygwin.
ifdef MING_LIKE
FPIC =
CC = gcc
CFLAGS += -DUSE_FILE32API
endif
all: ioapi.o zip.o ioapi.so zip.so
%.o : %.c
$(Q)$(CC) -c $(CFLAGS) $(TARGET_ARCH) $<
%.so : %.c
$(Q)$(CC) $(FPIC) -c $(CFLAGS) $(TARGET_ARCH) $< -o $@
clean:
$(Q)/bin/rm -f *.o *.so

View File

@@ -0,0 +1,45 @@
lib_LTLIBRARIES = libminizip.la
if COND_DEMOS
bin_PROGRAMS = miniunzip minizip
endif
zlib_top_srcdir = $(top_srcdir)/../..
zlib_top_builddir = $(top_builddir)/../..
AM_CPPFLAGS = -I$(zlib_top_srcdir)
AM_LDFLAGS = -L$(zlib_top_builddir)
if WIN32
iowin32_src = iowin32.c
iowin32_h = iowin32.h
endif
libminizip_la_SOURCES = \
ioapi.c \
mztools.c \
unzip.c \
zip.c \
${iowin32_src}
libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz
minizip_includedir = $(includedir)/minizip
minizip_include_HEADERS = \
crypt.h \
ioapi.h \
mztools.h \
unzip.h \
zip.h \
${iowin32_h}
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = minizip.pc
EXTRA_PROGRAMS = miniunzip minizip
miniunzip_SOURCES = miniunz.c
miniunzip_LDADD = libminizip.la
minizip_SOURCES = minizip.c
minizip_LDADD = libminizip.la -lz

View File

@@ -0,0 +1,29 @@
CC=cc
CFLAGS := $(CFLAGS) -O -I../..
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
.c.o:
$(CC) -c $(CFLAGS) $*.c
all: miniunz minizip
miniunz: $(UNZ_OBJS)
$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
minizip: $(ZIP_OBJS)
$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
test: miniunz minizip
@rm -f test.*
@echo hello hello hello > test.txt
./minizip test test.txt
./miniunz -l test.zip
@mv test.txt test.old
./miniunz test.zip
@cmp test.txt test.old
@rm -f test.*
clean:
/bin/rm -f *.o *~ minizip miniunz test.*

View File

@@ -0,0 +1,6 @@
MiniZip 1.1 was derived from MiniZip at version 1.01f
Change in 1.0 (Okt 2009)
- **TODO - Add history**

View File

@@ -0,0 +1,74 @@
MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson
Introduction
---------------------
MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html )
When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0.
All possible work was done for compatibility.
Background
---------------------
When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64
support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ )
That was used as a starting point. And after that ZIP64 support was added to zip.c
some refactoring and code cleanup was also done.
Changed from MiniZip 1.0 to MiniZip 1.1
---------------------------------------
* Added ZIP64 support for unzip ( by Even Rouault )
* Added ZIP64 support for zip ( by Mathias Svensson )
* Reverted some changed that Even Rouault did.
* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users.
* Added unzip patch for BZIP Compression method (patch create by Daniel Borca)
* Added BZIP Compress method for zip
* Did some refactoring and code cleanup
Credits
Gilles Vollant - Original MiniZip author
Even Rouault - ZIP64 unzip Support
Daniel Borca - BZip Compression method support in unzip
Mathias Svensson - ZIP64 zip support
Mathias Svensson - BZip Compression method support in zip
Resources
ZipLayout http://result42.com/projects/ZipFileLayout
Command line tool for Windows that shows the layout and information of the headers in a zip archive.
Used when debugging and validating the creation of zip files using MiniZip64
ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT
Zip File specification
Notes.
* To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined.
License
----------------------------------------------------------
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
----------------------------------------------------------

View File

@@ -0,0 +1,5 @@
The souce files in this directory are included in libxlsxwriter from the
contrib/minizip/ directory of zlib-1.2.8.
The files zip.h and ioapi.h have had a small number of comments modifed from
C++ to C style to avoid warnings with -pedantic -ansi.

View File

@@ -0,0 +1,32 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
AC_CONFIG_SRCDIR([minizip.c])
AM_INIT_AUTOMAKE([foreign])
LT_INIT
AC_MSG_CHECKING([whether to build example programs])
AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs]))
AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes])
if test "$enable_demos" = yes
then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
case "${host}" in
*-mingw* | mingw*)
WIN32="yes"
;;
*)
;;
esac
AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
AC_SUBST([HAVE_UNISTD_H], [0])
AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], [])
AC_CONFIG_FILES([Makefile minizip.pc])
AC_OUTPUT

View File

@@ -0,0 +1,128 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
(void)pcrc_32_tab;
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) {
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static unsigned crypthead(const char* passwd, /* password string */
unsigned char* buf, /* where to write header */
int bufSize,
unsigned long* pkeys,
const z_crc_t* pcrc_32_tab,
unsigned long crcForCrypting) {
unsigned n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

View File

@@ -0,0 +1,231 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
*/
#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
#define _CRT_SECURE_NO_WARNINGS
#endif
#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif
#include "ioapi.h"
voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) {
if (pfilefunc->zfile_func64.zopen64_file != NULL)
return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
else
{
return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
}
}
long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) {
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
else
{
uLong offsetTruncated = (uLong)offset;
if (offsetTruncated != offset)
return -1;
else
return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
}
}
ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) {
if (pfilefunc->zfile_func64.zseek64_file != NULL)
return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
else
{
uLong tell_uLong = (uLong)(*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
if ((tell_uLong) == MAXU32)
return (ZPOS64_T)-1;
else
return tell_uLong;
}
}
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) {
p_filefunc64_32->zfile_func64.zopen64_file = NULL;
p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
p_filefunc64_32->zfile_func64.ztell64_file = NULL;
p_filefunc64_32->zfile_func64.zseek64_file = NULL;
p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
}
static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) {
FILE* file = NULL;
const char* mode_fopen = NULL;
(void)opaque;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) {
FILE* file = NULL;
const char* mode_fopen = NULL;
(void)opaque;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = FOPEN_FUNC((const char*)filename, mode_fopen);
return file;
}
static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) {
uLong ret;
(void)opaque;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) {
uLong ret;
(void)opaque;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) {
long ret;
(void)opaque;
ret = ftell((FILE *)stream);
return ret;
}
static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) {
ZPOS64_T ret;
(void)opaque;
ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream);
return ret;
}
static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) {
int fseek_origin=0;
long ret;
(void)opaque;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if (fseek((FILE *)stream, (long)offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
int fseek_origin=0;
long ret;
(void)opaque;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) {
int ret;
(void)opaque;
ret = fclose((FILE *)stream);
return ret;
}
static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) {
int ret;
(void)opaque;
ret = ferror((FILE *)stream);
return ret;
}
void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) {
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) {
pzlib_filefunc_def->zopen64_file = fopen64_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell64_file = ftell64_file_func;
pzlib_filefunc_def->zseek64_file = fseek64_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}

View File

@@ -0,0 +1,216 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
For more info read MiniZip_info.txt
Changes
Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
More if/def section may be needed to support other platforms
Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
(but you should use iowin32.c for windows instead)
*/
/* Pragma added by libxlsxwriter to avoid warnings with -pedantic -ansi. */
#ifndef _WIN32
#pragma GCC system_header
#endif
#ifndef _ZLIBIOAPI64_H
#define _ZLIBIOAPI64_H
#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
// Linux needs this to support file operation on files larger then 4+GB
// But might need better if/def to select just the platforms that needs them.
#ifndef __USE_FILE_OFFSET64
#define __USE_FILE_OFFSET64
#endif
#ifndef __USE_LARGEFILE64
#define __USE_LARGEFILE64
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#ifndef _FILE_OFFSET_BIT
#define _FILE_OFFSET_BIT 64
#endif
#endif
#include <stdio.h>
#include <stdlib.h>
#include "zlib.h"
#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
#define fopen64 fopen
#define ftello64 ftello
#define fseeko64 fseeko
#endif
#ifdef _MSC_VER
#define fopen64 fopen
#if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
#define ftello64 _ftelli64
#define fseeko64 _fseeki64
#else // old MSC
#define ftello64 ftell
#define fseeko64 fseek
#endif
#endif
#endif
/*
#ifndef ZPOS64_T
#ifdef _WIN32
#define ZPOS64_T fpos_t
#else
#include <stdint.h>
#define ZPOS64_T uint64_t
#endif
#endif
*/
#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif
/* a type chosen by DEFINE */
#ifdef HAVE_64BIT_INT_CUSTOM
typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
#else
#ifdef HAS_STDINT_H
#include "stdint.h"
typedef uint64_t ZPOS64_T;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
#else
typedef unsigned long long int ZPOS64_T;
#endif
#endif
#endif
/* Maximum unsigned 32-bit value used as placeholder for zip64 */
#ifndef MAXU32
#define MAXU32 (0xffffffff)
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
/* here is the "old" 32 bits structure structure */
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream);
typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin);
typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode);
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc64_def;
void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
/* now internal definition, only for zip.c and unzip.h */
typedef struct zlib_filefunc64_32_def_s
{
zlib_filefunc64_def zfile_func64;
open_file_func zopen32_file;
tell_file_func ztell32_file;
seek_file_func zseek32_file;
} zlib_filefunc64_32_def;
#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode);
long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin);
ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream);
void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More