summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-reader/Reb.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-reader/Reb.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-reader/Reb.cpp789
1 files changed, 789 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/Reb.cpp b/noncore/apps/opie-reader/Reb.cpp
new file mode 100644
index 0000000..2e6c1fc
--- a/dev/null
+++ b/noncore/apps/opie-reader/Reb.cpp
@@ -0,0 +1,789 @@
1#include <stdio.h>
2#include <string.h>
3#include <qimage.h>
4#include "decompress.h"
5#include "Reb.h"
6#include "my_list.h"
7#include "Bkmks.h"
8#include "Model.h"
9/*
10#ifdef offsetof
11#define OffsetOf(type, field) ((int) offsetof(type, field))
12#else
13#define OffsetOf(type, field) ((int) ((char *) &((type *) 0)->field))
14#endif
15
16template<class T>
17UInt32 binarychop(T* data, UInt32 n, T val)
18{
19 UInt32 jl = 0,jh = n-1,jm = (jl+jh)/2;
20 while (jh > jl+1)
21 {
22 if (data[jm] > val)
23 {
24 jh = jm;
25 }
26 else
27 {
28 jl = jm;
29 }
30 jm = (jl+jh)/2;
31 }
32 return jl;
33}
34
35template<class T, class D>
36UInt32 binarychop(D* data, UInt32 n, T val, UInt32 offset)
37{
38 UInt32 jl = 0,jh = n-1,jm = (jl+jh)/2;
39 while (jh > jl+1)
40 {
41 T* d = reinterpret_cast<T*>(reinterpret_cast<char*>(data+jm)+offset);
42 if (*d > val)
43 {
44 jh = jm;
45 }
46 else
47 {
48 jl = jm;
49 }
50 jm = (jl+jh)/2;
51 }
52 return jl;
53}
54*/
55
56CReb::CReb()
57:
58 fin(NULL), m_indexpages(NULL), m_pagedetails(NULL),tagoffset(0),
59 tags(NULL), paras(NULL), noparas(0), joins(NULL), nojoins(0)
60{
61}
62
63CReb::~CReb()
64{
65 if (fin != NULL) fclose(fin);
66 if (m_indexpages != NULL) delete [] m_indexpages;
67 if (m_pagedetails != NULL) delete [] m_pagedetails;
68 if (tags != NULL) delete [] tags;
69 if (paras != NULL) delete [] paras;
70 if (joins != NULL) delete [] joins;
71}
72
73unsigned int CReb::locate()
74{
75 return m_pagedetails[currentpage.pageno()].pagestart+currentpage.offset();
76}
77
78void CReb::locate(unsigned int n)
79{
80 /*
81 UInt32 cp = nopages-1;
82 for (int i = 0; i < nopages; ++i)
83 {
84 if (m_pagedetails[i].pagestart > n)
85 {
86 cp = i-1;
87 break;
88 }
89 }
90 qDebug("Requesting %u from page %u [%u]", n, cp, n - m_pagedetails[cp].pagestart);
91 */
92 //UInt32 jl = binarychop<UInt32, Page_detail>(m_pagedetails, nopages, n, OffsetOf(Page_detail, pagestart));
93
94 UInt32 jl = 0,jh = nopages-1,jm = (jl+jh)/2;
95 while (jh > jl+1)
96 {
97 if (m_pagedetails[jm].pagestart > n)
98 {
99 jh = jm;
100 }
101 else
102 {
103 jl = jm;
104 }
105 jm = (jl+jh)/2;
106 }
107
108 unsuspend();
109 Page_detail rs = m_pagedetails[jl];
110 UInt32 val = n - rs.pagestart;
111 if (jl != currentpage.pageno()) readindex(jl);
112 currentpage.setoffset(page2pos(jl), jl, ((rs.flags & 8) != 0), rs.len, val);
113 if (noparas > 0)
114 {
115 //jl = binarychop<int, ParaRef>(paras, noparas, val, OffsetOf(ParaRef, pos));
116
117 UInt32 jl = 0,jh = noparas-1,jm = (jl+jh)/2;
118 while (jh > jl+1)
119 {
120 if (paras[jm].pos > val)
121 {
122 jh = jm;
123 }
124 else
125 {
126 jl = jm;
127 }
128 jm = (jl+jh)/2;
129 }
130
131 qDebug("TAGS:%s", (const char*)tags[paras[jl].tag]);
132 tagstring = tags[paras[jl].tag]+"<br>"; // Add br to set extra space to 0
133 tagoffset = 0;
134 }
135 unsigned long current = locate();
136 if (m_currentstart > current || current > m_currentend)
137 {
138 start2endSection();
139 }
140 if (current != n) qDebug("ERROR:Ended up at %u", current);
141}
142
143bool CReb::getFile(const QString& href, const QString& nm)
144{
145 qDebug("File:%s, Name:%s", (const char*)href, (const char*)nm);
146 QMap<QString, UInt32>::Iterator iter = m_index.find(href);
147 if (iter != m_index.end())
148 {
149 qDebug("REB:BEFORE:%u", locate());
150 startpage(iter.data());
151 qDebug("REB:AFTER:%u", locate());
152 return true;
153 }
154 else
155 {
156 return false;
157 }
158}
159
160QImage* CReb::getPicture(const QString& ref)
161{
162 QMap<QString, UInt32>::Iterator iter = m_index.find(ref);
163 if (iter != m_index.end())
164 {
165 unsuspend();
166 Page_detail rs = m_pagedetails[iter.data()];
167 char* imgbuffer = new char[rs.len];
168 fseek(fin, page2pos(iter.data()), SEEK_SET);
169 fread(imgbuffer, rs.len, 1, fin);
170 QByteArray arr;
171 arr.assign((const char*)imgbuffer, rs.len);
172 QImage* qimage = new QImage(arr);
173 return qimage;
174 }
175 else
176 {
177 return NULL;
178 }
179}
180
181CList<Bkmk>* CReb::getbkmklist() { return NULL; }
182
183void CReb::home()
184{
185 startpage(m_homepage);
186}
187
188int CReb::OpenFile(const char *src)
189{
190 m_binary = false;
191 if (fin != NULL) fclose(fin);
192 fin = fopen(src, "r");
193 if (fin == NULL)
194 {
195 return -1;
196 }
197 UInt32 type;
198 fseek(fin, 6, SEEK_SET);
199 fread(&type, 1, sizeof(type), fin);
200 qDebug("CREB:Okay %x", type);
201
202 if (type == 0x4f56554e || type == 0x574d4954 || type == 0x576d6954)
203 {
204 struct stat _stat;
205 stat(src, &_stat);
206 file_length = _stat.st_size;
207 fread(&m_blocksize, 1, sizeof(m_blocksize), fin);
208 if (type == 0x574d4954 || type == 0x576d6954)
209 {
210 if (type == 0x576d6954) m_binary = true;
211 qDebug("Blocksize(1) %x", m_blocksize);
212 unsigned char ct = (m_blocksize >> 24) & 0xff;
213 qDebug("Compress type:%x", ct);
214 switch (ct)
215 {
216 case 0:
217 m_decompress = UnZip;
218 break;
219 case 3:
220 m_decompress = getdecompressor("PluckerDecompress3");
221 break;
222 case 4:
223 m_decompress = getdecompressor("PluckerDecompress4");
224 break;
225 }
226 if (m_decompress == NULL) return -1;
227 m_blocksize = 1024*(m_blocksize & 0xffffff);
228 }
229 else
230 {
231 m_blocksize = 4096;
232 m_decompress = UnZip;
233 }
234 qDebug("Blocksize %u", m_blocksize);
235 currentpage.init(fin, m_blocksize, m_decompress);
236 qDebug("Its a REB!!!!");
237 fseek(fin, 0x18, SEEK_SET);
238 fread(&toc, 1, sizeof(toc), fin);
239 qDebug("Expect this to be 128 or 20:%x", toc);
240 fread(&type, 1, sizeof(type), fin);
241 qDebug("File length:%u", type);
242 fseek(fin, toc, SEEK_SET);
243 fread(&nopages, 1, sizeof(nopages), fin);
244 m_indexpages = new UInt32[nopages];
245 m_pagedetails = new Page_detail[nopages];
246 qDebug("There are %u pages", nopages);
247 UInt32 loc = 0;
248 UInt32 homeguess = nopages-1;
249 QString homeurl;
250 for (int i = 0; i < nopages; ++i)
251 {
252 char name[32];
253 UInt32 len, pos, flags;
254 fread(name, 1, 32, fin);
255 fread(&len, 1, 4, fin);
256 fread(&pos, 1, 4, fin);
257 fread(&flags, 1, 4, fin);
258 //qDebug("Page %u (%s) is %u bytes at %u (%u) of type %u", i, name, len, pos, loc, flags);
259 m_index[name] = i;
260 m_pagedetails[i] = Page_detail(loc, len, flags);
261
262 if (QString(name).find(".htm", 0, false) >= 0)
263 {
264 if (homeguess > i) homeguess = i;
265 if ((flags & 8) != 0)
266 {
267 UInt32 lastpos = ftell(fin);
268 loc += pagelength(i);
269 fseek(fin, lastpos, SEEK_SET);
270 }
271 else
272 {
273 loc += len;
274 }
275 }
276 if ((flags & 2) != 0)
277 {
278 UInt32 lastpos = ftell(fin);
279 RBPage* idx = new RBPage();
280 idx->init(fin, m_blocksize, m_decompress);
281 idx->startpage(page2pos(i), i, ((flags & 8) != 0), len);
282 int c = 0;
283 while (c != EOF)
284 {
285 QString s("");
286 while (1)
287 {
288 c = idx->getch(this);
289 if (c == 10 || c == EOF) break;
290 s += c;
291 }
292 if (s.left(5) == "BODY=")
293 {
294 homeurl = s.right(s.length()-5);
295 qDebug("Home:%s", (const char*)homeurl);
296 }
297 else
298 {
299 qDebug("Info:%s", (const char*)s);
300 }
301 }
302 delete idx;
303 fseek(fin, lastpos, SEEK_SET);
304 }
305 }
306 text_length = loc;
307 qDebug("Looking for homepage");
308 if (homeurl.isEmpty())
309 {
310 m_homepage = homeguess;
311 }
312 else
313 {
314 QMap<QString, UInt32>::Iterator iter = m_index.find(homeurl);
315 if (iter != m_index.end())
316 {
317 m_homepage = iter.data();
318 }
319 else
320 {
321 m_homepage = homeguess;
322 }
323 }
324 m_homepos = m_pagedetails[m_homepage].pagestart;
325 qDebug("Finding indices");
326 for (QMap<QString, UInt32>::Iterator iter = m_index.begin(); iter != m_index.end(); ++iter)
327 {
328 QString href = iter.key();
329 if (href.find(".htm", 0, false) >= 0)
330 {
331 QString hind = href.left(href.find(".htm", 0, false))+".hidx";
332 //qDebug("Index is %s", (const char*)hind);
333 QMap<QString, UInt32>::Iterator iter2 = m_index.find(hind);
334 if (iter2 != m_index.end())
335 {
336 m_indexpages[iter.data()] = iter2.data();
337 }
338 }
339 }
340 qDebug("Going home");
341 home();
342 return 0;
343 }
344 else
345 {
346 char * tmp = (char*)(&type);
347 for (int i = 0; i < 4; ++i) qDebug("%d:%c", i, tmp[i]);
348 return -1;
349 }
350}
351
352UInt32 CReb::page2pos(UInt32 page)
353{
354 fseek(fin, toc+40+44*page, SEEK_SET);
355 UInt32 pos;
356 fread(&pos, 1, 4, fin);
357 return pos;
358}
359
360UInt32 CReb::pagelength(UInt32 pagenum)
361{
362 fseek(fin, toc+40+44*pagenum, SEEK_SET);
363 UInt32 pos;
364 fread(&pos, 1, 4, fin);
365 fseek(fin, pos+4, SEEK_SET);
366 UInt32 len;
367 fread(&len, 1, sizeof(len), fin);
368 return len;
369}
370
371void CReb::readindex(UInt32 cp)
372{
373 if (joins != NULL)
374 {
375 delete [] joins;
376 joins = NULL;
377 }
378 if (tags != NULL)
379 {
380 delete [] tags;
381 tags = NULL;
382 }
383 if (paras != NULL)
384 {
385 delete [] paras;
386 paras = NULL;
387 }
388 noparas = 0;
389 nojoins = 0;
390 names.clear();
391
392 UInt32 rspage = m_indexpages[cp];
393 if (rspage != 0)
394 {
395 Page_detail rs = m_pagedetails[rspage];
396 int count = 0;
397 RBPage* idx = new RBPage();
398 idx->init(fin, m_blocksize, m_decompress);
399 idx->startpage(page2pos(rspage), rspage, ((rs.flags & 8) != 0), rs.len);
400 int c = 0;
401 int phase = 0;
402 int i;
403 if (m_binary)
404 {
405 count = idx->getuint(this);
406 qDebug("tag count:%d", count);
407 tags = new QString[count];
408 for (int i = 0; i < count; ++i)
409 {
410 QString s;
411 while (1)
412 {
413 c = idx->getch(this);
414 if (c == 0 || c == EOF) break;
415 s += c;
416 }
417 unsigned short val = idx->getuint(this);
418 if (val != 0xffff)
419 {
420 tags[i] = tags[val]+s;
421 }
422 else
423 {
424 tags[i] = s;
425 }
426 //qDebug("tags[%d](%d) = %s", i, val, (const char*)tags[i]);
427 }
428 noparas = idx->getint(this);
429 qDebug("Para count %d", noparas);
430 paras = new ParaRef[noparas];
431 for (int i = 0; i < noparas; ++i)
432 {
433 paras[i] = ParaRef(idx->getint(this), idx->getuint(this));
434 }
435 count = idx->getint(this);
436 qDebug("Name count %d", count);
437 for (int i = 0; i < count; ++i)
438 {
439 QString s;
440 while (1)
441 {
442 c = idx->getch(this);
443 if (c == 0 || c == EOF) break;
444 s += c;
445 }
446 int val = idx->getint(this);
447 names[s.mid(1,s.length()-2)] = val;
448 qDebug("names[%s] = %d", (const char*)s, val);
449 }
450 count = idx->getint(this);
451 qDebug("Join count %d", count);
452 if (count > 0)
453 {
454 nojoins = count+2;
455 joins = new UInt32[count+2];
456 joins[0] = 0;
457 joins[count+1] = currentpage.length();
458 for (int i = 1; i < count+1; ++i)
459 {
460 joins[i] = idx->getint(this);
461 }
462 }
463 }
464 else
465 {
466 while (c != EOF)
467 {
468 QString s("");
469 while (1)
470 {
471 c = idx->getch(this);
472 if (c == 10 || c == EOF) break;
473 s += c;
474 }
475 //qDebug("%s", (const char*)s);
476 if (count > 0)
477 {
478 --count;
479 int sp = s.findRev(' ');
480 QString l = s.left(sp);
481 int val = s.right(s.length()-sp).toInt();
482 switch (phase)
483 {
484 case 4:
485 //qDebug("Join %d is at offset %d", i, val);
486 joins[i++] = val;
487 break;
488 case 3:
489 //qDebug("Name %s is at offset %d", (const char*)l.mid(1,l.length()-2), val+m_pagedetails[cp].pagestart);
490 names[l.mid(1,l.length()-2)] = val;
491 break;
492 case 1:
493 //qDebug("%s:%d [%d]", (const char*)l, val, i);
494 if (val >= 0)
495 {
496 tags[i++] = tags[val]+l;
497 }
498 else
499 {
500 tags[i++] = l;
501 }
502 //qDebug("TAG:%s", (const char*)tags[i-1]);
503 break;
504 case 2:
505 paras[i++] = ParaRef(QString(l).toInt(), val);
506 //qDebug("Para:%u - %u (%s)", QString(l).toInt(), val, (const char*)s);
507 break;
508 default:
509 qDebug("%s:%d", (const char*)l, val);
510 break;
511 }
512 }
513 else
514 {
515 QString key = "[tags ";
516 if (s.left(key.length()) == key)
517 {
518 phase = 1;
519 i = 0;
520 count = s.mid(key.length(),s.length()-key.length()-1).toInt();
521 qDebug("%s:%s:%d", (const char*)key, (const char*)s, count);
522 tags = new QString[count];
523 }
524 key = "[paragraphs ";
525 if (s.left(key.length()) == key)
526 {
527 phase = 2;
528 i = 0;
529 count = s.mid(key.length(),s.length()-key.length()-1).toInt();
530 qDebug("%s:%s:%d", (const char*)key, (const char*)s, count);
531 paras = new ParaRef[count];
532 noparas = count;
533 }
534 key = "[names ";
535 if (s.left(key.length()) == key)
536 {
537 phase = 3;
538 count = s.mid(key.length(),s.length()-key.length()-1).toInt();
539 qDebug("%s:%s:%d", (const char*)key, (const char*)s, count);
540 }
541 key = "[joins ";
542 if (s.left(key.length()) == key)
543 {
544 phase = 4;
545 count = s.mid(key.length(),s.length()-key.length()-1).toInt();
546 qDebug("%s:%s:%d", (const char*)key, (const char*)s, count);
547 nojoins = count+2;
548 i = 1;
549 joins = new UInt32[count+2];
550 joins[0] = 0;
551 joins[count+1] = currentpage.length();
552 qDebug("%s:%s:%d", (const char*)key, (const char*)s, count);
553 }
554 qDebug("ZC:%s", (const char*)s);
555 }
556 }
557 }
558 // for (int i = 0; i < nojoins; ++i) qDebug("JOINS:%u %u", i, joins[i]);
559 delete idx;
560 }
561}
562
563bool CReb::findanchor(const QString& _info)
564{
565 QMap<QString, int>::Iterator iter = names.find(_info);
566 if (iter != names.end())
567 {
568 locate(iter.data()+m_pagedetails[currentpage.pageno()].pagestart);
569 return true;
570 }
571 return false;
572}
573
574#ifdef USEQPE
575void CReb::suspend()
576{
577 CExpander::suspend(fin);
578}
579void CReb::unsuspend()
580{
581 CExpander::unsuspend(fin);
582}
583#endif
584
585#ifndef __STATIC
586extern "C"
587{
588 CExpander* newcodec() { return new CReb; }
589}
590#endif
591
592void CReb::startpage(UInt32 pgno)
593{
594 Page_detail rs = m_pagedetails[pgno];
595 unsuspend();
596 readindex(pgno);
597 currentpage.startpage(page2pos(pgno), pgno, ((rs.flags & 8) != 0), rs.len);
598}
599
600void CReb::startpage(UInt32 _cp, bool _isCompressed, UInt32 _len)
601{
602 unsuspend();
603 readindex(_cp);
604 currentpage.startpage(page2pos(_cp), _cp, _isCompressed, _len);
605}
606
607void RBPage::initpage(UInt32 pos, size_t _cp, bool _isCompressed, UInt32 _len)
608{
609 filepos = pos;
610 m_pageno = _cp;
611 m_Compressed = _isCompressed;
612 m_pagelen = _len;
613 currentchunk = 0;
614 pageoffset = 0;
615
616 if (chunklist != NULL) delete [] chunklist;
617
618 fseek(fin, filepos, SEEK_SET);
619 if (m_Compressed)
620 {
621 fread(&nochunks, 1, sizeof(nochunks), fin);
622 fread(&m_pagelen, 1, sizeof(m_pagelen), fin);
623 chunklist = new UInt32[nochunks];
624 fread(chunklist, nochunks, 4, fin);
625 }
626 else
627 {
628 chunklist = NULL;
629 nochunks = (_len+m_blocksize-1)/m_blocksize;
630 }
631 m_startoff = 0;
632 m_endoff = m_pagelen;
633 chunkpos = ftell(fin);
634 qDebug("Compressed:%u Expanded:%u", _len, m_pagelen);
635}
636
637void RBPage::startpage(UInt32 pos, UInt32 _cp, bool _isCompressed, UInt32 _len)
638{
639 initpage(pos, _cp, _isCompressed, _len);
640 readchunk();
641}
642
643int CReb::getch()
644{
645 if (tagoffset < tagstring.length())
646 return tagstring[tagoffset++].unicode();
647 else
648 return currentpage.getch(this);
649}
650
651int RBPage::getch(CReb* parent)
652{
653 if (chunkoffset >= chunklen)
654 {
655 if (++currentchunk >= nochunks)
656 {
657 --currentchunk;
658 return EOF;
659 }
660 pageoffset += chunklen;
661 parent->unsuspend();
662 readchunk();
663 }
664 if (offset() == m_endoff) return EOF;
665 return chunk[chunkoffset++];
666}
667
668unsigned short int RBPage::getuint(CReb* parent)
669{
670 unsigned short int ret = 0;
671 char *buffer = (char*)(&ret);
672 for (int i = 0; i < 2; ++i)
673 {
674 int ch = getch(parent);
675 if (ch == EOF) return 0;
676 buffer[i] = ch;
677 }
678 return ret;
679}
680
681int RBPage::getint(CReb* parent)
682{
683 int ret = 0;
684 char *buffer = (char*)(&ret);
685 for (int i = 0; i < 4; ++i)
686 {
687 int ch = getch(parent);
688 if (ch == EOF) return 0;
689 buffer[i] = ch;
690 }
691 return ret;
692}
693
694void RBPage::readchunk()
695{
696 if (m_Compressed)
697 {
698 chunkoffset = 0;
699 fseek(fin, chunkpos, SEEK_SET);
700 UInt8* inbuf = new UInt8[chunklist[currentchunk]];
701 fread(inbuf, 1, chunklist[currentchunk], fin);
702 chunklen = (*m_decompress)(inbuf, chunklist[currentchunk], chunk, m_blocksize);
703 delete [] inbuf;
704 chunkpos = ftell(fin);
705 }
706 else
707 {
708 chunkoffset = 0;
709 chunklen = m_blocksize;
710 if (m_blocksize*(currentchunk+1) > m_pagelen)
711 {
712 chunklen = m_pagelen - currentchunk*m_blocksize;
713 }
714 fseek(fin, chunkpos, SEEK_SET);
715 chunklen = fread(chunk, 1, chunklen, fin);
716 chunkpos = ftell(fin);
717 }
718}
719
720void RBPage::setoffset(UInt32 pos, size_t _cp, bool _isCompressed, UInt32 _len, UInt32 _offset)
721{
722 if (m_pageno != _cp)
723 {
724 initpage(pos, _cp, _isCompressed, _len);
725 }
726 else
727 {
728 if (m_Compressed)
729 {
730 chunkpos = filepos + sizeof(nochunks) + sizeof(m_pagelen) + 4*nochunks;
731 }
732 else
733 {
734 chunkpos = filepos;
735 }
736 }
737
738 currentchunk = _offset/m_blocksize;
739 pageoffset = m_blocksize*currentchunk;
740 if (m_Compressed)
741 {
742 for (int i = 0; i < currentchunk; ++i)
743 {
744 chunkpos += chunklist[i];
745 }
746 }
747 else
748 {
749 chunkpos += pageoffset;
750 }
751 readchunk();
752 chunkoffset = _offset - pageoffset;
753}
754
755void CReb::start2endSection()
756{
757 if (m_pagedetails != NULL)
758 {
759 if (nojoins > 0)
760 {
761 //UInt32 jl = binarychop<UInt32>(joins, nojoins, currentpage.offset());
762
763 UInt32 jl = 0,jh = nojoins-1,jm = (jl+jh)/2;
764 while (jh > jl+1)
765 {
766 if (joins[jm] > currentpage.offset())
767 {
768 jh = jm;
769 }
770 else
771 {
772 jl = jm;
773 }
774 jm = (jl+jh)/2;
775 }
776
777 currentpage.m_startoff = joins[jl];
778 currentpage.m_endoff = joins[jl+1]-1;
779 //currentpage.m_endoff = joins[jh]-1;
780 }
781 m_currentstart = m_pagedetails[currentpage.pageno()].pagestart+currentpage.m_startoff;
782 m_currentend = m_pagedetails[currentpage.pageno()].pagestart+currentpage.m_endoff;
783 }
784 else
785 {
786 m_currentstart = m_currentend = 0;
787 }
788 qDebug("s2e:[%u, %u, %u]", m_currentstart, locate(), m_currentend);
789}