mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-28 06:12:53 -06:00
Testing usvn
git-svn-id: svn://ultimatepp.org/upp/trunk@1342 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
255c218e23
commit
79a9e1fb12
88 changed files with 18578 additions and 16 deletions
560
uppdev/XLS/workbook.cpp
Normal file
560
uppdev/XLS/workbook.cpp
Normal file
|
|
@ -0,0 +1,560 @@
|
|||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* This file is part of xlslib -- A multiplatform, C/C++ library
|
||||
* for dynamic generation of Excel(TM) files.
|
||||
*
|
||||
* xlslib is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* xlslib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with xlslib. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2004 Yeico S. A. de C. V.
|
||||
* Copyright 2008 David Hoerl
|
||||
*
|
||||
* $Source: /cvsroot/xlslib/xlslib/src/xlslib/workbook.cpp,v $
|
||||
* $Revision: 1.3 $
|
||||
* $Author: dhoerl $
|
||||
* $Date: 2008/10/25 18:39:54 $
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
* File description:
|
||||
*
|
||||
*
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <XLS/workbook.h>
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace xlslib_core;
|
||||
|
||||
#define CHANGE_DUMPSTATE(state) { \
|
||||
m_PreviousDumpState = m_DumpState; \
|
||||
m_DumpState = state; \
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
workbook class implementation
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
workbook::workbook()
|
||||
: m_DumpState(WB_INIT),
|
||||
m_PreviousDumpState(WB_FINISH),
|
||||
m_pCurrentData(NULL),
|
||||
m_pContinueRecord(NULL),
|
||||
dump_not_started(true),
|
||||
globalrec_size(0),
|
||||
current_sheet(0),
|
||||
offset(0)
|
||||
{
|
||||
#ifdef XLS_PHP
|
||||
write_fptr = NULL;
|
||||
m_Disposition = STK_ATTACHMENT;
|
||||
#endif
|
||||
#ifdef HAVE_ICONV
|
||||
iconv_code = "wchar_t";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef XLS_PHP
|
||||
workbook::workbook(write_fptr_t w_fptr)
|
||||
: m_DumpState(WB_INIT),
|
||||
m_PreviousDumpState(WB_FINISH),
|
||||
m_pCurrentData(NULL),
|
||||
m_pContinueRecord(NULL),
|
||||
dump_not_started(true),
|
||||
globalrec_size(0),
|
||||
current_sheet(0),
|
||||
offset(0)
|
||||
{
|
||||
write_fptr = w_fptr;
|
||||
m_Disposition = STK_ATTACHMENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
workbook::~workbook()
|
||||
{
|
||||
if(!m_Sheets.empty())
|
||||
{
|
||||
for(unsigned32_t i = 0; i<m_Sheets.size(); i++)
|
||||
{
|
||||
delete m_Sheets[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ICONV
|
||||
int workbook::iconvInType(const char *inType)
|
||||
{
|
||||
int ret;
|
||||
iconv_t cd;
|
||||
|
||||
cd = iconv_open("UCS-2-INTERNAL", inType);
|
||||
if(cd != (iconv_t)(-1)) {
|
||||
iconv_close(cd);
|
||||
iconv_code = inType;
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = errno;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
|
||||
worksheet* workbook::sheet(string sheetname)
|
||||
{
|
||||
|
||||
worksheet* pnewsheet = new worksheet(&m_GlobalRecords);
|
||||
|
||||
m_Sheets.push_back(pnewsheet);
|
||||
|
||||
// NOTE: Streampos defaults to 0
|
||||
// It has to be set somewhere else
|
||||
m_GlobalRecords.AddBoundingSheet(0, BSHEET_ATTR_WORKSHEET, sheetname);
|
||||
|
||||
// Return a pointer to the just added sheet
|
||||
return (m_Sheets.back());
|
||||
}
|
||||
#if VERSION_BIFF == VERSION_BIFF8
|
||||
worksheet* workbook::sheet(ustring sheetname)
|
||||
{
|
||||
#ifdef HAVE_ICONV
|
||||
worksheet* pnewsheet = new worksheet(&m_GlobalRecords, iconv_code);
|
||||
m_Sheets.push_back(pnewsheet);
|
||||
|
||||
// NOTE: Streampos defaults to 0
|
||||
// It has to be set somewhere else
|
||||
m_GlobalRecords.AddBoundingSheet(0, BSHEET_ATTR_WORKSHEET, sheetname, iconv_code);
|
||||
#else
|
||||
worksheet* pnewsheet = new worksheet(&m_GlobalRecords);
|
||||
|
||||
m_Sheets.push_back(pnewsheet);
|
||||
|
||||
// NOTE: Streampos defaults to 0
|
||||
// It has to be set somewhere else
|
||||
m_GlobalRecords.AddBoundingSheet(0, BSHEET_ATTR_WORKSHEET, sheetname);
|
||||
#endif
|
||||
|
||||
// Return a pointer to the just added sheet
|
||||
return (m_Sheets.back());
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
|
||||
worksheet* workbook::GetSheet(unsigned16_t sheetnum)
|
||||
{
|
||||
if(sheetnum < m_Sheets.size())
|
||||
{
|
||||
return m_Sheets[sheetnum];
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
font_t* workbook::font(string name)
|
||||
{
|
||||
font_t* newfont = new font_t;
|
||||
newfont->SetName(name);
|
||||
|
||||
return(m_GlobalRecords.AddFont(newfont));
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
format_t* workbook::format(string formatstr)
|
||||
{
|
||||
format_t* newformat = new format_t(0x0000, formatstr);
|
||||
|
||||
return(m_GlobalRecords.AddFormat(newformat));
|
||||
}
|
||||
|
||||
xf_t* workbook::xformat(void)
|
||||
{
|
||||
xf_t* newxf = new xf_t;
|
||||
newxf->MarkUsed();
|
||||
|
||||
return(m_GlobalRecords.AddXFormat(newxf));
|
||||
}
|
||||
|
||||
xf_t* workbook::xformat(font_t* font)
|
||||
{
|
||||
xf_t* newxf = new xf_t;
|
||||
newxf->MarkUsed();
|
||||
newxf->SetFont(font);
|
||||
|
||||
return(m_GlobalRecords.AddXFormat(newxf));
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
#define SETWORKBOOK5() \
|
||||
CDataStorage biffdata; \
|
||||
CUnit* precorddata; \
|
||||
bool keep = true; \
|
||||
do { \
|
||||
precorddata = DumpData(); \
|
||||
\
|
||||
if(precorddata != NULL) \
|
||||
biffdata += precorddata; \
|
||||
else \
|
||||
keep = false; \
|
||||
}while(keep); \
|
||||
\
|
||||
AddFile("/Book",&biffdata); \
|
||||
string name; \
|
||||
name = (char)0x05; \
|
||||
name += "SummaryInformation"; \
|
||||
AddFile(name, &m_SummaryInfo); \
|
||||
name = (char)0x05; \
|
||||
name += "DocumentSummaryInformation"; \
|
||||
AddFile(name, &m_DocSummaryInfo);
|
||||
|
||||
#define SETWORKBOOK8() \
|
||||
CDataStorage biffdata; \
|
||||
CUnit* precorddata; \
|
||||
bool keep = true; \
|
||||
do { \
|
||||
precorddata = DumpData(); \
|
||||
\
|
||||
if(precorddata != NULL) \
|
||||
biffdata += precorddata; \
|
||||
else \
|
||||
keep = false; \
|
||||
} while(keep); \
|
||||
\
|
||||
AddFile("/Workbook",&biffdata); \
|
||||
string name; \
|
||||
name = (char)0x05; \
|
||||
name += "SummaryInformation"; \
|
||||
AddFile(name, &m_SummaryInfo); \
|
||||
name = (char)0x05; \
|
||||
name += "DocumentSummaryInformation"; \
|
||||
AddFile(name, &m_DocSummaryInfo);
|
||||
|
||||
#ifdef XLS_PHP
|
||||
/******************************
|
||||
* This function has to be called before any output to the php-string
|
||||
* (this includes any non-php-script text in the source file or
|
||||
* zend_printf call) because it makes use of headers() php-function,
|
||||
* which has to be called before any of those kind of output.
|
||||
* If this restraint isn't followed, the html-header won't be modified
|
||||
* and the binary data will be displayed in the browser (in the best of
|
||||
* cases).
|
||||
* This can also be avoided using buffering in the PHP environment
|
||||
* See chapter LXXVIII. "Output Control Functions" of the PHP manual.
|
||||
******************************/
|
||||
void workbook::Stroke(string filename)
|
||||
{
|
||||
SetStroke();
|
||||
|
||||
#if VERSION_BIFF == VERSION_BIFF5
|
||||
SETWORKBOOK5();
|
||||
#else // VERSION_BIFF8
|
||||
SETWORKBOOK8();
|
||||
#endif
|
||||
DumpOleFile();
|
||||
}
|
||||
|
||||
void workbook::Disposition(Stroke_Disposition_t disp)
|
||||
{
|
||||
m_Disposition = disp;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int workbook::Dump(string filename)
|
||||
{
|
||||
int errors;
|
||||
|
||||
if(m_Sheets.empty()) {
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XLS_PHP
|
||||
UnSetStroke();
|
||||
#endif
|
||||
|
||||
errors = Open(filename);
|
||||
if(errors == NO_ERRORS) {
|
||||
#if VERSION_BIFF == VERSION_BIFF5
|
||||
SETWORKBOOK5();
|
||||
#else // VERSION_BIFF8
|
||||
SETWORKBOOK8();
|
||||
#endif
|
||||
errors = DumpOleFile();
|
||||
Close();
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
/*
|
||||
***********************************
|
||||
***********************************
|
||||
*/
|
||||
|
||||
CUnit* workbook::DumpData(void)
|
||||
{
|
||||
|
||||
bool repeat = false;
|
||||
XTRACE("\nworkbook::DumpData");
|
||||
|
||||
do
|
||||
{
|
||||
switch(m_DumpState)
|
||||
{
|
||||
case WB_INIT:
|
||||
|
||||
dump_not_started = true;
|
||||
globalrec_size = 0;
|
||||
current_sheet = 0;
|
||||
offset = 0;
|
||||
|
||||
CHANGE_DUMPSTATE(WB_GLOBALRECORDS);
|
||||
|
||||
repeat = true;
|
||||
break;
|
||||
|
||||
case WB_GLOBALRECORDS:
|
||||
|
||||
XTRACE("\tGLOBALRECORDS");
|
||||
|
||||
repeat = false;
|
||||
|
||||
if(dump_not_started)
|
||||
{ // the following code is executed only if this is the first pas to the first dump-state
|
||||
// Basically, streampositions of BoundingSheet records are initialized.
|
||||
dump_not_started = false;
|
||||
|
||||
globalrec_size = m_GlobalRecords.GetSize();
|
||||
offset = globalrec_size;
|
||||
|
||||
unsigned32_t offset_from_globalrecs = 0;
|
||||
|
||||
if(!m_Sheets.empty())
|
||||
{
|
||||
|
||||
Boundsheet_List_Itor_t bs = m_GlobalRecords.GetFirstBoundSheet();
|
||||
|
||||
for(unsigned16_t i = 0; i < m_Sheets.size(); i++)
|
||||
{
|
||||
|
||||
(*bs) -> streampos = globalrec_size + offset_from_globalrecs;
|
||||
m_GlobalRecords.GetBoundingSheets(bs);
|
||||
offset_from_globalrecs += m_Sheets[i]->GetSize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Nothing else to do.
|
||||
}
|
||||
|
||||
|
||||
//TODO: Add other EOF/BOF blocks here
|
||||
}
|
||||
|
||||
m_pCurrentData = m_GlobalRecords.DumpData();
|
||||
if(m_pCurrentData == NULL)
|
||||
{
|
||||
if(!m_Sheets.empty())
|
||||
{
|
||||
// get in advance the first record of the first sheet
|
||||
//m_pCurrentData = m_Sheets[0].DumpData(globalrec_size);
|
||||
repeat = true;
|
||||
CHANGE_DUMPSTATE(WB_SHEETS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing else to do. Branch to the FINISH state
|
||||
m_pCurrentData = NULL;
|
||||
|
||||
CHANGE_DUMPSTATE(WB_FINISH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do nothing. Continue in this state.
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WB_SHEETS:
|
||||
{
|
||||
|
||||
XTRACE("\tSHEETS");
|
||||
|
||||
repeat = false;
|
||||
// If I got here, there's at least one sheet which has already
|
||||
// sent the first record block of data.
|
||||
//m_GlobalRecords.GetSize();
|
||||
|
||||
m_pCurrentData = m_Sheets[current_sheet]->DumpData(offset);
|
||||
|
||||
if(m_pCurrentData == NULL)
|
||||
{
|
||||
if((unsigned16_t)(current_sheet+1) < m_Sheets.size())
|
||||
{
|
||||
// Update the offset for the next sheet
|
||||
offset += m_Sheets[current_sheet]->GetSize();
|
||||
current_sheet++;
|
||||
|
||||
// ... and get the first record of the next sheet.
|
||||
// m_pCurrentData = m_Sheets[current_sheet].DumpData(offset);
|
||||
repeat = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// I'm done with all the sheets
|
||||
// Nothing else to do. Branch to the FINISH state
|
||||
CHANGE_DUMPSTATE(WB_FINISH);
|
||||
|
||||
repeat = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case WB_FINISH:
|
||||
XTRACE("\tFINISH");
|
||||
|
||||
repeat = false;
|
||||
m_pCurrentData = NULL;
|
||||
|
||||
CHANGE_DUMPSTATE(WB_INIT);
|
||||
|
||||
break;
|
||||
|
||||
case WB_CONTINUE_REC:
|
||||
XTRACE("\tCONTINUE-REC");
|
||||
|
||||
repeat = false;
|
||||
|
||||
if(m_ContinueIndex == 0)
|
||||
{
|
||||
//Create a new data unit containing the max data size
|
||||
m_pContinueRecord = (CUnit*)(new CRecord());
|
||||
|
||||
// The real size of the record is the size of the buffer minus the
|
||||
// size of the header record
|
||||
|
||||
((CUnit*)(m_pContinueRecord))->AddDataArray(((CRecord*)m_pCurrentData)->GetRecordDataBuffer(),MAX_RECORD_SIZE);
|
||||
((CRecord*)(m_pContinueRecord))->SetRecordType(((CRecord*)m_pCurrentData)->GetRecordType());
|
||||
((CRecord*)(m_pContinueRecord))->SetRecordLength(MAX_RECORD_SIZE);
|
||||
|
||||
// m_pContinueRecord->SetValueAt(MAX_RECORD_SIZE-4,2);
|
||||
m_ContinueIndex++;
|
||||
|
||||
return m_pContinueRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Delete_Pointer(m_pContinueRecord);
|
||||
|
||||
// Get a pointer to the next chunk of data
|
||||
unsigned8_t* pdata = (((CRecord*)m_pCurrentData)->GetRecordDataBuffer()) + m_ContinueIndex*MAX_RECORD_SIZE;
|
||||
|
||||
// Get the size of the chunk of data (that is the MAX_REC_SIZE except by the last one)
|
||||
unsigned32_t csize = 0;
|
||||
if(( ((CRecord*)m_pCurrentData)->GetRecordDataSize()/MAX_RECORD_SIZE) > (m_ContinueIndex))
|
||||
{
|
||||
csize = MAX_RECORD_SIZE;
|
||||
m_ContinueIndex++;
|
||||
|
||||
m_pContinueRecord =(CUnit*) ( new CContinue(pdata, csize));
|
||||
|
||||
return m_pContinueRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned32_t data_size = ((CRecord*)m_pCurrentData)->GetRecordDataSize();
|
||||
|
||||
csize = (data_size - (m_ContinueIndex) * MAX_RECORD_SIZE);
|
||||
|
||||
// Restore the previous state (*Don't use the macro*)
|
||||
m_DumpState = m_PreviousDumpState;
|
||||
m_PreviousDumpState = WB_CONTINUE_REC;
|
||||
|
||||
m_ContinueIndex = 0;
|
||||
|
||||
if(csize)
|
||||
{
|
||||
m_pContinueRecord = (CUnit*) new CContinue(pdata, csize);
|
||||
Delete_Pointer(m_pCurrentData);
|
||||
return m_pContinueRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
Delete_Pointer(m_pCurrentData);
|
||||
repeat = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
XTRACE("\tDEFAULT");
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_pCurrentData != NULL)
|
||||
if(((CRecord*)m_pCurrentData)->GetRecordDataSize() >= MAX_RECORD_SIZE && m_DumpState != WB_CONTINUE_REC)
|
||||
{
|
||||
|
||||
// Save the current dump satate and change to the CONTINUE Record state
|
||||
CHANGE_DUMPSTATE(WB_CONTINUE_REC);
|
||||
|
||||
m_ContinueIndex = 0;
|
||||
|
||||
repeat = true;
|
||||
}
|
||||
} while(repeat);
|
||||
|
||||
return m_pCurrentData;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* $Log: workbook.cpp,v $
|
||||
* Revision 1.3 2008/10/25 18:39:54 dhoerl
|
||||
* 2008
|
||||
*
|
||||
* Revision 1.2 2004/09/01 00:47:21 darioglz
|
||||
* + Modified to gain independence of target
|
||||
*
|
||||
* Revision 1.1.1.1 2004/08/27 16:31:49 darioglz
|
||||
* Initial Import.
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
Loading…
Add table
Add a link
Reference in a new issue