Subversion Repositories Scribus

Rev

Rev 4622 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/

#include <qfiledialog.h>
#include <qcstring.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qstring.h>
#include <qstringlist.h>
#include <qtextcodec.h>
#include <qcursor.h>

#include "pdbim.h"
#include "gtwriter.h"
#include "gtparagraphstyle.h"
#include "scribusstructs.h"
#include "scribus.h"


/*! \brief A dummy 0 filler (helper procedure)
\param p binary structure to fill with 0
\param len how much 0 to go */

static void _zero_fill(  Byte *p,  int len )
{
        while ( len-- > 0 )
                *p++ = '\0';
}

QString FileFormatName()
{
        return QObject::tr("Palm PDB Documents", "PDB Importer");
}

QStringList FileExtensions()
{
    return QStringList("pdb");
}

void GetText(QString filename, QString encoding, bool /* textOnly */, gtWriter *writer)
{
        if (filename.isNull())
                return;
        qApp->setOverrideCursor(QCursor(Qt::WaitCursor), true);
        ScMW->mainWindowProgressBar->reset();
        PdbIm *im = new PdbIm(filename, encoding, writer);
        im->write();
        delete im;
        ScMW->mainWindowProgressBar->reset();
        qApp->restoreOverrideCursor();
}


PdbIm::PdbIm(const QString& fname, const QString& enc, gtWriter *w)
{
        m_buf = new buffer;
        _zero_fill(m_buf->buf, BUFFER_SIZE);
        m_buf->len = BUFFER_SIZE;
        m_buf->position = 0;
        writer = w;
        encoding = enc;
        selectSwap();
        loadFile(fname);
}

void PdbIm::write()
{
        QTextCodec *codec;
        if (encoding.isEmpty())
                codec = QTextCodec::codecForLocale();
        else
                codec = QTextCodec::codecForName(encoding);
        data = codec->toUnicode(data);
        gtParagraphStyle *pstyle = new gtParagraphStyle(*(writer->getDefaultStyle()));
        pstyle->setName(writer->getFrameName() + "-" + QObject::tr("PDB_data", "PDB Importer"));
        writer->append(data, pstyle);
        delete pstyle;
}

void PdbIm::loadFile(QString fname)
{
        FILE *m_pdfp = fopen(fname, "rb");
        pdb_header m_header;
        DWord file_size, offset;
        doc_record0 m_rec0;

        if (!m_pdfp)
        {
                QMessageBox::warning(ScMW, QObject::tr("PDB Import", "PDB Importer"),
                                                         "<qt>" + QObject::tr("Could not open file %1", "PDB Importer").arg(fname) + "</qt>",
                                                         0);
                return;
        }
        fread( &m_header, PDB_HEADER_SIZE, 1, m_pdfp );
        if (strncmp(m_header.type, DOC_TYPE, sizeof(m_header.type) ) ||
                strncmp( m_header.creator, DOC_CREATOR, sizeof(m_header.creator)))
        {
                QMessageBox::warning(ScMW, QObject::tr("PDB Import", "PDB Importer"),
                                                         "<qt>" + QObject::tr("This file is not recognized as a PDB document. Please, report this as a bug if you are sure it is one.", "PDB Importer") + "</qt>",
                                                         0);
                return;
        }

        // progressbar
        int num_records = swap_Word( m_header.numRecords ) - 1;
        ScMW->mainWindowProgressBar->setTotalSteps(num_records);
        fseek(m_pdfp, PDB_HEADER_SIZE, SEEK_SET);
        GET_DWord(m_pdfp, offset);
        fseek(m_pdfp, offset, SEEK_SET);
        fread(&m_rec0, sizeof(m_rec0), 1, m_pdfp);

        if (swap_Word( m_rec0.version ) == 2 )
                bCompressed = true;

        fseek( m_pdfp, 0, SEEK_END );
        file_size = ftell( m_pdfp );
        for (int rec_num = 1; rec_num <= num_records; ++rec_num )
        {
                DWord next_offset;

                ScMW->mainWindowProgressBar->setProgress(rec_num);
                fseek( m_pdfp, PDB_HEADER_SIZE + PDB_RECORD_HEADER_SIZE * rec_num, SEEK_SET);
                GET_DWord( m_pdfp, offset );
                if( rec_num < num_records )
                {
                        fseek( m_pdfp, PDB_HEADER_SIZE + PDB_RECORD_HEADER_SIZE * (rec_num + 1), SEEK_SET);
                        GET_DWord( m_pdfp, next_offset );
                }
                else
                        next_offset = file_size;
                fseek( m_pdfp, offset, SEEK_SET );
                // be overly cautious here
                _zero_fill (m_buf->buf, BUFFER_SIZE);
                m_buf->position = fread( m_buf->buf, 1, next_offset - offset, m_pdfp );

                if ( bCompressed )
                        uncompress( m_buf );

                m_buf->position = 0;
                while ( (m_buf->position) < (m_buf->len) )
                {
                        if (m_buf->buf[m_buf->position] == '\0')
                        {
                                ++m_buf->position;
                                continue;
                        }
                        data += m_buf->buf[m_buf->position];
                        ++m_buf->position;
                }
        }
}

void PdbIm::selectSwap()
{
        union { char c[2];  Word n; }  w;
        strncpy(  w.c, "\1\2",     2 );

        if ( w.n == 0x0201 )
                m_littlendian = true;
        else
                m_littlendian = false;

}  

Word PdbIm::swap_Word( Word r )
{
        if (m_littlendian)
                return (r >> 8) | (r << 8);
        else
                return r;
}

DWord PdbIm::swap_DWord( DWord r )
{
        if (m_littlendian)
                return ( (r >> 24) & 0x00FF ) | (r << 24) | ( (r >> 8) & 0xFF00 ) | ( (r << 8) & 0xFF0000 );
        else
                return r;
}

void PdbIm::uncompress( buffer *m_buf )
{
        buffer *m_new_buf = new buffer;
        UT_uint16 i, j;
        Byte c;

        _zero_fill (m_new_buf->buf, BUFFER_SIZE);

        for (i = j = 0; i < m_buf->position && j < BUFFER_SIZE; )
        {
                c = m_buf->buf[ i++ ];

                if ( c >= 1 && c <= 8 )
                        while ( c-- && j < BUFFER_SIZE-1)
                                m_new_buf->buf[ j++ ] = m_buf->buf[ i++ ];

                else if ( c <= 0x7F )
                        m_new_buf->buf[ j++ ] = c;

                else if ( c >= 0xC0 && j < BUFFER_SIZE-2)
                {
                        m_new_buf->buf[ j++ ] = ' ';
                        m_new_buf->buf[ j++ ] = c ^ 0x80;
                }
                else
                {
                        int di, n;
                        unsigned int temp_c = c;
                    // c--> temp_c //tomy 2001.11.13
                        temp_c = (temp_c << 8) ;
                        temp_c = temp_c + m_buf->buf[ i++ ];
                        di = (temp_c & 0x3FFF) >> COUNT_BITS;
                        for (n = (temp_c & ((1 << COUNT_BITS) - 1)) + 3; n-- && j < BUFFER_SIZE; ++j )
                                m_new_buf->buf[ j ] = m_new_buf->buf[ j - di ];
                        temp_c = 0;
                }
        }
        //UT_ASSERT(j <= BUFFER_SIZE);

        memcpy( static_cast<void *>(m_buf->buf), static_cast<void *>(m_new_buf->buf), static_cast<size_t>(j) );

        m_buf->position = j;
        delete( m_new_buf );
}