kde-extraapps/okular/generators/plucker/unpluck/qunpluck.cpp

1209 lines
43 KiB
C++
Raw Normal View History

/***************************************************************************
* Copyright (C) 2007 by Tobias Koenig <tokoe@kde.org> *
* *
* Based on code written by Bill Janssen 2002 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include <QtCore/QDateTime>
#include <QtCore/QFile>
#include <QtCore/QHash>
#include <QtCore/QStack>
#include <QtCore/QString>
#include <QtCore/QUrl>
#include <QtCore/QDateTime>
#include <QtGui/QAbstractTextDocumentLayout>
#include <QtGui/QFont>
#include <QtGui/qtextobject.h>
#include <QtGui/qtextformat.h>
#include <QtGui/QTextCursor>
#include <QtGui/QTextDocument>
#include <QtGui/QLabel>
#include <core/action.h>
#include <core/document.h>
#include "qunpluck.h"
#include "image.h"
#define GET_FUNCTION_CODE_TYPE(x) (((x)>>3) & 0x1F)
#define GET_FUNCTION_CODE_DATALEN(x) ((x) & 0x7)
#define CELLS(row,col) cells[row*cols+col]
#define READ_BIGENDIAN_SHORT(p) (((p)[0] << 8)|((p)[1]))
#define READ_BIGENDIAN_LONG(p) (((p)[0] << 24)|((p)[1] << 16)|((p)[2] << 8)|((p)[3]))
/*
static void LinkRecords
(
char* dir
)
{
RecordNode* ptr;
char* realfilename;
char* linkname;
realfilename = (char*)malloc (strlen (dir) + 20);
linkname = (char*)malloc (strlen (dir) + 20);
for (ptr = records; ptr != NULL; ptr = ptr->next) {
if (ptr->page_id != ptr->index) {
sprintf (realfilename, "%s/r%d.html", dir, ptr->page_id);
sprintf (linkname, "%s/r%d.html", dir, ptr->index);
link (realfilename, linkname);
}
}
free (realfilename);
free (linkname);
}
*/
class Context
{
public:
int recordId;
QTextDocument *document;
QTextCursor *cursor;
QStack<QTextCharFormat> stack;
QList<int> images;
QString linkUrl;
int linkStart;
int linkPage;
};
class RecordNode
{
public:
int index;
int page_id;
bool done;
};
static Okular::DocumentViewport calculateViewport( QTextDocument *document, const QTextBlock &block )
{
if ( !block.isValid() )
return Okular::DocumentViewport();
const QRectF rect = document->documentLayout()->blockBoundingRect( block );
const QSizeF size = document->size();
int page = qRound( rect.y() ) / qRound( size.height() );
Okular::DocumentViewport viewport( page );
viewport.rePos.normalizedX = (double)rect.x() / (double)size.width();
viewport.rePos.normalizedY = (double)rect.y() / (double)size.height();
viewport.rePos.enabled = true;
viewport.rePos.pos = Okular::DocumentViewport::Center;
return viewport;
}
QUnpluck::QUnpluck()
: mDocument( 0 )
{
}
QUnpluck::~QUnpluck()
{
mLinks.clear();
mNamedTargets.clear();
mPages.clear();
}
bool QUnpluck::open( const QString &fileName )
{
mLinks.clear();
mNamedTargets.clear();
mPages.clear();
mDocument = plkr_OpenDBFile( QFile::encodeName( fileName ).data() );
if ( !mDocument ) {
mErrorString = QObject::tr( "Unable to open document" );
return false;
}
bool status = true;
mInfo.insert( "name", plkr_GetName( mDocument ) );
mInfo.insert( "title", plkr_GetTitle( mDocument ) );
mInfo.insert( "author", plkr_GetAuthor( mDocument ) );
mInfo.insert( "time", QDateTime::fromTime_t( plkr_GetPublicationTime( mDocument ) ).toString() );
AddRecord( plkr_GetHomeRecordID( mDocument ) );
int number = GetNextRecordNumber();
while ( number > 0 ) {
status = TranscribeRecord( number );
number = GetNextRecordNumber ();
}
// Iterate over all records again to add those which aren't linked directly
for ( int i = 1; i < plkr_GetRecordCount( mDocument ); ++i )
AddRecord( plkr_GetUidForIndex( mDocument, i ) );
number = GetNextRecordNumber();
while ( number > 0 ) {
status = TranscribeRecord( number );
number = GetNextRecordNumber ();
}
for ( int i = 0; i < mRecords.count(); ++i )
delete mRecords[ i ];
mRecords.clear();
plkr_CloseDoc( mDocument );
/**
* Calculate hash map
*/
QHash<int, int> pageHash;
for ( int i = 0; i < mContext.count(); ++i )
pageHash.insert( mContext[ i ]->recordId, i );
/**
* Convert ids
*/
for ( int i = 0; i < mContext.count(); ++i ) {
Context *context = mContext[ i ];
for ( int j = 0; j < context->images.count(); ++j ) {
int imgNumber = context->images[ j ];
context->document->addResource( QTextDocument::ImageResource,
QUrl( QString( "%1.jpg" ).arg( imgNumber ) ),
mImages[ imgNumber ] );
}
mPages.append( context->document );
}
qDeleteAll( mContext );
mContext.clear();
// convert record_id into page
for ( int i = 0; i < mLinks.count(); ++i ) {
mLinks[ i ].page = pageHash[ mLinks[ i ].page ];
if ( mLinks[ i ].url.startsWith( "page:" ) ) {
int page = mLinks[ i ].url.mid( 5 ).toInt();
Okular::DocumentViewport viewport( pageHash[ page ] );
viewport.rePos.normalizedX = 0;
viewport.rePos.normalizedY = 0;
viewport.rePos.enabled = true;
viewport.rePos.pos = Okular::DocumentViewport::TopLeft;
mLinks[ i ].link = new Okular::GotoAction( QString(), viewport );
} else if ( mLinks[ i ].url.startsWith( "para:" ) ) {
QPair<int, QTextBlock> data = mNamedTargets[ mLinks[ i ].url ];
QTextDocument *document = mPages[ mLinks[ i ].page ];
Okular::DocumentViewport viewport = calculateViewport( document, data.second );
mLinks[ i ].link = new Okular::GotoAction( QString(), viewport );
} else {
mLinks[ i ].link = new Okular::BrowseAction( mLinks[ i ].url );
}
}
return true;
}
int QUnpluck::GetNextRecordNumber()
{
int index = 0;
for ( int pos = 0; pos < mRecords.count(); ++pos ) {
if ( !mRecords[ pos ]->done ) {
index = mRecords[ pos ]->index;
break;
}
}
return index;
}
int QUnpluck::GetPageID( int index )
{
for ( int pos = 0; pos < mRecords.count(); ++pos ) {
if ( mRecords[ pos ]->index == index ) {
return mRecords[ pos ]->page_id;
}
}
return 0;
}
void QUnpluck::AddRecord( int index )
{
for ( int pos = 0; pos < mRecords.count(); ++pos ) {
if ( mRecords[ pos ]->index == index ) {
return;
}
}
RecordNode *node = new RecordNode;
node->done = false;
node->index = index;
node->page_id = index;
mRecords.append( node );
}
void QUnpluck::MarkRecordDone( int index )
{
for ( int pos = 0; pos < mRecords.count(); ++pos ) {
if ( mRecords[ pos ]->index == index ) {
mRecords[ pos ]->done = true;
return;
}
}
AddRecord( index );
MarkRecordDone( index );
}
void QUnpluck::SetPageID( int index, int page_id )
{
for ( int pos = 0; pos < mRecords.count(); ++pos ) {
if ( mRecords[ pos ]->index == index ) {
mRecords[ pos ]->page_id = page_id;
return;
}
}
AddRecord( index );
SetPageID( index, page_id );
}
QString QUnpluck::MailtoURLFromBytes( unsigned char* record_data )
{
unsigned char* bytes = record_data + 8;
int to_offset = (bytes[0] << 8) + bytes[1];
int cc_offset = (bytes[2] << 8) + bytes[3];
int subject_offset = (bytes[4] << 8) + bytes[5];
int body_offset = (bytes[6] << 8) + bytes[7];
QString url( "mailto:" );
if ( to_offset != 0 )
url += QString::fromLatin1( (char *)(bytes + to_offset) );
if ( (cc_offset != 0) || (subject_offset != 0) || (body_offset != 0) )
url += QLatin1String( "?" );
if ( cc_offset != 0 )
url += QLatin1String( "cc=" ) + QString::fromLatin1( (char *)(bytes + cc_offset) );
if ( subject_offset != 0 )
url += QLatin1String( "subject=" ) + QString::fromLatin1( (char *)(bytes + subject_offset) );
if ( body_offset != 0 )
url += QLatin1String( "body=" ) + QString::fromLatin1( (char *)(bytes + body_offset) );
return url;
}
QImage QUnpluck::TranscribeImageRecord( unsigned char* bytes )
{
QImage image;
TranscribePalmImageToJPEG( bytes + 8, image );
return image;
}
void QUnpluck::DoStyle( Context* context, int style, bool start )
{
if ( start ) {
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
int pointSize = qRound( format.fontPointSize() );
switch (style) {
case 1:
format.setFontWeight( QFont::Bold );
pointSize += 3;
break;
case 2:
format.setFontWeight( QFont::Bold );
pointSize += 2;
break;
case 3:
format.setFontWeight( QFont::Bold );
pointSize += 1;
break;
case 4:
format.setFontWeight( QFont::Bold );
break;
case 5:
format.setFontWeight( QFont::Bold );
pointSize += -1;
break;
case 6:
format.setFontWeight( QFont::Bold );
pointSize += -2;
break;
case 7:
format.setFontWeight( QFont::Bold );
break;
case 8:
format.setFontFamily( QString::fromLatin1( "Courier New,courier" ) );
break;
}
format.setFontPointSize( qMax( pointSize, 1 ) );
context->cursor->setCharFormat( format );
} else {
if ( !context->stack.isEmpty() )
context->cursor->setCharFormat( context->stack.pop() );
}
}
void QUnpluck::ParseText
(
plkr_Document* doc,
unsigned char* ptr,
int text_len,
int* font,
int* style,
Context* context
)
{
unsigned char* end;
int fctype;
int fclen;
end = ptr + text_len;
while (ptr < end) {
if (ptr[0]) {
context->cursor->insertText( QString( (char*)ptr ) );
ptr += strlen ((char*)ptr);
}
else {
fctype = GET_FUNCTION_CODE_TYPE (ptr[1]);
fclen = 2 + GET_FUNCTION_CODE_DATALEN (ptr[1]);
switch (fctype) {
case PLKR_TFC_LINK:
switch (fclen) {
case 4: /* ANCHOR_BEGIN */
{
int record_id =
(ptr[2] << 8) + ptr[3];
/** TODO:
plkr_DataRecordType type =
(plkr_DataRecordType)plkr_GetRecordType (doc, record_id);
if (type ==
PLKR_DRTYPE_IMAGE
|| type ==
PLKR_DRTYPE_IMAGE_COMPRESSED)
output += QString( "<A HREF=\"r%1.jpg\">" ).arg(record_id);
else
output += QString( "<A HREF=\"r%1.html\">" ).arg(record_id);
*/
AddRecord (record_id);
}
break;
case 2: /* ANCHOR_END */
//TODO: output += QString( "</A>" );
break;
}
ptr += fclen;
break;
case PLKR_TFC_FONT:
DoStyle (context, *style, false);
*style = ptr[2];
DoStyle (context, *style, true);
ptr += fclen;
break;
case PLKR_TFC_NEWLINE:
{
// TODO: remove the setCharFormat when Qt is fixed
QTextCharFormat format( context->cursor->charFormat() );
context->cursor->insertText( "\n" );
context->cursor->setCharFormat( format );
ptr += fclen;
break;
}
case PLKR_TFC_BITALIC:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontItalic( true );
context->cursor->setCharFormat( format );
ptr += fclen;
break;
}
case PLKR_TFC_EITALIC:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontItalic( false );
context->cursor->setCharFormat( format );
ptr += fclen;
break;
}
case PLKR_TFC_COLOR:
if (*font) {
*font--;
if ( !context->stack.isEmpty() )
context->cursor->setCharFormat( context->stack.pop() );
}
{
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
format.setForeground( QColor((ptr[2] << 16), (ptr[3] << 8), ptr[4]) );
context->cursor->setCharFormat( format );
}
*font++;
ptr += fclen;
break;
case PLKR_TFC_BULINE:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontUnderline( true );
context->cursor->setCharFormat( format );
ptr += fclen;
}
break;
case PLKR_TFC_EULINE:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontUnderline( false );
context->cursor->setCharFormat( format );
ptr += fclen;
}
break;
case PLKR_TFC_BSTRIKE:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontStrikeOut( true );
context->cursor->setCharFormat( format );
ptr += fclen;
break;
}
case PLKR_TFC_ESTRIKE:
{
QTextCharFormat format( context->cursor->charFormat() );
format.setFontStrikeOut( false );
context->cursor->setCharFormat( format );
ptr += fclen;
break;
}
case PLKR_TFC_TABLE:
if (fclen == 4) {
int record_id, datalen;
plkr_DataRecordType type = (plkr_DataRecordType)0;
unsigned char *bytes = NULL;
record_id = (ptr[2] << 8) + ptr[3];
bytes =
plkr_GetRecordBytes
(doc, record_id, &datalen, &type);
TranscribeTableRecord (doc, context, bytes);
}
ptr += fclen;
break;
default:
ptr += fclen;
}
}
}
}
bool QUnpluck::TranscribeTableRecord
(
plkr_Document* doc,
Context* context,
unsigned char* bytes
)
{
unsigned char* ptr = &bytes[24];
unsigned char* end;
// char* align_names[] = { "left", "right", "center" };
bool in_row = false;
int cols;
int size;
int rows;
int border;
int record_id;
int align;
int text_len;
int colspan;
int rowspan;
int font = 0;
int style = 0;
int fctype;
int fclen;
long border_color;
long link_color;
size = (bytes[8] << 8) + bytes[9];
cols = (bytes[10] << 8) + bytes[11];
rows = (bytes[12] << 8) + bytes[13];
border = bytes[15];
border_color = (bytes[17] << 16) + (bytes[18] << 8) + (bytes[19] << 8);
link_color = (bytes[21] << 16) + (bytes[22] << 8) + (bytes[23] << 8);
end = ptr + size - 1;
/**
output += QString( "<TABLE border=%1 bordercolor=\"#%2\" "
"linkcolor=\"#%3\">\n" ).arg(border, border_color, link_color);
*/
while (ptr < end) {
if (ptr[0] == '\0') {
fctype = GET_FUNCTION_CODE_TYPE (ptr[1]);
fclen = 2 + GET_FUNCTION_CODE_DATALEN (ptr[1]);
switch (fctype) {
case PLKR_TFC_TABLE:
switch (fclen) {
case 2: /* NEW_ROW */
/*
if (in_row)
output += QString( "</TR>\n" );
output += QString( "<TR>\n" );
*/
in_row = true;
ptr += fclen;
break;
case 9: /* NEW_CELL */
align = ptr[2];
colspan = ptr[5];
rowspan = ptr[6];
/**
output += QString( "<TD align=\"%1\" colspan=%2 "
"rowspan=%3 bordercolor=\"#\">" ).arg(
align_names[align], colspan, rowspan );
// border_color);
*/
if ( (record_id = READ_BIGENDIAN_SHORT (&ptr[3])) ) {
QTextCharFormat format = context->cursor->charFormat();
context->cursor->insertImage( QString( "%1.jpg" ).arg(record_id) );
context->cursor->setCharFormat( format );
context->images.append( record_id );
AddRecord (record_id);
}
DoStyle (context, style, true);
text_len = READ_BIGENDIAN_SHORT (&ptr[7]);
ptr += fclen;
ParseText (doc, ptr, text_len, &font, &style, context);
ptr += text_len;
DoStyle (context, style, false);
//output += QString( "</TD>\n" );
break;
default:
ptr += fclen;
}
break;
default:
ptr += fclen;
}
}
else {
//output += QString( "</TABLE>\n" );
return false;
}
}
// output += QString( "</TABLE>\n" );
return true;
}
typedef struct {
int size;
int attributes;
} ParagraphInfo;
static ParagraphInfo *ParseParagraphInfo
(
unsigned char* bytes,
int* nparas
)
{
ParagraphInfo* paragraph_info;
int j;
int n;
n = (bytes[2] << 8) + bytes[3];
paragraph_info = (ParagraphInfo *) malloc (sizeof (ParagraphInfo) * n);
for (j = 0; j < n; j++) {
paragraph_info[j].size =
(bytes[8 + (j * 4) + 0] << 8) + bytes[8 + (j * 4) + 1];
paragraph_info[j].attributes =
(bytes[8 + (j * 4) + 2] << 8) + bytes[8 + (j * 4) + 3];
}
*nparas = n;
return paragraph_info;
}
bool QUnpluck::TranscribeTextRecord
(
plkr_Document* doc,
int id,
Context *context,
unsigned char* bytes,
plkr_DataRecordType type
)
{
unsigned char* ptr;
unsigned char* run;
unsigned char* para_start;
unsigned char* data;
unsigned char* start;
ParagraphInfo* paragraphs;
bool first_record_of_page = true;
bool current_link;
bool current_italic;
bool current_struckthrough;
bool current_underline;
int fctype;
int fclen;
int para_index;
int para_len;
int textlen;
int data_len;
int current_font;
int record_index;
int current_alignment;
int current_left_margin;
int current_right_margin;
int nparagraphs;
long current_color;
record_index = id;
paragraphs = ParseParagraphInfo (bytes, &nparagraphs);
start = bytes + 8 + ((bytes[2] << 8) + bytes[3]) * 4;
for (para_index = 0, ptr = start, run = start;
para_index < nparagraphs; para_index++) {
para_len = paragraphs[para_index].size;
/* If the paragraph is the last in the record, and it consists
of a link to the next record in the logical page, we trim off
the paragraph and instead insert the whole page */
if (((para_index + 1) == nparagraphs) &&
(para_len == (sizeof ("Click here for the next part") + 5)) &&
(*ptr == 0) && (ptr[1] == ((PLKR_TFC_LINK << 3) + 2)) &&
(strcmp ((char*)(ptr + 4), "Click here for the next part") == 0)) {
record_index = (ptr[2] << 8) + ptr[3];
if ((data =
plkr_GetRecordBytes (doc, record_index, &data_len,
&type)) == NULL) {
// ShowWarning ("Can't open record %d!", record_index);
free (paragraphs);
return false;
}
else if (!(type == PLKR_DRTYPE_TEXT_COMPRESSED ||
type == PLKR_DRTYPE_TEXT)) {
// ShowWarning ("Bad record type %d in record linked from end of record %d", type, id);
free (paragraphs);
return false;
}
first_record_of_page = false;
para_index = 0;
ptr = data + 8 + ((data[2] << 8) + data[3]) * 4;
run = ptr;
free (paragraphs);
paragraphs = ParseParagraphInfo (data, &nparagraphs);
para_len = paragraphs[para_index].size;
MarkRecordDone (record_index);
SetPageID (record_index, id);
}
if ((para_index == 0) && !first_record_of_page &&
(*ptr == 0) && (ptr[1] == ((PLKR_TFC_LINK << 3) + 2)) &&
(strcmp ((char*)(ptr + 4), "Click here for the previous part") == 0)) {
/* throw away this inserted paragraph */
ptr += para_len;
run = ptr;
continue;
}
QTextCharFormat format( context->cursor->charFormat() );
QTextBlockFormat blockFormat( context->cursor->blockFormat() );
blockFormat.setAlignment( Qt::AlignLeft );
context->cursor->insertBlock( blockFormat );
context->cursor->setCharFormat( format );
mNamedTargets.insert( QString( "para:%1-%2" ).arg( record_index ).arg( para_index ),
QPair<int, QTextBlock>( GetPageID( record_index ), context->cursor->block() ) );
current_link = false;
/* at the beginning of a paragraph, we start with a clean graphics context */
current_font = 0;
current_alignment = 0;
current_color = 0;
current_italic = false;
current_underline = false;
current_struckthrough = false;
current_left_margin = 0;
current_right_margin = 0;
for (para_start = ptr, textlen = 0; (ptr - para_start) < para_len;) {
if (*ptr == 0) {
/* function code */
if ((ptr - run) > 0) {
/* write out any pending text */
context->cursor->insertText( QString::fromLatin1( (char*)run, ptr - run ) );
textlen += (ptr - run);
}
ptr++;
fctype = GET_FUNCTION_CODE_TYPE (*ptr);
fclen = GET_FUNCTION_CODE_DATALEN (*ptr);
ptr++;
if (fctype == PLKR_TFC_NEWLINE) {
// TODO: remove the setCharFormat when Qt is fixed
QTextCharFormat format( context->cursor->charFormat() );
context->cursor->insertText( "\n" );
context->cursor->setCharFormat( format );
}
else if (fctype == PLKR_TFC_LINK) {
int record_id, real_record_id,
datalen;
plkr_DataRecordType type = (plkr_DataRecordType)0;
unsigned char *bytes = NULL;
char *url = NULL;
if (fclen == 0) {
if (current_link) {
if ( !context->stack.isEmpty() )
context->cursor->setCharFormat( context->stack.pop() );
if ( !context->linkUrl.isEmpty() ) {
Link link;
link.url = context->linkUrl;
link.start = context->linkStart;
link.end = context->cursor->position();
link.page = GetPageID( id );
mLinks.append( link );
}
}
current_link = false;
}
else {
record_id = (ptr[0] << 8) + ptr[1];
bytes =
plkr_GetRecordBytes (doc, record_id, &datalen,
&type);
if (!bytes) {
url = plkr_GetRecordURL (doc, record_id);
}
if (bytes && (type == PLKR_DRTYPE_MAILTO)) {
context->linkUrl = MailtoURLFromBytes( bytes );
context->linkStart = context->cursor->position();
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
format.setForeground( Qt::blue );
format.setUnderlineStyle( QTextCharFormat::SingleUnderline );
context->cursor->setCharFormat( format );
current_link = true;
}
else if (!bytes && url) {
context->linkUrl = QString::fromLatin1( url );
context->linkStart = context->cursor->position();
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
format.setForeground( Qt::blue );
format.setUnderlineStyle( QTextCharFormat::SingleUnderline );
context->cursor->setCharFormat( format );
current_link = true;
}
else if (bytes && (fclen == 2)) {
AddRecord (record_id);
real_record_id = GetPageID (record_id);
if (type == PLKR_DRTYPE_IMAGE
|| type == PLKR_DRTYPE_IMAGE_COMPRESSED) {
context->linkUrl = QString( "%1.jpg" ).arg( record_id );
context->linkStart = context->cursor->position();
}
else {
context->linkUrl = QString( "page:%1" ).arg( real_record_id );
context->linkStart = context->cursor->position();
}
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
format.setForeground( Qt::blue );
format.setUnderlineStyle( QTextCharFormat::SingleUnderline );
context->cursor->setCharFormat( format );
current_link = true;
}
else if (bytes && (fclen == 4)) {
AddRecord (record_id);
context->linkUrl = QString( "para:%1-%2" ).arg( record_id ).arg( (ptr[2] << 8) + ptr[3] );
context->linkStart = context->cursor->position();
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
format.setForeground( Qt::blue );
format.setUnderlineStyle( QTextCharFormat::SingleUnderline );
context->cursor->setCharFormat( format );
current_link = true;
}
else {
// ShowWarning("odd link found: record_id=%d, bytes=0x%p, type=%d, url=%s", record_id, bytes, type, (url ? url : "0x0"));
}
}
}
else if (fctype == PLKR_TFC_FONT) {
if (current_font != *ptr) {
if ( !context->stack.isEmpty() )
context->cursor->setCharFormat( context->stack.pop() );
QTextCharFormat format( context->cursor->charFormat() );
context->stack.push( format );
int pointSize = qRound( format.fontPointSize() );
if (*ptr == 1) {
format.setFontWeight( QFont::Bold );
pointSize += 3;
}
else if (*ptr == 2) {
format.setFontWeight( QFont::Bold );
pointSize += 2;
}
else if (*ptr == 3) {
format.setFontWeight( QFont::Bold );
pointSize += 1;
}
else if (*ptr == 4) {
format.setFontWeight( QFont::Bold );
}
else if (*ptr == 5) {
format.setFontWeight( QFont::Bold );
pointSize += -1;
}
else if (*ptr == 6) {
format.setFontWeight( QFont::Bold );
pointSize += -2;
}
else if (*ptr == 7) {
format.setFontWeight( QFont::Bold );
}
else if (*ptr == 8) {
format.setFontFamily( QString::fromLatin1( "Courier New,courier" ) );
}
else if (*ptr == 11) {
format.setVerticalAlignment( QTextCharFormat::AlignSuperScript );
}
format.setFontPointSize( qMax( pointSize, 1 ) );
context->cursor->setCharFormat( format );
current_font = *ptr;
}
}
else if (fctype == PLKR_TFC_BITALIC) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontItalic( true );
context->cursor->setCharFormat( format );
current_italic = true;
}
else if (fctype == PLKR_TFC_EITALIC) {
if (current_italic) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontItalic( false );
context->cursor->setCharFormat( format );
current_italic = false;
}
}
else if (fctype == PLKR_TFC_BULINE) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontUnderline( true );
context->cursor->setCharFormat( format );
current_underline = true;
}
else if (fctype == PLKR_TFC_EULINE) {
if (current_underline) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontUnderline( false );
context->cursor->setCharFormat( format );
current_underline = false;
}
}
else if (fctype == PLKR_TFC_BSTRIKE) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontStrikeOut( true );
context->cursor->setCharFormat( format );
current_struckthrough = true;
}
else if (fctype == PLKR_TFC_ESTRIKE) {
if (current_struckthrough) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontStrikeOut( false );
context->cursor->setCharFormat( format );
current_struckthrough = false;
}
}
else if (fctype == PLKR_TFC_HRULE) {
QTextCharFormat charFormat = context->cursor->charFormat();
QTextBlockFormat oldBlockFormat = context->cursor->blockFormat();
QTextBlockFormat blockFormat;
blockFormat.setProperty( QTextFormat::BlockTrailingHorizontalRulerWidth, "100%");
context->cursor->insertBlock( blockFormat );
context->cursor->insertBlock( oldBlockFormat );
context->cursor->setCharFormat( charFormat );
}
else if (fctype == PLKR_TFC_ALIGN) {
current_alignment = 0;
if (*ptr < 4) {
QTextBlockFormat format( context->cursor->blockFormat() );
if (*ptr == 0)
format.setAlignment( Qt::AlignLeft );
else if (*ptr == 1)
format.setAlignment( Qt::AlignRight );
else if (*ptr == 2)
format.setAlignment( Qt::AlignCenter );
else if (*ptr == 3)
format.setAlignment( Qt::AlignJustify );
QTextCharFormat charFormat( context->cursor->charFormat() );
context->cursor->insertBlock( format );
context->cursor->setCharFormat( charFormat );
current_alignment = (*ptr) + 1;
}
}
else if (fctype == PLKR_TFC_MARGINS) {
/* Not easy to set, in HTML */
#if 0
output += QString( "<!-- margins: %1, %2 -->" ).arg(ptr[0], ptr[1]);
if (current_left_margin != ptr[0]
|| current_right_margin != ptr[1]) {
if (current_right_margin != 0)
fprintf (fp, "</td><td width=%d>&nbsp;",
current_right_margin);
fprintf (fp, "</td></tr></table>\n");
}
current_left_margin = ptr[0];
current_right_margin = ptr[1];
if (current_right_margin > 0
|| current_left_margin > 0) {
fprintf (fp, "<table border=1><tr>");
if (current_left_margin != 0) {
fprintf (fp, "<td width=%d align=right>",
current_left_margin);
if ((ptr - run) > 2) {
fwrite (run, 1, ((ptr - 2) - run), fp);
textlen += ((ptr - 2) - run);
}
else {
fprintf (fp, "&nbsp;");
}
fprintf (fp, "</td>");
}
fprintf (fp, "<td>");
if (current_left_margin == 0 && (ptr - run) > 2) {
fwrite (run, 1, ((ptr - 2) - run), fp);
textlen += ((ptr - 2) - run);
}
}
else {
if ((ptr - run) > 2) {
fwrite (run, 1, ((ptr - 2) - run), fp);
textlen += ((ptr - 2) - run);
}
}
#endif
current_left_margin = ptr[0];
current_right_margin = ptr[1];
}
else if (fctype == PLKR_TFC_COLOR) {
/* not sure what to do here yet */
/*
fprintf (fp, "<!-- color=\"#%02x%02x%02x\" -->",
ptr[0], ptr[1], ptr[2]);*/
current_color =
(ptr[0] << 16) + (ptr[1] << 8) + ptr[2];
} else if (fctype == PLKR_TFC_IMAGE || fctype == PLKR_TFC_IMAGE2) {
QTextCharFormat format = context->cursor->charFormat();
context->cursor->insertImage( QString( "%1.jpg" ).arg( (ptr[0] << 8) + ptr[1] ) );
context->images.append( (ptr[0] << 8) + ptr[1] );
context->cursor->setCharFormat( format );
AddRecord ((ptr[0] << 8) + ptr[1]);
}
else if (fctype == PLKR_TFC_TABLE) {
int record_id, datalen;
plkr_DataRecordType type = (plkr_DataRecordType)0;
unsigned char *bytes = NULL;
record_id = (ptr[0] << 8) + ptr[1];
bytes =
plkr_GetRecordBytes (doc, record_id, &datalen,
&type);
TranscribeTableRecord (doc, context, bytes);
}
else if (fctype == PLKR_TFC_UCHAR) {
if (fclen == 3)
context->cursor->insertText( QChar( (ptr[1] << 8) + ptr[2] ) );
else if (fclen == 5)
context->cursor->insertText( QChar( (ptr[3] << 8) + ptr[4] ) );
/* skip over alternate text */
ptr += ptr[0];
}
else {
/* ignore function */
//output += QString( "<!-- function code %1 ignored -->" ).arg(fctype);
}
ptr += fclen;
run = ptr;
}
else {
ptr++;
}
}
if ((ptr - run) > 0) {
/* output any pending text at the end of the paragraph */
context->cursor->insertText( QString::fromLatin1( (char *)run, ptr - run ) );
textlen += (ptr - run);
run = ptr;
}
/* clear the graphics state again */
if (current_font > 0 && current_font < 9 ) {
if ( !context->stack.isEmpty() )
context->cursor->setCharFormat( context->stack.pop() );
}
if (current_italic) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontItalic( false );
context->cursor->setCharFormat( format );
}
if (current_underline) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontUnderline( false );
context->cursor->setCharFormat( format );
}
if (current_struckthrough) {
QTextCharFormat format( context->cursor->charFormat() );
format.setFontStrikeOut( false );
context->cursor->setCharFormat( format );
}
#if 0
if (current_alignment > 0) {
context->cursor->insertBlock();
}
if (current_right_margin > 0)
fprintf (fp, "</td><td width=%d>&nbsp;</td></tr></table>",
current_right_margin);
else if (current_left_margin > 0)
fprintf (fp, "</td></tr></table>");
/* end the paragraph */
context->cursor->insertBlock();
#endif
}
free (paragraphs);
return true;
}
bool QUnpluck::TranscribeRecord( int index )
{
plkr_DataRecordType type;
int data_len;
bool status = true;
unsigned char *data = plkr_GetRecordBytes( mDocument, index, &data_len, &type);
if ( !data ) {
MarkRecordDone( index );
return false;
}
if (type == PLKR_DRTYPE_TEXT_COMPRESSED || type == PLKR_DRTYPE_TEXT) {
QTextDocument *document = new QTextDocument;
QTextFrameFormat format( document->rootFrame()->frameFormat() );
format.setMargin( 20 );
document->rootFrame()->setFrameFormat( format );
Context *context = new Context;
context->recordId = index;
context->document = document;
context->cursor = new QTextCursor( document );
QTextCharFormat charFormat;
charFormat.setFontPointSize( 10 );
charFormat.setFontFamily( "Helvetica" );
context->cursor->setCharFormat( charFormat );
status = TranscribeTextRecord( mDocument, index, context, data, type );
document->setTextWidth( 600 );
delete context->cursor;
mContext.append( context );
} else if (type == PLKR_DRTYPE_IMAGE_COMPRESSED || type == PLKR_DRTYPE_IMAGE) {
QImage image = TranscribeImageRecord( data );
mImages.insert( index, image );
} else if (type == PLKR_DRTYPE_MULTIIMAGE) {
QImage image;
if ( TranscribeMultiImageRecord( mDocument, image, data ) )
mImages.insert( index, image );
} else {
status = false;
}
// plkr_GetHomeRecordID (doc)))
MarkRecordDone( index );
return status;
}