filters
palmdoc.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "palmdoc.h"
00021
00022 #include <qcstring.h>
00023 #include <qdatetime.h>
00024 #include <qptrlist.h>
00025 #include <qstring.h>
00026
00027 PalmDoc::PalmDoc(): PalmDB()
00028 {
00029 m_result = PalmDoc::OK;
00030 setText( QString::null );
00031 }
00032
00033 PalmDoc::~PalmDoc()
00034 {
00035 }
00036
00037 bool PalmDoc::load( const char* filename )
00038 {
00039 bool ok;
00040
00041 ok = PalmDB::load( filename );
00042 if( !ok )
00043 {
00044 m_result = PalmDoc::ReadError;
00045 return FALSE;
00046 }
00047
00048 if( type() != "TEXt" )
00049 {
00050 qDebug( "Type is \"%s\", not \"TEXt\", so this is not Palm DOC!", type().latin1() );
00051 m_result = PalmDoc::InvalidFormat;
00052 return FALSE;
00053 }
00054
00055 if( creator() != "REAd" )
00056 {
00057 qDebug( "Creator is \"%s\", not \"REAd\", so this is not Palm DOC!",
00058 creator().latin1() );
00059 m_result = PalmDoc::InvalidFormat;
00060 return FALSE;
00061 }
00062
00063
00064 if( records.count() < 2 )
00065 {
00066 qDebug( "Palm DOC has at least 2 records!" );
00067 m_result = PalmDoc::InvalidFormat;
00068 return FALSE;
00069 }
00070
00071
00072
00073 QByteArray header( *records.at( 0 ) );
00074
00075
00076 int format = (header[0]<<8) + header[1];
00077 qDebug( "DOC format: %d (%s)", format,
00078 (format==1) ? "Plain" : (format==2) ? "Compressed" : "Unknown" );
00079
00080
00081 if( ( format != 1 ) && ( format != 2 ) )
00082 {
00083 qDebug( "Unknown format of document!" );
00084 m_result = PalmDoc::InvalidFormat;
00085 return FALSE;
00086 }
00087
00088
00089 setText( QString::null );
00090
00091
00092 QByteArray rec;
00093 unsigned i = 0;
00094 for( unsigned r = 1; r < records.count(); r++ )
00095 {
00096 QByteArray *p = records.at( r );
00097 if( !p ) continue;
00098 rec.resize( rec.size() + p->size() );
00099 for( unsigned s=0; s<p->size(); s++ )
00100 rec[i++] = p->at( s );
00101 }
00102
00103
00104 if( format == 2 )
00105 setText( uncompress( rec ) );
00106
00107
00108 if( format == 1 )
00109 setText( QString::fromLatin1( rec.data(),rec.count() ) );
00110
00111
00112 m_result = OK;
00113 return TRUE;
00114 }
00115
00116 bool PalmDoc::save( const char* filename )
00117 {
00118
00119 setType( "TEXt" );
00120 setCreator( "REAd" );
00121
00122
00123 setModificationDate( QDateTime::currentDateTime() );
00124
00125
00126 unsigned recsize = 4096;
00127
00128
00129 QByteArray data = compress( text() );
00130
00131
00132 records.clear();
00133 for( unsigned i=0; i<data.count(); )
00134 {
00135 QByteArray* ptr = new QByteArray;
00136 unsigned rs = data.count() - i;
00137 if( rs > recsize ) rs = recsize;
00138 ptr->resize( rs );
00139 for( unsigned m=0; m<rs; m++ )
00140 (*ptr)[m] = data[i++];
00141 records.append( ptr );
00142 }
00143
00144
00145 QByteArray header( 16 );
00146 int docsize = m_text.length();
00147 header[0] = 0; header[1] = 2;
00148 header[2] = header[3] = 0;
00149 header[4] = (docsize >> 24) & 255;
00150 header[5] = (docsize >> 16) & 255;
00151 header[6] = (docsize >> 8) & 255;
00152 header[7] = docsize & 255;
00153 header[8] = records.count()>> 8;
00154 header[9] = records.count() & 255;
00155 header[10] = recsize >>8;
00156 header[11] = recsize & 255;
00157 header[12] = header[13] = 0;
00158 header[14] = header[15] = 0;
00159
00160
00161 records.prepend( new QByteArray( header ) );
00162
00163
00164 bool ok = PalmDB::save( filename );
00165 if( !ok )
00166 {
00167 m_result = WriteError;
00168 return FALSE;
00169 }
00170
00171
00172 m_result = OK;
00173 return TRUE;
00174 }
00175
00176
00177 QByteArray PalmDoc::compress( const QString& text )
00178 {
00179 QByteArray result;
00180 unsigned textlen = text.length();
00181 const char *ctext = text.latin1();
00182 unsigned int i, j;
00183
00184
00185
00186 result.resize( textlen );
00187
00188 for( i=j=0; i<textlen; )
00189 {
00190 int horizon = 2047;
00191 int start = (i < horizon) ? 0 : i-horizon;
00192 bool match = false;
00193 int match_pos=0, match_len=0;
00194
00195
00196 for( int back = i-1; (!match) && (back > start); back-- )
00197 if( ctext[i] == ctext[back] )
00198 if( ctext[i+1] == ctext[back+1] )
00199 if( ctext[i+2] == ctext[back+2] )
00200 {
00201 match = true;
00202 match_pos = i-back;
00203 match_len = 3;
00204
00205 if( i+3 < textlen )
00206 if( ctext[i+3] == ctext[back+3] )
00207 {
00208 match_len = 4;
00209 if( i+4 < textlen )
00210 if( ctext[i+4] == ctext[back+4] )
00211 {
00212 match_len = 5;
00213 }
00214 }
00215
00216 }
00217
00218 if( match )
00219 {
00220 unsigned char p = 0x80 | ((match_pos >> 5)&0x3f);
00221 unsigned char q = ((match_pos & 0x1f) << 3) | (match_len-3);
00222 result[j++] = p;
00223 result[j++] = q;
00224 i+= match_len;
00225 }
00226 else
00227 {
00228 char ch = ctext[i++] & 0x7f;
00229 bool space_pack = false;
00230
00231 if( ch == 0x20 )
00232 if ( i<textlen )
00233 if( ctext[i] >= 0x40 )
00234 space_pack = true;
00235
00236 if( !space_pack ) result[j++] = ch;
00237 else result[j++] = ctext[i++] | 0x80;
00238 }
00239
00240 }
00241
00242 result.resize( j );
00243
00244 return result;
00245 }
00246
00247 #define INRANGE(v,p,q) ((v)>=(p))&&((v)<=(q))
00248
00249
00250 QString PalmDoc::uncompress( QByteArray rec )
00251 {
00252 QString result;
00253
00254 for( unsigned i = 0; i < rec.size(); i++ )
00255 {
00256 unsigned char c = rec[i];
00257
00258 if( INRANGE(c,1,8) )
00259 {
00260 i++;
00261 if( i < rec.size() )
00262 for( unsigned char v = rec[i]; c>0; c-- )
00263 result.append( v );
00264 }
00265
00266 else if( INRANGE(c,0x09,0x7F) )
00267 result.append( c );
00268
00269 else if( INRANGE(c,0xC0,0xFF) )
00270 result.append( 32 ).append( c^ 0x80 );
00271
00272 else if( INRANGE(c,0x80,0xBF) )
00273 {
00274 unsigned char d = rec[++i];
00275 int back = (((c<<8)+d) & 0x3fff) >> 3;
00276 int count = (d & 7) + 3;
00277 if( result.length()-back >= 0 )
00278 for(; count>0; count-- )
00279 result.append( result[result.length()-back] );
00280 }
00281
00282 }
00283
00284 return result;
00285 }
|