00001 #include <stdio.h>
00002 #include <string.h>
00003 #include <qmessagebox.h>
00004 #include <qpixmap.h>
00005 #ifdef USEQPE
00006 #include <qpe/qcopenvelope_qws.h>
00007 #endif
00008 #ifdef LOCALPICTURES
00009 #include <qscrollview.h>
00010 #endif
00011 #ifdef USEQPE
00012 #include <qpe/global.h>
00013 #endif
00014 #include <qclipboard.h>
00015 #ifndef USEQPE
00016 #include <qapplication.h>
00017 #else
00018 #include <qpe/qpeapplication.h>
00019 #endif
00020 #include <qimage.h>
00021
00022 #include "plucker_base.h"
00023 #include "Aportis.h"
00024 #include "hrule.h"
00025 #include "decompress.h"
00026
00027 const UInt8 CPlucker_base::continuation_bit = 1;
00028
00029 CPlucker_base::CPlucker_base() :
00030 #ifdef LOCALPICTURES
00031 m_viewer(NULL),
00032 m_picture(NULL),
00033 #endif
00034 expandedtextbuffer(NULL),
00035 compressedtextbuffer(NULL),
00036 bufferrec(-1),
00037 m_offset(0)
00038
00039 { }
00040
00041
00042 void CPlucker_base::Expand(UInt32 reclen, UInt8 type, UInt8* buffer, UInt32 buffersize)
00043 {
00044 unsuspend();
00045 if ((type%2 == 0) && (type != 14))
00046 {
00047 fread(buffer, reclen, sizeof(char), fin);
00048 }
00049 else
00050 {
00051 UInt8* readbuffer = NULL;
00052 if (reclen > compressedbuffersize)
00053 {
00054 readbuffer = new UInt8[reclen];
00055 }
00056 else
00057 {
00058 readbuffer = compressedtextbuffer;
00059 }
00060 if (readbuffer != NULL)
00061 {
00062 fread(readbuffer, reclen, sizeof(char), fin);
00063 (*m_decompress)(readbuffer, reclen, buffer, buffersize);
00064 if (reclen > compressedbuffersize)
00065 {
00066 delete [] readbuffer;
00067 }
00068 }
00069 }
00070 }
00071
00072 void CPlucker_base::sizes(unsigned long& _file, unsigned long& _text)
00073 {
00074 _file = file_length;
00075 if (textlength == 0)
00076 {
00077 for (int recptr = 1; recptr < ntohs(head.recordList.numRecords); recptr++)
00078 {
00079 gotorecordnumber(recptr);
00080 UInt16 thishdr_uid, thishdr_nParagraphs;
00081 UInt32 thishdr_size;
00082 UInt8 thishdr_type, thishdr_reserved;
00083 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00084 if (thishdr_type < 2) textlength += thishdr_size;
00085 }
00086 }
00087 _text = textlength;
00088
00089 }
00090
00091 char* CPlucker_base::geturl(UInt16 tgt)
00092 {
00093 char * pRet = NULL;
00094 gotorecordnumber(0);
00095 fread(&hdr0, 1, 6, fin);
00096 unsigned int nrecs = ntohs(hdr0.nRecords);
00097
00098 UInt16 urlid = 0;
00099 bool urlsfound = false;
00100 char* urls = NULL;
00101 size_t urlsize = 0;
00102 for (unsigned int i = 0; i < nrecs; i++)
00103 {
00104 UInt16 id, name;
00105 fread(&name, 1, sizeof(name), fin);
00106 fread(&id, 1, sizeof(id), fin);
00107
00108 if (ntohs(name) == 2)
00109 {
00110 urlsfound = true;
00111 urlid = id;
00112
00113 }
00114
00115 }
00116 if (urlsfound)
00117 {
00118 unsigned short recptr = finduid(ntohs(urlid));
00119 if (recptr != 0)
00120 {
00121 gotorecordnumber(recptr);
00122 UInt16 thishdr_uid, thishdr_nParagraphs;
00123 UInt32 thishdr_size;
00124 UInt8 thishdr_type, thishdr_reserved;
00125 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00126 UInt16 urlctr = 0;
00127 while (1)
00128 {
00129 UInt16 tctr;
00130 fread(&tctr, 1, sizeof(tctr), fin);
00131 fread(&urlid, 1, sizeof(urlid), fin);
00132 tctr = ntohs(tctr);
00133
00134 if (tctr >= tgt)
00135 {
00136 break;
00137 }
00138 urlctr = tctr;
00139 }
00140
00141 recptr = finduid(ntohs(urlid));
00142 if (recptr != 0)
00143 {
00144 UInt32 reclen = recordlength(recptr) - HeaderSize();
00145 gotorecordnumber(recptr);
00146 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00147
00148 urlsize = thishdr_size;
00149 urls = new char[urlsize];
00150 Expand(reclen, thishdr_type, (UInt8*)urls, urlsize);
00151 char* ptr = urls;
00152 int rn = urlctr+1;
00153 while (ptr - urls < urlsize)
00154 {
00155 if (rn == tgt)
00156 {
00157
00158 int len = strlen(ptr)+1;
00159 pRet = new char[len];
00160 memcpy(pRet, ptr, len);
00161 break;
00162 }
00163 ptr += strlen(ptr)+1;
00164 rn++;
00165 }
00166 delete [] urls;
00167 }
00168 }
00169 }
00170 else
00171 {
00172 pRet = NULL;
00173 }
00174 return pRet;
00175 }
00176
00177 CPlucker_base::~CPlucker_base()
00178 {
00179 if (expandedtextbuffer != NULL) delete [] expandedtextbuffer;
00180 if (compressedtextbuffer != NULL) delete [] compressedtextbuffer;
00181 #ifdef LOCALPICTURES
00182 if (m_viewer != NULL) delete m_viewer;
00183 #endif
00184 }
00185
00186 int CPlucker_base::getch() { return getch(false); }
00187
00188 void CPlucker_base::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00189 {
00190 pos = locate();
00191 ch = getch(false);
00192 sty = mystyle;
00193 }
00194
00195 unsigned int CPlucker_base::locate()
00196 {
00197 return currentpos;
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 }
00215
00216 void CPlucker_base::locate(unsigned int n)
00217 {
00218
00219
00220 if (n >= currentpos-bufferpos && n < currentpos - bufferpos + buffercontent)
00221 {
00222 currentpos -= bufferpos;
00223 expand(bufferrec);
00224 while (currentpos < n && bufferpos < buffercontent) getch_base(true);
00225 return;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 UInt16 thisrec = 0;
00289 unsigned long locpos = 0;
00290 unsigned long bs = 0;
00291 unsigned int np1 = n+1;
00292 UInt16 thishdr_uid, thishdr_nParagraphs;
00293 UInt32 thishdr_size;
00294 UInt8 thishdr_type, thishdr_reserved;
00295 do
00296 {
00297 thisrec++;
00298 locpos += bs;
00299 gotorecordnumber(thisrec);
00300 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00301 if (thishdr_type < 2)
00302 {
00303 bs = thishdr_size;
00304 }
00305 else
00306 {
00307 bs = 0;
00308 }
00309 } while (locpos + bs < np1);
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 currentpos = locpos;
00329 expand(thisrec);
00330 while (currentpos < n && bufferpos < buffercontent) getch_base(true);
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 }
00350
00351 bool CPlucker_base::expand(int thisrec)
00352 {
00353 mystyle.unset();
00354 if (bufferrec != thisrec)
00355 {
00356 size_t reclen = recordlength(thisrec);
00357 gotorecordnumber(thisrec);
00358 UInt16 thishdr_uid, thishdr_nParagraphs;
00359 UInt32 thishdr_size;
00360 UInt8 thishdr_type, thishdr_reserved;
00361 while (1)
00362 {
00363 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00364
00365 if (thishdr_type < 2) break;
00366
00367 if (++thisrec >= ntohs(head.recordList.numRecords) - 1) return false;
00368 reclen = recordlength(thisrec);
00369 gotorecordnumber(thisrec);
00370 }
00371 m_nParas = thishdr_nParagraphs;
00372 m_bufferisreserved = (thishdr_reserved != 0);
00373
00374 uid = thishdr_uid;
00375
00376
00377 for (int i = 0; i < m_nParas; i++)
00378 {
00379 UInt16 ubytes, attrs;
00380 fread(&ubytes, 1, sizeof(ubytes), fin);
00381 fread(&attrs, 1, sizeof(attrs), fin);
00382 m_ParaOffsets[i] = ntohs(ubytes);
00383 m_ParaAttrs[i] = ntohs(attrs);
00384
00385 }
00386
00387 reclen -= HeaderSize()+4*m_nParas;
00388
00389 buffercontent = thishdr_size;
00390
00391 if (thishdr_size > buffersize)
00392 {
00393 delete [] expandedtextbuffer;
00394 buffersize = thishdr_size;
00395 expandedtextbuffer = new UInt8[buffersize];
00396 }
00397 Expand(reclen, thishdr_type, expandedtextbuffer, buffercontent);
00398 bufferrec = thisrec;
00399 }
00400
00401
00402 if (m_nParas > 0)
00403 {
00404 m_nextPara = m_ParaOffsets[0];
00405
00406 m_nextParaIndex = 0;
00407 }
00408 else
00409 {
00410 m_nextPara = -1;
00411 }
00412 bufferpos = 0;
00413
00414 return true;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 size_t CPlucker_base::UnDoc(UInt8* compressedbuffer, size_t reclen, UInt8* tgtbuffer, size_t bsize)
00455 {
00456
00457 UInt16 docSize;
00458 UInt16 i;
00459 UInt16 j;
00460 UInt16 k;
00461
00462 UInt8 *inBuf = compressedbuffer;
00463 UInt8 *outBuf = tgtbuffer;
00464
00465
00466 docSize = reclen;
00467
00468 j = 0;
00469 k = 0;
00470 while ( j < docSize ) {
00471 i = 0;
00472 while ( i < bsize && j < docSize ) {
00473 UInt16 c;
00474
00475 c = (UInt16) inBuf[ j++ ];
00476 if ( 0 < c && c < 9 ) {
00477 while ( 0 < c-- )
00478 outBuf[ i++ ] = inBuf[ j++ ];
00479 }
00480 else if ( c < 0x80 )
00481 outBuf[ i++ ] = c;
00482 else if ( 0xc0 <= c ) {
00483 outBuf[ i++ ] = ' ';
00484 outBuf[ i++ ] = c ^ 0x80;
00485 }
00486 else {
00487 Int16 m;
00488 Int16 n;
00489
00490 c <<= 8;
00491 c += inBuf[ j++ ];
00492
00493 m = ( c & 0x3fff ) >> COUNT_BITS;
00494 n = c & ( ( 1 << COUNT_BITS ) - 1 );
00495 n += 2;
00496
00497 do {
00498 outBuf[ i ] = outBuf[ i - m ];
00499 i++;
00500 } while ( 0 < n-- );
00501 }
00502 }
00503 k += bsize;
00504 }
00505 return i;
00506 }
00507
00508 void CPlucker_base::home()
00509 {
00510 currentpos = 0;
00511 expand(1);
00512 }
00513
00514 CList<Bkmk>* CPlucker_base::getbkmklist()
00515 {
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 return NULL;
00536 }
00537
00538 #include <qnamespace.h>
00539
00540 QImage* CPlucker_base::expandimg(UInt16 tgt, bool border)
00541 {
00542 QImage* qimage = getimg(tgt);
00543 QImage* ret;
00544 if (qimage == NULL) return NULL;
00545 if (border)
00546 {
00547 QPixmap* image = new QPixmap(0,0);
00548 image->convertFromImage(*qimage);
00549 delete qimage;
00550 QPixmap* pret = new QPixmap(image->width()+4, image->height()+4);
00551 pret->fill(Qt::red);
00552 bitBlt(pret, 2, 2, image, 0, 0, -1, -1);
00553 delete image;
00554 ret = new QImage(pret->convertToImage());
00555 }
00556 else
00557 {
00558 ret = qimage;
00559 }
00560 return ret;
00561 }
00562
00563 #ifdef _BUFFERPICS
00564 #include <qmap.h>
00565 #endif
00566
00567 QImage* CPlucker_base::getPicture(unsigned long tgt)
00568 {
00569 #ifdef _BUFFERPICS
00570 static QMap<unsigned long, QPixmap> pix;
00571 QMap<unsigned long, QPixmap>::Iterator t = pix.find(tgt);
00572 if (t == pix.end())
00573 {
00574 pix[tgt] = *expandimg(tgt);
00575 return &pix[tgt];
00576 }
00577 else
00578 return &(t.data());
00579 #else
00580 return expandimg(tgt >> 16);
00581 #endif
00582 }
00583
00584 #ifdef LOCALPICTURES
00585 #include <unistd.h>
00586 #include <qpe/global.h>
00587 void CPlucker_base::showimg(UInt16 tgt)
00588 {
00589
00590 QPixmap* qimage = expandimg(tgt);
00591 m_picture->setFixedSize(qimage->size());
00592 m_picture->setBackgroundPixmap(*qimage);
00593 delete qimage;
00594 m_viewer->show();
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 }
00619
00620 #endif
00621
00622 unsigned short CPlucker_base::finduid(unsigned short urlid)
00623 {
00624
00625 unsigned short jmin = 1, jmax = ntohs(head.recordList.numRecords);
00626 unsigned short jmid = (jmin+jmax) >> 1;
00627 while (jmax - jmin > 1)
00628 {
00629 gotorecordnumber(jmid);
00630 UInt16 thishdr_uid, thishdr_nParagraphs;
00631 UInt32 thishdr_size;
00632 UInt8 thishdr_type, thishdr_reserved;
00633 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00634 unsigned short luid = thishdr_uid;
00635
00636 if (luid == urlid)
00637 {
00638 return jmid;
00639 }
00640 if (luid < urlid)
00641 {
00642 jmin = jmid;
00643 }
00644 else
00645 {
00646 jmax = jmid;
00647 }
00648 jmid = (jmin+jmax) >> 1;
00649 }
00650 gotorecordnumber(jmin);
00651 UInt16 thishdr_uid, thishdr_nParagraphs;
00652 UInt32 thishdr_size;
00653 UInt8 thishdr_type, thishdr_reserved;
00654 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00655 unsigned short luid = thishdr_uid;
00656
00657 if (luid == urlid)
00658 {
00659 return jmin;
00660 }
00661 gotorecordnumber(jmax);
00662 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00663 luid = thishdr_uid;
00664
00665 if (luid == urlid)
00666 {
00667 return jmax;
00668 }
00669
00670 return 0;
00671 }
00672
00673 #include <qnamespace.h>
00674
00675 void CPlucker_base::setSaveData(unsigned char*& data, unsigned short& len, unsigned char* src, unsigned short srclen)
00676 {
00677 unsigned short sz = 0;
00678 for (CList<unsigned long>::iterator it = visited.begin(); it != visited.end(); it++)
00679 {
00680 sz++;
00681 }
00682 size_t newlen = srclen+sizeof(sz)+sz*sizeof(unsigned long);
00683 unsigned char* newdata = new unsigned char[newlen];
00684 unsigned char* pdata = newdata;
00685 memcpy(newdata, src, srclen);
00686 newdata += srclen;
00687 memcpy(newdata, &sz, sizeof(sz));
00688 newdata += sizeof(sz);
00689 #ifdef _WINDOWS
00690 for (it = visited.begin(); it != visited.end(); it++)
00691 #else
00692 for (CList<unsigned long>::iterator it = visited.begin(); it != visited.end(); it++)
00693 #endif
00694 {
00695 unsigned long t = *it;
00696
00697 memcpy(newdata, &t, sizeof(t));
00698 newdata += sizeof(t);
00699 }
00700 m_nav.setSaveData(data, len, pdata, newlen);
00701 delete [] pdata;
00702 }
00703
00704 void CPlucker_base::putSaveData(unsigned char*& src, unsigned short& srclen)
00705 {
00706 unsigned short sz;
00707 if (srclen >= sizeof(sz))
00708 {
00709 memcpy(&sz, src, sizeof(sz));
00710 src += sizeof(sz);
00711 srclen -= sizeof(sz);
00712 }
00713 for (int i = 0; i < sz; i++)
00714 {
00715 unsigned long t;
00716 if (srclen >= sizeof(t))
00717 {
00718 memcpy(&t, src, sizeof(t));
00719
00720 visited.push_front(t);
00721 src += sizeof(t);
00722 srclen -= sizeof(t);
00723 }
00724 else
00725 {
00726 QMessageBox::warning(NULL, PROGNAME, "File data mismatch\nMight fix itself");
00727 break;
00728 }
00729 }
00730 m_nav.putSaveData(src, srclen);
00731 }
00732
00733 int CPlucker_base::OpenFile(const char *src)
00734 {
00735 qDebug("plucker openfile:%s", src);
00736 m_lastBreak = 0;
00737 if (!Cpdb::openpdbfile(src))
00738 {
00739 return -1;
00740 }
00741
00742 if (!CorrectDecoder()) return -1;
00743
00744 gotorecordnumber(0);
00745 fread(&hdr0, 1, 6, fin);
00746 qDebug("Compression type:%u", ntohs(hdr0.version));
00747
00748
00749 switch (ntohs(hdr0.version))
00750 {
00751 case 2:
00752 m_decompress = UnZip;
00753 break;
00754 case 1:
00755 m_decompress = UnDoc;
00756 break;
00757 #ifdef USENEF
00758 case 3:
00759 m_decompress = getdecompressor("PluckerDecompress3");
00760 break;
00761 case 4:
00762 m_decompress = getdecompressor("PluckerDecompress4");
00763 break;
00764 #endif
00765 default:
00766 m_decompress = NULL;
00767 }
00768 if (m_decompress == NULL) return -1;
00769
00770 setbuffersize();
00771 compressedtextbuffer = new UInt8[compressedbuffersize];
00772 expandedtextbuffer = new UInt8[buffersize];
00773
00774 unsigned int nrecs = ntohs(hdr0.nRecords);
00775 qDebug("Version %u, no. reserved recs %u", ntohs(hdr0.version), nrecs);
00776 textlength = ntohl(head.sortInfoID);
00777 qDebug("Textlength at startup:%u", textlength);
00778 UInt16 homerecid = 1;
00779 for (unsigned int i = 0; i < nrecs; i++)
00780 {
00781 UInt16 id, name;
00782 fread(&name, 1, sizeof(name), fin);
00783 fread(&id, 1, sizeof(id), fin);
00784
00785 if (ntohs(name) == 0) homerecid = ntohs(id);
00786 }
00787
00788 textlength = 0;
00789 for (int recptr = 1; recptr < ntohs(head.recordList.numRecords); recptr++)
00790 {
00791 gotorecordnumber(recptr);
00792 UInt16 thishdr_uid, thishdr_nParagraphs;
00793 UInt32 thishdr_size;
00794 UInt8 thishdr_type, thishdr_reserved;
00795 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00796 if (thishdr_uid == homerecid)
00797 {
00798 m_homepos = textlength;
00799 break;
00800 }
00801 if (thishdr_type < 2) textlength += thishdr_size;
00802 }
00803 qDebug("Found home");
00804 textlength = 0;
00805 home();
00806 qDebug("Gone home");
00807 #ifdef LOCALPICTURES
00808 if (m_viewer == NULL)
00809 {
00810 m_viewer = new QScrollView(NULL);
00811 m_picture = new QWidget(m_viewer->viewport());
00812 m_viewer->addChild(m_picture);
00813 }
00814 #endif
00815 return 0;
00816
00817 }
00818
00819 QImage* CPlucker_base::getimg(UInt16 tgt)
00820 {
00821 size_t reclen;
00822 UInt16 thisrec = finduid(tgt);
00823 qDebug("getimg:Found %u from uid:%u", thisrec, tgt);
00824 reclen = recordlength(thisrec);
00825 gotorecordnumber(thisrec);
00826 UInt16 thishdr_uid, thishdr_nParagraphs;
00827 UInt32 thishdr_size;
00828 UInt8 thishdr_type, thishdr_reserved;
00829 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00830 if (thishdr_type == 15)
00831 {
00832 char *buffer = new char[thishdr_size];
00833 fread(buffer, thishdr_size, sizeof(char), fin);
00834 unsigned short tmp;
00835 memcpy(&tmp, buffer, sizeof(tmp));
00836 unsigned short cols = ntohs(tmp);
00837 memcpy(&tmp, buffer+sizeof(tmp), sizeof(tmp));
00838 unsigned short rows = ntohs(tmp);
00839 qDebug("Found a picture of type:%u [%u,%u]", thishdr_type, rows, cols);
00840 QImage*** images;
00841 images = new QImage**[rows];
00842 #ifdef _WINDOWS
00843 int i;
00844 for (i = 0; i < rows; i++)
00845 #else
00846 for (int i = 0; i < rows; i++)
00847 #endif
00848 {
00849 images[i] = new QImage*[cols];
00850 }
00851 int height = 0;
00852 int width = 0;
00853 #ifdef _WINDOWS
00854 for (i = 0; i < rows; i++)
00855 #else
00856 for (int i = 0; i < rows; i++)
00857 #endif
00858 {
00859 width = 0;
00860 for (int j = 0; j < cols; j++)
00861 {
00862 memcpy(&tmp, buffer+(i*cols+j+2)*sizeof(tmp), sizeof(tmp));
00863 unsigned short uid = ntohs(tmp);
00864 images[i][j] = getimg(uid);
00865 width += images[i][j]->width();
00866 }
00867 height += images[i][0]->height();
00868 }
00869 delete [] buffer;
00870 QPixmap pm(width, height);
00871 int hoffset = 0;
00872 #ifdef _WINDOWS
00873 for (i = 0; i < rows; i++)
00874 #else
00875 for (int i = 0; i < rows; i++)
00876 #endif
00877 {
00878 int woffset = 0;
00879 int delht = images[i][0]->height();
00880 for (int j = 0; j < cols; j++)
00881 {
00882 QPixmap pm2;
00883 pm2.convertFromImage(*(images[i][j]));
00884 delete images[i][j];
00885 bitBlt(&pm, woffset, hoffset, &pm2, 0, 0, pm2.width(), pm2.height());
00886 woffset += pm2.width();
00887 }
00888 hoffset += delht;
00889 }
00890 #ifdef _WINDOWS
00891 for (i = 0; i < rows; i++)
00892 #else
00893 for (int i = 0; i < rows; i++)
00894 #endif
00895 {
00896 delete [] images[i];
00897 }
00898 delete [] images;
00899 return new QImage(pm.convertToImage());
00900 }
00901 else
00902 {
00903 qDebug("Found a picture of type:%u", thishdr_type);
00904 reclen -= HeaderSize();
00905
00906 UInt32 imgsize = thishdr_size;
00907 UInt8* imgbuffer = new UInt8[imgsize];
00908
00909 Expand(reclen, thishdr_type, imgbuffer, imgsize);
00910
00911 return imagefromdata(imgbuffer, imgsize);
00912 }
00913 }
00914
00915 linkType CPlucker_base::hyperlink(unsigned int n, unsigned int offset, QString& wrd, QString&)
00916 {
00917 visited.push_front(n);
00918 UInt16 tuid = (n >> 16);
00919 n &= 0xffff;
00920 char *turl = geturl(tuid);
00921 if (turl != NULL)
00922 {
00923 qDebug("URL in PB:%s", turl);
00924 wrd = turl;
00925 delete [] turl;
00926 }
00927 else
00928 {
00929 wrd.truncate(0);
00930 }
00931 qDebug("Hyper: UID:%u, Para:%u, Offset:%u", tuid, n, offset);
00932 UInt16 thisrec = 1;
00933 currentpos = 0;
00934 gotorecordnumber(thisrec);
00935 UInt16 thishdr_uid, thishdr_nParagraphs;
00936 UInt32 thishdr_size;
00937 UInt8 thishdr_type, thishdr_reserved;
00938 while (1)
00939 {
00940 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
00941 if (tuid == thishdr_uid) break;
00942 if (thishdr_type < 2) currentpos += thishdr_size;
00943
00944 thisrec++;
00945 if (thisrec >= ntohs(head.recordList.numRecords))
00946 {
00947 if (wrd.isEmpty())
00948 {
00949 QMessageBox::information(NULL,
00950 QString(PROGNAME),
00951 QString("Couldn't find link")
00952 );
00953 }
00954 else
00955 {
00956 #ifdef USEQPE
00957 if (wrd.length() > 10)
00958 {
00959 Global::statusMessage(wrd.left(8) + "..");
00960 }
00961 else
00962 {
00963 Global::statusMessage(wrd);
00964 }
00965 #else
00966 #endif
00967
00968
00969 }
00970 return eNone;
00971 }
00972 gotorecordnumber(thisrec);
00973 }
00974 if (thishdr_type > 1)
00975 {
00976 if (thishdr_type == 4)
00977 {
00978 QMessageBox::information(NULL,
00979 QString(PROGNAME),
00980 QString("Mailto links\nnot yet supported (2)"));
00981 }
00982 else
00983 {
00984 if (thishdr_type > 3 && thishdr_type != 15)
00985 {
00986 QMessageBox::information(NULL,
00987 QString(PROGNAME),
00988 QString("External links\nnot yet supported (2)")
00989 );
00990 return eNone;
00991 }
00992 else
00993 {
00994 #ifdef LOCALPICTURES
00995 showimg(tuid);
00996 #else
00997 return ePicture;
00998 #endif
00999 }
01000 }
01001 return eNone;
01002 }
01003
01004
01005
01006
01007
01008
01009
01010 else
01011 {
01012 expand(thisrec);
01013 unsigned int paraoffset = offset;
01014
01015 if (n != 0)
01016 {
01017 if (n >= m_nParas)
01018 {
01019 QMessageBox::information(NULL,
01020 QString(PROGNAME),
01021 QString("Error in link\nPara # too big")
01022 );
01023 return eNone;
01024 }
01025 unsigned int noff = 0;
01026 for (unsigned int i = 0; i < n; i++) noff += m_ParaOffsets[i];
01027
01028 paraoffset += noff;
01029 }
01030 if (paraoffset > thishdr_size)
01031 {
01032 QMessageBox::information(NULL,
01033 QString(PROGNAME),
01034 QString("Error in link\nOffset too big")
01035 );
01036 return eNone;
01037 }
01038 while (bufferpos < paraoffset && bufferpos < buffercontent) getch_base(true);
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058 }
01059 return eLink;
01060 }
01061 QString CPlucker_base::getTableAsHtml(unsigned long tgt)
01062 {
01063 qDebug("CPlucker_base::getTableAsHtml:%u", tgt);
01064 size_t reclen;
01065 UInt16 thisrec = finduid(tgt);
01066 qDebug("getimg:Found %u from uid:%u", thisrec, tgt);
01067 reclen = recordlength(thisrec);
01068 gotorecordnumber(thisrec);
01069 UInt16 thishdr_uid, thishdr_nParagraphs;
01070 UInt32 thishdr_size;
01071 UInt8 thishdr_type, thishdr_reserved;
01072 GetHeader(thishdr_uid, thishdr_nParagraphs, thishdr_size, thishdr_type, thishdr_reserved);
01073 qDebug("Found a table of type:%u", thishdr_type);
01074 reclen -= HeaderSize();
01075 UInt32 imgsize = thishdr_size;
01076 UInt8* imgbuffer = new UInt8[imgsize];
01077 Expand(reclen, thishdr_type, imgbuffer, imgsize);
01078
01079 QString ret;
01080
01081 UInt16 size, columns, rows;
01082 UInt8 depth, border;
01083 UInt32 borderColour, linkColour;
01084 UInt8* dp(imgbuffer);
01085
01086 memcpy(&size, dp, sizeof(size));
01087 size = ntohs(size);
01088 dp += sizeof(size);
01089 memcpy(&columns, dp, sizeof(columns));
01090 columns = ntohs(columns);
01091 dp += sizeof(columns);
01092 memcpy(&rows, dp, sizeof(rows));
01093 rows = ntohs(rows);
01094 dp += sizeof(rows);
01095 qDebug("Rows:%u Cols:%u", rows, columns);
01096
01097 memcpy(&depth, dp, sizeof(depth));
01098 dp += sizeof(depth);
01099 memcpy(&border, dp, sizeof(border));
01100 dp += sizeof(border);
01101
01102 qDebug("Depth:%u, Border:%u", depth, border);
01103
01104 memcpy(&borderColour, dp, sizeof(borderColour));
01105 dp += sizeof(borderColour);
01106 memcpy(&linkColour, dp, sizeof(linkColour));
01107 dp += sizeof(linkColour);
01108
01109 qDebug("Colours: border:%x, link:%x", borderColour, linkColour);
01110
01111 if (border)
01112 {
01113 ret = "<table border>";
01114 }
01115 else
01116 {
01117 ret = "<table>";
01118 }
01119 bool firstrow = true;
01120 bool firstcol = true;
01121 while (dp < imgbuffer+imgsize)
01122 {
01123 UInt8 ch = *dp++;
01124 if (ch == 0x00)
01125 {
01126 ch = *dp++;
01127 if (ch == 0x90)
01128 {
01129 if (firstrow)
01130 {
01131 ret += "<tr>";
01132 firstrow = false;
01133 firstcol = true;
01134 }
01135 else
01136 {
01137 ret += "</tr><tr>";
01138 }
01139 }
01140 else if (ch == 0x97)
01141 {
01142 if (firstcol)
01143 {
01144 ret += "<td";
01145 firstcol = false;
01146 }
01147 else
01148 {
01149 ret += "</td><td";
01150 }
01151 UInt8 align;
01152 UInt16 imgid;
01153 UInt8 cols, rows;
01154 UInt16 len;
01155 memcpy(&align, dp, sizeof(align));
01156 dp += sizeof(align);
01157 memcpy(&imgid, dp, sizeof(imgid));
01158 dp += sizeof(imgid);
01159 imgid = ntohs(imgid);
01160 memcpy(&cols, dp, sizeof(cols));
01161 dp += sizeof(cols);
01162 memcpy(&rows, dp, sizeof(rows));
01163 dp += sizeof(rows);
01164 memcpy(&len, dp, sizeof(len));
01165 dp += sizeof(len);
01166 len = ntohs(len);
01167 switch (align)
01168 {
01169 case 1:
01170 ret += " align=right";
01171 break;
01172 case 2:
01173 ret += " align=center";
01174 break;
01175 case 3:
01176 ret += " align=justify";
01177 break;
01178 case 0:
01179 break;
01180 default:
01181 qDebug("Unknown table cell alignment:%u", align);
01182 }
01183 if (cols != 1)
01184 {
01185 QString num;
01186 num.setNum(cols);
01187 ret += " colspan=";
01188 ret += num;
01189 }
01190 if (rows != 1)
01191 {
01192 QString num;
01193 num.setNum(rows);
01194 ret += " rowspan=";
01195 ret += num;
01196 }
01197 ret += ">";
01198 }
01199 else
01200 {
01201 dp += (ch & 7);
01202 }
01203 }
01204 else
01205 {
01206 ret += QChar(ch);
01207 }
01208 }
01209
01210 ret += "</td></tr></table>";
01211 delete [] imgbuffer;
01212 return ret;
01213 }
01214
01215 tchar CPlucker_base::getch_base(bool fast)
01216 {
01217 mystyle.setTable(0xffffffff);
01218 int ch = bgetch();
01219 while (ch == 0)
01220 {
01221 ch = bgetch();
01222
01223 switch (ch)
01224 {
01225 case 0x38:
01226
01227 if (m_lastBreak == locate())
01228 {
01229 ch = bgetch();
01230 }
01231 else
01232 {
01233 ch = 10;
01234 }
01235 m_lastBreak = locate();
01236 break;
01237 case 0x0a:
01238 case 0x0c:
01239 {
01240 unsigned long ln = 0;
01241 int skip = ch & 7;
01242 for (int i = 0; i < 2; i++)
01243 {
01244 int ch = bgetch();
01245 ln = (ln << 8) + ch;
01246
01247 }
01248 if (skip == 2)
01249 {
01250 ln <<= 16;
01251 }
01252 else
01253 {
01254 for (int i = 0; i < 2; i++)
01255 {
01256 int ch = bgetch();
01257 ln = (ln << 8) + ch;
01258
01259 }
01260 }
01261
01262 mystyle.setLink(true);
01263 mystyle.setData(ln);
01264
01265 bool hasseen = false;
01266 for (CList<unsigned long>::iterator it = visited.begin(); it != visited.end(); it++)
01267 {
01268 if (*it == ln)
01269 {
01270 hasseen = true;
01271 break;
01272 }
01273 }
01274 if (hasseen)
01275 {
01276 mystyle.setStrikethru();
01277 }
01278 mystyle.setOffset(m_offset);
01279 m_offset = 0;
01280 ch = bgetch();
01281 }
01282 break;
01283 case 0x08:
01284 ch = bgetch();
01285
01286 mystyle.unsetUnderline();
01287 mystyle.unsetStrikethru();
01288 mystyle.setLink(false);
01289 mystyle.setData(0);
01290 break;
01291 case 0x40:
01292 mystyle.setItalic();
01293 ch = bgetch();
01294 break;
01295 case 0x48:
01296 mystyle.unsetItalic();
01297 ch = bgetch();
01298 break;
01299 case 0x11:
01300 {
01301 ch = bgetch();
01302
01303 mystyle.setVOffset(0);
01304 mystyle.unsetMono();
01305 mystyle.unsetBold();
01306 switch (ch)
01307 {
01308 case 0:
01309 mystyle.setFontSize(0);
01310 break;
01311 case 1:
01312 mystyle.setFontSize(3);
01313 mystyle.setBold();
01314 break;
01315 case 2:
01316 mystyle.setFontSize(2);
01317 mystyle.setBold();
01318 break;
01319 case 3:
01320 mystyle.setFontSize(1);
01321 mystyle.setBold();
01322 break;
01323 case 4:
01324 mystyle.setFontSize(0);
01325 mystyle.setBold();
01326 break;
01327 case 5:
01328 mystyle.setFontSize(0);
01329 mystyle.setBold();
01330 break;
01331 case 6:
01332 mystyle.setFontSize(0);
01333 mystyle.setBold();
01334 break;
01335 case 7:
01336 mystyle.setFontSize(0);
01337 mystyle.setBold();
01338 break;
01339 case 8:
01340
01341 mystyle.setFontSize(0);
01342 mystyle.setMono();
01343 break;
01344 case 9:
01345
01346 mystyle.setFontSize(-1);
01347 break;
01348 case 10:
01349 mystyle.setFontSize(-2);
01350 mystyle.setVOffset(1);
01351 break;
01352 case 11:
01353 mystyle.setFontSize(-2);
01354 mystyle.setVOffset(-1);
01355 break;
01356 default:
01357 qDebug("Unrecognised font");
01358 break;
01359 }
01360 ch = bgetch();
01361 }
01362 break;
01363 case 0x29:
01364 ch = bgetch();
01365 switch (ch)
01366 {
01367 case 0:
01368 mystyle.setLeftJustify();
01369
01370 break;
01371 case 1:
01372 mystyle.setRightJustify();
01373
01374 break;
01375 case 2:
01376 mystyle.setCentreJustify();
01377
01378 break;
01379 case 3:
01380 mystyle.setFullJustify();
01381
01382 break;
01383
01384 }
01385 ch = bgetch();
01386 break;
01387 case 0x53:
01388 {
01389 int r = bgetch();
01390 int g = bgetch();
01391 int b = bgetch();
01392 mystyle.setColour(r,g,b);
01393 ch = bgetch();
01394 }
01395 break;
01396 case 0x1a:
01397 case 0x5c:
01398 {
01399 bool hasalternate = (ch == 0x5c);
01400 UInt16 ir = bgetch();
01401 ir = (ir << 8) + bgetch();
01402 if (hasalternate)
01403 {
01404
01405 UInt16 ir2 = bgetch();
01406 ir2 = (ir2 << 8) + bgetch();
01407 if (!fast) mystyle.setPicture(true, expandimg(ir2, true), true, ir << 16);
01408 #ifdef LOCALPICTURES
01409 UInt32 ln = ir;
01410 ln <<= 16;
01411 mystyle.setLink(true);
01412 mystyle.setData(ln);
01413 #endif
01414 }
01415 else
01416 {
01417 if (!fast) mystyle.setPicture(true, expandimg(ir));
01418 }
01419
01420 ch = '#';
01421 }
01422
01423 break;
01424 case 0x33:
01425 {
01426 UInt8 h = bgetch();
01427 UInt8 wc = bgetch();
01428 UInt8 pc = bgetch();
01429 UInt16 w = wc;
01430
01431 if (w == 0)
01432 {
01433 w = (m_scrWidth*(unsigned long)pc)/100;
01434 }
01435 if (w == 0) w = m_scrWidth;
01436 mystyle.setPicture(false, hRule(w,h,mystyle.Red(),mystyle.Green(),mystyle.Blue()));
01437
01438 ch = '#';
01439 }
01440 break;
01441 case 0x60:
01442 mystyle.setUnderline();
01443 ch = bgetch();
01444 break;
01445 case 0x68:
01446 mystyle.unsetUnderline();
01447 ch = bgetch();
01448 break;
01449 case 0x22:
01450 ch = bgetch();
01451 mystyle.setLeftMargin(ch);
01452
01453 ch = bgetch();
01454 mystyle.setRightMargin(ch);
01455
01456 ch = bgetch();
01457 break;
01458 case 0x70:
01459 mystyle.setStrikethru();
01460 ch = bgetch();
01461 break;
01462 case 0x78:
01463 mystyle.unsetStrikethru();
01464 ch = bgetch();
01465 break;
01466 case 0x83:
01467 {
01468 int tlen = bgetch();
01469 ch = bgetch();
01470 ch <<= 8;
01471 ch |= (tchar)bgetch();
01472 for (int i = 0; i < tlen; i++) bgetch();
01473
01474 }
01475 break;
01476 case 0x9a:
01477 {
01478 m_offset = 255*bgetch();
01479 m_offset += bgetch();
01480 qDebug("Found offset:%u", m_offset);
01481 ch = bgetch();
01482 }
01483 break;
01484 case 0x92:
01485 {
01486 ch = bgetch();
01487 ch <<= 8;
01488 ch |= (tchar)bgetch();
01489 mystyle.setTable(ch);
01490 ch = 0x16e5;
01491 }
01492 break;
01493 case 0x85:
01494 default:
01495 qDebug("Function:%x NOT IMPLEMENTED", ch);
01496 {
01497 int skip = ch & 7;
01498 for (int i = 0; i < skip; i++)
01499 {
01500 ch = bgetch();
01501
01502 }
01503 ch = bgetch();
01504 }
01505 }
01506 }
01507
01508 if (m_lastIsBreak && !mystyle.isMono())
01509 {
01510 while (ch == ' ')
01511 {
01512 ch = getch(false);
01513 }
01514 }
01515
01516 m_lastIsBreak = (ch == 10);
01517
01518 return (ch == EOF) ? UEOF : ch;
01519 }
01520
01521 QString CPlucker_base::about()
01522 {
01523 QString abt = "Plucker base codec (c) Tim Wentford";
01524 if (m_decompress != UnDoc && m_decompress != UnZip)
01525 {
01526 abt += "\nSpecial decompression (c) Tim Wentford (ppmd by Dmitry Shkarin";
01527 }
01528 return abt;
01529 }