23#include <tqdatetime.h>
27PalmDoc::PalmDoc(): PalmDB()
29 m_result = PalmDoc::OK;
30 setText( TQString() );
37bool PalmDoc::load(
const char* filename )
41 ok = PalmDB::load( filename );
44 m_result = PalmDoc::ReadError;
48 if( type() !=
"TEXt" )
50 tqDebug(
"Type is \"%s\", not \"TEXt\", so this is not Palm DOC!", type().latin1() );
51 m_result = PalmDoc::InvalidFormat;
55 if( creator() !=
"REAd" )
57 tqDebug(
"Creator is \"%s\", not \"REAd\", so this is not Palm DOC!",
59 m_result = PalmDoc::InvalidFormat;
64 if( records.count() < 2 )
66 tqDebug(
"Palm DOC has at least 2 records!" );
67 m_result = PalmDoc::InvalidFormat;
73 TQByteArray header( *records.at( 0 ) );
76 int format = (header[0]<<8) + header[1];
77 tqDebug(
"DOC format: %d (%s)", format,
78 (format==1) ?
"Plain" : (format==2) ?
"Compressed" :
"Unknown" );
81 if( ( format != 1 ) && ( format != 2 ) )
83 tqDebug(
"Unknown format of document!" );
84 m_result = PalmDoc::InvalidFormat;
89 setText( TQString() );
94 for(
unsigned r = 1; r < records.count(); r++ )
96 TQByteArray *p = records.at( r );
98 rec.resize( rec.size() + p->size() );
99 for(
unsigned s=0; s<p->size(); s++ )
100 rec[i++] = p->at( s );
105 setText( uncompress( rec ) );
109 setText( TQString::fromLatin1( rec.data(),rec.count() ) );
116bool PalmDoc::save(
const char* filename )
120 setCreator(
"REAd" );
123 setModificationDate( TQDateTime::currentDateTime() );
126 unsigned recsize = 4096;
129 TQByteArray data = compress( text() );
133 for(
unsigned i=0; i<data.count(); )
135 TQByteArray* ptr =
new TQByteArray;
136 unsigned rs = data.count() - i;
137 if( rs > recsize ) rs = recsize;
139 for(
unsigned m=0; m<rs; m++ )
140 (*ptr)[m] = data[i++];
141 records.append( ptr );
145 TQByteArray header( 16 );
146 int docsize = m_text.length();
147 header[0] = 0; header[1] = 2;
148 header[2] = header[3] = 0;
149 header[4] = (docsize >> 24) & 255;
150 header[5] = (docsize >> 16) & 255;
151 header[6] = (docsize >> 8) & 255;
152 header[7] = docsize & 255;
153 header[8] = records.count()>> 8;
154 header[9] = records.count() & 255;
155 header[10] = recsize >>8;
156 header[11] = recsize & 255;
157 header[12] = header[13] = 0;
158 header[14] = header[15] = 0;
161 records.prepend(
new TQByteArray( header ) );
164 bool ok = PalmDB::save( filename );
167 m_result = WriteError;
177TQByteArray PalmDoc::compress(
const TQString& text )
180 unsigned textlen = text.length();
181 const char *ctext = text.latin1();
186 result.resize( textlen );
188 for( i=j=0; i<textlen; )
191 int start = (i < horizon) ? 0 : i-horizon;
193 int match_pos=0, match_len=0;
196 for(
int back = i-1; (!match) && (back > start); back-- )
197 if( ctext[i] == ctext[back] )
198 if( ctext[i+1] == ctext[back+1] )
199 if( ctext[i+2] == ctext[back+2] )
206 if( ctext[i+3] == ctext[back+3] )
210 if( ctext[i+4] == ctext[back+4] )
220 unsigned char p = 0x80 | ((match_pos >> 5)&0x3f);
221 unsigned char q = ((match_pos & 0x1f) << 3) | (match_len-3);
228 char ch = ctext[i++] & 0x7f;
229 bool space_pack =
false;
233 if( ctext[i] >= 0x40 )
236 if( !space_pack ) result[j++] = ch;
237 else result[j++] = ctext[i++] | 0x80;
247#define INRANGE(v,p,q) ((v)>=(p))&&((v)<=(q))
250TQString PalmDoc::uncompress( TQByteArray rec )
254 for(
unsigned i = 0; i < rec.size(); i++ )
256 unsigned char c = rec[i];
262 for(
unsigned char v = rec[i]; c>0; c-- )
266 else if( INRANGE(c,0x09,0x7F) )
269 else if( INRANGE(c,0xC0,0xFF) )
270 result.append( 32 ).append( c^ 0x80 );
272 else if( INRANGE(c,0x80,0xBF) )
274 unsigned char d = rec[++i];
275 int back = (((c<<8)+d) & 0x3fff) >> 3;
276 int count = (d & 7) + 3;
277 if( result.length()-back >= 0 )
278 for(; count>0; count-- )
279 result.append( result[result.length()-back] );