summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-reader/Aportis.cpp291
-rw-r--r--noncore/apps/opie-reader/Aportis.h86
-rw-r--r--noncore/apps/opie-reader/BuffDoc.cpp126
-rw-r--r--noncore/apps/opie-reader/BuffDoc.h138
-rw-r--r--noncore/apps/opie-reader/CBuffer.cpp35
-rw-r--r--noncore/apps/opie-reader/CBuffer.h45
-rw-r--r--noncore/apps/opie-reader/CEncoding.cpp150
-rw-r--r--noncore/apps/opie-reader/CEncoding.h53
-rw-r--r--noncore/apps/opie-reader/CExpander.h145
-rw-r--r--noncore/apps/opie-reader/CFilter.h354
-rw-r--r--noncore/apps/opie-reader/QTReader.cpp1034
-rw-r--r--noncore/apps/opie-reader/QTReader.h217
-rw-r--r--noncore/apps/opie-reader/QTReaderApp.cpp1433
-rw-r--r--noncore/apps/opie-reader/QTReaderApp.h206
-rw-r--r--noncore/apps/opie-reader/QtrListView.cpp24
-rw-r--r--noncore/apps/opie-reader/QtrListView.h20
-rw-r--r--noncore/apps/opie-reader/Queue.h21
-rw-r--r--noncore/apps/opie-reader/README162
-rw-r--r--noncore/apps/opie-reader/Text.h28
-rw-r--r--noncore/apps/opie-reader/ZText.h35
-rw-r--r--noncore/apps/opie-reader/arith.h43
-rw-r--r--noncore/apps/opie-reader/arith_d.cpp94
-rw-r--r--noncore/apps/opie-reader/cbkmkselector.h41
-rw-r--r--noncore/apps/opie-reader/config.h21
-rw-r--r--noncore/apps/opie-reader/fileBrowser.cpp185
-rw-r--r--noncore/apps/opie-reader/fileBrowser.h70
-rw-r--r--noncore/apps/opie-reader/infowin.cpp41
-rw-r--r--noncore/apps/opie-reader/infowin.h52
-rw-r--r--noncore/apps/opie-reader/main.cpp38
-rw-r--r--noncore/apps/opie-reader/my_list.h172
-rw-r--r--noncore/apps/opie-reader/opie-reader.control9
-rw-r--r--noncore/apps/opie-reader/opie-reader.pro48
-rw-r--r--noncore/apps/opie-reader/pdb.cpp57
-rw-r--r--noncore/apps/opie-reader/pdb.h90
-rw-r--r--noncore/apps/opie-reader/ppm.cpp756
-rw-r--r--noncore/apps/opie-reader/ppm.h179
-rw-r--r--noncore/apps/opie-reader/ppm_expander.cpp108
-rw-r--r--noncore/apps/opie-reader/ppm_expander.h46
-rwxr-xr-xnoncore/apps/opie-reader/update.sh11
-rw-r--r--noncore/apps/opie-reader/ustring.h71
-rw-r--r--noncore/apps/opie-reader/utypes.h14
-rw-r--r--noncore/apps/opie-reader/version.h3
-rw-r--r--noncore/apps/opie-reader/ztxt.cpp159
-rw-r--r--noncore/apps/opie-reader/ztxt.h102
44 files changed, 7013 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/Aportis.cpp b/noncore/apps/opie-reader/Aportis.cpp
new file mode 100644
index 0000000..595b385
--- a/dev/null
+++ b/noncore/apps/opie-reader/Aportis.cpp
@@ -0,0 +1,291 @@
+#include <stdio.h>
+#include <string.h>
+#include "Aportis.h"
+
+Aportis::Aportis() { /*printf("constructing:%x\n",fin);*/ }
+
+CList<Bkmk>* Aportis::getbkmklist()
+{
+ if (bCompressed != 4) return NULL;
+ CList<Bkmk>* t = new CList<Bkmk>;
+ size_t cur = ftell(fin);
+ for (int i = 0; i < nRecs2; i++)
+ {
+ DWORD dwPos;
+ fseek(fin, 0x56 + 8*i, SEEK_SET);
+ fread(&dwPos, 4, 1, fin);
+ dwPos = SwapLong(dwPos);
+ fseek(fin,dwPos,SEEK_SET);
+ unsigned char ch;
+ fread(&ch,1,1,fin);
+ if (ch != 241)
+ {
+ char name[17];
+ name[16] = '\0';
+ fseek(fin,dwPos,SEEK_SET);
+ fread(name,1,16,fin);
+ unsigned long lcn;
+ fread(&lcn,sizeof(lcn),1,fin);
+ lcn = SwapLong(lcn);
+#ifdef _UNICODE
+ tchar tname[17];
+ memset(tname, 0, sizeof(tname));
+ for (int i = 0; name[i] != 0; i++)
+ {
+ tname[i] = name[i];
+ }
+ t->push_back(Bkmk(tname,lcn));
+#else
+ t->push_back(Bkmk(name,lcn));
+#endif
+ }
+ }
+ fseek(fin, cur, SEEK_SET);
+ return t;
+}
+
+int Aportis::openfile(const char *src)
+{
+
+ // printf("In openfile\n");
+ int ret = 0;
+
+ if (!Cpdb::openfile(src)) return -1;
+
+ if (head.creator != 0x64414552 // 'dAER'
+ || head.type != 0x74584554) // 'tXET')
+ {
+ return -2;
+ }
+
+ gotorecordnumber(0);
+ tDocRecord0 hdr0;
+ fread(&hdr0, sizeof(hdr0), 1, fin);
+ bCompressed = SwapWord(hdr0.wVersion);
+ if (bCompressed!=1 && bCompressed!=2 && bCompressed != 4) {
+ ret = bCompressed;
+ bCompressed = 2;
+ }
+
+ fseek(fin,0,SEEK_END);
+ dwLen = ftell(fin);
+ nRecs2 = nRecs = SwapWord(head.recordList.numRecords) - 1;
+
+ switch (bCompressed)
+ {
+ case 4:
+ {
+ dwTLen = 0;
+ int i;
+ for (i = 0; i < nRecs; i++)
+ {
+ unsigned int bs = GetBS(i);
+ if (bs == 0) break;
+ else dwTLen += bs;
+ }
+ nRecs = i;
+ BlockSize = 0;
+ }
+ break;
+ case 1:
+ case 2:
+ default:
+ dwTLen = SwapLong(hdr0.dwStoryLen);
+ BlockSize = SwapWord(hdr0.wRecSize);
+ if (BlockSize == 0)
+ {
+ BlockSize = 4096;
+ printf("WARNING: Blocksize not set in source file\n");
+ }
+ }
+
+
+ // this is the main record buffer
+ // it knows how to stretch to accomodate the decompress
+ currentrec = 0;
+ cbptr = 0;
+ outptr = 0;
+ refreshbuffer();
+ return ret;
+}
+
+int Aportis::getch()
+{
+ if (bCompressed == 1)
+ {
+ if ((dwRecLen == 0) && !refreshbuffer()) return EOF;
+ else
+ {
+ int c = getc(fin);
+ dwRecLen--;
+ currentpos++;
+ return c;
+ }
+ }
+ if (outptr != cbptr)
+ {
+ currentpos++;
+ return (circbuf[outptr = (outptr + 1) % 2048]);
+ }
+ if ((dwRecLen == 0) && !refreshbuffer()) return EOF;
+ currentpos++;
+ unsigned int c;
+
+ // take a char from the input buffer
+ c = getc(fin);
+ dwRecLen--;
+ // separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xBF, 0xC0...0xFF
+
+ // codes 1...8 mean copy that many chars; for accented chars & binary
+ if (c == 0)
+ {
+ circbuf[outptr = cbptr = (cbptr+1)%2048] = c;
+ return c;
+ }
+ else if (c >= 0x09 && c <= 0x7F)
+ {
+ circbuf[outptr = cbptr = (cbptr+1)%2048] = c;
+ return c;
+ }
+ else if (c >= 0x01 && c <= 0x08)
+ {
+ dwRecLen -= c;
+ while(c--)
+ {
+ circbuf[cbptr = (cbptr+1)%2048] = getc(fin);
+ }
+ return circbuf[outptr = (outptr+1)%2048];
+ }
+ else if (c >= 0x80 && c <= 0xBF)
+ {
+ int m,n;
+ c <<= 8;
+ c += getc(fin);
+ dwRecLen--;
+ m = (c & 0x3FFF) >> COUNT_BITS;
+ n = c & ((1<<COUNT_BITS) - 1);
+ n += 3;
+ while (n--)
+ {
+ cbptr = (cbptr+1)%2048;
+ circbuf[cbptr] = circbuf[(cbptr+2048-m)%2048];
+ }
+ return circbuf[outptr = (outptr+1)%2048];
+ }
+ else if (c >= 0xC0 && c <= 0xFF)
+ {
+ circbuf[cbptr = (cbptr+1)%2048] = ' ';
+ circbuf[cbptr = (cbptr+1)%2048] = c^0x80;
+ return circbuf[outptr = (outptr+1)%2048];
+ }
+}
+
+unsigned int Aportis::GetBS(unsigned int bn)
+{
+ DWORD dwPos;
+ WORD fs;
+
+ fseek(fin, 0x56 + 8*bn, SEEK_SET);
+ fread(&dwPos, 4, 1, fin);
+ dwPos = SwapLong(dwPos);
+ fseek(fin,dwPos,SEEK_SET);
+
+// gotorecordnumber(bn+1);
+ unsigned char ch;
+ fread(&ch,1,1,fin);
+ if (ch == 241)
+ {
+ fread(&fs,sizeof(fs),1,fin);
+ fs = SwapWord(fs);
+ }
+ else
+ fs = 0;
+ return fs;
+}
+
+unsigned int Aportis::locate()
+{
+ if (bCompressed == 4)
+ {
+ size_t cur = ftell(fin);
+ unsigned int clen = 0;
+ for (unsigned int i = 0; i < currentrec-1; i++)
+ {
+ unsigned int bs = GetBS(i);
+ if (bs == 0) break;
+ clen += bs;
+ }
+ fseek(fin,cur,SEEK_SET);
+ return clen+currentpos;
+ }
+ else
+ return (currentrec-1)*BlockSize+currentpos;
+}
+
+void Aportis::locate(unsigned int n)
+{
+ unsigned int offset;
+ // currentrec = (n >> OFFBITS);
+ switch (bCompressed)
+ {
+ case 4:
+ {
+ DWORD clen = 0;
+ offset = n;
+ unsigned int i;
+ for (i = 0; i < nRecs; i++)
+ {
+ unsigned int bs = GetBS(i);
+ if (bs == 0) break;
+ clen += bs;
+ if (clen > n) break;
+ offset = n - clen;
+ }
+ currentrec = i;
+ }
+ break;
+ case 1:
+ case 2:
+ default:
+ currentrec = n / BlockSize;
+ offset = n % BlockSize;
+ }
+
+ outptr = cbptr;
+ refreshbuffer();
+ while (currentpos < offset && getch() != EOF);
+}
+
+bool Aportis::refreshbuffer()
+{
+ if (currentrec < nRecs)
+ {
+ dwRecLen = recordlength(currentrec+1);
+ gotorecordnumber(currentrec+1);
+ if (bCompressed == 4)
+ {
+ unsigned char t[3];
+ fread(t,1,3,fin);
+ if (t[0] != 241)
+ {
+ printf("You shouldn't be here!\n");
+ return false;
+ }
+ dwRecLen -= 3;
+ }
+ /*
+ int n = fread(t.buf, 1, dwRecLen, fin);
+ t.len = n;
+ // if(bCompressed)
+ t.Decompress();
+
+ t.buf[t.Len()] = '\0';
+ */
+ currentpos = 0;
+ currentrec++;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
diff --git a/noncore/apps/opie-reader/Aportis.h b/noncore/apps/opie-reader/Aportis.h
new file mode 100644
index 0000000..08016f4
--- a/dev/null
+++ b/noncore/apps/opie-reader/Aportis.h
@@ -0,0 +1,86 @@
+/*
+ Derived from makedoc9 by Pat Beirne
+*/
+
+#ifndef __Aportis_h
+#define __Aportis_h
+
+#include "CExpander.h"
+#include "pdb.h"
+
+typedef UInt32 DWORD;
+typedef UInt16 WORD;
+
+#define DISP_BITS 11
+#define COUNT_BITS 3
+/*
+// all numbers in these structs are big-endian, MAC format
+struct tDocHeader {
+ char sName[32];
+ DWORD dwUnknown1;
+ DWORD dwTime1;
+ DWORD dwTime2;
+ DWORD dwTime3;
+ DWORD dwLastSync;
+ DWORD ofsSort;
+ DWORD ofsCatagories;
+ DWORD dwCreator;
+ DWORD dwType;
+ DWORD dwUnknown2;
+ DWORD dwUnknown3;
+ WORD wNumRecs;
+};
+*/
+struct tDocRecord0 {
+ WORD wVersion; // 1=plain text, 2=compressed
+ WORD wSpare;
+ DWORD dwStoryLen; // in chars, when decompressed
+ WORD wNumRecs; // text records only; equals tDocHeader.wNumRecs-1
+ WORD wRecSize; // usually 0x1000
+ DWORD dwSpare2;
+};
+
+////////////// utilities //////////////////////////////////////
+
+inline WORD SwapWord(WORD r)
+{
+ return (r>>8) + (r<<8);
+}
+
+inline DWORD SwapLong(DWORD r)
+{
+ return ((r>>24) & 0xFF) + (r<<24) + ((r>>8) & 0xFF00) + ((r<<8) & 0xFF0000);
+}
+
+class Aportis : public CExpander, Cpdb {
+ DWORD dwLen;
+ WORD nRecs2;
+ DWORD dwTLen;
+ WORD nRecs;
+ WORD BlockSize;
+ DWORD dwRecLen;
+ int currentrec, currentpos;
+ unsigned int cbptr;
+ unsigned int outptr;
+ unsigned char circbuf[2048];
+ char bCompressed;
+public:
+ virtual void sizes(unsigned long& _file, unsigned long& _text)
+ {
+ _file = dwLen;
+ _text = dwTLen;
+ }
+ virtual bool hasrandomaccess() { return true; }
+ virtual ~Aportis() {}
+ Aportis();
+ virtual int openfile(const char *src);
+ virtual int getch();
+ virtual unsigned int locate();
+ virtual void locate(unsigned int n);
+ virtual CList<Bkmk>* getbkmklist();
+private:
+ bool refreshbuffer();
+ unsigned int GetBS(unsigned int bn);
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/BuffDoc.cpp b/noncore/apps/opie-reader/BuffDoc.cpp
new file mode 100644
index 0000000..df2f4eb
--- a/dev/null
+++ b/noncore/apps/opie-reader/BuffDoc.cpp
@@ -0,0 +1,126 @@
+#include "BuffDoc.h"
+//#include <FL/fl_draw.h>
+#include "config.h"
+
+void BuffDoc::locate(unsigned int n)
+{
+ // qDebug("BuffDoc:locating:%u",n);
+
+ lastword[0] = '\0';
+ lastsizes[0] = laststartline = n;
+ lastispara = false;
+ // tchar linebuf[1024];
+ if (exp != NULL) exp->locate(n);
+ // qDebug("BuffDoc:Located");
+}
+
+bool BuffDoc::getline(CBuffer* buff, int w)
+{
+ if (exp == NULL)
+ {
+ (*buff)[0] = '\0';
+ return false;
+ }
+ int len = 0, ch, lastcheck = 0;
+ *buff = lastword.data();
+ lastcheck = len = buff->length();
+ // unsigned int slen = fl_widthi(buff->data(),len);
+#ifdef _UNICODE
+ unsigned int slen = m_fm->width(toQString(buff->data()),len);
+#else
+ unsigned int slen = m_fm->width(buff->data(),len);
+#endif
+ if (slen > w)
+ {
+ for ( ; len > 0; len--)
+ {
+ // if (fl_widthi(buff->data(),len) < w) break;
+#ifdef _UNICODE
+ if (m_fm->width(toQString(buff->data()),len) < w) break;
+#else
+ if (m_fm->width(buff->data(),len) < w) break;
+#endif
+ }
+ lastword = buff->data() + len - 1;
+ for (int i = 0; i < buff->length(); i++) lastsizes[i] = lastsizes[i+len-1];
+ (*buff)[len-1] = '-';
+ (*buff)[len] = '\0';
+ laststartline = lastsizes[len-1];
+ return true;
+ }
+ if (lastispara)
+ {
+ lastispara = false;
+ lastword[0] = '\0';
+ len = buff->length();
+ // while (fl_widthi(buff->data(),len) > w) len--;
+#ifdef _UNICODE
+ while (m_fm->width(toQString(buff->data()),len) > w) len--;
+#else
+ while (m_fm->width(buff->data(),len) > w) len--;
+#endif
+ (*buff)[len] = '\0';
+ laststartline = exp->locate();
+ return true;
+ }
+ lastispara = false;
+ for (int i = 0; i < len; i++) allsizes[i] = lastsizes[i];
+ while (slen < w)
+ {
+ lastcheck = len;
+ allsizes[len] = exp->locate();
+ while ((ch = getch()) != ' ' && ch != '\012' && ch != UEOF && len < 128)
+ {
+ (*buff)[len++] = ch;
+ allsizes[len] = exp->locate();
+ }
+ (*buff)[len] = 0;
+#ifdef _UNICODE
+ slen = m_fm->width(toQString(buff->data()),len);
+#else
+ slen = m_fm->width(buff->data(),len);
+#endif
+ (*buff)[len++] = ' ';
+ allsizes[len] = exp->locate();
+ if (slen < w && ch != ' ')
+ {
+ lastcheck = len;
+ break;
+ }
+ lastispara = (ch == '\012');
+ }
+ (*buff)[len] = '\0';
+ lastword = buff->data()+lastcheck;
+ for (int i = 0; i < lastword.length(); i++) lastsizes[i] = allsizes[i+lastcheck];
+ if (lastcheck > 0)
+ {
+ laststartline = allsizes[lastcheck];
+ (*buff)[lastcheck-1] = '\0';
+ }
+ else
+ {
+ laststartline = (lastcheck == len) ? exp->locate() : allsizes[lastcheck+1];
+ (*buff)[lastcheck] = '\0';
+ }
+// laststartline = sizes[lastcheck+1];
+// (*buff)[(lastcheck > 0) ? lastcheck-1:lastcheck] = '\0';
+ return (ch != UEOF);
+}
+
+bool BuffDoc::getline(CBuffer* buff, int w, int cw)
+{
+ if (exp == NULL)
+ {
+ (*buff)[0] = '\0';
+ return false;
+ }
+ tchar ch;
+ int i = 0;
+ while ((i < w/cw) && ((ch = getch()) != '\012') && (ch != UEOF))
+ {
+ (*buff)[i++] = ch;
+ }
+ (*buff)[i] = '\0';
+ laststartline = exp->locate();
+ return (ch != UEOF);
+}
diff --git a/noncore/apps/opie-reader/BuffDoc.h b/noncore/apps/opie-reader/BuffDoc.h
new file mode 100644
index 0000000..7c5ef9a
--- a/dev/null
+++ b/noncore/apps/opie-reader/BuffDoc.h
@@ -0,0 +1,138 @@
+#ifndef __BuffDoc_h
+#define __BuffDoc_h
+
+#include "CBuffer.h"
+#include "ZText.h"
+#include "Aportis.h"
+#include "ztxt.h"
+#include "ppm_expander.h"
+#include "CFilter.h"
+#include <qfontmetrics.h>
+#include <qmessagebox.h>
+
+class BuffDoc
+{
+ CBuffer lastword;
+ CSizeBuffer lastsizes, allsizes;
+ size_t laststartline;
+ bool lastispara;
+ CExpander* exp;
+ CFilterChain* filt;
+ QFontMetrics* m_fm;
+ public:
+ ~BuffDoc()
+ {
+ delete filt;
+ delete exp;
+ }
+ BuffDoc() : m_fm(NULL)
+ {
+ exp = NULL;
+ filt = NULL;
+ // qDebug("Buffdoc created");
+ }
+ bool empty() { return (exp == NULL); }
+ void setfm(QFontMetrics* fm)
+ {
+ m_fm = fm;
+ // qDebug("Buffdoc:setfm");
+ }
+ void setfilter(CFilterChain* _f)
+ {
+ if (filt != NULL) delete filt;
+ filt = _f;
+ filt->setsource(exp);
+ }
+ CList<Bkmk>* getbkmklist() { return exp->getbkmklist(); }
+ bool hasrandomaccess() { return (exp == NULL) ? false : exp->hasrandomaccess(); }
+ bool iseol() { return (lastword[0] == '\0'); }
+ int openfile(QWidget* _parent, const char *src)
+ {
+ // qDebug("BuffDoc:Openfile:%s", src);
+ // qDebug("Trying aportis %x",exp);
+ if (exp != NULL) delete exp;
+ lastword[0] = '\0';
+ lastsizes[0] = laststartline = 0;
+ lastispara = false;
+ /*
+ exp = new Text;
+ int ret = exp->openfile(src);
+ */
+
+ exp = new Aportis;
+ // qDebug("Calling openfile");
+ int ret = exp->openfile(src);
+ // qDebug("Called openfile");
+ if (ret == -1)
+ {
+ // qDebug("problem opening source file:%s",src);
+ delete exp;
+ exp = NULL;
+ return ret;
+ }
+ if (ret == -2)
+ {
+
+ delete exp;
+// qDebug("Trying ztxt");
+ exp = new ztxt;
+ ret = exp->openfile(src);
+ }
+#ifndef SMALL
+ if (ret != 0)
+ {
+ delete exp;
+// qDebug("Trying ppms");
+ exp = new ppm_expander;
+ ret = exp->openfile(src);
+ }
+
+ if (ret != 0)
+ {
+ delete exp;
+ exp = new Text;
+// qDebug("Trying text");
+ ret = exp->openfile(src);
+ }
+#else
+ if (ret != 0)
+ {
+ delete exp;
+ exp = new Text;
+ ret = exp->openfile(src);
+ }
+#endif
+ if (ret != 0)
+ {
+ delete exp;
+ QMessageBox::information(_parent, "QTReader", "Unknown file compression type","Try another file");
+ return ret;
+ }
+ // qDebug("Doing final open:%x:%x",exp,filt);
+
+ lastword[0] = '\0';
+ lastsizes[0] = laststartline = 0;
+ lastispara = false;
+ exp->locate(0);
+ filt->setsource(exp);
+ // qDebug("BuffDoc:file opened");
+ return 0;
+ }
+ int getch() { return (exp == NULL) ? UEOF : filt->getch(); }
+ unsigned int locate() { return (exp == NULL) ? 0 : laststartline; }
+ void locate(unsigned int n);
+ bool getline(CBuffer* buff, int w);
+ bool getline(CBuffer* buff, int w, int cw);
+ void sizes(unsigned long& fs, unsigned long& ts) { exp->sizes(fs,ts); }
+ int getpara(CBuffer& buff)
+ {
+ int ch, i = 0;
+ while ((ch = getch()) != 10 && ch != UEOF) buff[i++] = ch;
+ buff[i] = '\0';
+ if (i == 0 && ch == UEOF) i = -1;
+ laststartline = exp->locate();
+ return i;
+ }
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/CBuffer.cpp b/noncore/apps/opie-reader/CBuffer.cpp
new file mode 100644
index 0000000..db52476
--- a/dev/null
+++ b/noncore/apps/opie-reader/CBuffer.cpp
@@ -0,0 +1,35 @@
+#include "CBuffer.h"
+
+CBuffer& CBuffer::operator=(const tchar*sztmp)
+{
+ int i;
+ for (i = 0; sztmp[i] != '\0'; i++) (*this)[i] = sztmp[i];
+ (*this)[i] = '\0';
+ return *this;
+}
+
+tchar& CBuffer::operator[](int i)
+{
+ if (i >= len)
+ {
+ tchar *newbuff = new tchar[i+1];
+ memcpy(newbuff,buffer,sizeof(tchar)*len);
+ delete [] buffer;
+ buffer = newbuff;
+ len = i+1;
+ }
+ return buffer[i];
+}
+
+size_t& CSizeBuffer::operator[](int i)
+{
+ if (i >= len)
+ {
+ size_t *newbuff = new size_t[i+1];
+ memcpy(newbuff,buffer,sizeof(size_t)*len);
+ delete [] buffer;
+ buffer = newbuff;
+ len = i+1;
+ }
+ return buffer[i];
+}
diff --git a/noncore/apps/opie-reader/CBuffer.h b/noncore/apps/opie-reader/CBuffer.h
new file mode 100644
index 0000000..9807d27
--- a/dev/null
+++ b/noncore/apps/opie-reader/CBuffer.h
@@ -0,0 +1,45 @@
+#ifndef __CBUFFER_H
+#define __CBUFFER_H
+
+#include <stdlib.h>
+#include <string.h>
+#include "config.h"
+
+class CBuffer
+{
+ size_t len;
+ tchar *buffer;
+ CBuffer(const CBuffer&);
+ public:
+ CBuffer& operator=(const tchar*sztmp);
+#ifdef _UNICODE
+ size_t length() { return ustrlen(buffer); }
+#else
+ size_t length() { return strlen(buffer); }
+#endif
+ tchar* data() { return buffer; }
+ CBuffer(size_t n = 16) : len(n)
+ {
+ buffer = new tchar[len];
+ buffer[0] = '\0';
+ }
+ ~CBuffer() { delete [] buffer; }
+ tchar& operator[](int i);
+};
+
+class CSizeBuffer
+{
+ size_t len;
+ size_t *buffer;
+ CSizeBuffer(const CSizeBuffer&);
+ public:
+ size_t* data() { return buffer; }
+ CSizeBuffer(size_t n = 16) : len(n)
+ {
+ buffer = new size_t[len];
+ }
+ ~CSizeBuffer() { delete [] buffer; }
+ size_t& operator[](int i);
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/CEncoding.cpp b/noncore/apps/opie-reader/CEncoding.cpp
new file mode 100644
index 0000000..18d18d3
--- a/dev/null
+++ b/noncore/apps/opie-reader/CEncoding.cpp
@@ -0,0 +1,150 @@
+#include <stdio.h>
+#include "CEncoding.h"
+
+tchar CUtf8::getch()
+{
+ int iret = parent->getch();
+ if (iret == EOF) return UEOF;
+ tchar ret = iret;
+ int count = 0;
+ if (ret & (1 << 7))
+ {
+ unsigned char flags = ret << 1;
+ while ((flags & (1 << 7)) != 0)
+ {
+ ret <<= 6;
+ ret += parent->getch() & 0x3f;
+ flags <<= 1;
+ count++;
+ }
+ switch (count)
+ {
+ case 0:
+ break;
+ case 1:
+ ret &= 0x07ff;
+ break;
+ case 2:
+ break;
+ case 3:
+ case 4:
+ case 5:
+ default:
+ printf("Only 16bit unicode supported...");
+ }
+ }
+ return ret;
+}
+
+
+tchar CUcs16be::getch()
+{
+ int iret = parent->getch();
+ if (iret == EOF) return UEOF;
+ tchar ret = iret;
+ return (ret << 8) + parent->getch();
+}
+
+tchar CUcs16le::getch()
+{
+ int iret = parent->getch();
+ if (iret == EOF) return UEOF;
+ tchar ret = iret;
+ return ret + (parent->getch() << 8);
+}
+
+tchar Ccp1252::getch()
+{
+ int iret = parent->getch();
+ switch (iret)
+ {
+ case EOF:
+ return UEOF;
+ case 0x80:
+ return 0x20ac;
+ case 0x82:
+ return 0x201a;
+ case 0x83:
+ return 0x0192;
+ case 0x84:
+ return 0x201e;
+ case 0x85:
+ return 0x2026;
+ case 0x86:
+ return 0x2020;
+ case 0x87:
+ return 0x2021;
+ case 0x88:
+ return 0x02c6;
+ case 0x89:
+ return 0x2030;
+ case 0x8a:
+ return 0x0160;
+ case 0x8b:
+ return 0x2039;
+ case 0x8c:
+ return 0x0152;
+ case 0x8e:
+ return 0x017d;
+ case 0x91:
+ return 0x2018;
+ case 0x92:
+ return 0x2019;
+ case 0x93:
+ return 0x201c;
+ case 0x94:
+ return 0x201d;
+ case 0x95:
+ return 0x2022;
+ case 0x96:
+ return 0x2013;
+ case 0x97:
+ return 0x2014;
+ case 0x98:
+ return 0x02dc;
+ case 0x99:
+ return 0x2122;
+ case 0x9a:
+ return 0x0161;
+ case 0x9b:
+ return 0x203a;
+ case 0x9c:
+ return 0x0153;
+ case 0x9e:
+ return 0x017e;
+ case 0x9f:
+ return 0x0178;
+ default:
+ return iret;
+ }
+}
+
+tchar CPalm::getch()
+{
+ tchar iret = Ccp1252::getch();
+ switch (iret)
+ {
+ case 0x18:
+ return 0x2026;
+ case 0x19:
+ return 0x2007;
+ case 0x8d:
+ return 0x2662;
+ case 0x8e:
+ return 0x2663;
+ case 0x8f:
+ return 0x2661;
+ case 0x90:
+ return 0x2660;
+ default:
+ return iret;
+ }
+}
+
+tchar CAscii::getch()
+{
+ int iret = parent->getch();
+ if (iret == EOF) return UEOF;
+ return iret;
+}
+
diff --git a/noncore/apps/opie-reader/CEncoding.h b/noncore/apps/opie-reader/CEncoding.h
new file mode 100644
index 0000000..1eee29e
--- a/dev/null
+++ b/noncore/apps/opie-reader/CEncoding.h
@@ -0,0 +1,53 @@
+#ifndef __CENCODING_H
+#define __CENCODING_H
+
+#include "CExpander.h"
+
+class CEncoding : public CCharacterSource
+{
+ friend class CFilterChain;
+ protected:
+ CExpander* parent;
+public:
+ CEncoding() : parent(NULL) {}
+ void setparent(CExpander* p) { parent = p; }
+ virtual ~CEncoding() {};
+};
+
+class CUtf8 : public CEncoding
+{
+public:
+ tchar getch();
+};
+
+class CUcs16be : public CEncoding
+{
+public:
+ tchar getch();
+};
+
+class CUcs16le : public CEncoding
+{
+public:
+ tchar getch();
+};
+
+class Ccp1252 : public CEncoding
+{
+public:
+ virtual tchar getch();
+};
+
+class CPalm : public Ccp1252
+{
+public:
+ tchar getch();
+};
+
+class CAscii : public CEncoding
+{
+public:
+ tchar getch();
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/CExpander.h b/noncore/apps/opie-reader/CExpander.h
new file mode 100644
index 0000000..07c14fa
--- a/dev/null
+++ b/noncore/apps/opie-reader/CExpander.h
@@ -0,0 +1,145 @@
+#ifndef __CExpander_h
+#define __CExpander_h
+
+#include "my_list.h"
+#include "config.h"
+
+class Bkmk
+{
+ friend class BkmkFile;
+ tchar* m_name;
+ unsigned int m_position;
+ public:
+ Bkmk() : m_name(NULL), m_position(0) {};
+ Bkmk(const tchar* _nm, unsigned int _p) : m_position(_p)
+ {
+ int len = ustrlen(_nm)+1;
+ m_name = new tchar[len];
+ for (int i = 0; i < len; i++) m_name[i] = _nm[i];
+ }
+ Bkmk(const Bkmk& rhs) : m_name(NULL)
+ {
+ *this = rhs;
+ }
+ ~Bkmk() { if (m_name != NULL) delete [] m_name; }
+ unsigned int value() const { return m_position; }
+ tchar *name() const { return m_name; }
+ bool operator<(const Bkmk& rhs) { return (m_position < rhs.m_position); }
+ Bkmk& operator=(const Bkmk& rhs)
+ {
+ if (m_name != NULL) delete [] m_name;
+ if (rhs.m_name != NULL)
+ {
+ int len = ustrlen(rhs.m_name)+1;
+ m_name = new tchar[len];
+ for (int i = 0; i < len; i++) m_name[i] = rhs.m_name[i];
+ }
+ else
+ m_name = NULL;
+ m_position = rhs.m_position;
+ return *this;
+ }
+ bool operator==(const Bkmk& rhs)
+ {
+ return (m_position == rhs.m_position && ustrcmp(m_name,rhs.m_name) == 0);
+ }
+};
+
+class BkmkFile
+{
+ FILE* f;
+ bool wt;
+public:
+ BkmkFile(const char *fnm, bool w = false)
+ :
+ wt(w)
+ {
+ if (w)
+ f = fopen(fnm, "wb");
+ else
+ f = fopen(fnm, "rb");
+ }
+ ~BkmkFile()
+ {
+ if (f != NULL) fclose(f);
+ }
+ void write(tchar* nm, const unsigned int& pos)
+ {
+ if (f != NULL)
+ {
+ unsigned short ln = ustrlen(nm);
+ fwrite(&ln,sizeof(ln),1,f);
+ fwrite(nm,sizeof(tchar),ln,f);
+ fwrite(&pos,sizeof(pos),1,f);
+ }
+ }
+ void write(const Bkmk& b) { write(b.name(), b.value()); }
+ void write(CList<Bkmk>& bl)
+ {
+ if (f != NULL)
+ {
+ for (CList<Bkmk>::iterator i = bl.begin(); i != bl.end(); i++)
+ {
+ write(*i);
+ }
+ }
+ }
+ Bkmk* read()
+ {
+ Bkmk* b = NULL;
+ if (f != NULL)
+ {
+ unsigned short ln;
+ if (fread(&ln,sizeof(ln),1,f) == 1)
+ {
+ b = new Bkmk;
+ b->m_name = new tchar[ln+1];
+ fread(b->m_name,sizeof(tchar),ln,f);
+ b->m_name[ln] = 0;
+ fread(&b->m_position,sizeof(b->m_position),1,f);
+ }
+ }
+ return b;
+ }
+ CList<Bkmk>* readall()
+ {
+ CList<Bkmk>* bl = NULL;
+ if (f != NULL)
+ {
+ bl = new CList<Bkmk>;
+ while (1)
+ {
+ Bkmk* b = read();
+ if (b == NULL) break;
+ bl->push_back(*b);
+ delete b;
+ }
+ }
+ return bl;
+ }
+};
+
+class CCharacterSource
+{
+ public:
+#ifdef _UNICODE
+ virtual tchar getch() = 0;
+#else
+ virtual int getch() = 0;
+#endif
+};
+
+class CExpander
+{
+ public:
+ CExpander() {};
+ virtual ~CExpander() {};
+ virtual int openfile(const char *src) = 0;
+ virtual unsigned int locate() = 0;
+ virtual void locate(unsigned int n) = 0;
+ virtual bool hasrandomaccess() = 0;
+ virtual void sizes(unsigned long& file, unsigned long& text) = 0;
+ virtual CList<Bkmk>* getbkmklist() { return NULL; }
+ virtual int getch() = 0;
+};
+#endif
diff --git a/noncore/apps/opie-reader/CFilter.h b/noncore/apps/opie-reader/CFilter.h
new file mode 100644
index 0000000..4f609dc
--- a/dev/null
+++ b/noncore/apps/opie-reader/CFilter.h
@@ -0,0 +1,354 @@
+#ifndef __CFILTER_H
+#define __CFILTER_H
+
+#include "CExpander.h"
+#include "CEncoding.h"
+
+class CFilter : public CCharacterSource
+{
+ friend class CFilterChain;
+ protected:
+ CCharacterSource* parent;
+public:
+ CFilter() : parent(NULL) {}
+ void setparent(CCharacterSource* p) { parent = p; }
+ virtual ~CFilter() {};
+};
+
+class vanilla : public CFilter
+{
+public:
+ vanilla() {}
+ virtual ~vanilla() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+#else
+ virtual int getch()
+#endif
+ {
+ return parent->getch();
+ }
+};
+
+class CFilterChain
+{
+ CExpander* expander;
+ CEncoding* encoder;
+ CFilter* first;
+ CCharacterSource* front;
+ public:
+ CFilterChain(CEncoding* _e) : encoder(_e), first(NULL), front(_e) {};
+ ~CFilterChain()
+ {
+ CCharacterSource* p = front;
+ while (p != encoder)
+ {
+ CFilter* pnext = (CFilter*)p;
+ p = ((CFilter*)p)->parent;
+ delete pnext;
+ }
+ delete encoder;
+ }
+ int getch() { return front->getch(); }
+ void addfilter(CFilter* p)
+ {
+ if (first == NULL)
+ {
+ front = first = p;
+ p->setparent(encoder);
+ }
+ else
+ {
+ p->setparent(front);
+ front = p;
+ }
+ }
+ void setsource(CExpander* p)
+ {
+ expander = p;
+ encoder->setparent(p);
+ }
+ void setencoder(CEncoding* p)
+ {
+ delete encoder;
+ encoder = p;
+ first->setparent(p);
+ encoder->setparent(expander);
+ }
+};
+
+class stripcr : public CFilter
+{
+public:
+ stripcr() {}
+ virtual ~stripcr() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+ {
+ tchar ch;
+ do
+ {
+ ch = parent->getch();
+ }
+ while (ch == 13);
+ return ch;
+ }
+#else
+ virtual int getch()
+ {
+ int ch;
+ do
+ {
+ ch = parent->getch();
+ }
+ while (ch == 13);
+ return ch;
+ }
+#endif
+};
+
+class dehyphen : public CFilter
+{
+ bool m_bCharWaiting;
+ tchar m_nextChar;
+ public:
+ dehyphen() : m_bCharWaiting(false) {}
+ virtual ~dehyphen() {}
+ virtual tchar getch()
+ {
+ if (m_bCharWaiting)
+ {
+ m_bCharWaiting = false;
+ return m_nextChar;
+ }
+ tchar ch = parent->getch();
+ if (ch != '-') return ch;
+ m_nextChar = parent->getch();
+ if (m_nextChar != 10)
+ {
+ m_bCharWaiting = true;
+ return '-';
+ }
+ return parent->getch();
+ }
+};
+
+class striphtml : public CFilter
+{
+public:
+ striphtml() {}
+ virtual ~striphtml() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+ {
+ tchar ch;
+ ch = parent->getch();
+ while (ch == '<')
+ {
+ while (ch != '>')
+ {
+ ch = parent->getch();
+ }
+ ch = parent->getch();
+ }
+ if (ch == '&')
+ {
+ ch = parent->getch();
+ if (ch == '#')
+ {
+ int id = 0;
+ while ((ch = parent->getch()) != ';') id = 10*id+ch-'0';
+ ch = id;
+ }
+ }
+ return ch;
+ }
+#else
+ virtual int getch()
+ {
+ int ch;
+ ch = parent->getch();
+ while (ch == '<')
+ {
+ while (ch != '>')
+ {
+ ch = parent->getch();
+ }
+ ch = parent->getch();
+ }
+ if (ch == '&')
+ {
+ ch = parent->getch();
+ if (ch == '#')
+ {
+ int id = 0;
+ while ((ch = parent->getch()) != ';') id = 10*id+ch-'0';
+ ch = id;
+ }
+ }
+ return ch;
+ }
+#endif
+};
+
+class unindent : public CFilter
+{
+ tchar lc;
+public:
+ unindent() : lc(0) {}
+ virtual ~unindent() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+ {
+ tchar ch;
+ if (lc == 10)
+ {
+ while ((ch = parent->getch()) == ' ');
+ }
+ else ch = parent->getch();
+ lc = ch;
+ return ch;
+ }
+#else
+ virtual int getch()
+ {
+ int ch;
+ if (lc == 10)
+ {
+ while ((ch = parent->getch()) == ' ');
+ }
+ else ch = parent->getch();
+ lc = ch;
+ return ch;
+ }
+#endif
+};
+
+#ifdef _UNICODE
+class repara : public CFilter
+{
+ tchar tch;
+public:
+ repara() : tch(0) {}
+ virtual ~repara() {}
+ virtual tchar getch()
+ {
+ tchar ch = parent->getch();
+ if (ch == 10)
+ {
+ if (tch == 10)
+ {
+ return ch;
+ }
+ else
+ {
+ tch = ch;
+ return ' ';
+ }
+ }
+ tch = ch;
+ return ch;
+ }
+};
+#else
+class repara : public CFilter
+{
+ int tch;
+public:
+ repara() : tch(0) {}
+ virtual ~repara() {}
+ virtual int getch()
+ {
+ int ch = parent->getch();
+ if (ch == 10)
+ {
+ if (tch == 10)
+ {
+ return ch;
+ }
+ else
+ {
+ tch = ch;
+ return ' ';
+ }
+ }
+ tch = ch;
+ return ch;
+ }
+};
+#endif
+
+class indenter : public CFilter
+{
+ int amnt;
+ int indent;
+public:
+ indenter(int _a=5) : amnt(_a), indent(0) {}
+ virtual ~indenter() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+ {
+ if (indent > 0)
+ {
+ indent--;
+ return ' ';
+ }
+ tchar ch = parent->getch();
+ if (ch == 10)
+ {
+ indent = amnt;
+ }
+ return ch;
+ }
+#else
+ virtual int getch()
+ {
+ if (indent > 0)
+ {
+ indent--;
+ return ' ';
+ }
+ int ch = parent->getch();
+ if (ch == 10)
+ {
+ indent = amnt;
+ }
+ return ch;
+ }
+#endif
+};
+
+class dblspce : public CFilter
+{
+ bool lastlf;
+public:
+ dblspce() : lastlf(false) {}
+ virtual ~dblspce() {}
+#ifdef _UNICODE
+ virtual tchar getch()
+ {
+ if (lastlf)
+ {
+ lastlf = false;
+ return 10;
+ }
+ tchar ch = parent->getch();
+ lastlf = (ch == 10);
+ return ch;
+ }
+#else
+ virtual int getch()
+ {
+ if (lastlf)
+ {
+ lastlf = false;
+ return 10;
+ }
+ int ch = parent->getch();
+ lastlf = (ch == 10);
+ return ch;
+ }
+#endif
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/QTReader.cpp b/noncore/apps/opie-reader/QTReader.cpp
new file mode 100644
index 0000000..6251812
--- a/dev/null
+++ b/noncore/apps/opie-reader/QTReader.cpp
@@ -0,0 +1,1034 @@
+/****************************************************************************
+** $Id$
+**
+** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "config.h"
+#include "QTReader.h"
+#include "QTReaderApp.h"
+#include <qpe/qpeapplication.h>
+#include <math.h>
+#include <ctype.h>
+#include <stdio.h> //for sprintf
+#include <qpe/config.h>
+#include <qpe/applnk.h>
+#include <qfontdatabase.h>
+#include <qpe/global.h>
+#include <qpe/qcopenvelope_qws.h>
+
+#ifdef _UNICODE
+const char *QTReader::fonts[] = { "unifont", "Courier", "Times", 0 };
+#else
+const char *QTReader::fonts[] = { "Helvetica", "Courier", "Times", 0 };
+#endif
+//const int QTReader::fontsizes[] = { 8, 10, 12, 14, 18, 24, 30, 40, 50, 60, 70, 80, 90, 100, 0 };
+
+//const tchar *QTReader::fonts[] = { "unifont", "fixed", "micro", "smoothtimes", "Courier", "Times", 0 };
+//const int QTReader::fontsizes[] = {10,16,17,22,0};
+//const tchar *QTReader::fonts[] = { "verdana", "Courier", "Times", 0 };
+//const int QTReader::fontsizes[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,0};
+
+QTReader::QTReader( QWidget *parent=0, const char *name=0, WFlags f = 0) :
+ QWidget(parent, name, f),
+ m_delay(100),
+ m_scrolldy(0),
+ m_autoScroll(false),
+ textarray(NULL),
+ locnarray(NULL),
+ numlines(0),
+ m_fontname("unifont"),
+ m_fm(NULL)
+{
+ m_overlap = 1;
+ fontsizes = NULL;
+// init();
+}
+/*
+QTReader::QTReader( const QString& filename, QWidget *parent=0, const tchar *name=0, WFlags f = 0) :
+ QWidget(parent, name, f),
+ m_textfont(0),
+ m_textsize(1),
+ textarray(NULL),
+ numlines(0),
+ bstripcr(true),
+ bunindent(false),
+ brepara(false),
+ bdblspce(false),
+ btight(false),
+ bindenter(0),
+ m_fm(NULL)
+{
+ init();
+ // qDebug("Load_file(1)");
+ load_file((const tchar*)filename);
+}
+*/
+
+long QTReader::real_delay()
+{
+ return ( 8976 + m_delay ) / ( m_linespacing * m_linespacing );
+}
+
+void QTReader::mouseReleaseEvent( QMouseEvent* _e )
+//void QTReader::mouseDoubleClickEvent( QMouseEvent* _e )
+{
+ if (textarray != NULL)
+ {
+// printf("(%u, %u)\n", _e->x(), _e->y());
+ QString wrd = QString::null;
+ int lineno = _e->y()/m_linespacing;
+ if (m_bMonoSpaced)
+ {
+ int chno = _e->x()/m_charWidth;
+ if (chno < ustrlen(textarray[lineno]->data()))
+ {
+ wrd[0] = textarray[lineno]->data()[chno];
+ }
+ }
+ else
+ {
+ CBuffer* t = textarray[lineno];
+ int first = 0;
+ while (1)
+ {
+ int i = first+1;
+// while ((*t)[i] != ' ' && (*t)[i] != 0) i++;
+ while (QChar((*t)[i]).isLetter() && (*t)[i] != 0) i++;
+ if (m_fm->width(toQString(t->data()), i) > _e->x())
+ {
+ wrd = toQString(t->data()+first, i - first);
+ break;
+ }
+// while ((*t)[i] == ' ' && (*t)[i] != 0) i++;
+ while (!QChar((*t)[i]).isLetter() && (*t)[i] != 0) i++;
+ if ((*t)[i] == 0) break;
+ first = i;
+ }
+ }
+ if (!wrd.isEmpty())
+ {
+ QClipboard* cb = QApplication::clipboard();
+ cb->setText(wrd);
+ Global::statusMessage(wrd);
+ if (!m_targetapp.isEmpty() && !m_targetmsg.isEmpty())
+ {
+ QCopEnvelope e(("QPE/Application/"+m_targetapp).utf8(), (m_targetmsg+"(QString)").utf8());
+ e << wrd;
+ }
+ }
+ }
+}
+
+void QTReader::focusInEvent(QFocusEvent* e)
+{
+ if (m_autoScroll) timer->start(real_delay(), false);
+ update();
+}
+
+void QTReader::focusOutEvent(QFocusEvent* e)
+{
+ if (m_autoScroll)
+ {
+ timer->stop();
+ m_scrolldy = 0;
+ }
+}
+
+#include <qapplication.h>
+#include <qdrawutil.h>
+#include <unistd.h>
+
+void QTReader::goDown()
+{
+ if (m_bpagemode)
+ {
+ dopagedn();
+ }
+ else
+ {
+ lineDown();
+ }
+}
+
+void QTReader::goUp()
+{
+ if (m_bpagemode)
+ {
+ dopageup();
+ }
+ else
+ {
+ lineUp();
+ }
+}
+
+void QTReader::keyPressEvent(QKeyEvent* e)
+{
+ switch (e->key())
+ {
+ case Key_Down:
+ {
+ e->accept();
+ if (m_autoScroll)
+ {
+ if (m_delay < 59049)
+ {
+ m_delay = (3*m_delay)/2;
+ timer->changeInterval(real_delay());
+ }
+ else
+ {
+ m_delay = 59049;
+ }
+ }
+ else
+ {
+ goDown();
+ }
+ }
+ break;
+ case Key_Up:
+ {
+ e->accept();
+ if (m_autoScroll)
+ {
+ if (m_delay > 1024)
+ {
+ m_delay = (2*m_delay)/3;
+ timer->changeInterval(real_delay());
+ }
+ else
+ {
+ m_delay = 1024;
+ }
+ }
+ else
+ {
+ goUp();
+ }
+ }
+ break;
+ /*
+ case Key_Left:
+ {
+ e->accept();
+ if (m_textfont > 0)
+ {
+ m_textfont--;
+ setfont(NULL);
+ locate(pagelocate());
+ update();
+ }
+ }
+ break;
+ case Key_Right:
+ {
+ e->accept();
+ if (fonts[++m_textfont] == 0)
+ {
+ m_textfont--;
+ }
+ else
+ {
+ setfont(NULL);
+ locate(pagelocate());
+ update();
+ }
+ }
+ break;
+ */
+ case Key_Right:
+ {
+ e->accept();
+ if (fontsizes[++m_textsize] == 0)
+ {
+ m_textsize--;
+ }
+ else
+ {
+ bool sc = m_autoScroll;
+ m_autoScroll = false;
+ setfont(NULL);
+ locate(pagelocate());
+ update();
+ m_autoScroll = sc;
+ if (m_autoScroll) autoscroll();
+ }
+ }
+ break;
+ case Key_Left:
+ {
+ e->accept();
+ if (m_textsize > 0)
+ {
+ bool sc = m_autoScroll;
+ m_autoScroll = false;
+ m_textsize--;
+ setfont(NULL);
+ locate(pagelocate());
+ update();
+ m_autoScroll = sc;
+ if (m_autoScroll) autoscroll();
+ }
+ }
+ break;
+ case Key_Space:
+// case Key_Enter:
+ case Key_Return:
+ {
+ e->accept();
+ setautoscroll(!m_autoScroll);
+ ((QTReaderApp*)parent()->parent())->setScrollState(m_autoScroll);
+ }
+ break;
+ default:
+ e->ignore();
+ }
+}
+
+void QTReader::setautoscroll(bool _sc)
+{
+ if (_sc == m_autoScroll) return;
+ if (m_autoScroll)
+ {
+ m_autoScroll = false;
+ }
+ else
+ {
+ m_autoScroll = true;
+ autoscroll();
+ }
+}
+
+bool QTReader::getline(CBuffer *buff)
+{
+ if (m_bMonoSpaced)
+ {
+ return buffdoc.getline(buff ,width(), m_charWidth);
+ }
+ else
+ {
+ return buffdoc.getline(buff, width());
+ }
+}
+
+void QTReader::doscroll()
+{
+ if (!m_autoScroll)
+ {
+ timer->stop();
+ return;
+ }
+// timer->changeInterval(real_delay());
+ QPainter p( this );
+ QBrush b( white);
+ bitBlt(this,0,0,this,0,1,width(),-1);
+ qDrawPlainRect(&p,0,height() - 2,width(),2,white,1,&b);
+
+ if (++m_scrolldy == m_linespacing)
+ {
+ setfont(&p);
+ m_scrolldy = 0;
+// qDrawPlainRect(&p,0,height() - m_linespacing,width(),m_linespacing,white,1,&b);
+ pagepos = locnarray[1];
+ CBuffer* buff = textarray[0];
+ for (int i = 1; i < numlines; i++)
+ {
+ textarray[i-1] = textarray[i];
+ locnarray[i-1] = locnarray[i];
+ }
+ locnarray[numlines-1] = locate();
+ if (getline(buff))
+ {
+ textarray[numlines-1] = buff;
+ drawText( p, 0, height() - m_descent - 2, buff->data());
+ mylastpos = locate();
+ }
+ else
+ {
+// (*buff)[0] = '\0';
+ textarray[numlines-1] = buff;
+ m_autoScroll = false;
+ ((QTReaderApp*)parent()->parent())->setScrollState(m_autoScroll);
+ }
+ }
+}
+
+void QTReader::drawText(QPainter& p, int x, int y, tchar* _text)
+{
+ QString text = toQString(_text);
+ if (m_bMonoSpaced)
+ {
+ for (int i = 0; i < text.length(); i++)
+ {
+ p.drawText( x+i*m_charWidth, y, QString(text[i]) );
+ }
+ }
+ else
+ {
+ p.drawText( x, y, text );
+ }
+}
+
+void QTReader::autoscroll()
+{
+ timer->start(real_delay(), false);
+}
+
+void QTReader::setfont(QPainter* p)
+{
+ // qDebug("Fontsize = %u",fontsizes[m_textsize]);
+ // qDebug("SetFont %x",p);
+ QFont font(m_fontname, fontsizes[m_textsize], (m_bBold) ? QFont::Bold : QFont::Normal );
+ m_charWidth = (m_charpc*fontsizes[m_textsize])/100;
+ if (m_charWidth <= 0) m_charWidth = 1;
+// font.setFixedPitch(m_bMonoSpaced);
+// qDebug("Raw name = %s", (const char*)font.rawName());
+ if (p != NULL) p->setFont( font );
+ if (m_fm == NULL)
+ {
+ m_fm = new QFontMetrics(font);
+ buffdoc.setfm(m_fm);
+ }
+ else
+ {
+ *m_fm = QFontMetrics(font);
+ }
+ m_ascent = m_fm->ascent();
+ m_descent = m_fm->descent();
+ m_linespacing = m_fm->lineSpacing();
+}
+
+void QTReader::drawFonts( QPainter *p )
+{
+ setfont(p);
+ if (m_lastwidth != width())
+ {
+ m_lastwidth = width();
+ locate(pagepos);
+ }
+ else
+ {
+ int sl = screenlines();
+ if (sl < numlines)
+ {
+// qDebug("df:<%u,%u>",sl,numlines);
+
+ size_t newpos = locnarray[sl];
+ CBuffer** nta = new CBuffer*[sl];
+ size_t* nla = new size_t[sl];
+ for (int i = 0; i < sl; i++)
+ {
+ nta[i] = textarray[i];
+ nla[i] = locnarray[i];
+ }
+ for (int i = sl; i < numlines; i++) delete textarray[i];
+ delete [] textarray;
+ delete [] locnarray;
+ textarray = nta;
+ locnarray = nla;
+ numlines = sl;
+ jumpto(mylastpos = newpos);
+// locate(pagepos);
+ }
+ if (sl > numlines)
+ {
+// qDebug("df:<%u,%u>",sl,numlines);
+ CBuffer** nta = new CBuffer*[sl];
+ size_t* nla = new size_t[sl];
+ for (int i = 0; i < numlines; i++)
+ {
+ nta[i] = textarray[i];
+ nla[i] = locnarray[i];
+ }
+ if (locate() != mylastpos) jumpto(mylastpos);
+ for (int i = numlines; i < sl; i++)
+ {
+ nta[i] = new CBuffer;
+ nla[i] = locate();
+ getline(nta[i]);
+ }
+ mylastpos = locate();
+ delete [] textarray;
+ delete [] locnarray;
+ textarray = nta;
+ locnarray = nla;
+ numlines = sl;
+ }
+ int ypos = (btight) ? 0 : m_ascent-m_linespacing;
+ // int linespacing = (tight) ? m_ascent : m_ascent+m_descent;
+ for (int i = 0; i < numlines; i++)
+ {
+ drawText( *p, 0, ypos += m_linespacing, textarray[i]->data());
+ }
+ /*
+
+
+
+ int nlines = height()/(fontmetric.ascent()+fontmetric.descent());
+ tchar buffer[1024];
+ for (int i = 0; i < nlines; i++)
+ {
+ y += fontmetric.ascent();
+ sprintf(buffer, "%d:%d:%s[%d]:Lines %d:%s", i+1, m_textfont, fonts[m_textfont], m_fs, nlines, (const tchar*)m_string);
+ drawText( *p, 0, y, buffer );
+ y += fontmetric.descent();
+ }
+ */
+ }
+ m_scrolldy = 0;
+}
+
+QString QTReader::firstword()
+{
+ if (m_bMonoSpaced)
+ {
+ return toQString(textarray[0]->data());
+ }
+ else
+ {
+ int start, end, len, j;
+ for (j = 0; j < numlines; j++)
+ {
+ len = textarray[j]->length();
+ for (start = 0; start < len && !isalpha((*textarray[j])[start]); start++);
+ if (start < len) break;
+ }
+ if (j < numlines)
+ {
+ QString ret = "";
+ for (end = start; end < len && isalpha((*textarray[j])[end]); end++)
+ ret += (*textarray[j])[end];
+ if (ret.isEmpty()) ret = "Current position";
+ return ret;
+ }
+ else
+ return "Current position";
+ }
+}
+
+//
+// Construct the QTReader with buttons.
+//
+
+void QTReader::ChangeFont(int tgt)
+{
+
+ QValueList<int>::Iterator it;
+
+// QValueList<int> sizes = QFontDatabase::pointSizes(m_fontname, (m_bBold) ? QFont::Bold : QFont::Normal);
+ QFontDatabase fdb;
+/*
+ QStringList styles = fdb.styles(m_fontname);
+ for ( QStringList::Iterator it = styles.begin(); it != styles.end(); ++it )
+ {
+ printf( "%s \n", (*it).latin1() );
+ }
+*/
+ QValueList<int> sizes = fdb.pointSizes(m_fontname, (m_bBold) ? QString("Bold") : QString::null);
+ uint n = sizes.count();
+ if (fontsizes != NULL) delete [] fontsizes;
+ fontsizes = new unsigned int[n+1];
+ uint i = 0;
+ uint best = 0;
+ for (it = sizes.begin(); it != sizes.end(); it++)
+ {
+ fontsizes[i] = (*it)/10;
+ if (abs(tgt-fontsizes[i]) < abs(tgt-fontsizes[best]))
+ {
+ best = i;
+ }
+ i++;
+ }
+ m_textsize = best;
+ fontsizes[i] = 0;
+ setfont(NULL);
+ QFont font(m_fontname, fontsizes[m_textsize], (m_bBold) ? QFont::Bold : QFont::Normal );
+ if (m_fm == NULL)
+ {
+ m_fm = new QFontMetrics(font);
+ buffdoc.setfm(m_fm);
+ }
+}
+
+void QTReader::init()
+{
+ // setCaption( "Qt Draw Demo Application" );
+
+ setBackgroundColor( white );
+// QPainter p(this);
+// p.setBackgroundMode( Qt::OpaqueMode );
+ buffdoc.setfilter(getfilter());
+ ChangeFont(m_textsize);
+ // setFocusPolicy(QWidget::StrongFocus);
+ // resize( 240, 320 );
+ //setFocus();
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(doscroll()));
+// QMessageBox::information(this, "init", m_lastfile, 1);
+ m_lastwidth = width();
+ if (!m_lastfile.isEmpty())
+ {
+ m_string = DocLnk(m_lastfile).name();
+ load_file(m_lastfile);
+ }
+}
+
+//
+// Clean up
+//
+QTReader::~QTReader()
+{
+ if (fontsizes != NULL) delete [] fontsizes;
+#ifndef QT_NO_PRINTER
+ // delete printer;
+#endif
+}
+
+//
+// Calls the drawing function as specified by the radio buttons.
+//
+
+void QTReader::drawIt( QPainter *p )
+{
+ drawFonts(p);
+}
+
+//
+// Called when the print button is clicked.
+//
+/*
+void QTReader::printIt()
+{
+#ifndef QT_NO_PRINTER
+ if ( printer->setup( this ) ) {
+ QPainter paint;
+ if ( !paint.begin( printer ) )
+ return;
+ drawIt( &paint );
+ }
+#endif
+}
+*/
+//
+// Called when the widget needs to be updated.
+//
+
+void QTReader::paintEvent( QPaintEvent * )
+{
+ QPainter paint( this );
+ drawIt( &paint );
+}
+
+//
+// Called when the widget has been resized.
+// Moves the button group to the upper right corner
+// of the widget.
+
+/*
+void QTReader::resizeEvent( QResizeEvent * )
+{
+ // qDebug("resize:(%u,%u)", width(), height());
+ // bgroup->move( width()-bgroup->width(), 0 );
+}
+*/
+
+//
+// Create and display our widget.
+//
+/*
+int main( int argc, tchar **argv )
+{
+ QApplication app( argc, argv );
+ QTReader draw;
+ app.setMainWidget( &draw );
+ draw.setCaption("Qt Example - Drawdemo");
+ draw.show();
+ return app.exec();
+}
+*/
+
+
+bool QTReader::locate(unsigned long n) {
+ //printf("Locate\n");
+ buffdoc.locate(n);
+ // qDebug("&buffdoc.located");
+ fillbuffer();
+ // qDebug("&Buffer filled");
+ update();
+ // qDebug("&Located");
+ return true;
+}
+
+unsigned int QTReader::screenlines()
+{
+ // int linespacing = (tight) ? m_ascent : m_ascent+m_descent;
+ // return (height()-m_descent)/(m_linespacing);
+ return (height()-2)/(m_linespacing);
+};
+
+bool QTReader::fillbuffer() {
+ //printf("Fillbuffer\n");
+ m_scrolldy = 0;
+ int ch;
+ bool ret = false;
+ int delta = screenlines();
+ // qDebug("fillbuffer:%u-%u",delta,numlines);
+ if (delta != numlines)
+ {
+ if (textarray != NULL)
+ {
+ for (int i = 0; i < numlines; i++) delete textarray[i];
+ delete [] textarray;
+ delete [] locnarray;
+ }
+ numlines = delta;
+ textarray = new CBuffer*[numlines];
+ locnarray = new size_t[numlines];
+ for (int i = 0; i < numlines; i++) textarray[i] = new CBuffer;
+ }
+ // qDebug("fillbuffer:pagepos:%u",pagepos);
+ unsigned int oldpagepos = pagepos;
+// if (textarray != NULL)
+// pagepos = locnarray[0];
+// else
+ pagepos = locate();
+ for (int i = 0; i < delta; i++)
+ {
+ locnarray[i] = locate();
+ ch = getline(textarray[i]);
+ // if (ch == EOF) {
+ if (!ch)
+ {
+ if (i == 0)
+ {
+ pagepos = oldpagepos;
+ return false;
+ }
+ else
+ {
+ ret = true;
+ for (int j = i+1; j < delta; j++)
+ {
+ locnarray[j] = locnarray[j-1];
+ (*(textarray[j]))[0] = '\0';
+ }
+ break;
+ }
+ }
+ if (ch == '\012') ret = true;
+ }
+ mylastpos = locate();
+ // qDebug("fillbuffer:lastpos:%u",mylastpos);
+ return true;
+}
+
+
+void QTReader::dopagedn()
+{
+ if (m_overlap == 0)
+ {
+ if (locate() != mylastpos) jumpto(mylastpos);
+ }
+ else
+ {
+ if (m_overlap >= screenlines()) m_overlap = screenlines()/2;
+ jumpto(locnarray[screenlines()-m_overlap]);
+ }
+ if (fillbuffer())
+ {
+ update();
+ }
+}
+
+void QTReader::dopageup()
+{
+ CBuffer** buff = textarray;
+ unsigned int *loc = new unsigned int[numlines];
+ int cbptr = 0;
+ if (locate() != mylastpos) jumpto(mylastpos);
+ if (m_overlap >= screenlines()) m_overlap = screenlines()/2;
+ unsigned int target = locnarray[m_overlap];
+ if (buffdoc.hasrandomaccess())
+ {
+ unsigned int delta = locate()-pagelocate();
+ if (delta < 64) delta = 64;
+ if (delta % 2 != 0) delta++;
+ if (target % 2 != 0) target++;
+ do
+ {
+ delta <<= 1;
+ if (delta >= target)
+ {
+ delta = target;
+ jumpto(0);
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ getline(buff[i]);
+ }
+ break;
+ }
+ jumpto(target-delta);
+ do
+ {
+ getline(buff[0]);
+#ifdef WS
+ //printf("Trying:%s\n",buff[0]);
+#endif
+ if (locate() > target) continue;
+ }
+ while (!buffdoc.iseol());
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ getline(buff[i]);
+#ifdef WS
+ //printf("Filling:%s\n",buff[i]);
+#endif
+ }
+ }
+ while (locate() >= target && delta < 4096);
+#ifdef WS
+ //printf("Delta:%u\n",delta);
+#endif
+ }
+ else
+ {
+ jumpto(0);
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ getline(buff[i]);
+ }
+ }
+ cbptr = 0;
+ while (locate() < target)
+ {
+ loc[cbptr] = locate();
+ getline(buff[cbptr]);
+#ifdef WS
+ //printf("Adding:%s\n",buff[cbptr]->data());
+#endif
+ cbptr = (cbptr+1) % numlines;
+ }
+ pagepos = loc[cbptr];
+ textarray = new CBuffer*[numlines];
+ for (int i = 0; i < numlines; i++)
+ {
+ int j = (cbptr+i)%numlines;
+ textarray[i] = buff[j];
+ locnarray[i] = loc[j];
+ }
+ delete [] buff;
+ delete [] loc;
+ mylastpos = locate();
+ update();
+}
+
+bool QTReader::load_file(const char *newfile, unsigned int _lcn)
+{
+// QMessageBox::information(this, "Name", name, 1);
+// QMessageBox::information(this, "load_file", newfile, 1);
+
+ bool bRC = false;
+ unsigned int lcn = _lcn;
+ if (m_lastfile == newfile)
+ {
+ lcn = m_lastposn;
+ }
+ m_lastfile = newfile;
+ // QMessageBox::information(0, "Opening...", newfile);
+ if (buffdoc.openfile(this,newfile) == 0)
+ {
+ bRC = true;
+ // qDebug("buffdoc.openfile done");
+ locate(lcn);
+ // qDebug("buffdoc.locate done");
+ }
+ update();
+ // qDebug("Updated");
+ return bRC;
+}
+
+void QTReader::lineDown()
+{
+ pagepos = locnarray[1];
+ CBuffer* buff = textarray[0];
+ for (int i = 1; i < numlines; i++)
+ {
+ textarray[i-1] = textarray[i];
+ locnarray[i-1] = locnarray[i];
+ }
+ locnarray[numlines-1] = locate();
+ if (getline(buff))
+ {
+ textarray[numlines-1] = buff;
+ mylastpos = locate();
+ }
+ else
+ {
+ textarray[numlines-1] = buff;
+ }
+ update();
+}
+/*
+void QTReader::lineUp()
+{
+ CBuffer** buff = textarray;
+ unsigned int *loc = new unsigned int[numlines];
+ int cbptr = 0;
+ if (locate() != mylastpos) jumpto(mylastpos);
+ unsigned int target = locnarray[numlines-1];
+ if (buffdoc.hasrandomaccess())
+ {
+ unsigned int delta = locate()-pagelocate();
+ if (delta < 64) delta = 64;
+ do
+ {
+ delta <<= 1;
+ if (delta >= target)
+ {
+ delta = target;
+ jumpto(0);
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ getline(buff[i]);
+ }
+ break;
+ }
+ jumpto(target-delta);
+ do
+ {
+ buffdoc.getline(buff[0],width());
+#ifdef WS
+ //printf("Trying:%s\n",buff[0]);
+#endif
+ if (locate() > target) continue;
+ }
+ while (!buffdoc.iseol());
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ buffdoc.getline(buff[i],width());
+#ifdef WS
+ //printf("Filling:%s\n",buff[i]);
+#endif
+ }
+ }
+ while (locate() >= target && delta < 4096);
+#ifdef WS
+ //printf("Delta:%u\n",delta);
+#endif
+ }
+ else
+ {
+ jumpto(0);
+ for (int i = 0; i < numlines; i++)
+ {
+ loc[i] = locate();
+ buffdoc.getline(buff[i],width());
+ }
+ }
+ cbptr = 0;
+ while (locate() < target)
+ {
+ loc[cbptr] = locate();
+ buffdoc.getline(buff[cbptr], width());
+#ifdef WS
+ //printf("Adding:%s\n",buff[cbptr]->data());
+#endif
+ cbptr = (cbptr+1) % numlines;
+ }
+ pagepos = loc[cbptr];
+ textarray = new CBuffer*[numlines];
+ for (int i = 0; i < numlines; i++)
+ {
+ int j = (cbptr+i)%numlines;
+ textarray[i] = buff[j];
+ locnarray[i] = loc[j];
+ }
+ delete [] buff;
+ delete [] loc;
+ mylastpos = locate();
+ update();
+}
+*/
+void QTReader::lineUp()
+{
+ CBuffer* buff = textarray[numlines-1];
+ unsigned int loc;
+ unsigned int end = locnarray[numlines-1];
+ int cbptr = 0;
+ if (locate() != mylastpos) jumpto(mylastpos);
+ unsigned int target = locnarray[0];
+ if (buffdoc.hasrandomaccess())
+ {
+ unsigned int delta = locate()-pagelocate();
+ if (delta < 64) delta = 64;
+ do
+ {
+ delta <<= 1;
+ if (delta >= target)
+ {
+ delta = target;
+ jumpto(0);
+ for (int i = 0; i < numlines; i++)
+ {
+ loc = locate();
+ getline(buff);
+ }
+ break;
+ }
+ jumpto(target-delta);
+ do
+ {
+ getline(buff);
+#ifdef WS
+ //printf("Trying:%s\n",buff[0]);
+#endif
+ if (locate() > target) continue;
+ }
+ while (!buffdoc.iseol());
+ loc = locate();
+ getline(buff);
+ }
+ while (locate() >= target && delta < 4096);
+ }
+ else
+ {
+ jumpto(0);
+ loc = locate();
+ getline(buff);
+ }
+ cbptr = 0;
+ while (locate() < target)
+ {
+ loc = locate();
+ getline(buff);
+ }
+ pagepos = loc;
+ for (int i = numlines-1; i > 0; i--)
+ {
+ textarray[i] = textarray[i-1];
+ locnarray[i] = locnarray[i-1];
+ }
+ textarray[0] = buff;
+ locnarray[0] = loc;
+// delete [] buff;
+// delete [] loc;
+ mylastpos = locate();
+ jumpto(end);
+ update();
+}
+
+bool QTReader::empty()
+{
+ return buffdoc.empty();
+}
diff --git a/noncore/apps/opie-reader/QTReader.h b/noncore/apps/opie-reader/QTReader.h
new file mode 100644
index 0000000..2efb988
--- a/dev/null
+++ b/noncore/apps/opie-reader/QTReader.h
@@ -0,0 +1,217 @@
+#ifndef __QTREADER_H
+#define __QTREADER_H
+
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qclipboard.h>
+#include "CBuffer.h"
+#include "my_list.h"
+#include "BuffDoc.h"
+#include <qtimer.h>
+
+class QTReader : public QWidget
+{
+ Q_OBJECT
+
+ friend class QTReaderApp;
+ void drawText(QPainter& p, int x, int y, tchar* text);
+ int m_delay;
+ unsigned int m_overlap;
+ bool m_autoScroll;
+ void autoscroll();
+ QTimer* timer;
+ int m_scrolldy, m_encd;
+ void focusInEvent(QFocusEvent*);
+ void focusOutEvent(QFocusEvent*);
+ void ChangeFont(int);
+ bool getline(CBuffer*);
+ int m_charWidth;
+ int m_charpc;
+public:
+ QTReader( QWidget *parent=0, const char *name=0, WFlags f = 0);
+ // QTReader( const QString& filename, QWidget *parent=0, const tchar *name=0, WFlags f = 0);
+ ~QTReader();
+ bool empty();
+ void toggle_autoscroll();
+ void setautoscroll(bool);
+ void disableAutoscroll() { m_autoScroll = false; }
+ void copy()
+ {
+/*
+ size_t nd = locate();
+ jumpto(m_mark);
+ QString text;
+ while (m_mark < nd)
+ {
+ text += buffdoc.getch();
+ m_mark++;
+ }
+ QApplication::clipboard()->setText(text);
+ jumpto(nd);
+*/
+ };
+ void clear() {};
+ void setText(const QString& n, const QString& s) { m_string = n; load_file((const char*)s); };
+ /*
+ void setText(bool oldfile)
+ {
+ if (oldfile)
+ {
+ m_string = m_lastfile;
+ load_file((const tchar*)m_string);
+ }
+ else
+ {
+ m_string = QString::null;
+ }
+ };
+ */
+ void setstripcr(bool _b)
+ {
+ bstripcr = _b;
+ setfilter(getfilter());
+ }
+ void setstriphtml(bool _b)
+ {
+ bstriphtml = _b;
+ setfilter(getfilter());
+ }
+ void setdehyphen(bool _b)
+ {
+ bdehyphen = _b;
+ setfilter(getfilter());
+ }
+ void setunindent(bool _b)
+ {
+ bunindent = _b;
+ setfilter(getfilter());
+ }
+ void setrepara(bool _b)
+ {
+ brepara = _b;
+ setfilter(getfilter());
+ }
+ void setdblspce(bool _b)
+ {
+ bdblspce = _b;
+ setfilter(getfilter());
+ }
+ void indentplus()
+ {
+ if (bindenter < 15) bindenter += 2;
+ setfilter(getfilter());
+ }
+ void indentminus()
+ {
+ if (bindenter > 1) bindenter -= 2;
+ setfilter(getfilter());
+ }
+ void setpagemode(bool _b)
+ {
+ m_bpagemode = _b;
+ }
+ void setmono(bool _b)
+ {
+ m_bMonoSpaced = _b;
+ ChangeFont(fontsizes[m_textsize]);
+ locate(pagepos);
+ }
+ void setencoding(int _f)
+ {
+ m_encd = _f;
+ setfilter(getfilter());
+ }
+ CEncoding* getencoding()
+ {
+ switch (m_encd)
+ {
+ case 5:
+ return new Ccp1252;
+ case 4:
+ return new CPalm;
+ case 1:
+ return new CUtf8;
+ case 2:
+ return new CUcs16be;
+ case 3:
+ return new CUcs16le;
+ case 0:
+ default:
+ return new CAscii;
+ }
+ }
+ CFilterChain* getfilter()
+ {
+ CFilterChain * filt = new CFilterChain(getencoding());
+ if (bstripcr) filt->addfilter(new stripcr);
+ if (bstriphtml) filt->addfilter(new striphtml);
+ if (bdehyphen) filt->addfilter(new dehyphen);
+ if (bunindent) filt->addfilter(new unindent);
+ if (brepara) filt->addfilter(new repara);
+ if (bindenter) filt->addfilter(new indenter(bindenter));
+ if (bdblspce) filt->addfilter(new dblspce);
+ return filt;
+ }
+
+
+private slots:
+ void doscroll();
+ void drawIt( QPainter * );
+ void paintEvent( QPaintEvent * );
+// void resizeEvent( QResizeEvent * p ) { update(); }
+ void keyPressEvent(QKeyEvent*);
+ void drawFonts(QPainter*);
+ private:
+ void init();
+ void mouseReleaseEvent( QMouseEvent* );
+// void mouseDoubleClickEvent( QMouseEvent* );
+ QString m_string, m_fontname;
+ void setfont(QPainter*);
+ //myoutput stuff
+ private:
+ void dopageup();
+ void lineDown();
+ void lineUp();
+ void dopagedn();
+ long real_delay();
+ int m_textsize;
+ int m_lastwidth;
+ CBuffer** textarray;
+ size_t* locnarray;
+ unsigned int numlines;
+ bool bstripcr, bstriphtml, bdehyphen, bunindent, brepara, bdblspce, btight, m_bBold;
+ bool m_bpagemode, m_bMonoSpaced;
+ QString m_targetapp, m_targetmsg;
+ unsigned char bindenter;
+ QString m_lastfile;
+ size_t m_lastposn;
+ public:
+ int getch() { return buffdoc.getch(); }
+ bool tight;
+ bool load_file(const char *newfile, unsigned int lcn=0);
+ BuffDoc buffdoc;
+ CList<Bkmk>* getbkmklist() { return buffdoc.getbkmklist(); }
+ bool locate(unsigned long n);
+ void jumpto(unsigned long n) { buffdoc.locate(n); }
+ unsigned long locate() { return buffdoc.locate(); }
+ unsigned long pagelocate() { return pagepos; }
+ unsigned long pagepos, mylastpos;
+ void setfilter(CFilterChain *f) { buffdoc.setfilter(f); locate(pagepos); }
+ void restore() { jumpto(mylastpos); }
+ void goUp();
+ void refresh() { locate(pagepos); }
+ void goDown();
+ // bool bold;
+ int textsize() { return m_textsize; }
+ void textsize(int ts) { m_textsize = ts; }
+ bool fillbuffer();
+ unsigned int screenlines();
+ void sizes(unsigned long& fs, unsigned long& ts) { buffdoc.sizes(fs,ts); }
+ static const char *fonts[];
+ unsigned int *fontsizes;
+ int m_ascent, m_descent, m_linespacing;
+ QFontMetrics* m_fm;
+ QString firstword();
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/QTReaderApp.cpp b/noncore/apps/opie-reader/QTReaderApp.cpp
new file mode 100644
index 0000000..620e93e
--- a/dev/null
+++ b/noncore/apps/opie-reader/QTReaderApp.cpp
@@ -0,0 +1,1433 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qt Palmtop Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#include <qwidgetstack.h>
+#include <qpe/qpemenubar.h>
+#include <qpe/qpetoolbar.h>
+#include <qpe/fontdatabase.h>
+#include <qcombobox.h>
+#include <qpopupmenu.h>
+#include <qaction.h>
+#include <qapplication.h>
+#include <qlineedit.h>
+#include <qtoolbutton.h>
+#include <qspinbox.h>
+#include <qobjectlist.h>
+#include <qpe/global.h>
+#include <qpe/applnk.h>
+#include <qfileinfo.h>
+#include <stdlib.h> //getenv
+#include <qprogressbar.h>
+#include <qpe/config.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+
+#include "cbkmkselector.h"
+#include "infowin.h"
+
+//#include <qpe/fontdatabase.h>
+
+#include <qpe/resource.h>
+#include <qpe/qpeapplication.h>
+
+#include "QTReaderApp.h"
+#include "fileBrowser.h"
+
+
+unsigned long QTReaderApp::m_uid = 0;
+
+void QTReaderApp::setScrollState(bool _b) { m_scrollButton->setOn(_b); }
+
+#include <unistd.h>
+#include <stddef.h>
+#include <dirent.h>
+
+void QTReaderApp::listBkmkFiles()
+{
+ bkmkselector->clear();
+ int cnt = 0;
+ DIR *d;
+ d = opendir((const char *)Global::applicationFileName("uqtreader",""));
+
+ while(1)
+ {
+ struct dirent* de;
+ struct stat buf;
+ de = readdir(d);
+ if (de == NULL) break;
+
+ if (lstat((const char *)Global::applicationFileName("uqtreader",de->d_name),&buf) == 0 && S_ISREG(buf.st_mode))
+ {
+ bkmkselector->insertItem(de->d_name);
+ cnt++;
+ }
+ }
+
+ closedir(d);
+
+ if (cnt > 0)
+ {
+ menu->hide();
+ editBar->hide();
+ if (m_fontVisible) m_fontBar->hide();
+ if (regVisible) regBar->hide();
+ if (searchVisible) searchBar->hide();
+ m_nRegAction = cRmBkmkFile;
+ editorStack->raiseWidget( bkmkselector );
+ }
+ else
+ QMessageBox::information(this, "QTReader", "No bookmark files");
+}
+
+QTReaderApp::QTReaderApp( QWidget *parent, const char *name, WFlags f )
+ : QMainWindow( parent, name, f ), bFromDocView( FALSE )
+{
+// qDebug("Application directory = %s", (const tchar *)QPEApplication::documentDir());
+// qDebug("Application directory = %s", (const tchar *)Global::applicationFileName("uqtreader","bkmks.xml"));
+
+ pBkmklist = NULL;
+ doc = 0;
+
+ m_fBkmksChanged = false;
+
+ QString lang = getenv( "LANG" );
+
+ m_autogenstr = "^ *[A-Z].*[a-z] *$";
+ setToolBarsMovable( FALSE );
+
+ setIcon( Resource::loadPixmap( "uqtreader" ) );
+
+ QPEToolBar *bar = new QPEToolBar( this );
+ bar->setHorizontalStretchable( TRUE );
+ addToolBar(bar, "tool",QMainWindow::Top, true);
+ menu = bar;
+
+ QPEMenuBar *mb = new QPEMenuBar( bar );
+ QPopupMenu *file = new QPopupMenu( this );
+ QPopupMenu *format = new QPopupMenu( this );
+ // QPopupMenu *edit = new QPopupMenu( this );
+
+// bar = new QToolBar( this );
+ editBar = bar;
+
+ /*
+ QAction *a = new QAction( tr( "New" ), Resource::loadPixmap( "new" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( fileNew() ) );
+ a->addTo( bar );
+ a->addTo( file );
+ */
+
+ editorStack = new QWidgetStack( this );
+ setCentralWidget( editorStack );
+
+ searchVisible = FALSE;
+ regVisible = FALSE;
+ m_fontVisible = false;
+
+ pbar = new QProgressBar(this);
+ pbar->hide();
+
+ m_infoWin = new infowin(editorStack);
+ editorStack->addWidget(m_infoWin, get_unique_id());
+ connect( m_infoWin, SIGNAL( Close() ), this, SLOT( infoClose() ) );
+
+// bkmkselector = new QListBox(editorStack, "Bookmarks");
+ bkmkselector = new CBkmkSelector(editorStack, "Bookmarks");
+ // connect(bkmkselector, SIGNAL( selected(const QString&) ), this, SLOT( gotobkmk(const QString&) ) );
+ connect(bkmkselector, SIGNAL( selected(int) ), this, SLOT( gotobkmk(int) ) );
+ connect(bkmkselector, SIGNAL( cancelled() ), this, SLOT( cancelbkmk() ) );
+ editorStack->addWidget( bkmkselector, get_unique_id() );
+
+/*
+ importSelector = new FileSelector( "*", editorStack, "importselector", false );
+ connect( importSelector, SIGNAL( fileSelected( const DocLnk &) ), this, SLOT( importFile( const DocLnk & ) ) );
+
+ editorStack->addWidget( importSelector, get_unique_id() );
+
+ // don't need the close visible, it is redundant...
+ importSelector->setCloseVisible( FALSE );
+*/
+
+ reader = new QTReader( editorStack );
+ Config config( "uqtreader" );
+ config.setGroup( "View" );
+
+ reader->bstripcr = config.readBoolEntry( "StripCr", true );
+ reader->bstriphtml = config.readBoolEntry( "StripHtml", false );
+ reader->bdehyphen = config.readBoolEntry( "Dehyphen", false );
+ reader->bunindent = config.readBoolEntry( "Unindent", false );
+ reader->brepara = config.readBoolEntry( "Repara", false );
+ reader->bdblspce = config.readBoolEntry( "DoubleSpace", false );
+ reader->bindenter = config.readNumEntry( "Indent", 0 );
+ reader->m_textsize = config.readNumEntry( "FontSize", 12 );
+ reader->m_bBold = config.readBoolEntry( "Bold", false );
+ reader->m_delay = config.readNumEntry( "ScrollDelay", 5184);
+ reader->m_lastfile = config.readEntry( "LastFile", QString::null );
+ reader->m_lastposn = config.readNumEntry( "LastPosn", 0 );
+ reader->m_bpagemode = config.readBoolEntry( "PageMode", true );
+ reader->m_bMonoSpaced = config.readBoolEntry( "MonoSpaced", false);
+ reader->m_fontname = config.readEntry( "Fontname", "helvetica" );
+ reader->m_encd = config.readNumEntry( "Encoding", 0 );
+ reader->m_charpc = config.readNumEntry( "CharSpacing", 100 );
+ reader->m_overlap = config.readNumEntry( "Overlap", 0 );
+ reader->m_targetapp = config.readEntry( "TargetApp", QString::null );
+ reader->m_targetmsg = config.readEntry( "TargetMsg", QString::null );
+ reader->init();
+ editorStack->addWidget( reader, get_unique_id() );
+
+ QAction *a = new QAction( tr( "Open" ), Resource::loadPixmap( "fileopen" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( fileOpen() ) );
+ a->addTo( bar );
+ a->addTo( file );
+
+ /*
+ a = new QAction( tr( "Revert" ), Resource::loadPixmap( "close" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( fileRevert() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Cut" ), Resource::loadPixmap( "cut" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( editCut() ) );
+ a->addTo( editBar );
+ a->addTo( edit );
+ */
+
+ a = new QAction( tr( "Info" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( showinfo() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Start Block" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( editMark() ) );
+ file->insertSeparator();
+ a->addTo( file );
+
+ a = new QAction( tr( "Copy Block" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( editCopy() ) );
+ a->addTo( file );
+
+ a = m_scrollButton = new QAction( tr( "Scroll" ), Resource::loadPixmap( "panel-arrow-down" ), QString::null, 0, this, 0, true );
+// connect( a, SIGNAL( activated() ), this, SLOT( autoScroll() ) );
+ a->setOn(false);
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( autoScroll(bool) ) );
+ file->insertSeparator();
+ a->addTo( bar );
+ a->addTo( file );
+
+ /*
+ a = new QAction( tr( "Find" ), QString::null, 0, this, NULL, true );
+ // connect( a, SIGNAL( activated() ), this, SLOT( pagedn() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Find Again" ), QString::null, 0, this, NULL, true );
+ // connect( a, SIGNAL( activated() ), this, SLOT( pagedn() ) );
+ a->addTo( file );
+ */
+ a = new QAction( tr( "Jump" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( jump() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Page/Line scroll" ), QString::null, 0, this, NULL, true );
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( pagemode(bool) ) );
+ a->setOn(reader->m_bpagemode);
+ a->addTo( file );
+
+ a = new QAction( tr( "Set Overlap" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( setoverlap() ) );
+ a->addTo( file );
+
+ a = new QAction( tr( "Set Dictionary" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( settarget() ) );
+ a->addTo( file );
+
+/*
+ a = new QAction( tr( "Import" ), QString::null, 0, this, NULL );
+ connect( a, SIGNAL( activated() ), this, SLOT( importFiles() ) );
+ a->addTo( file );
+*/
+
+ a = new QAction( tr( "Up" ), Resource::loadPixmap( "up" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( pageup() ) );
+ a->addTo( editBar );
+
+ a = new QAction( tr( "Down" ), Resource::loadPixmap( "down" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( pagedn() ) );
+ a->addTo( editBar );
+
+ /*
+ a = new QAction( tr( "Paste" ), Resource::loadPixmap( "paste" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( editPaste() ) );
+ a->addTo( editBar );
+ a->addTo( edit );
+ */
+
+ a = new QAction( tr( "Find..." ), Resource::loadPixmap( "find" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( editFind() ) );
+ file->insertSeparator();
+ a->addTo( bar );
+ a->addTo( file );
+
+
+ a = new QAction( tr( "Strip CR" ), QString::null, 0, this, NULL, true );
+ a->setOn(reader->bstripcr);
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( stripcr(bool) ) );
+ a->addTo( format );
+ // a->setOn(true);
+
+ a = new QAction( tr( "Strip HTML" ), QString::null, 0, this, NULL, true );
+ a->setOn(reader->bstriphtml);
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( striphtml(bool) ) );
+ a->addTo( format );
+
+ a = new QAction( tr( "Dehyphen" ), QString::null, 0, this, NULL, true );
+ a->setOn(reader->bdehyphen);
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( dehyphen(bool) ) );
+ a->addTo( format );
+
+ a = new QAction( tr( "Unindent" ), QString::null, 0, this, NULL, true );
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( unindent(bool) ) );
+ a->setOn(reader->bunindent);
+ a->addTo( format );
+
+ a = new QAction( tr( "Re-paragraph" ), QString::null, 0, this, NULL, true );
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( repara(bool) ) );
+ a->setOn(reader->brepara);
+ a->addTo( format );
+
+ a = new QAction( tr( "Double Space" ), QString::null, 0, this, NULL, true );
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( dblspce(bool) ) );
+ a->setOn(reader->bdblspce);
+ a->addTo( format );
+
+ a = new QAction( tr( "Indent+" ), QString::null, 0, this, NULL );
+ connect( a, SIGNAL( activated() ), this, SLOT( indentplus() ) );
+ a->addTo( format );
+
+ a = new QAction( tr( "Indent-" ), QString::null, 0, this, NULL );
+ connect( a, SIGNAL( activated() ), this, SLOT( indentminus() ) );
+ a->addTo( format );
+
+ a = new QAction( tr( "Bold" ), QString::null, 0, this, NULL, true );
+ a->setOn(reader->m_bBold);
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( setbold(bool) ) );
+ a->addTo( format );
+
+ // a = new QAction( tr( "Zoom" ), QString::null, 0, this, NULL, true );
+ // a = new QAction( tr( "Zoom" ), Resource::loadPixmap( "mag" ), QString::null, 0, this, 0 );
+ a = new QAction( tr( "Zoom" ), QString::null, 0, this);
+ connect( a, SIGNAL( activated() ), this, SLOT( TBDzoom() ) );
+ format->insertSeparator();
+ a->addTo( format );
+ // a->addTo( editBar );
+
+
+ a = new QAction( tr( "Ideogram/Word" ), QString::null, 0, this, NULL, true );
+ connect( a, SIGNAL( toggled(bool) ), this, SLOT( monospace(bool) ) );
+ a->setOn(reader->m_bMonoSpaced);
+ format->insertSeparator();
+ a->addTo( format );
+
+ a = new QAction( tr( "Set width" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( setspacing() ) );
+ a->addTo( format );
+
+ QPopupMenu *encoding = new QPopupMenu(this);
+ format->insertSeparator();
+ format->insertItem( tr( "Encoding" ), encoding );
+
+ QActionGroup* ag = new QActionGroup(this);
+
+ m_EncodingAction[0] = new QAction( tr( "Ascii" ), QString::null, 0, ag, NULL, true );
+
+ m_EncodingAction[1] = new QAction( tr( "UTF-8" ), QString::null, 0, ag, NULL, true );
+
+ m_EncodingAction[2] = new QAction( tr( "UCS-2(BE)" ), QString::null, 0, ag, NULL, true );
+
+ m_EncodingAction[3] = new QAction( tr( "USC-2(LE)" ), QString::null, 0, ag, NULL, true );
+
+ m_EncodingAction[4] = new QAction( tr( "Palm" ), QString::null, 0, ag, NULL, true );
+
+ m_EncodingAction[5] = new QAction( tr( "Windows(1252)" ), QString::null, 0, ag, NULL, true );
+
+ ag->addTo(encoding);
+
+ connect(ag, SIGNAL( selected(QAction*) ), this, SLOT( encodingSelected(QAction*) ) );
+
+ a = new QAction( tr( "Set Font" ), QString::null, 0, this);
+ connect( a, SIGNAL( activated() ), this, SLOT( setfont() ) );
+ format->insertSeparator();
+ a->addTo( format );
+
+ QPopupMenu *marks = new QPopupMenu( this );
+
+ a = new QAction( tr( "Mark" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( addbkmk() ) );
+ a->addTo( marks );
+
+ a = new QAction( tr( "Goto" ), QString::null, 0, this, NULL, false );
+ connect( a, SIGNAL( activated() ), this, SLOT( do_gotomark() ) );
+ a->addTo( marks );
+
+ a = new QAction( tr( "Delete" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( do_delmark() ) );
+ a->addTo( marks );
+
+ a = new QAction( tr( "Autogen" ), QString::null, 0, this, NULL, false );
+ connect( a, SIGNAL( activated() ), this, SLOT( do_autogen() ) );
+ marks->insertSeparator();
+ a->addTo( marks );
+
+ a = new QAction( tr( "Clear" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( clearBkmkList() ) );
+ a->addTo( marks );
+
+ a = new QAction( tr( "Save" ), QString::null, 0, this, NULL );
+ connect( a, SIGNAL( activated() ), this, SLOT( savebkmks() ) );
+ a->addTo( marks );
+
+ a = new QAction( tr( "Tidy" ), QString::null, 0, this, NULL);
+ connect( a, SIGNAL( activated() ), this, SLOT( listBkmkFiles() ) );
+ marks->insertSeparator();
+ a->addTo( marks );
+
+ mb->insertItem( tr( "File" ), file );
+ // mb->insertItem( tr( "Edit" ), edit );
+ mb->insertItem( tr( "Format" ), format );
+ mb->insertItem( tr( "Marks" ), marks );
+
+ searchBar = new QToolBar( "Search", this, QMainWindow::Top, TRUE );
+
+ searchBar->setHorizontalStretchable( TRUE );
+
+ searchEdit = new QLineEdit( searchBar, "searchEdit" );
+// QFont f("unifont", 16 /*, QFont::Bold*/);
+// searchEdit->setFont( f );
+ searchBar->setStretchableWidget( searchEdit );
+#ifdef __ISEARCH
+ connect( searchEdit, SIGNAL( textChanged( const QString & ) ),
+ this, SLOT( search( const QString& ) ) );
+#else
+ connect( searchEdit, SIGNAL( returnPressed( ) ),
+ this, SLOT( search( ) ) );
+#endif
+ a = new QAction( tr( "Find Next" ), Resource::loadPixmap( "next" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( findNext() ) );
+ a->addTo( searchBar );
+
+ a = new QAction( tr( "Close Find" ), Resource::loadPixmap( "close" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( findClose() ) );
+ a->addTo( searchBar );
+
+ searchBar->hide();
+
+ regBar = new QToolBar( "Autogen", this, QMainWindow::Top, TRUE );
+
+ regBar->setHorizontalStretchable( TRUE );
+
+ regEdit = new QLineEdit( regBar, "regEdit" );
+// regEdit->setFont( f );
+
+ regBar->setStretchableWidget( regEdit );
+
+ connect( regEdit, SIGNAL( returnPressed( ) ),
+ this, SLOT( do_regaction() ) );
+
+ a = new QAction( tr( "Do Reg" ), Resource::loadPixmap( "enter" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( do_regaction() ) );
+ a->addTo( regBar );
+
+ a = new QAction( tr( "Close Edit" ), Resource::loadPixmap( "close" ), QString::null, 0, this, 0 );
+ connect( a, SIGNAL( activated() ), this, SLOT( regClose() ) );
+ a->addTo( regBar );
+
+ regBar->hide();
+
+ m_fontBar = new QToolBar( "Autogen", this, QMainWindow::Top, TRUE );
+
+ m_fontBar->setHorizontalStretchable( TRUE );
+
+ m_fontSelector = new QComboBox(false, m_fontBar);
+ m_fontBar->setStretchableWidget( m_fontSelector );
+ {
+ FontDatabase f;
+ m_fontSelector->insertStringList(f.families());
+ } // delete the FontDatabase!!!
+ connect( m_fontSelector, SIGNAL( activated(const QString& ) ),
+ this, SLOT( do_setfont(const QString&) ) );
+
+ m_fontBar->hide();
+ m_fontVisible = false;
+
+ connect(qApp, SIGNAL( appMessage(const QCString&, const QByteArray& ) ),
+ this, SLOT( msgHandler(const QCString&, const QByteArray&) ) );
+
+
+ if (!reader->m_lastfile.isEmpty())
+ {
+ openFile( reader->m_lastfile );
+ doc = new DocLnk(reader->m_lastfile);
+ }
+ m_EncodingAction[reader->m_encd]->setOn(true);
+ do_setfont(reader->m_fontname);
+}
+
+void QTReaderApp::msgHandler(const QCString& _msg, const QByteArray& _data)
+{
+ QString msg = QString::fromUtf8(_msg);
+
+// qDebug("Received:%s", (const char*)msg);
+
+ QDataStream stream( _data, IO_ReadOnly );
+ if ( msg == "info(QString)" )
+ {
+ QString info;
+ stream >> info;
+ QMessageBox::information(this, "QTReader", info);
+ } else if ( msg == "warn(QString)" )
+ {
+ QString info;
+ stream >> info;
+ QMessageBox::warning(this, "QTReader", info);
+ }
+}
+
+int QTReaderApp::EncNameToInt(const QString& _enc)
+{
+ for (int i = 0; i < MAX_ENCODING; i++)
+ {
+ if (m_EncodingAction[i]->text() == _enc) return i;
+ }
+ return 0;
+/*
+ if (_enc == "Ascii") return 0;
+ if (_enc == "UTF-8") return 1;
+ if (_enc == "UCS-2(BE)") return 2;
+ if (_enc == "USC-2(LE)") return 3;
+*/
+}
+
+void QTReaderApp::encodingSelected(QAction* _a)
+{
+// qDebug("es:%x : %s", _a, (const char *)(_a->text()));
+ reader->setencoding(EncNameToInt(_a->text()));
+}
+
+QTReaderApp::~QTReaderApp()
+{
+}
+
+void QTReaderApp::autoScroll(bool _b)
+{
+ reader->setautoscroll(_b);
+}
+
+void QTReaderApp::TBD()
+{
+ QMessageBox::information(this, "QTReader", "Not yet implemented", 1);
+}
+
+void QTReaderApp::TBDzoom()
+{
+ QMessageBox::information(this, "QTReader", "Zooming is done interactively\nTry left/right cursor keys", 1);
+}
+
+void QTReaderApp::clearBkmkList()
+{
+ delete pBkmklist;
+ pBkmklist = NULL;
+ m_fBkmksChanged = false;
+}
+
+void QTReaderApp::fileOpen()
+{
+/*
+ menu->hide();
+ editBar->hide();
+ if (regVisible) regBar->hide();
+ if (searchVisible) searchBar->hide();
+*/
+ if (pBkmklist != NULL)
+ {
+ if (m_fBkmksChanged)
+ {
+ if (QMessageBox::warning(this, "QTReader", "Save bookmarks?", "Save", "Don't bother") == 0)
+ savebkmks();
+ }
+ delete pBkmklist;
+ pBkmklist = NULL;
+ m_fBkmksChanged = false;
+ }
+ reader->disableAutoscroll();
+/*
+ editorStack->raiseWidget( fileSelector );
+ fileSelector->reread();
+*/
+ fileBrowser* fb = new fileBrowser(this,"QTReader",TRUE,
+ 0,
+// WStyle_Customize | WStyle_NoBorderEx,
+ "*", QFileInfo(reader->m_lastfile).dirPath(true));
+
+ if (fb->exec())
+ {
+ QString fn(fb->fileList[0]);
+// fb->populateList();
+ if (!fn.isEmpty() && QFileInfo(fn).isFile()) openFile(fn);
+ }
+ delete fb;
+}
+
+void QTReaderApp::showinfo()
+{
+ unsigned long fs, ts, pl;
+ if (reader->empty())
+ {
+ QMessageBox::information(this, "QTReader", "No file loaded", 1);
+ }
+ else
+ {
+ reader->sizes(fs,ts);
+ pl = reader->pagelocate();
+ m_infoWin->setFileSize(fs);
+ m_infoWin->setTextSize(ts);
+ m_infoWin->setRatio(100-(100*fs + (ts >> 1))/ts);
+ m_infoWin->setLocation(pl);
+ m_infoWin->setRead((100*pl + (ts >> 1))/ts);
+ editorStack->raiseWidget( m_infoWin );
+ m_infoWin->setFocus();
+ }
+}
+
+void QTReaderApp::infoClose()
+{
+ showEditTools();
+}
+
+/*
+void QTReaderApp::fileRevert()
+{
+ clear();
+ fileOpen();
+}
+
+void QTReaderApp::editCut()
+{
+#ifndef QT_NO_CLIPBOARD
+ editor->cut();
+#endif
+}
+*/
+void QTReaderApp::editMark()
+{
+ m_savedpos = reader->pagelocate();
+}
+
+void QTReaderApp::editCopy()
+{
+ QClipboard* cb = QApplication::clipboard();
+ QString text;
+ int ch;
+ unsigned long currentpos = reader->pagelocate();
+ unsigned long endpos = reader->locate();
+ reader->jumpto(m_savedpos);
+ while (reader->locate() < endpos && (ch = reader->getch()) != UEOF)
+ {
+ text += ch;
+ }
+ cb->setText(text);
+// text = cb->text();
+// if (text)
+// qDebug("The clipboard contains: %s", (const tchar*)text);
+ reader->locate(currentpos);
+#ifndef QT_NO_CLIPBOARD
+// TBD();
+ // reader->copy();
+#endif
+}
+
+void QTReaderApp::pageup()
+{
+ reader->goUp();
+}
+
+void QTReaderApp::pagedn()
+{
+ reader->goDown();
+}
+
+void QTReaderApp::stripcr(bool _b)
+{
+ reader->setstripcr(_b);
+}
+void QTReaderApp::striphtml(bool _b)
+{
+ reader->setstriphtml(_b);
+}
+void QTReaderApp::dehyphen(bool _b)
+{
+ reader->setdehyphen(_b);
+}
+void QTReaderApp::unindent(bool _b)
+{
+ reader->setunindent(_b);
+}
+void QTReaderApp::repara(bool _b)
+{
+ reader->setrepara(_b);
+}
+void QTReaderApp::setbold(bool _b)
+{
+ reader->m_bBold = _b;
+ reader->ChangeFont(reader->fontsizes[reader->m_textsize]);
+ reader->refresh();
+}
+void QTReaderApp::dblspce(bool _b)
+{
+ reader->setdblspce(_b);
+}
+void QTReaderApp::pagemode(bool _b)
+{
+ reader->setpagemode(_b);
+}
+
+void QTReaderApp::monospace(bool _b)
+{
+ reader->setmono(_b);
+}
+
+void QTReaderApp::setspacing()
+{
+ m_nRegAction = cMonoSpace;
+ char lcn[20];
+ sprintf(lcn, "%lu", reader->m_charpc);
+ regEdit->setText(lcn);
+ do_regedit();
+}
+
+void QTReaderApp::setoverlap()
+{
+ m_nRegAction = cOverlap;
+ char lcn[20];
+ sprintf(lcn, "%lu", reader->m_overlap);
+ regEdit->setText(lcn);
+ do_regedit();
+}
+
+void QTReaderApp::settarget()
+{
+ m_nRegAction = cSetTarget;
+ QString text = ((reader->m_targetapp.isEmpty()) ? QString("") : reader->m_targetapp)
+ + "/"
+ + ((reader->m_targetmsg.isEmpty()) ? QString("") : reader->m_targetmsg);
+ regEdit->setText(text);
+ do_regedit();
+}
+
+void QTReaderApp::do_overlap(const QString& lcn)
+{
+ bool ok;
+ unsigned long ulcn = lcn.toULong(&ok);
+ if (ok)
+ {
+ reader->m_overlap = ulcn;
+ }
+ else
+ QMessageBox::information(this, "QTReader", "Must be a number");
+}
+
+void QTReaderApp::do_mono(const QString& lcn)
+{
+ bool ok;
+ unsigned long ulcn = lcn.toULong(&ok);
+ if (ok)
+ {
+ reader->m_charpc = ulcn;
+// reader->setmono(true);
+ }
+ else
+ QMessageBox::information(this, "QTReader", "Must be a number");
+}
+
+/*
+void QTReaderApp::editPaste()
+{
+#ifndef QT_NO_CLIPBOARD
+ editor->paste();
+#endif
+}
+*/
+
+void QTReaderApp::editFind()
+{
+ searchStart = reader->pagelocate();
+#ifdef __ISEARCH
+ searchStack = new QStack<searchrecord>;
+#endif
+ searchBar->show();
+ searchVisible = TRUE;
+ searchEdit->setFocus();
+#ifdef __ISEARCH
+ searchStack->push(new searchrecord("",reader->pagelocate()));
+#endif
+}
+
+void QTReaderApp::findNext()
+{
+ // qDebug("findNext called\n");
+#ifdef __ISEARCH
+ QString arg = searchEdit->text();
+#else
+ QRegExp arg = searchEdit->text();
+#endif
+ CBuffer test;
+ size_t start = reader->pagelocate();
+ reader->jumpto(start);
+ reader->buffdoc.getline(&test,reader->width());
+ dosearch(start, test, arg);
+}
+
+void QTReaderApp::findClose()
+{
+ searchVisible = FALSE;
+ searchEdit->setText("");
+ searchBar->hide();
+#ifdef __ISEARCH
+// searchStack = new QStack<searchrecord>;
+ while (!searchStack->isEmpty())
+ {
+ delete searchStack->pop();
+ }
+ delete searchStack;
+#endif
+ reader->setFocus();
+}
+
+void QTReaderApp::regClose()
+{
+ regVisible = FALSE;
+ regEdit->setText("");
+ regBar->hide();
+ reader->setFocus();
+}
+
+#ifdef __ISEARCH
+bool QTReaderApp::dosearch(size_t start, CBuffer& test, const QString& arg)
+#else
+bool QTReaderApp::dosearch(size_t start, CBuffer& test, const QRegExp& arg)
+#endif
+{
+ bool ret = true;
+ size_t pos = start;
+ reader->buffdoc.getline(&test,reader->width());
+#ifdef __ISEARCH
+ while (strstr(test.data(),(const tchar*)arg) == NULL)
+#else
+#ifdef _UNICODE
+ while (arg.match(toQString(test.data())) == -1)
+#else
+ while (arg.match(test.data()) == -1)
+#endif
+#endif
+ {
+ pos = reader->locate();
+ if (!reader->buffdoc.getline(&test,reader->width()))
+ {
+ if (QMessageBox::warning(this, "Can't find", searchEdit->text(), 1, 2) == 2)
+ pos = searchStart;
+ else
+ pos = start;
+ ret = false;
+ findClose();
+ break;
+ }
+ }
+ reader->locate(pos);
+ return ret;
+}
+
+#ifdef __ISEARCH
+void QTReaderApp::search(const QString & arg)
+{
+ searchrecord* ss = searchStack->top();
+ CBuffer test;
+ size_t start = reader->pagelocate();
+ bool haspopped = false;
+ while (arg.left(ss->s.length()) != ss->s)
+ {
+ haspopped = true;
+ start = ss->pos;
+// reader->locate(start);
+ searchStack->pop();
+ delete ss;
+ }
+ if (haspopped) reader->locate(start);
+/*
+ if (arg.length() < ss->len)
+ {
+ start = ss->pos;
+ reader->locate(start);
+ searchStack->pop();
+ delete ss;
+ }
+*/
+ else
+ {
+ start = reader->pagelocate();
+ reader->jumpto(start);
+ searchStack->push(new searchrecord(arg,start));
+ }
+ dosearch(start, test, arg);
+}
+#else
+void QTReaderApp::search()
+{
+ QRegExp arg = searchEdit->text();
+ CBuffer test;
+ size_t start = reader->pagelocate();
+// reader->jumpto(start);
+ dosearch(start, test, arg);
+}
+#endif
+
+void QTReaderApp::openFile( const QString &f )
+{
+ openFile(DocLnk(f));
+}
+
+void QTReaderApp::openFile( const DocLnk &f )
+{
+ clear();
+ FileManager fm;
+ if ( fm.exists( f ) )
+ {
+// QMessageBox::information(0, "Progress", "Calling fileNew()");
+
+ clear();
+
+ // editorStack->raiseWidget( reader );
+
+ // reader->setFocus();
+
+ // QMessageBox::information(0, "DocLnk", "Begin");
+ doc = new DocLnk(f);
+ // QMessageBox::information(0, "DocLnk done", doc->file());
+ // QMessageBox::information(0, "Progress", "Calling setText()");
+ // QMessageBox::information(0, "Progress", "Textset");
+
+ // updateCaption();
+ showEditTools();
+ reader->setText(doc->name(), doc->file());
+ readbkmks();
+ }
+ else
+ {
+ QMessageBox::information(this, "QTReader", "File does not exist");
+ }
+
+}
+
+void QTReaderApp::showEditTools()
+{
+ if ( !doc )
+ close();
+// fileSelector->hide();
+ menu->show();
+ editBar->show();
+ if ( searchVisible )
+ searchBar->show();
+ if ( regVisible )
+ regBar->show();
+ if (m_fontVisible) m_fontBar->show();
+
+ updateCaption();
+ editorStack->raiseWidget( reader );
+ reader->setFocus();
+}
+/*
+void QTReaderApp::save()
+{
+ if ( !doc )
+ return;
+ if ( !editor->edited() )
+ return;
+
+ QString rt = editor->text();
+ QString pt = rt;
+
+ if ( doc->name().isEmpty() ) {
+ unsigned ispace = pt.find( ' ' );
+ unsigned ienter = pt.find( '\n' );
+ int i = (ispace < ienter) ? ispace : ienter;
+ QString docname;
+ if ( i == -1 ) {
+ if ( pt.isEmpty() )
+ docname = "Empty Text";
+ else
+ docname = pt;
+ } else {
+ docname = pt.left( i );
+ }
+ doc->setName(docname);
+ }
+ FileManager fm;
+ fm.saveFile( *doc, rt );
+}
+*/
+
+void QTReaderApp::clear()
+{
+ if (doc != 0)
+ {
+// QMessageBox::information(this, "QTReader", "Deleting doc", 1);
+ delete doc;
+// QMessageBox::information(this, "QTReader", "Deleted doc", 1);
+ doc = 0;
+ }
+ reader->clear();
+}
+
+void QTReaderApp::updateCaption()
+{
+ if ( !doc )
+ setCaption( tr("QTReader") );
+ else {
+ QString s = doc->name();
+ if ( s.isEmpty() )
+ s = tr( "Unnamed" );
+ setCaption( s + " - " + tr("QTReader") );
+ }
+}
+
+void QTReaderApp::setDocument(const QString& fileref)
+{
+ bFromDocView = TRUE;
+//QMessageBox::information(0, "setDocument", fileref);
+ openFile(DocLnk(fileref));
+// showEditTools();
+}
+
+void QTReaderApp::closeEvent( QCloseEvent *e )
+{
+ if (editorStack->visibleWidget() == reader)
+ {
+ if (m_fontVisible)
+ {
+ m_fontBar->hide();
+ m_fontVisible = false;
+ }
+ if (regVisible)
+ {
+ regBar->hide();
+ regVisible = false;
+ return;
+ }
+ if (searchVisible)
+ {
+ searchBar->hide();
+ searchVisible = false;
+ return;
+ }
+ if (m_fBkmksChanged && pBkmklist != NULL)
+ {
+ if (QMessageBox::warning(this, "QTReader", "Save bookmarks?", "Save", "Don't bother") == 0)
+ savebkmks();
+ delete pBkmklist;
+ pBkmklist = NULL;
+ m_fBkmksChanged = false;
+ }
+ bFromDocView = FALSE;
+ saveprefs();
+ e->accept();
+ }
+ else
+ {
+ showEditTools();
+ }
+}
+
+void QTReaderApp::do_gotomark()
+{
+ m_nRegAction = cGotoBkmk;
+ listbkmk();
+}
+
+void QTReaderApp::do_delmark()
+{
+ m_nRegAction = cDelBkmk;
+ listbkmk();
+}
+
+void QTReaderApp::listbkmk()
+{
+ bkmkselector->clear();
+ int cnt = 0;
+ if (pBkmklist != NULL)
+ {
+ if (m_fBkmksChanged) pBkmklist->sort();
+ for (CList<Bkmk>::iterator i = pBkmklist->begin(); i != pBkmklist->end(); i++)
+ {
+#ifdef _UNICODE
+ bkmkselector->insertItem(toQString(i->name()));
+#else
+ bkmkselector->insertItem(i->name());
+#endif
+ cnt++;
+ }
+ }
+ if (cnt > 0)
+ {
+ menu->hide();
+ editBar->hide();
+ if (m_fontVisible) m_fontBar->hide();
+ if (regVisible) regBar->hide();
+ if (searchVisible) searchBar->hide();
+ editorStack->raiseWidget( bkmkselector );
+ }
+ else
+ QMessageBox::information(this, "QTReader", "No bookmarks in memory");
+}
+
+void QTReaderApp::do_autogen()
+{
+ m_nRegAction = cAutoGen;
+ regEdit->setText(m_autogenstr);
+ do_regedit();
+}
+
+void QTReaderApp::do_regedit()
+{
+// editBar->hide();
+ regBar->show();
+ regVisible = true;
+ regEdit->setFocus();
+}
+
+void QTReaderApp::gotobkmk(int ind)
+{
+ switch (m_nRegAction)
+ {
+ case cGotoBkmk:
+ reader->locate((*pBkmklist)[ind]->value());
+ break;
+ case cDelBkmk:
+// qDebug("Deleting:%s\n",(*pBkmklist)[ind]->name());
+ pBkmklist->erase(ind);
+ m_fBkmksChanged = true;
+ break;
+ case cRmBkmkFile:
+ unlink((const char *)Global::applicationFileName("uqtreader",bkmkselector->text(ind)));
+ break;
+ }
+ showEditTools();
+}
+
+void QTReaderApp::cancelbkmk()
+{
+ showEditTools();
+}
+
+void QTReaderApp::jump()
+{
+ m_nRegAction = cJump;
+ char lcn[20];
+ sprintf(lcn, "%lu", reader->pagelocate());
+ regEdit->setText(lcn);
+ do_regedit();
+}
+
+void QTReaderApp::do_jump(const QString& lcn)
+{
+ bool ok;
+ unsigned long ulcn = lcn.toULong(&ok);
+ if (ok)
+ reader->locate(ulcn);
+ else
+ QMessageBox::information(this, "QTReader", "Must be a number");
+}
+
+void QTReaderApp::do_regaction()
+{
+ regBar->hide();
+ regVisible = false;
+ switch(m_nRegAction)
+ {
+ case cAutoGen:
+ do_autogen(regEdit->text());
+ break;
+ case cAddBkmk:
+ do_addbkmk(regEdit->text());
+ break;
+ case cJump:
+ do_jump(regEdit->text());
+ break;
+ case cMonoSpace:
+ do_mono(regEdit->text());
+ break;
+ case cOverlap:
+ do_overlap(regEdit->text());
+ break;
+ case cSetTarget:
+ do_settarget(regEdit->text());
+ break;
+ }
+ reader->restore();
+// editBar->show();
+ reader->setFocus();
+}
+
+void QTReaderApp::do_settarget(const QString& _txt)
+{
+ int ind = _txt.find('/');
+ if (ind == -1)
+ {
+ reader->m_targetapp = "";
+ reader->m_targetmsg = "";
+ QMessageBox::information(this, "QTReader", "Format is\nappname/messagename");
+ }
+ else
+ {
+ reader->m_targetapp = _txt.left(ind);
+ reader->m_targetmsg = _txt.right(_txt.length()-ind-1);
+ }
+}
+
+void QTReaderApp::setfont()
+{
+ for (int i = 1; i <= m_fontSelector->count(); i++)
+ {
+ if (m_fontSelector->text(i) == reader->m_fontname)
+ {
+ m_fontSelector->setCurrentItem(i);
+ break;
+ }
+ }
+ m_fontBar->show();
+ m_fontVisible = true;
+}
+
+void QTReaderApp::do_setfont(const QString& lcn)
+{
+ QFont f(lcn, 10 /*, QFont::Bold*/);
+ bkmkselector->setFont( f );
+ regEdit->setFont( f );
+ searchEdit->setFont( f );
+ reader->m_fontname = lcn;
+ reader->ChangeFont(reader->fontsizes[reader->m_textsize]);
+ reader->refresh();
+ m_fontBar->hide();
+ m_fontVisible = false;
+ showEditTools();
+}
+
+void QTReaderApp::do_autogen(const QString& regText)
+{
+ unsigned long fs, ts;
+ reader->sizes(fs,ts);
+ // qDebug("Reg:%s\n", (const tchar*)(regEdit->text()));
+ m_autogenstr = regText;
+ QRegExp re(regText);
+ CBuffer buff;
+ if (pBkmklist != NULL) delete pBkmklist;
+ pBkmklist = new CList<Bkmk>;
+ m_fBkmksChanged = true;
+ pbar->show();
+pbar->resize(width(), editBar->height());
+ pbar->reset();
+ qApp->processEvents();
+ reader->setFocus();
+ reader->jumpto(0);
+ int lastpc = 0;
+ int i = 0;
+ while (i >= 0)
+ {
+ unsigned int lcn = reader->locate();
+ int pc = (100*lcn)/ts;
+ if (pc != lastpc)
+ {
+ pbar->setProgress(pc);
+ qApp->processEvents();
+ if (reader->locate() != lcn) reader->jumpto(lcn);
+ reader->setFocus();
+ lastpc = pc;
+ }
+ i = reader->buffdoc.getpara(buff);
+#ifdef _UNICODE
+ if (re.match(toQString(buff.data())) != -1)
+#else
+ if (re.match(buff.data()) != -1)
+#endif
+ pBkmklist->push_back(Bkmk(buff.data(),lcn));
+ }
+ pbar->setProgress(100);
+ qApp->processEvents();
+ pbar->hide();
+}
+
+void QTReaderApp::saveprefs()
+{
+// reader->saveprefs("uqtreader");
+ Config config( "uqtreader" );
+ config.setGroup( "View" );
+
+ reader->m_lastposn = reader->pagelocate();
+
+ config.writeEntry( "StripCr", reader->bstripcr );
+ config.writeEntry( "StripHtml", reader->bstriphtml );
+ config.writeEntry( "Dehyphen", reader->bdehyphen );
+ config.writeEntry( "Unindent", reader->bunindent );
+ config.writeEntry( "Repara", reader->brepara );
+ config.writeEntry( "DoubleSpace", reader->bdblspce );
+ config.writeEntry( "Indent", reader->bindenter );
+ config.writeEntry( "FontSize", (int)(reader->fontsizes[reader->m_textsize]) );
+ config.writeEntry( "Bold", reader->m_bBold );
+ config.writeEntry( "ScrollDelay", reader->m_delay);
+ config.writeEntry( "LastFile", reader->m_lastfile );
+ config.writeEntry( "LastPosn", (int)(reader->pagelocate()) );
+ config.writeEntry( "PageMode", reader->m_bpagemode );
+ config.writeEntry( "MonoSpaced", reader->m_bMonoSpaced );
+ config.writeEntry( "Fontname", reader->m_fontname );
+ config.writeEntry( "Encoding", reader->m_encd );
+ config.writeEntry( "CharSpacing", reader->m_charpc );
+ config.writeEntry( "Overlap", (int)(reader->m_overlap) );
+ config.writeEntry( "TargetApp", reader->m_targetapp );
+ config.writeEntry( "TargetMsg", reader->m_targetmsg );
+}
+
+void QTReaderApp::indentplus()
+{
+ reader->indentplus();
+}
+
+void QTReaderApp::indentminus()
+{
+ reader->indentminus();
+}
+
+/*
+void QTReaderApp::oldFile()
+{
+ qDebug("oldFile called");
+ reader->setText(true);
+ qDebug("settext called");
+ showEditTools();
+ qDebug("showedit called");
+}
+*/
+
+/*
+void info_cb(Fl_Widget* o, void* _data)
+{
+
+ if (infowin == NULL)
+ {
+
+ infowin = new Fl_Window(160,240);
+ filename = new Fl_Output(45,5,110,14,"Filename");
+ filesize = new Fl_Output(45,25,110,14,"Filesize");
+ textsize = new Fl_Output(45,45,110,14,"Textsize");
+ comprat = new CBar(45,65,110,14,"Ratio %");
+ posn = new Fl_Output(45,85,110,14,"Location");
+ frcn = new CBar(45,105,110,14,"% Read");
+ about = new Fl_Multiline_Output(5,125,150,90);
+ about->value("TWReader - $Name$\n\nA file reader program for the Agenda\n\nReads text, PalmDoc and ppms format files");
+ Fl_Button *jump_accept = new Fl_Button(62,220,35,14,"Okay");
+ infowin->set_modal();
+ }
+ if (((reader_ui *)_data)->g_filename[0] != '\0')
+ {
+ unsigned long fs,ts;
+ tchar sz[20];
+ ((reader_ui *)_data)->input->sizes(fs,ts);
+ unsigned long pl = ((reader_ui *)_data)->input->locate();
+
+ filename->value(((reader_ui *)_data)->g_filename);
+
+ sprintf(sz,"%u",fs);
+ filesize->value(sz);
+
+ sprintf(sz,"%u",ts);
+ textsize->value(sz);
+
+ comprat->value(100-(100*fs + (ts >> 1))/ts);
+
+ sprintf(sz,"%u",pl);
+ posn->value(sz);
+
+ frcn->value((100*pl + (ts >> 1))/ts);
+ }
+ infowin->show();
+}
+*/
+
+void QTReaderApp::savebkmks()
+{
+ if (pBkmklist != NULL)
+ {
+ BkmkFile bf((const char *)Global::applicationFileName("uqtreader",reader->m_string), true);
+ bf.write(*pBkmklist);
+ }
+ m_fBkmksChanged = false;
+}
+
+void QTReaderApp::readbkmks()
+{
+ if (pBkmklist != NULL)
+ {
+ delete pBkmklist;
+ }
+ BkmkFile bf((const char *)Global::applicationFileName("uqtreader",reader->m_string));
+ pBkmklist = bf.readall();
+ m_fBkmksChanged = false;
+ if (pBkmklist == NULL)
+ {
+ pBkmklist = reader->getbkmklist();
+ }
+ if (pBkmklist != NULL)
+ pBkmklist->sort();
+}
+
+void QTReaderApp::addbkmk()
+{
+ m_nRegAction = cAddBkmk;
+ regEdit->setText(reader->firstword());
+ do_regedit();
+}
+
+void QTReaderApp::do_addbkmk(const QString& text)
+{
+ if (text.isEmpty())
+ {
+ QMessageBox::information(this, "QTReader", "Need a name for the bookmark\nSelect add again", 1);
+ }
+ else
+ {
+ if (pBkmklist == NULL) pBkmklist = new CList<Bkmk>;
+#ifdef _UNICODE
+ CBuffer buff;
+ int i = 0;
+ for (i = 0; i < text.length(); i++)
+ {
+ buff[i] = text[i].unicode();
+ }
+ buff[i] = 0;
+ pBkmklist->push_front(Bkmk(buff.data(), reader->pagelocate()));
+#else
+ pBkmklist->push_front(Bkmk((const tchar*)text,reader->pagelocate()));
+#endif
+ m_fBkmksChanged = true;
+ }
+}
diff --git a/noncore/apps/opie-reader/QTReaderApp.h b/noncore/apps/opie-reader/QTReaderApp.h
new file mode 100644
index 0000000..48575e9
--- a/dev/null
+++ b/noncore/apps/opie-reader/QTReaderApp.h
@@ -0,0 +1,206 @@
+/**********************************************************************
+** Copyright (C) 2000 Trolltech AS. All rights reserved.
+**
+** This file is part of Qt Palmtop Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+#ifndef __QTREADERAPP_H
+#define __QTREADERAPP_H
+
+//#define __ISEARCH
+
+#define MAX_ENCODING 6
+
+#include <qmainwindow.h>
+#include "QTReader.h"
+#include <qlist.h>
+#include <qpe/filemanager.h>
+#include <qmap.h>
+#include <qlineedit.h>
+#include <qstack.h>
+#include <qlistbox.h>
+#include "Queue.h"
+
+class QWidgetStack;
+class QToolButton;
+class QPopupMenu;
+class QToolBar;
+class CBkmkSelector;
+class QProgressBar;
+class QAction;
+
+#ifdef __ISEARCH
+struct searchrecord
+{
+ QString s;
+ size_t pos;
+ searchrecord(const QString& _s, size_t _pos) : s(_s), pos(_pos) {}
+};
+#endif
+
+class infowin;
+
+class QTReaderApp : public QMainWindow
+{
+ Q_OBJECT
+
+ unsigned long m_savedpos;
+
+ public:
+ QTReaderApp( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+ ~QTReaderApp();
+
+ void openFile( const QString & );
+
+ void setScrollState(bool _b);
+
+ protected:
+ void closeEvent( QCloseEvent *e );
+ void readbkmks();
+ void do_mono(const QString&);
+ void do_jump(const QString&);
+ void do_overlap(const QString&);
+ void do_settarget(const QString&);
+ int EncNameToInt(const QString&);
+ void saveprefs();
+
+private slots:
+ void do_setfont(const QString&);
+ void encodingSelected(QAction*);
+ void msgHandler(const QCString&, const QByteArray&);
+ void monospace(bool);
+ void jump();
+ void setoverlap();
+ void settarget();
+ void setspacing();
+ void setfont();
+ void clearBkmkList();
+ void listBkmkFiles();
+ void editMark();
+ void autoScroll(bool);
+ void addbkmk();
+ void savebkmks();
+// void importFiles();
+ void infoClose();
+ // void oldFile();
+ void showinfo();
+ void setDocument(const QString&);
+ void TBD();
+ void TBDzoom();
+
+ void indentplus();
+ void indentminus();
+
+ void fileOpen();
+
+ void editCopy();
+ void editFind();
+
+ void pageup();
+ void pagedn();
+
+ void findNext();
+ void findClose();
+
+ void regClose();
+
+#ifdef __ISEARCH
+// void search( const QString& );
+#else
+ void search();
+#endif
+
+ void openFile( const DocLnk & );
+ void showEditTools();
+
+ void stripcr(bool);
+ void striphtml(bool);
+ void dehyphen(bool);
+ void unindent(bool);
+ void repara(bool);
+ void setbold(bool);
+ void dblspce(bool);
+ void pagemode(bool);
+ // void gotobkmk(const QString& bm);
+ void gotobkmk(int);
+ void cancelbkmk();
+ void do_gotomark();
+ void do_delmark();
+ void do_autogen();
+ void do_regaction();
+
+ private:
+ void listbkmk();
+ void do_regedit();
+ void colorChanged( const QColor &c );
+ void clear();
+ void updateCaption();
+ void do_autogen(const QString&);
+ void do_addbkmk(const QString&);
+
+ private:
+
+ QAction* m_scrollButton;
+
+ QAction* m_EncodingAction[MAX_ENCODING];
+
+ CBkmkSelector* bkmkselector;
+
+ size_t searchStart;
+#ifdef __ISEARCH
+ QStack<searchrecord>* searchStack;
+ bool dosearch(size_t start, CBuffer& test, const QString& arg);
+#else
+ bool dosearch(size_t start, CBuffer& test, const QRegExp& arg);
+#endif
+ QWidgetStack *editorStack;
+ QTReader* reader;
+ QComboBox* m_fontSelector;
+ QToolBar *menu, *editBar, *searchBar, *regBar, *m_fontBar;
+ QLineEdit *searchEdit, *regEdit;
+ DocLnk *doc;
+ bool searchVisible;
+ bool regVisible;
+ bool m_fontVisible;
+ bool bFromDocView;
+ static unsigned long m_uid;
+ long unsigned get_unique_id() { return m_uid++; }
+ /*
+ void resizeEvent( QResizeEvent * r)
+ {
+ qDebug("resize:(%u,%u)", r->oldSize().width(), r->oldSize().height());
+ qDebug("resize:(%u,%u)", r->size().width(), r->size().height());
+ // bgroup->move( width()-bgroup->width(), 0 );
+ }
+ */
+ CList<Bkmk>* pBkmklist;
+ infowin* m_infoWin;
+ QProgressBar* pbar;
+ bool m_fBkmksChanged;
+ int m_nRegAction;
+ QString m_autogenstr;
+};
+
+const int cAutoGen = 0;
+const int cAddBkmk = 1;
+const int cDelBkmk = 2;
+const int cGotoBkmk = 3;
+const int cRmBkmkFile = 4;
+const int cJump = 5;
+const int cMonoSpace = 6;
+const int cOverlap = 7;
+const int cSetTarget = 8;
+#endif
diff --git a/noncore/apps/opie-reader/QtrListView.cpp b/noncore/apps/opie-reader/QtrListView.cpp
new file mode 100644
index 0000000..67040f8
--- a/dev/null
+++ b/noncore/apps/opie-reader/QtrListView.cpp
@@ -0,0 +1,24 @@
+#include "QtrListView.h"
+
+void QtrListView::keyPressEvent(QKeyEvent* e)
+{
+ switch (e->key())
+ {
+ case Key_Space:
+ e->accept();
+ emit OnCentreButton(currentItem());
+ break;
+// case Key_Enter:
+// case Key_Return:
+ case Key_F33:
+ e->accept();
+ emit OnOKButton(currentItem());
+ break;
+ case Key_Escape:
+ e->accept();
+ emit OnCancelButton();
+ break;
+ default:
+ QListView::keyPressEvent(e);
+ }
+}
diff --git a/noncore/apps/opie-reader/QtrListView.h b/noncore/apps/opie-reader/QtrListView.h
new file mode 100644
index 0000000..c1b7f4d
--- a/dev/null
+++ b/noncore/apps/opie-reader/QtrListView.h
@@ -0,0 +1,20 @@
+#ifndef __QTRLISTVIEW_H
+#define __QTRLISTVIEW_H
+
+#include <qlistview.h>
+
+class QtrListView : public QListView
+{
+ Q_OBJECT
+
+ virtual void keyPressEvent(QKeyEvent* e);
+ public:
+ QtrListView(QWidget* parent, char* name) : QListView(parent, name) {};
+
+ signals:
+ void OnOKButton(QListViewItem*);
+ void OnCentreButton(QListViewItem*);
+ void OnCancelButton();
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/Queue.h b/noncore/apps/opie-reader/Queue.h
new file mode 100644
index 0000000..f1bd4b4
--- a/dev/null
+++ b/noncore/apps/opie-reader/Queue.h
@@ -0,0 +1,21 @@
+#ifndef __QUEUE_H
+#define __QUEUE_H
+
+#include "my_list.h"
+
+template<class T>
+class CQueue : public CList<T>
+{
+ public:
+ bool empty() { return (front == NULL); }
+ void push(const T& t) { push_back(t); }
+ T pop()
+ {
+ T data = front->data;
+ node* n = front;
+ front = front->next;
+ delete n;
+ return data;
+ }
+};
+#endif
diff --git a/noncore/apps/opie-reader/README b/noncore/apps/opie-reader/README
new file mode 100644
index 0000000..d091010
--- a/dev/null
+++ b/noncore/apps/opie-reader/README
@@ -0,0 +1,162 @@
+What is QT Reader?
+==================
+
+QT Reader is an e-text reading program which understands several
+varieties of PalmDoc format (types 1,2 and 4), zTxt, plain text and
+gzipped text.
+
+In addition it supports its own very highly compressed format which is
+based on ppm (regarded by many as the best available compression
+technique) with modifications by Fabrice Bellard for speed and memory
+efficiency and by myself to support random access on smaller
+devices. I call this modified format ppms (for ppm, segmented).
+
+The ppms program which is used to produce ppms files from plain text
+is available from http://www.timwentford.uklinux.net where there is
+also a comparison of file sizes produced by several compression
+methods. This is summarised below:
+
+Compression method Size in bytes Memory required to decompress
+Plain text 573714 N/A
+Makedoc (PalmDoc format) 329543 2k
+ppms (default) 184187 350k
+ppms (best) 151733 800k
+bzip2 -1 180175 340k
+bzip2 -9 154280 2.2M
+
+The default settings used here were chosen to suit the Agenda VR3. I
+would expect the Zaurus to be able to use settings which give 170kb
+file size and 500k memory without any problem. The format encodes the
+settings used so the user may choose whatever suits them. I choose
+based on the amount of memory required and on whether or not pageup
+performance is acceptable.
+
+General Use
+===========
+
+Start it up and then choose "File/Open" from the menu. Select a
+palmdoc, plain text, gzipped text or ppms file from the file selector
+and use the cursor keys to page up/down (up/down keys) and to make the
+text size comfortable (left/right keys) and thats it for most
+uses. See below for more advanced use.
+
+What the Menu Options Do
+========================
+
+File
+====
+
+File operations live in this menu.
+
+Open Brings up the file selector to allow you to choose a
+ new file to read.
+Info Displays info about the currently open file. Needs
+ reformatting.
+Start Block Marks the text at the top of the currently displayed
+ page ready for copying.
+Copy Block Copies all text from the mark to the bottom of the
+ currently displayed page to the clipboard.
+Scroll Starts/stops autoscroll. The speed can be adjusted
+ using the up/down keys while autoscroll is on (page
+ up and down are still functional and can be activated
+ by using the up and down arrows on the task bar).
+Jump Jumps to a specific offset in the file. If you note
+ down the current location from the File/Info display
+ you can then jump to the same position again using
+ this function (or you could bokmark it 8^)).
+Page/Line scroll When this is On pressing the arrows (keys or
+ icons on the task bar) moves you a page at a time.
+ When this is off, pressing the arrows moves you a
+ line at a time.
+Set Overlap Sets the number of lines of overlap between pages
+ when scrolling by page.
+Set Dictionary When you tap on the screen the word under the
+ pointer is copied to the clipboard ready for pasting
+ into (e.g.) a dictionary program. Using this function
+ allows the word to be sent to compatible dictionary
+ programs direct. The format is exename/messagename
+ where exename is the name of the executable for the
+ dictionary program and messagename is the name of the
+ message it is expecting. You can get some idea of how
+ it works by using some debug functionality which I
+ deliberately left in QTReader. Set this to
+ uqtreader/info.
+ To deactivate it again, set it to /.
+Find Brings up the search requester where you can enter a
+ regular expression to search (again) for.
+
+Format
+======
+
+Used to alter the way the text is reformatted before display.
+
+Strip CR Removes those pesky DOS crs from the file.
+Strip HTML Uses a very simple minded filter to remove html mark-up.
+Dehyphen Removes hyphens from e-texts which have been formatted to
+ fit on different sized displays by hyphenating words
+ which no longer appear at the end of the line.
+Unindent Removes leading spaces from the beginning of paragraphs.
+Re-paragraph Removes/adds line breaks as necessary to make the text
+ look nice on the display.
+Double Space Adds an extra space between paragraphs.
+Indent+ Increases the number of extra leading spaces inserted
+ before paragraphs.
+Indent- Decreases the number of extra leading spaces inserted
+ before paragraphs.
+Bold Sets the font to bold (if its supported by the currently
+ selected font).
+
+For e-texts from fictionwise I don't need any of these enabled. For
+Project Gutenberg e-texts I enable Strip CR, Re-paragraph and either 3 lots
+of indent+ and/or double space.
+
+Zoom Menu option not implemented but pops up an info box
+ telling you that left/right cursor keys will zoom
+ out/in.
+Ideogram/Char grouping When selected, treats each character as a word
+ and enforces uniform character spacing - suitable for
+ many eastern character sets. When not selected, looks for
+ spaces in the text to identify words - suitable for most
+ western texts. (I'm not a language expert so forgive my,
+ probably inaccurate, generalisations).
+Set Width Sets the character spacing as a percentage of the text
+ height to be used when in ideogram mode. Start at 100 and
+ experiment to find what you like best.
+Encoding Allows you to choose from a variety of codings. Ascii is
+ actually unprocessed text so its precise behaviour may
+ depend on the machines locale setting. Palm and code page
+ 1252 are very similar and are useful if you have an etext
+ aimed at Palms or Windows machines which use an extended
+ character set - though you will need to use a unicode
+ enabled font to show all the characters. The U... fonts
+ are different varieties of unicode encodings. If you
+ don't know what that means you probably don't need them
+ (they allow texts to access the full range of characters
+ required for non US English languages).
+Set Font Allows you to choose which font the text is displayed
+ in. Helvetica or smoothtimes are probably best for ascii type
+ texts, unifont or cyberbit (if you have installed them)
+ are best for extended character sets (other unicode fonts
+ may also be available but these are all I've found, so far).
+Marks
+=====
+
+Mark Saves the current position as a bookmark
+Goto Allows selection of a bookmark to jump to.
+Delete Deletes an unwanted bookmark from the current text.
+Autogen Displays a box for entering a regular
+ expression which will be used to determine which
+ paragraphs (not lines) will be marked to allow jumping to
+ directly using the Goto option. The format options
+ described above are applied before the regular expression
+ matching is done.
+ This operation is performed in the background allowing
+ you to continue paging up/down the e-text.
+Clear Deletes all in-memory bookmarks from the current document.
+Save Saves the "in-memory" bookmarks to disk.
+Tidy Deletes bookmark file for a document. The operations
+ above work on an in-memory copy of the bookmarks. This
+ option makes that copy more permanent (you will also be
+ prompted to save the bookmarks when closing a text if the
+ in-memory copy is different to the saved copy).
+
diff --git a/noncore/apps/opie-reader/Text.h b/noncore/apps/opie-reader/Text.h
new file mode 100644
index 0000000..4c689be
--- a/dev/null
+++ b/noncore/apps/opie-reader/Text.h
@@ -0,0 +1,28 @@
+#ifndef __Text_h
+#define __Text_h
+#include <stdio.h>
+#include <sys/stat.h>
+#include "CExpander.h"
+
+class Text: public CExpander {
+ FILE* file;
+public:
+ Text() : file(NULL) {};
+ virtual ~Text() { if (file != NULL) fclose(file); }
+ virtual int openfile(const tchar *src)
+ {
+ if (file != NULL) fclose(file);
+ return ((file = fopen(src,"rb")) == NULL);
+ }
+ virtual int getch() { return fgetc(file); }
+ virtual unsigned int locate() { return ftell(file); }
+ virtual void locate(unsigned int n) { fseek(file,n,SEEK_SET); }
+ virtual bool hasrandomaccess() { return true; }
+ virtual void sizes(unsigned long& _file, unsigned long& _text)
+ {
+ struct stat _stat;
+ fstat(fileno(file),&_stat);
+ _text = _file = _stat.st_size;
+ }
+};
+#endif
diff --git a/noncore/apps/opie-reader/ZText.h b/noncore/apps/opie-reader/ZText.h
new file mode 100644
index 0000000..2848af7
--- a/dev/null
+++ b/noncore/apps/opie-reader/ZText.h
@@ -0,0 +1,35 @@
+#ifndef __Text_h
+#define __Text_h
+#include <stdio.h>
+#include <zlib.h>
+#include <sys/stat.h>
+
+#include "CExpander.h"
+
+class Text: public CExpander {
+ gzFile file;
+ unsigned long fsize;
+public:
+ Text() : file(NULL) {};
+ virtual ~Text()
+ {
+ if (file != NULL) gzclose(file);
+ }
+ virtual int openfile(const char *src)
+ {
+ if (file != NULL) gzclose(file);
+ struct stat _stat;
+ stat(src,&_stat);
+ fsize = _stat.st_size;
+ return ((file = gzopen(src,"rb")) == NULL);
+ }
+ virtual int getch() { return gzgetc(file); }
+ virtual unsigned int locate() { return gztell(file); }
+ virtual void locate(unsigned int n) { gzseek(file,n,SEEK_SET); }
+ virtual bool hasrandomaccess() { return true; }
+ virtual void sizes(unsigned long& _file, unsigned long& _text)
+ {
+ _text = _file = fsize;
+ }
+};
+#endif
diff --git a/noncore/apps/opie-reader/arith.h b/noncore/apps/opie-reader/arith.h
new file mode 100644
index 0000000..19ca646
--- a/dev/null
+++ b/noncore/apps/opie-reader/arith.h
@@ -0,0 +1,43 @@
+/*
+ * Encodage & décodage arithmétique
+ */
+
+#ifndef ARITH_H
+
+#define ARITH_H
+
+#include "utypes.h"
+#include <stdio.h>
+
+class PPM_ReadBuf
+{
+ FILE *my_file_in;
+public:
+ PPM_ReadBuf(FILE* f) : my_file_in(f) {}
+ UINT readbuf(UCHAR *buf,UINT len)
+ {
+ UINT len1;
+ len1=fread(buf,1,len,my_file_in);
+ return len1;
+ }
+};
+
+class ArithClass
+{
+
+UCHAR *ainbuf;
+UCHAR *apinbuf,*aendinbuf;
+UINT ainbufsize;
+USHORT avalue,alow,ahigh;
+PPM_ReadBuf* areadbuf;
+UCHAR abitcnt;
+USHORT abitbuf;
+
+ public:
+void Arith_DecodeInit(PPM_ReadBuf* readbuf,UCHAR *buf,UINT bufsize);
+UINT Arith_DecodeVal(UINT size);
+void Arith_Decode(UINT min,UINT max,UINT size);
+void Arith_DecodeEnd(void);
+
+};
+#endif
diff --git a/noncore/apps/opie-reader/arith_d.cpp b/noncore/apps/opie-reader/arith_d.cpp
new file mode 100644
index 0000000..c43d697
--- a/dev/null
+++ b/noncore/apps/opie-reader/arith_d.cpp
@@ -0,0 +1,94 @@
+/* décodage arithmétique
+ * optimisé pour une arithmétique 16 bits
+ */
+#include <stdlib.h>
+#include "arith.h"
+
+
+/*
+ * Initialisation du décodeur.
+ * bufsize doit être multiple de 2 et supérieur à 4
+ */
+
+void ArithClass::Arith_DecodeInit(PPM_ReadBuf* readbuf,UCHAR *buf,UINT bufsize) {
+
+ /* gestion buffer */
+
+ ainbuf=buf;
+ ainbufsize=bufsize;
+ areadbuf=readbuf;
+ aendinbuf=ainbuf+ainbufsize;
+ areadbuf->readbuf(ainbuf,ainbufsize);
+ apinbuf=ainbuf;
+
+ /* intervalle et position dans l'intervalle */
+ alow=0;
+ ahigh=0xFFFF;
+ avalue=(*apinbuf++)<<8;
+ avalue|=(*apinbuf++);
+
+ /* remplissage du buffer 16 bits */
+
+ abitbuf=(*apinbuf++)<<8;
+ abitbuf|=(*apinbuf++);
+ abitcnt=16;
+}
+
+#define DIV16(a,b) ( (UINT)(a)/(UINT)(b) )
+#define MUL16(a,b) ( (UINT)(a)*(UINT)(b) )
+
+/*
+ * Décodage: première étape
+ */
+
+UINT ArithClass::Arith_DecodeVal(UINT asize) {
+ USHORT range,c;
+
+ range=ahigh-alow+1;
+ c=avalue-alow+1;
+ if (range!=0) {
+ if (c==0) return DIV16(((UINT)asize<<16)-1,range);
+ else return DIV16(MUL16(c,asize)-1,range);
+ } else {
+ if (c==0) return (asize-1);
+ else return (MUL16(c,asize)-1)>>16;
+ }
+}
+
+/*
+ * Décodage: deuxième étape
+ */
+
+void ArithClass::Arith_Decode(UINT amin,UINT amax,UINT asize) {
+ USHORT range;
+
+ range = ahigh - alow;
+ if (amax!=asize) ahigh=alow+DIV16(MUL16(range,amax)+amax,asize)-1;
+ if (amin!=0) alow+=DIV16(MUL16(range,amin)+amin,asize);
+ for ( ; ; ) {
+ if ( alow>=0x4000 && ahigh<0xC000 ) {
+ avalue -= 0x4000; alow -= 0x4000; ahigh -= 0x4000;
+ } else if ( ahigh>=0x8000 && alow<0x8000 ) break;
+
+ alow+=alow;
+ ahigh+=ahigh+1;
+ avalue=(avalue<<1)|( (abitbuf&0x8000)!=0 );
+ abitbuf<<=1;
+ if ( (--abitcnt)==0 ) {
+ abitbuf=(*apinbuf++)<<8;
+ abitbuf|=(*apinbuf++);
+ abitcnt=16;
+ if (apinbuf>=aendinbuf) {
+ areadbuf->readbuf(ainbuf,ainbufsize);
+ apinbuf=ainbuf;
+ }
+ }
+ }
+}
+
+/*
+ * fin du décodage: rien à faire
+ */
+
+void ArithClass::Arith_DecodeEnd(void) {
+}
diff --git a/noncore/apps/opie-reader/cbkmkselector.h b/noncore/apps/opie-reader/cbkmkselector.h
new file mode 100644
index 0000000..1a49c5a
--- a/dev/null
+++ b/noncore/apps/opie-reader/cbkmkselector.h
@@ -0,0 +1,41 @@
+#include <qwidget.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+
+class CBkmkSelector : public QWidget
+{
+
+ Q_OBJECT
+
+ QListBox* bkmkselector;
+
+signals:
+ void selected(int i);
+ void cancelled();
+private slots:
+ void slotSelected(QListBoxItem* t) { emit selected(bkmkselector->index(t)); }
+ void slotSelected(int t) { emit selected(t); }
+ void slotCancel() { emit cancelled(); }
+public:
+ CBkmkSelector( QWidget *parent=0, const char *name=0, WFlags f = 0) :
+ QWidget(parent, name, f)
+ {
+
+// QFont f("unifont", 16);
+// setFont( f );
+
+ QVBoxLayout* grid = new QVBoxLayout(this);
+ bkmkselector = new QListBox(this, "Bookmarks");
+ QPushButton* exitButton = new QPushButton("Cancel", this);
+ connect(bkmkselector, SIGNAL( selected(int) ), this, SLOT( slotSelected(int) ) );
+ connect(bkmkselector, SIGNAL( clicked(QListBoxItem*) ), this, SLOT( slotSelected(QListBoxItem*) ) );
+ connect(exitButton, SIGNAL( released() ), this, SLOT( slotCancel() ) );
+ grid->addWidget(bkmkselector,1);
+ grid->addWidget(exitButton);
+ }
+ void clear() { bkmkselector->clear(); }
+ void insertItem(const QString& item) { bkmkselector->insertItem(item); }
+ QString text(int index) const { return bkmkselector->text(index); }
+};
+
diff --git a/noncore/apps/opie-reader/config.h b/noncore/apps/opie-reader/config.h
new file mode 100644
index 0000000..5150270
--- a/dev/null
+++ b/noncore/apps/opie-reader/config.h
@@ -0,0 +1,21 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define _UNICODE
+
+#ifdef _UNICODE
+#include <limits.h>
+
+#define UTF8
+
+typedef unsigned short tchar;
+const tchar UEOF = USHRT_MAX;
+
+#else
+typedef char tchar;
+const int UEOF = -1;
+#endif
+
+#include "ustring.h"
+
+#endif
diff --git a/noncore/apps/opie-reader/fileBrowser.cpp b/noncore/apps/opie-reader/fileBrowser.cpp
new file mode 100644
index 0000000..def988f
--- a/dev/null
+++ b/noncore/apps/opie-reader/fileBrowser.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+
+Derived from a file browser which was
+
+** copyright 2001 ljp ljp@llornkcor.com
+
+Extensive modification by Tim Wentford to allow it to work in rotated mode
+
+****************************************************************************/
+#include "fileBrowser.h"
+
+#include "QtrListView.h"
+#include <qpushbutton.h>
+#include <qfile.h>
+#include <qmessagebox.h>
+#include <unistd.h>
+#include <qlayout.h>
+
+fileBrowser::fileBrowser( QWidget* parent, const char* name, bool modal, WFlags fl , const QString filter, const QString iPath )
+ : QDialog( parent, name, modal, fl )
+{
+// showMaximized();
+ if ( !name )
+ setName( "fileBrowser" );
+ if (parent != NULL) resize( parent->width(), parent->height() );
+ setCaption(tr( "Browse for file" ) );
+ filterStr=filter;
+
+ buttonOk = new QPushButton( this, "buttonOk" );
+ buttonOk->setFixedSize( 25, 25 );
+ buttonOk->setText( tr( "/" ) );
+
+ dirLabel = new QLabel(this, "DirLabel");
+ dirLabel->setText(currentDir.canonicalPath());
+
+ ListView = new QtrListView( this, "ListView" );
+ ListView->addColumn( tr( "Name" ) );
+ ListView->setSorting( 2, FALSE);
+ ListView->addColumn( tr( "Size" ) );
+ ListView->setSelectionMode(QListView::Single);
+
+ ListView->setAllColumnsShowFocus( TRUE );
+
+ // signals and slots connections
+ connect( buttonOk, SIGNAL( clicked() ), this, SLOT( OnRoot() ) );
+ connect( ListView, SIGNAL(doubleClicked( QListViewItem*)), SLOT(listDoubleClicked(QListViewItem *)) );
+ connect( ListView, SIGNAL(clicked( QListViewItem*)), SLOT(listClicked(QListViewItem *)) );
+ connect( ListView, SIGNAL(OnOKButton( QListViewItem*)), SLOT(listClicked(QListViewItem *)) );
+ connect( ListView, SIGNAL(OnCentreButton( QListViewItem*)), SLOT(listClicked(QListViewItem *)) );
+ connect( ListView, SIGNAL(OnCancelButton()), SLOT(OnCancel()) );
+
+ QVBoxLayout* grid = new QVBoxLayout(this);
+ QHBoxLayout* hgrid = new QHBoxLayout(grid);
+ hgrid->addWidget(dirLabel,1);
+ hgrid->addWidget(buttonOk);
+ grid->addWidget(ListView,1);
+
+ if (QFileInfo(iPath).exists())
+ {
+ currentDir.setPath(iPath);
+ chdir(iPath.latin1());
+ }
+ else
+ {
+ currentDir.setPath(QDir::currentDirPath());
+ chdir(QDir::currentDirPath().latin1());
+ }
+
+ populateList();
+}
+
+void fileBrowser::resizeEvent(QResizeEvent* e)
+{
+ ListView->setColumnWidth(1,(ListView->width())/4);
+ ListView->setColumnWidth(0,ListView->width()-20-ListView->columnWidth(1));
+}
+
+fileBrowser::~fileBrowser()
+{
+}
+
+
+void fileBrowser::populateList()
+{
+ ListView->clear();
+//qDebug(currentDir.canonicalPath());
+// currentDir.setFilter( QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );
+ currentDir.setFilter( QDir::All );
+ currentDir.setSorting(/* QDir::Size*/ /*| QDir::Reversed | */QDir::DirsFirst);
+ currentDir.setMatchAllDirs(TRUE);
+
+ currentDir.setNameFilter(filterStr);
+// currentDir.setNameFilter("*.txt;*.etx");
+ QString fileL, fileS;
+ const QFileInfoList *list = currentDir.entryInfoList(QDir::All);
+ QFileInfoListIterator it(*list);
+ QFileInfo *fi;
+ while ( (fi=it.current()) )
+ {
+ if (fi->fileName() != ".")
+ {
+ fileS.sprintf( "%10li", fi->size() );
+ fileL.sprintf( "%s",fi->fileName().data() );
+ if( fi->isDir() )
+ {
+ fileL+="/";
+ }
+ else
+ {
+// qDebug("Not a dir: "+currentDir.canonicalPath()+fileL);
+ }
+ new QListViewItem( ListView,fileL,fileS );
+ }
+ ++it;
+ }
+ ListView->setSorting( 2, FALSE);
+ dirLabel->setText("Current Directory:\n"+currentDir.canonicalPath());
+}
+
+void fileBrowser::upDir()
+{
+// qDebug(currentDir.canonicalPath());
+}
+
+void fileBrowser::listClicked(QListViewItem *selectedItem)
+{
+ if (selectedItem == NULL) return;
+ QString strItem=selectedItem->text(0);
+
+// qDebug("%s", (const char*)strItem);
+
+
+ QString strSize=selectedItem->text(1);
+
+ strSize.stripWhiteSpace();
+
+ bool ok;
+
+ QFileInfo fi(strItem);
+ while (fi.isSymLink()) fi.setFile(fi.readLink());
+ if (fi.isDir())
+ {
+ strItem=QDir::cleanDirPath(currentDir.canonicalPath()+"/"+strItem);
+
+ if(QDir(strItem).exists())
+ {
+ currentDir.cd(strItem, TRUE);
+ populateList();
+ }
+ } else
+ OnOK();
+ chdir(strItem.latin1());
+//
+
+}
+
+// you may want to switch these 2 functions. I like single clicks
+void fileBrowser::listDoubleClicked(QListViewItem *selectedItem)
+{
+}
+
+void fileBrowser::OnOK() {
+
+ QListViewItemIterator it1( ListView);
+ for ( ; it1.current(); ++it1 ) {
+ if ( it1.current()->isSelected() ) {
+ selectedFileName=QDir::cleanDirPath(currentDir.canonicalPath()+"/"+it1.current()->text(0));
+// qDebug("selected filename is "+selectedFileName);
+ fileList.append( selectedFileName );
+ }
+ }
+ accept();
+}
+
+void fileBrowser::OnRoot()
+{
+ currentDir.cd("/", TRUE);
+ populateList();
+ chdir("/");
+}
+
+void fileBrowser::OnCancel()
+{
+ reject();
+}
diff --git a/noncore/apps/opie-reader/fileBrowser.h b/noncore/apps/opie-reader/fileBrowser.h
new file mode 100644
index 0000000..d222791
--- a/dev/null
+++ b/noncore/apps/opie-reader/fileBrowser.h
@@ -0,0 +1,70 @@
+/*
+Derived from the file browser published by ljp@llornkcor.com but extensively
+modified to work in rotated views on the Zaurus
+*/
+
+/****************************************************************************
+** Form interface generated from reading ui file 'fileBrowzer.ui'
+**
+** Created: Fri Dec 14 08:16:02 2001
+** by: The User Interface Compiler (uic)
+**
+** WARNING! All changes made in this file will be lost!
+blah,blah,blah
+****************************************************************************/
+#ifndef FILEBROWSER_H
+#define FILEBROWSER_H
+
+//#include <qvariant.h>
+#include <qdialog.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qstring.h>
+
+class QVBoxLayout;
+class QHBoxLayout;
+class QGridLayout;
+class QtrListView;
+class QListViewItem;
+class QPushButton;
+
+class fileBrowser : public QDialog
+{
+ Q_OBJECT
+
+public:
+ void populateList();
+ fileBrowser( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ,const QString filter=0, const QString iPath=0);
+ ~fileBrowser();
+
+ QPushButton* buttonOk;
+ QtrListView* ListView;
+ QPushButton* buttonCancel;
+ QLabel *dirLabel;
+ QString selectedFileName, filterStr;
+ QDir currentDir;
+ QFile file;
+ QStringList fileList;
+
+//QListViewItem * item;
+public slots:
+
+private:
+
+private slots:
+ void upDir();
+ void listDoubleClicked(QListViewItem *);
+ void listClicked(QListViewItem *);
+ void OnRoot();
+ void OnCancel();
+
+protected slots:
+
+protected:
+ void OnOK();
+ virtual void resizeEvent(QResizeEvent* e);
+};
+
+#endif // FILEBROWSER_H
diff --git a/noncore/apps/opie-reader/infowin.cpp b/noncore/apps/opie-reader/infowin.cpp
new file mode 100644
index 0000000..f9a6f5f
--- a/dev/null
+++ b/noncore/apps/opie-reader/infowin.cpp
@@ -0,0 +1,41 @@
+#include "infowin.h"
+#include "version.h"
+
+#define VERSION_STRING "QT Reader v" ## MAJOR ## "." ## MINOR ## " (" ## RELEASE_TYPE ## ")\nA small e-text reader"
+
+infowin::infowin( QWidget *parent=0, const char *name=0, WFlags f = 0) :
+ QWidget(parent, name, f)
+{
+ grid = new QGridLayout(this, 6, 2);
+ QLabel* l;
+ l = new QLabel("Compressed file size", this);
+ grid->addWidget(l, 0, 0);
+ fileSize = new QLabel("0", this);
+ fileSize->setAlignment( AlignVCenter | AlignRight );
+ grid->addWidget(fileSize, 0, 1);
+ l = new QLabel("Original text size", this);
+ grid->addWidget(l, 1, 0);
+ textSize = new QLabel("0", this);
+ textSize->setAlignment( AlignVCenter | AlignRight );
+ grid->addWidget(textSize, 1, 1);
+ l = new QLabel("Compression Ratio", this);
+ grid->addWidget(l, 2, 0);
+ ratio = new QLabel("0", this);
+ grid->addWidget(ratio, 2, 1);
+ ratio->setAlignment( AlignVCenter | AlignRight );
+ l = new QLabel("Current location", this);
+ grid->addWidget(l, 3, 0);
+ location = new QLabel("0", this);
+ location->setAlignment( AlignVCenter | AlignRight );
+ grid->addWidget(location, 3, 1);
+ l = new QLabel("Per centage read", this);
+ grid->addWidget(l, 4, 0);
+ read = new QLabel("0", this);
+ read->setAlignment( AlignVCenter | AlignRight );
+ grid->addWidget(read, 4, 1);
+ l = new QLabel(VERSION_STRING, this);
+ grid->addWidget(l, 5, 0);
+ QPushButton* exitbutton = new QPushButton("Cancel", this);
+ connect( exitbutton, SIGNAL( released() ), this, SLOT( infoClose() ) );
+ grid->addWidget(exitbutton, 5, 1);
+}
diff --git a/noncore/apps/opie-reader/infowin.h b/noncore/apps/opie-reader/infowin.h
new file mode 100644
index 0000000..9ddce36
--- a/dev/null
+++ b/noncore/apps/opie-reader/infowin.h
@@ -0,0 +1,52 @@
+#ifndef __INFOWIN_H
+#define __INFOWIN_H
+
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include <qgrid.h>
+#include <qlabel.h>
+
+class infowin : public QWidget
+{
+Q_OBJECT
+ QLabel* fileSize;
+ QLabel* textSize;
+ QLabel* ratio;
+ QLabel* location;
+ QLabel* read;
+ QGridLayout* grid;
+public:
+ infowin::infowin( QWidget *parent=0, const char *name=0, WFlags f = 0);
+/*
+ void addcancel(QPushButton* exitbutton)
+ {
+ grid->addWidget(exitbutton, 5, 1);
+ }
+*/
+ void setFileSize(int sz) { fileSize->setNum(sz); }
+ void setTextSize(int sz) { textSize->setNum(sz); }
+ void setRatio(int sz) { ratio->setText(QString().setNum(sz)+"%"); }
+ void setLocation(int sz) { location->setNum(sz); }
+ void setRead(int sz) { read->setText(QString().setNum(sz)+"%"); }
+/*
+ virtual void keyPressEvent(QKeyEvent* e)
+ {
+ printf("Received:%d\n", e->key());
+ switch (e->key())
+ {
+ case Key_Escape:
+ e->accept();
+ emit Close();
+ break;
+ default:
+ e->ignore();
+ }
+ }
+*/
+private slots:
+ void infoClose() { emit Close(); }
+ signals:
+ void Close();
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/main.cpp b/noncore/apps/opie-reader/main.cpp
new file mode 100644
index 0000000..e37f12c
--- a/dev/null
+++ b/noncore/apps/opie-reader/main.cpp
@@ -0,0 +1,38 @@
+#include <qpe/qpeapplication.h>
+//#include <qmainwindow.h>
+#include "QTReaderApp.h"
+
+
+
+
+
+/*
+class myapp : public QPEApplication
+{
+ public slots:
+ void receive( const QCString& msg, const QByteArray& data )
+ {
+
+ QDataStream stream( data, IO_ReadOnly );
+ if ( msg == "someMessage(int,int,int)" ) {
+ int a,b,c;
+ stream >> a >> b >> c;
+ ...
+ } else if ( msg == "otherMessage(QString)" ) {
+ ...
+ }
+
+ }
+}
+*/
+
+int main( int argc, char ** argv )
+{
+ QPEApplication a( argc, argv );
+
+ QTReaderApp m;
+ a.showMainDocumentWidget( &m );
+
+ return a.exec();
+}
+
diff --git a/noncore/apps/opie-reader/my_list.h b/noncore/apps/opie-reader/my_list.h
new file mode 100644
index 0000000..b3f0cc0
--- a/dev/null
+++ b/noncore/apps/opie-reader/my_list.h
@@ -0,0 +1,172 @@
+#ifndef __MY_LIST_H
+#define __MY_LIST_H
+
+template<class T>
+class CList
+{
+ struct node
+ {
+ T data;
+ node* next;
+ node(T _data, node* _next = NULL) : data(_data), next(_next) {}
+ node() : next(NULL) {};
+ };
+ protected:
+ node* front;
+ node* back;
+ public:
+ CList() : front(NULL), back(NULL) {}
+ ~CList()
+ {
+ if (front != NULL)
+ {
+ while (front != NULL)
+ {
+ node *p = front;
+ front = p->next;
+ delete p;
+ }
+ }
+ }
+ T* operator[](int n)
+ {
+ node* current = front;
+ while (n-- > 0)
+ {
+ if ((current = current->next) == NULL)
+ return NULL;
+ }
+ return &(current->data);
+ }
+ void push_front(const T& t)
+ {
+ node* n = new node(t,front);
+ if (front == NULL)
+ {
+ front = back = n;
+ }
+ else
+ front = n;
+ }
+ void push_back(const T& t)
+ {
+ node* n = new node(t);
+ if (front == NULL)
+ {
+ front = back = n;
+ }
+ else
+ {
+ back->next = n;
+ back = n;
+ }
+ }
+ void erase(unsigned int n)
+ {
+ node* p = front;
+ node* last = front;
+ while (n-- > 0)
+ {
+ last = p;
+ p = p->next;
+ if (p == NULL) return;
+ }
+ if (p == front)
+ {
+ front = p->next;
+ }
+ else
+ {
+ last->next = p->next;
+ }
+ if (p == back)
+ {
+ back = last;
+ }
+ delete p;
+ }
+ void sort()
+ {
+ int i,j,inc,n;
+ T v;
+ T* item;
+ node* t;
+ t = front;
+ n = 0;
+ while (t != NULL)
+ {
+ n++;
+ t = t->next;
+ }
+ if (n >= 2)
+ {
+ item = new T[n];
+ i = 0;
+ t = front;
+ for (t = front, i = 0; t != NULL; t = t->next, i++)
+ {
+ item[i] = t->data;
+ }
+
+ for (inc = 1; inc <= n; inc = 3*inc+1);
+
+ do
+ {
+ inc /= 3;
+ for (i = inc; i < n; i++)
+ {
+ v = item[i];
+ for (j = i; v < item[j-inc] && j >= inc; j -= inc)
+ {
+ item[j] = item[j-inc];
+ }
+ item[j] = v;
+ }
+ }
+ while (inc > 1);
+ for (t = front, i = 0; t != NULL; t = t->next, i++)
+ {
+ t->data = item[i];
+ }
+ // back = *(item[n-1]);
+ delete [] item;
+ }
+ }
+ class iterator
+ {
+ node* current;
+ public:
+ iterator(node* _c) : current(_c) {}
+ iterator& operator++()
+ {
+ current = current->next;
+ return *this;
+ }
+ iterator& operator++(int)
+ {
+ current = current->next;
+ return *this;
+ }
+ T operator*()
+ {
+ return current->data;
+ }
+ T* operator->()
+ {
+ return &(current->data);
+ }
+ bool operator!=(iterator t)
+ {
+ return (current != t.current);
+ }
+ };
+ iterator begin()
+ {
+ return iterator(front);
+ }
+ iterator end()
+ {
+ return iterator(NULL);
+ }
+};
+#endif
diff --git a/noncore/apps/opie-reader/opie-reader.control b/noncore/apps/opie-reader/opie-reader.control
new file mode 100644
index 0000000..e8c98bb
--- a/dev/null
+++ b/noncore/apps/opie-reader/opie-reader.control
@@ -0,0 +1,9 @@
+Files: bin/uqtreader apps/Applications/uqtreader.desktop pics/uqtreader.png pics/panel-arrow-down.png
+Priority: optional
+Section: applications
+Maintainer: Tim Wentford <timwentford@hotmail.com>
+Architecture: arm
+Version: 0_3r_beta_UTF8
+Depends:
+License: GPL
+Description: E-Book reader
diff --git a/noncore/apps/opie-reader/opie-reader.pro b/noncore/apps/opie-reader/opie-reader.pro
new file mode 100644
index 0000000..c4a87a4
--- a/dev/null
+++ b/noncore/apps/opie-reader/opie-reader.pro
@@ -0,0 +1,48 @@
+TEMPLATE = app
+CONFIG = qt warn_on release
+HEADERS = Aportis.h \
+ BuffDoc.h \
+ CBuffer.h \
+ CExpander.h \
+ CFilter.h \
+ QTReader.h \
+ QTReaderApp.h \
+ Text.h \
+ ZText.h \
+ arith.h \
+ my_list.h \
+ ppm.h \
+ ppm_expander.h \
+ cbkmkselector.h \
+ fileBrowser.h \
+ ztxt.h \
+ QtrListView.h \
+ infowin.h \
+ version.h \
+ pdb.h \
+ utypes.h \
+ ustring.h \
+ CEncoding.h \
+ config.h
+SOURCES = Aportis.cpp \
+ BuffDoc.cpp \
+ CBuffer.cpp \
+ QTReader.cpp \
+ QTReaderApp.cpp \
+ arith_d.cpp \
+ main.cpp \
+ ppm.cpp \
+ ppm_expander.cpp \
+ ztxt.cpp \
+ QtrListView.cpp \
+ infowin.cpp \
+ pdb.cpp \
+ CEncoding.cpp \
+ fileBrowser.cpp
+INTERFACES =
+DESTDIR = $(OPIEDIR)/bin
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += $(OPIEDIR)/include
+TARGET = uqtreader
+LIBS += -lqpe
+
diff --git a/noncore/apps/opie-reader/pdb.cpp b/noncore/apps/opie-reader/pdb.cpp
new file mode 100644
index 0000000..68b904e
--- a/dev/null
+++ b/noncore/apps/opie-reader/pdb.cpp
@@ -0,0 +1,57 @@
+#include "pdb.h"
+
+size_t Cpdb::recordpos(int n)
+{
+ UInt16 mxn = ntohs(head.recordList.numRecords);
+ if (n >= mxn)
+ {
+ return file_length;
+ }
+ else
+ {
+ size_t dataoffset = sizeof(DatabaseHdrType) - sizeof(UInt16);
+ dataoffset += /*dataoffset%4 + */ sizeof(RecordListType) * n;
+ fseek(fin, dataoffset, SEEK_SET);
+ RecordListType hdr;
+ fread(&hdr, 1, sizeof(hdr), fin);
+ return ntohl(hdr.nextRecordListID);
+ }
+
+}
+
+size_t Cpdb::recordlength(int n)
+{
+ return recordpos(n+1)-recordpos(n);
+}
+
+void Cpdb::gotorecordnumber(int n)
+{
+ fseek(fin, recordpos(n), SEEK_SET);
+}
+
+bool Cpdb::openfile(const char *src)
+{
+
+ // printf("In openfile\n");
+ int ret = 0;
+ // printf("closing fin:%x\n",fin);
+ if (fin != NULL) fclose(fin);
+ // printf("opening fin\n");
+ fin = fopen(src,"rb");
+
+ if (fin==0)
+ {
+ return false;
+ }
+
+ // just holds the first few chars of the file
+ // char buf[0x100];
+ fseek(fin,0,SEEK_END);
+ file_length = ftell(fin);
+
+ fseek(fin,0,SEEK_SET);
+
+ fread(&head, 1, sizeof(head), fin);
+
+ return true;
+}
diff --git a/noncore/apps/opie-reader/pdb.h b/noncore/apps/opie-reader/pdb.h
new file mode 100644
index 0000000..143c5cb
--- a/dev/null
+++ b/noncore/apps/opie-reader/pdb.h
@@ -0,0 +1,90 @@
+
+/*
+ * This header file defines some structures and types normally found in the
+ * Palm SDK. However, I don't want to require the presense of the SDK for a
+ * small utility since most Palm owners won't have it.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef __PDB_H__
+#define __PDB_H__
+
+#include <netinet/in.h>
+#include <stdio.h>
+
+/* Normal Palm typedefs */
+typedef unsigned char UInt8;
+typedef unsigned short UInt16;
+typedef unsigned long UInt32;
+typedef UInt32 LocalID;
+
+/* Max length of DB name */
+#define dmDBNameLength 0x20
+
+
+/************************************************************
+ * Structure of a Record entry
+ *************************************************************/
+typedef struct {
+ LocalID localChunkID; // local chunkID of a record
+ UInt8 attributes; // record attributes;
+ UInt8 uniqueID[3]; // unique ID of record; should
+ // not be 0 for a legal record.
+} RecordEntryType;
+
+
+/************************************************************
+ * Structure of a record list extension. This is used if all
+ * the database record/resource entries of a database can't fit into
+ * the database header.
+ *************************************************************/
+typedef struct {
+ LocalID nextRecordListID; // local chunkID of next list
+ UInt16 numRecords; // number of records in this list
+ UInt16 firstEntry; // array of Record/Rsrc entries
+ // starts here
+} RecordListType;
+
+
+/************************************************************
+ * Structure of a Database Header
+ *************************************************************/
+typedef struct {
+ UInt8 name[dmDBNameLength]; // name of database
+ UInt16 attributes; // database attributes
+ UInt16 version; // version of database
+ UInt32 creationDate; // creation date of database
+ UInt32 modificationDate; // latest modification date
+ UInt32 lastBackupDate; // latest backup date
+ UInt32 modificationNumber; // modification number of database
+ LocalID appInfoID; // application specific info
+ LocalID sortInfoID; // app specific sorting info
+ UInt32 type; // database type
+ UInt32 creator; // database creator
+ UInt32 uniqueIDSeed; // used to generate unique IDs.
+ // Note that only the low order
+ // 3 bytes of this is used (in
+ // RecordEntryType.uniqueID).
+ // We are keeping 4 bytes for
+ // alignment purposes.
+ RecordListType recordList; // first record list
+} DatabaseHdrType;
+
+
+class Cpdb
+{
+ protected:
+ size_t file_length;
+ FILE* fin;
+ size_t recordpos(int);
+ size_t recordlength(int);
+ void gotorecordnumber(int);
+ DatabaseHdrType head;
+ bool openfile(const char* src);
+ Cpdb() : fin(NULL) {}
+ ~Cpdb() { if (fin != NULL) fclose(fin); }
+};
+#endif
+
diff --git a/noncore/apps/opie-reader/ppm.cpp b/noncore/apps/opie-reader/ppm.cpp
new file mode 100644
index 0000000..e8bf110
--- a/dev/null
+++ b/noncore/apps/opie-reader/ppm.cpp
@@ -0,0 +1,756 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "arith.h"
+#include "ppm.h"
+
+/****************************************************************************
+ * Gestion des noeuds
+ ****************************************************************************/
+
+/*
+ * Désallocation du noeud p
+ */
+
+void ppm_worker::Node_Free(UINT p) {
+ node_heap[node_free_last].free_next=p;
+ node_heap[p].free_next=NIL;
+ node_free_last=p;
+ node_free_nb++;
+}
+
+/*
+ * Allocation d'un noeud
+ * s'il ne reste plus de place, on désalloue le contexte le moins utilisé.
+ */
+
+UINT ppm_worker::Node_Alloc(void) {
+ UINT p;
+ if (node_free_nb<=2) Context_DeleteLast();
+ p=node_free_first;
+ node_free_first=node_heap[node_free_first].free_next;
+ node_free_nb--;
+#ifdef DEBUG
+ printf("Node_Alloc: p=%d\n",p);
+#endif
+ return p;
+}
+
+/****************************************************************************
+ * Gestion des contextes
+ ****************************************************************************/
+
+
+/*
+ * Mise au début de la liste des contextes du contexte c
+ */
+void ppm_worker::Context_MoveFirst(UINT c) {
+ NODE *ctx;
+
+ if (c!=ctx_first) {
+ ctx=&node_heap[c];
+ /* suppression du contexte dans la liste */
+ if (c==ctx_last) {
+ ctx_last=ctx->hdr.ctx_prev;
+ } else {
+ node_heap[ctx->hdr.ctx_prev].hdr.ctx_next=ctx->hdr.ctx_next;
+ node_heap[ctx->hdr.ctx_next].hdr.ctx_prev=ctx->hdr.ctx_prev;
+ }
+ /* insertion au début de la liste */
+ node_heap[ctx_first].hdr.ctx_prev=c;
+ ctx->hdr.ctx_next=ctx_first;
+ ctx_first=c;
+ }
+}
+
+/*
+ * Destruction du contexte le moins utilisé (ctx_last)
+ */
+void ppm_worker::Context_DeleteLast(void) {
+ NODE *n;
+ UINT h,h_next,node,node_next;
+ USHORT *p;
+
+ n=&node_heap[ctx_last];
+
+ /* libération dans la table de hachage. Comme on ne dispose pas de
+ * pointeur hash_prev dans les contextes, il faut parcourir toute
+ * la liste. Heureusement, celle-ci est de longueur faible en moyenne
+ */
+ h_next=n->hdr.hash_next;
+ h=h_next;
+ while (h<HASH_ADDRESS) h=node_heap[h].hdr.hash_next;
+ p=&hash_table[h-HASH_ADDRESS];
+ while (*p!=ctx_last) p=&node_heap[*p].hdr.hash_next;
+ *p=h_next;
+
+ /* libération des noeuds & modification de ctx_last */
+
+ if (n->hdr.sf_max>=2) {
+ node=n->hdr.sf.l.sf_next;
+ while (1) {
+ node_next=node_heap[node].sf.sf_next;
+ Node_Free(node);
+ if (node_next==NIL) break;
+ node=node_next;
+ }
+ }
+
+ node=ctx_last;
+ ctx_last=n->hdr.ctx_prev;
+ Node_Free(node);
+ ctx_nb--;
+}
+
+/*
+ * Création d'un nouveau contexte avec un seul symbole sym de fréquence 1
+ * Utilisation implicite de sym_context et sym_hash.
+ * Libération de mémoire si nécessaire, et mise en premier dans la liste
+ */
+void ppm_worker::Context_New(int sym,int order) {
+ NODE *ctx;
+ UINT i,c;
+
+#ifdef DEBUG
+ printf("Context_New: sym=%d o=%d\n",sym,order);
+#endif
+
+ c=Node_Alloc();
+ ctx=&node_heap[c];
+
+ /* mise du contexte en tête de la liste */
+ ctx->hdr.ctx_next=ctx_first;
+ node_heap[ctx_first].hdr.ctx_prev=c;
+ ctx_first=c;
+ ctx_nb++;
+
+ /* insertion dans la table de hachage */
+ ctx->hdr.hash_next=hash_table[sym_hash[order]];
+ hash_table[sym_hash[order]]=ctx_first;
+
+ /* initialisation du contexte */
+ ctx->hdr.order=order;
+ for(i=0;i<order;i++) ctx->hdr.sym[i]=sym_context[i+1];
+
+ ctx->hdr.sf_max=0;
+ ctx->hdr.sf.sf[0].sym=sym;
+ ctx->hdr.sf.sf[0].freq=1;
+#ifdef DEBUG
+ Context_Print(ctx_first);
+#endif
+}
+
+/*
+ * Ajout d'un nouveau symbole au contexte c
+ */
+
+void ppm_worker::Context_NewSym(int sym,UINT c) {
+ NODE *n,*m;
+ UINT p,sf_max;
+
+#ifdef DEBUG
+ printf("Context_NewSym: sym=%d c=%d\n",sym,c);
+ Context_Print(c);
+#endif
+
+ n=&node_heap[c];
+ sf_max=n->hdr.sf_max;
+ n->hdr.sf_max++;
+ if (sf_max==0) {
+ n->hdr.sf.sf[1].sym=sym;
+ n->hdr.sf.sf[1].freq=1;
+ } else if (sf_max==1) {
+ p=Node_Alloc();
+ m=&node_heap[p];
+ m->sf.sf[0]=n->hdr.sf.sf[0];
+ m->sf.sf[1]=n->hdr.sf.sf[1];
+ m->sf.sf[2].sym=sym;
+ m->sf.sf[2].freq=1;
+ m->sf.sf_next=NIL;
+ n->hdr.sf.l.sf_next=p;
+ n->hdr.sf.l.freq_tot=((UINT)m->sf.sf[0].freq+(UINT)m->sf.sf[1].freq+1);
+ } else {
+ n->hdr.sf.l.freq_tot++;
+ m=&node_heap[n->hdr.sf.l.sf_next];
+ while (sf_max>=NODE_SFNB) {
+ sf_max-=NODE_SFNB;
+ m=&node_heap[m->sf.sf_next];
+ }
+ sf_max++;
+ if (sf_max==NODE_SFNB) {
+ p=Node_Alloc();
+ m->sf.sf_next=p;
+ m=&node_heap[p];
+ m->sf.sf_next=NIL;
+ sf_max=0;
+ }
+ m->sf.sf[sf_max].sym=sym;
+ m->sf.sf[sf_max].freq=1;
+ }
+#ifdef DEBUG
+ Context_Print(c);
+#endif
+}
+
+
+#ifdef STAT
+int hash_nb=1;
+int hash_cnt=0;
+#endif
+
+/*
+ * Recherche d'un contexte, utilisation de façon implicite de sym_context
+ * et de sym_hash.
+ * C'est une procédure très critique qui doit être particulièrement optimisée
+ */
+
+UINT ppm_worker::Context_Search(int order) {
+ UCHAR *sym;
+ UINT i,p;
+ NODE *n;
+#ifdef DEBUG
+ printf("Context_Search: o=%d\n",order);
+#endif
+
+ p=hash_table[sym_hash[order]];
+ sym=&sym_context[1];
+#ifdef STAT
+ hash_nb++;
+#endif
+ while (p<HASH_ADDRESS) {
+#ifdef STAT
+ hash_cnt++;
+#endif
+ n=&node_heap[p];
+ if (n->hdr.order==order) {
+ if (order==0) return p;
+ i=0;
+ while (sym[i]==n->hdr.sym[i]) {
+ i++;
+ if (i==order) return p;
+ }
+ }
+ p=n->hdr.hash_next;
+ }
+ return HASH_ADDRESS;
+}
+
+/*
+ * Cette macro est HORRIBLE mais permet de simplifier beaucoup le parcours
+ * des listes de couples symbole,fréquence tout en ayant un code rapide.
+ * Une alternative élégante mais lente aurait été de passer une fonction
+ * en paramètre contenant le code à exécuter
+ */
+
+#define SF_Read(n,p,code_to_execute) \
+{\
+ UINT nb,i;\
+ nb=(UINT)n->hdr.sf_max+1;\
+ if (nb<=HDR_SFNB) {\
+ p=&n->hdr.sf.sf[0];\
+ } else {\
+ p=&node_heap[n->hdr.sf.l.sf_next].sf.sf[0];\
+ while (nb>NODE_SFNB) {\
+ for(i=0;i<NODE_SFNB;i++) {\
+ code_to_execute;\
+ p++;\
+ }\
+ p=&node_heap[ *((USHORT *)p) ].sf.sf[0];\
+ nb-=NODE_SFNB;\
+ }\
+ }\
+ for(i=0;i<nb;i++) {\
+ code_to_execute;\
+ p++;\
+ }\
+}
+
+
+/*
+ * Renormalisation d'un contexte, ie, division de toutes les fréquences
+ * par 2 et élimination des symboles de fréquence nulle
+ * Note: le contexte obtenu n'est jamais vide.
+ * Une amélioration prévue mais non implémentée serait de trier le contexte
+ * dans l'ordre des fréquences décroissantes pour accélérer la recherche.
+ * Les gains en vitesse seraient de toute façon assez faibles car les
+ * contextes sont de toute façon à peu près triés vu leur méthode de
+ * construction: les caractères sont ajoutés à la fin de la liste
+ */
+void ppm_worker::Context_Renorm(UINT ctx) {
+ NODE *n,*m;
+ UINT a,b,c,i,freq_tot,sf_nb;
+ SYMFREQ s,*p,tab_sf[SYM_NB];
+
+#ifdef DEBUG
+ printf("Context_Renorm: c=%d\n",ctx);
+ Context_Print(ctx);
+#endif
+
+ n=&node_heap[ctx];
+ freq_tot=0;
+ sf_nb=0;
+
+ SF_Read(n,p, {
+ s=*p;
+ s.freq=s.freq/2;
+ if (s.freq!=0) {
+ freq_tot+=s.freq;
+ tab_sf[sf_nb]=s;
+ sf_nb++;
+ }
+ } );
+
+
+ /* libération des noeuds utilisés pour stocker les symboles */
+ if (n->hdr.sf_max>=HDR_SFNB) {
+ a=n->hdr.sf.l.sf_next;
+ do {
+ b=node_heap[a].sf.sf_next;
+ Node_Free(a);
+ a=b;
+ } while (a!=NIL);
+ }
+
+ /* reconstruction de la liste des "sf_nb" symboles d'apres le tableau
+ * "tab_sf"
+ */
+
+ n->hdr.sf_max=sf_nb-1;
+ if (sf_nb<=HDR_SFNB) {
+ for(i=0;i<sf_nb;i++) n->hdr.sf.sf[i]=tab_sf[i];
+ } else {
+ a=Node_Alloc();
+ n->hdr.sf.l.sf_next=a;
+ n->hdr.sf.l.freq_tot=freq_tot;
+ m=&node_heap[a];
+ i=0;
+ c=0;
+ while (1) {
+ m->sf.sf[c]=tab_sf[i];
+ i++;
+ if (i==sf_nb) break;
+ c++;
+ if (c==NODE_SFNB) {
+ c=0;
+ a=Node_Alloc();
+ m->sf.sf_next=a;
+ m=&node_heap[a];
+ }
+ }
+ m->sf.sf_next=NIL;
+ }
+
+#ifdef DEBUG
+ Context_Print(ctx);
+#endif
+}
+
+
+/*
+ * Mise à jour des index dans la table de hachage et des caractères du
+ * contexte courant.
+ * La fonction de hachage a été choisie de façon empirique en controlant
+ * qu'elle donne en moyenne de bons résultats.
+ */
+void ppm_worker::Hash_Update(int sym) {
+ UINT i,k;
+
+ for(i=ORDER_MAX;i>=2;i--)
+ sym_context[i]=sym_context[i-1];
+ sym_context[1]=sym;
+
+ for(i=ORDER_MAX;i>=2;i--) {
+ k=sym_hash[i-1];
+ sym_hash[i]=( (k<<6)-k+sym ) & (HASH_SIZE-1);
+ }
+ sym_hash[1]=sym+1;
+}
+
+
+/****************************************************************************
+ * Système d'exclusion des symboles
+ ****************************************************************************/
+
+
+/*
+ * Remise à zéro du tableau d'exclusion des symboles
+ */
+void ppm_worker::Sym_ExcludeReset(void) {
+ UINT i;
+
+ sym_excl_code++;
+ if (sym_excl_code==0) {
+ for(i=0;i<SYM_NB;i++) sym_excl[i]=0;
+ sym_excl_code=1;
+ }
+}
+
+
+/****************************************************************************
+ * Initialisation et Libération mémoire
+ ****************************************************************************/
+
+/*
+ * Initialisation des structures de données du compresseur/décompresseur
+ * retourne 0 si tout va bien
+ */
+int ppm_worker::PPM_Init(unsigned short NODE_NBMAX) {
+ UINT i;
+ node_heap= new NODE[NODE_NBMAX];
+ hash_table= new USHORT[HASH_SIZE];
+ if (node_heap==NULL || hash_table==NULL) {
+ if (node_heap!=NULL) delete [] node_heap;
+ if (hash_table!=NULL) delete [] hash_table;
+ return 1;
+ }
+ /* noeuds: tous vides */
+ for(i=0;i<=(NODE_NBMAX-2);i++) node_heap[i].free_next=i+1;
+ node_heap[NODE_NBMAX-1].free_next=NIL;
+ node_free_first=0;
+ node_free_last=NODE_NBMAX-1;
+ node_free_nb=NODE_NBMAX;
+
+ /* contextes */
+ for(i=0;i<HASH_SIZE;i++) hash_table[i]=HASH_ADDRESS+i;
+
+ /* cette initialisation n'est pas sûre mais simplifie beaucoup le code:
+ * on suppose que le premier contexte sera alloué dans le noeud 0
+ */
+ ctx_first=0;
+ ctx_last=0;
+ ctx_nb=0;
+
+ /* contexte courant */
+ for(i=0;i<=ORDER_MAX;i++) sym_context[i]=0;
+ for(i=0;i<=ORDER_MAX;i++) sym_hash[i]=0;
+
+ /* système d'exclusion des caractères */
+ sym_excl_code=0xFF;
+
+ return 0;
+}
+
+/*
+ * Fin de la compression/décompression: on libère la mémoire
+ */
+void ppm_worker::PPM_End(void) {
+ free(hash_table);
+ free(node_heap);
+}
+
+/****************************************************************************
+ * Décodage et décompression
+ ****************************************************************************/
+
+/*
+ * Décodage: cf Encode_NewSym
+ */
+int ppm_worker::Decode_NewSym(void) {
+ UINT i,freq_tot,freq_cum,f;
+ UCHAR code;
+
+ code=sym_excl_code;
+ freq_tot=0;
+ for(i=0;i<SYM_NB;i++) if (sym_excl[i]!=code) freq_tot++;
+ f=arith.Arith_DecodeVal(freq_tot+SYM_SPECIAL_NB);
+ if (f>=freq_tot) {
+ /* cas d'un symbole spécial */
+ arith.Arith_Decode(f,f+1,freq_tot+SYM_SPECIAL_NB);
+ return SYM_NB+f-freq_tot;
+ } else {
+ i=0;
+ freq_cum=0;
+ while (1) {
+ if (sym_excl[i]!=code) {
+ freq_cum++;
+ if (freq_cum>f) break;
+ }
+ i++;
+ }
+ arith.Arith_Decode(freq_cum-1,freq_cum,freq_tot+SYM_SPECIAL_NB);
+ return i;
+ }
+}
+
+/*
+ * Décodage: cf Decode_NoExclude
+ */
+int ppm_worker::Decode_NoExclude(UINT ctx) {
+ NODE *n;
+ UCHAR code;
+ UINT i,f,freq_tot,freq_cum,freq_sym,sf_nb;
+ SYMFREQ *p,s;
+
+
+ n=&node_heap[ctx];
+ code=sym_excl_code;
+
+ /* Calcul de la somme des fréquences des caractères */
+ if (n->hdr.sf_max<HDR_SFNB) {
+ freq_tot=0;
+ for(i=0;i<=n->hdr.sf_max;i++) freq_tot+=n->hdr.sf.sf[i].freq;
+ } else {
+ freq_tot=n->hdr.sf.l.freq_tot;
+ }
+
+ /* décodage */
+ sf_nb=(UINT) n->hdr.sf_max+1;
+ f=arith.Arith_DecodeVal(freq_tot+sf_nb);
+ if (f>=freq_tot) {
+ /* gestion du code ESCAPE */
+
+ /* marquage des caractères utilisés */
+ SF_Read(n,p, { sym_excl[p->sym]=code; });
+
+ /* décodage ESCAPE */
+ arith.Arith_Decode(freq_tot,freq_tot+sf_nb,freq_tot+sf_nb);
+ return SYM_ESCAPE;
+ }
+
+ /* recherche du caractère en calculant la fréquence */
+ freq_cum=0;
+ SF_Read(n,p, {
+ s=*p;
+ freq_cum+=s.freq;
+ if (freq_cum>f) goto decode_sym;
+ } );
+
+ decode_sym:
+
+ freq_sym=s.freq;
+ p->freq=freq_sym+1;
+ if (n->hdr.sf_max>=HDR_SFNB) n->hdr.sf.l.freq_tot=freq_tot+1;
+
+ arith.Arith_Decode(freq_cum-freq_sym,freq_cum,freq_tot+sf_nb);
+
+ /* test de la renormalisation */
+ if (freq_sym==(RENORM_FREQSYM-1) || freq_tot>=RENORM_FREQTOT) {
+ Context_Renorm(ctx);
+ }
+ return s.sym;
+}
+
+
+/*
+ * Décodage: cf Encode_Exclude
+ */
+
+int ppm_worker::Decode_Exclude(UINT ctx) {
+ UINT sf_nb,freq_sym,freq_cum,freq_tot,f;
+ NODE *n;
+ SYMFREQ s,*p;
+ UCHAR code;
+
+ n=&node_heap[ctx];
+ code=sym_excl_code;
+
+ freq_tot=0;
+ sf_nb=0;
+
+ SF_Read( n,p, {
+ s=*p;
+ if (sym_excl[s.sym]!=code)
+ {
+ freq_tot+=s.freq;
+ sf_nb++;
+ }
+ } );
+
+
+ f=arith.Arith_DecodeVal(freq_tot+sf_nb);
+
+ if (f>=freq_tot) {
+
+ /* ESCAPE */
+
+ SF_Read(n,p, { sym_excl[p->sym]=code; } );
+
+ arith.Arith_Decode(freq_tot,freq_tot+sf_nb,freq_tot+sf_nb);
+
+ return SYM_ESCAPE;
+ } else {
+
+ /* recherche du caractère */
+
+ freq_cum=0;
+ SF_Read(n,p, {
+ s=*p;
+ if (sym_excl[s.sym]!=code) {
+ freq_cum+=s.freq;
+ if (freq_cum>f) goto decode_sym;
+ }
+ } );
+
+ decode_sym:
+
+ /* incrémentation de la fréquence */
+
+ freq_sym=p->freq;
+ p->freq=freq_sym+1;
+ if (n->hdr.sf_max>=HDR_SFNB) n->hdr.sf.l.freq_tot++;
+
+ /* décodage du caractère */
+
+ arith.Arith_Decode(freq_cum-freq_sym,freq_cum,freq_tot+sf_nb);
+
+ if (freq_sym==(RENORM_FREQSYM-1) || freq_tot>=RENORM_FREQTOT) {
+ Context_Renorm(ctx);
+ }
+
+ return s.sym;
+ }
+}
+
+
+/*
+ * Décodage d'un symbole
+ */
+int ppm_worker::PPM_Decode(void) {
+ int i,order,sym;
+ UINT ctx,ctx_tab[ORDER_MAX+1],ctx_last;
+
+
+ /* recherche de l'ordre maximum */
+
+ Sym_ExcludeReset();
+ order=ORDER_MAX;
+ ctx_last=NIL;
+ while (1) {
+ ctx=Context_Search(order);
+ ctx_tab[order]=ctx;
+ if (ctx<HASH_ADDRESS) {
+ Context_MoveFirst(ctx);
+ if (ctx_last==NIL)
+ sym=Decode_NoExclude(ctx);
+ else
+ sym=Decode_Exclude(ctx);
+ if (sym!=SYM_ESCAPE) break;
+ ctx_last=ctx;
+ }
+ order--;
+ if (order==-1) {
+ sym=Decode_NewSym();
+ if (sym>=SYM_NB) return sym;
+ break;
+ }
+ }
+
+ for(i=order+1;i<=ORDER_MAX;i++) {
+ if (ctx_tab[i]>=HASH_ADDRESS)
+ Context_New(sym,i);
+ else
+ Context_NewSym(sym,ctx_tab[i]);
+ }
+
+ Hash_Update(sym);
+
+ return sym;
+}
+
+/*
+ * Décompression: idem
+ */
+
+#ifdef STAT
+
+/****************************************************************************
+ * Statistiques
+ ****************************************************************************/
+
+
+void ppm_worker::PrintStat(void) {
+ fprintf(stderr,"free=%d ctx_nb=%d hash_moy=%0.2f\n",
+ node_free_nb,ctx_nb,
+ (float)hash_cnt/(float)hash_nb);
+
+}
+
+/*
+ * Impression d'un caractère
+ */
+void ppm_worker::Sym_Print(int c) {
+ if (c>=32 && c<=126) printf("%c",c); else printf("\\%2X",c);
+}
+
+/*
+ * Impression couple SYMFREQ
+ */
+
+void ppm_worker::SF_Print(SYMFREQ s) {
+ Sym_Print(s.sym);
+ printf(":%d ",s.freq);
+}
+
+/*
+ * Impression du contenu d'un contexte
+ * utilisé pour les tests
+ */
+
+void ppm_worker::Context_Print(UINT c) {
+ NODE *n;
+ int i,sf_max,sf_nb,sf_freq;
+
+ n=&node_heap[c];
+
+ sf_max=n->hdr.sf_max;
+ sf_nb=sf_max+1;
+ if (sf_max>=2) sf_freq=n->hdr.sf.l.freq_tot;
+ else {
+ sf_freq=0;
+ for(i=0;i<=sf_max;i++) sf_freq+=n->hdr.sf.sf[i].freq;
+ }
+
+ printf("Ctx=%d: hash_n=%d ctx_p=%d ctx_n=%d o=%d sf_nb=%d sf_freq=%d\n",
+ c,n->hdr.hash_next,n->hdr.ctx_prev,n->hdr.ctx_next,
+ n->hdr.order,sf_nb,sf_freq);
+ for(i=0;i<n->hdr.order;i++) Sym_Print(n->hdr.sym[i]);
+ printf(": ");
+ if (sf_max<=1) {
+ for(i=0;i<=sf_max;i++) SF_Print(n->hdr.sf.sf[i]);
+ } else {
+ n=&node_heap[n->hdr.sf.l.sf_next];
+ i=0;
+ while (1) {
+ SF_Print(n->sf.sf[i]);
+ if (sf_max==0) break;
+ i++;
+ sf_max--;
+ if (i==NODE_SFNB) {
+ i=0;
+ n=&node_heap[n->sf.sf_next];
+ }
+ }
+ }
+ printf("\n");
+}
+
+
+/*
+ * Nombre total de contextes et nombre de contextes de longueur données.
+ * Utilisé pour les statistiques
+ */
+
+void ppm_worker::Context_Statistic(void) {
+ UINT i,p;
+ int tab[SYM_NB+1],tot,cnt;
+
+ for(i=0;i<=SYM_NB;i++) tab[i]=0;
+ tot=0;
+
+ p=ctx_first;
+ do {
+ cnt=node_heap[p].hdr.sf_max+1;
+ tab[cnt]++;
+ tot++;
+ p=node_heap[p].hdr.ctx_next;
+ } while (p!=ctx_last);
+
+
+ printf("Context_Statistic: ");
+ for(i=1;i<=SYM_NB;i++) {
+ printf("%d:%d (%0.2f%%),",i,tab[i],(float)tab[i]/(float)tot*100.0);
+ }
+ printf("\n");
+}
+
+#endif
+
diff --git a/noncore/apps/opie-reader/ppm.h b/noncore/apps/opie-reader/ppm.h
new file mode 100644
index 0000000..4df9085
--- a/dev/null
+++ b/noncore/apps/opie-reader/ppm.h
@@ -0,0 +1,179 @@
+#include "utypes.h"
+
+#ifndef PPM_H
+
+#define PPM_H
+
+#include "arith.h"
+
+/* pour le calcul éventuel de quelques statistiques */
+/* #define STAT */
+
+/* mise en mode debogage */
+/* #define DEBUG */
+
+/* nombre de noeuds maximum: peut être modifié, mais doit être tel que:
+ * HASH_SIZE+NODE_NBMAX<65530
+ */
+//#define NODE_NBMAX 40000
+
+/*
+ * taille des buffers d'entrée/sortie
+ */
+#define BUFSIZE 1024
+
+/*
+ * Taille de la table de hachage
+ */
+#define HASH_SIZE 16384
+
+/* ordre maximale de prédiction utilisé (Phi) */
+#define ORDER_MAX 4
+
+/* fréquence maximale d'un symbole */
+#define RENORM_FREQSYM 250
+
+/* fréquence maximale pour la somme des fréquences des symboles d'un contexte */
+#define RENORM_FREQTOT 15000
+
+/* nombre de couples symbole,fréquence dans les structures de noeuds
+ * ajusté pour faire au total 16 octets */
+#define NODE_SFNB 7
+#define HDR_SFNB 2
+
+/* nombre de symboles à coder sans compter les symboles spéciaux */
+#define SYM_NB 256
+
+/* nombre de symboles spéciaux: pour extension si besoin de signalisation */
+#define SYM_SPECIAL_NB 1
+
+/* code associé au symbole ESCAPE (jamais codé de façon explicite) */
+#define SYM_ESCAPE 256
+
+/* code de fin de fichier */
+#define SYM_EOF 256
+
+/* valeur NULL pour les pointeurs stockés dans des USHORT */
+#define NIL 0xFFFF
+
+/* codage de NIL utilisé pour retrouver l'adresse dans la table de hachage
+ * d'un contexte en regardant seulement CTXHDR.hash_next */
+#define HASH_ADDRESS (65530-HASH_SIZE)
+
+
+/* stockage d'un couple symbole, fréquence */
+typedef struct {
+ UCHAR sym; /* numéro du symbole */
+ UCHAR freq; /* fréquence du symbole */
+} SYMFREQ;
+
+
+/* header pour gérer un contexte */
+typedef struct {
+ USHORT ctx_next; /* contexte suivant (moins utilisé) */
+ USHORT ctx_prev; /* contexte précédent (plus utilisé) */
+ USHORT hash_next; /* contexte suivant dans une entrée de la table
+ * de hachage */
+ UCHAR order; /* ordre du contexte */
+ UCHAR sym[ORDER_MAX]; /* symboles constituant le contexte */
+ UCHAR sf_max; /* nombre de symboles-1 dans la liste L */
+ union {
+ SYMFREQ sf[HDR_SFNB]; /* s'il y a moins de HDR_SFNB symboles dans
+ * le contexte, on les stocke directement ici
+ */
+ struct {
+ USHORT freq_tot; /* sinon on stocke la fréquence totale (c) */
+ USHORT sf_next; /* et un pointeur sur le premier noeud
+ * constituant la liste L des symboles associés
+ * au contexte */
+ } l;
+ } sf;
+} CTXHDR;
+
+/* structure pour gérer NODE_SFNB éléments de la liste des symboles associés
+ * à un contexte */
+typedef struct {
+ SYMFREQ sf[NODE_SFNB]; /* les couples symbole, fréquence */
+ USHORT sf_next; /* pointeur sur l'éventuel bloc suivant */
+} CTXSYMFREQ;
+
+/*
+ * structure de base pour la gestion de la mémoire: le noeud
+ */
+
+typedef union _NODE {
+ CTXHDR hdr; /* si le noeud contient un header de contexte */
+ CTXSYMFREQ sf; /* si le noeud contient une partie de la liste L */
+ USHORT free_next; /* si le noeud est vide: pointeur sur un noeud vide
+ * suivant */
+} NODE;
+
+class ppm_worker
+{
+
+/* gestion des noeuds */
+NODE *node_heap; /* heap contenant tous les noeuds */
+UINT node_free_nb; /* nombre de noeuds vides */
+UINT node_free_first; /* premier noeud de la liste des noeuds vides */
+UINT node_free_last; /* dernier noeud de la liste des noeuds vides */
+
+/* gestion de la liste des contextes les plus utilisés */
+USHORT *hash_table; /* table de hachage pour rechercher un contexte */
+UINT ctx_first; /* premier contexte: le plus utilisé */
+UINT ctx_last; /* dernier contexte: le moins utilisé */
+UINT ctx_nb; /* nombre de contextes */
+
+/* données caractérisant le contexte courant */
+UCHAR sym_context[ORDER_MAX+1]; /* symboles précédants le symbole en cours
+ * de codage */
+int sym_hash[ORDER_MAX+1]; /* index dans la table de hachage
+ * correspondants aux différentes longueurs
+ * de contextes
+ */
+
+/* système d'exclusion des caractères */
+UCHAR sym_excl[SYM_NB]; /* tableau pour l'exclusion */
+UCHAR sym_excl_code; /* code courant pour l'exclusion */
+
+
+/* déclaration des fonctions de base */
+
+/* noeuds */
+void Node_Free(UINT p);
+UINT Node_Alloc(void);
+
+/* contextes */
+void Context_DeleteLast(void);
+void Context_MoveFirst(UINT c);
+void Context_New(int sym,int order);
+void Context_NewSym(int sym,UINT c);
+UINT Context_Search(int order);
+void Context_Renorm(UINT ctx);
+void Hash_Update(int sym);
+ void Sym_ExcludeReset(void);
+
+/* codage */
+/*
+void Encode_NewSym(int sym);
+int Encode_NoExclude(int sym,UINT ctx);
+int Decode_Exclude(UINT ctx);
+int PPM_Decode(void);
+*/
+
+/* décodage */
+int Decode_NewSym(void);
+int Decode_NoExclude(UINT ctx);
+int Decode_Exclude(UINT ctx);
+
+#ifdef STAT
+void PrintStat(void);
+#endif
+ public:
+ ArithClass arith;
+ int PPM_Init(unsigned short);
+ void PPM_End(void);
+ int PPM_Decode(void);
+};
+
+#endif
+
diff --git a/noncore/apps/opie-reader/ppm_expander.cpp b/noncore/apps/opie-reader/ppm_expander.cpp
new file mode 100644
index 0000000..4f0a277
--- a/dev/null
+++ b/noncore/apps/opie-reader/ppm_expander.cpp
@@ -0,0 +1,108 @@
+/*
+ * Interface pour le programme de compression
+ * (c) 1995 Fabrice Bellard
+ */
+
+#include <stdlib.h>
+//#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+/***************************************************************************
+ * Interface avec les routines de compression
+ */
+
+#define METHOD_NB 2 /* nombre total de méthodes de compression */
+
+#define METHOD_STORE 0
+#define METHOD_PPM 1
+
+
+#define DEFAULT_SUFFIX ".st" /* extension par défault */
+/* signature en début de fichier */
+#define STAT_MAGIC_SIZE 4
+char stat_magic[STAT_MAGIC_SIZE]={'P','P','M','S'};
+
+#include "ppm_expander.h"
+
+ppm_expander::~ppm_expander() {
+ if (needppmend) ppm.PPM_End();
+ ppm.arith.Arith_DecodeEnd();
+ if (buf_in!=NULL) delete [] buf_in;
+ if (buf_out!=NULL) delete [] buf_out;
+ if (my_read_buf != NULL) delete my_read_buf;
+ if (my_file_in != NULL) fclose(my_file_in);
+}
+
+int ppm_expander::openfile(const char* infile)
+{
+ my_file_in=fopen(infile,"rb");
+ my_read_buf = new PPM_ReadBuf(my_file_in);
+ return home();
+}
+
+void ppm_expander::sizes(unsigned long& file, unsigned long& text)
+{
+ struct stat _stat;
+ fstat(fileno(my_file_in),&_stat);
+ file = _stat.st_size;
+ text = numblocks*blocksize;
+}
+
+int ppm_expander::home()
+{
+ fseek(my_file_in,0, SEEK_SET);
+ unsigned char header[STAT_MAGIC_SIZE];
+ size_t len=fread(header,1,STAT_MAGIC_SIZE,my_file_in);
+ if (strncmp((char*)header,stat_magic,STAT_MAGIC_SIZE)!=0) {
+ return 1;
+ }
+ if (len!=(STAT_MAGIC_SIZE)) {
+ return 1;
+ }
+ if (fread(&maxnode,sizeof(maxnode),1,my_file_in) != 1) return 1;
+ if (fread(&blocksize,sizeof(blocksize),1,my_file_in) != 1) return 1;
+ if (fread(&numblocks,sizeof(numblocks),1,my_file_in) != 1) return 1;
+ //fprintf(stderr,"<%u,%u,%u>\n",maxnode,blocksize,numblocks);
+ int err = locate(0,0);
+ outbytes = 0;
+ return err;
+}
+
+void ppm_expander::locate(unsigned int n) {
+ locate(n/blocksize, n%blocksize);
+ outbytes = n;
+}
+
+int ppm_expander::locate(unsigned short block, unsigned int n)
+{
+ if (needppmend)
+ {
+ ppm.PPM_End();
+ needppmend = false;
+ }
+ size_t fpos;
+ fseek(my_file_in,STAT_MAGIC_SIZE+sizeof(maxnode)+sizeof(blocksize)+sizeof(numblocks)+block*sizeof(fpos),SEEK_SET);
+ if (fread(&fpos,sizeof(fpos),1,my_file_in) != 1) return 1;
+ fseek(my_file_in,fpos,SEEK_SET);
+
+ ppm.arith.Arith_DecodeInit(my_read_buf,buf_in,bufsize);
+ int err=ppm.PPM_Init(maxnode);
+ needppmend = true;
+ curblock = block;
+ for (int i = 0; i < n; i++) getch();
+}
+
+int ppm_expander::getch() {
+ if (curblock >= numblocks) return EOF;
+ int c=ppm.PPM_Decode();
+ if (c == SYM_EOF)
+ {
+ if (++curblock >= numblocks) return EOF;
+ locate(curblock,0);
+ c = ppm.PPM_Decode();
+ }
+ outbytes++;
+ return (c==SYM_EOF) ? EOF : c;
+}
diff --git a/noncore/apps/opie-reader/ppm_expander.h b/noncore/apps/opie-reader/ppm_expander.h
new file mode 100644
index 0000000..ce95db7
--- a/dev/null
+++ b/noncore/apps/opie-reader/ppm_expander.h
@@ -0,0 +1,46 @@
+#ifndef __ppm_expander_h
+#define __ppm_expander_h
+
+#include "CExpander.h"
+#include <sys/stat.h>
+
+
+#include "utypes.h"
+#include "ppm.h"
+#include "arith.h"
+
+
+#define SYM_EOF 256
+
+class ppm_expander : public CExpander {
+ UCHAR *buf_in,*buf_out;
+ unsigned int bufsize;
+ unsigned int outbytes;
+ unsigned long blocksize;
+ unsigned short numblocks;
+ unsigned short curblock;
+ unsigned short maxnode;
+ bool needppmend;
+ int home();
+ FILE* my_file_in;
+ PPM_ReadBuf* my_read_buf;
+ ppm_worker ppm;
+ public:
+ ppm_expander() : needppmend(false), my_file_in(NULL), my_read_buf(NULL)
+ {
+ bufsize = 1024;
+ buf_in = new UCHAR[bufsize];
+ buf_out = new UCHAR[bufsize];
+ outbytes = 0;
+ }
+ virtual int openfile(const char* infile);
+ virtual int getch();
+ int locate(unsigned short block, unsigned int n);
+ virtual ~ppm_expander();
+ virtual unsigned int locate() { return outbytes; }
+ virtual void locate(unsigned int n);
+ virtual bool hasrandomaccess() { return (numblocks > 1); }
+ virtual void sizes(unsigned long& file, unsigned long& text);
+};
+
+#endif
diff --git a/noncore/apps/opie-reader/update.sh b/noncore/apps/opie-reader/update.sh
new file mode 100755
index 0000000..05dc175
--- a/dev/null
+++ b/noncore/apps/opie-reader/update.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+cp /home/tim/uqtreader/uqtreader.desktop /opt/Qtopia/apps/Applications/
+cp /home/tim/bin/uqtreader /opt/Qtopia/bin/
+cp /home/tim/uqtreader/uqtreader.png /opt/Qtopia/pics/
+cp /home/tim/qtreader/panel-arrow-down.png /opt/Qtopia/pics/
+cp /home/tim/uqtreader/uqtreader.desktop /opt/Qtopia/sharp/apps/Applications/
+cp /home/tim/bin/uqtreader /opt/Qtopia/sharp/bin/
+cp /home/tim/uqtreader/uqtreader.png /opt/Qtopia/sharp/pics/
+cp /home/tim/qtreader/panel-arrow-down.png /opt/Qtopia/sharp/pics/
+#source /home/tim/bin/setz.sh
+#mkipks qpe-qtreader.control
diff --git a/noncore/apps/opie-reader/ustring.h b/noncore/apps/opie-reader/ustring.h
new file mode 100644
index 0000000..a4dc048
--- a/dev/null
+++ b/noncore/apps/opie-reader/ustring.h
@@ -0,0 +1,71 @@
+#include <qstring.h>
+
+#ifdef _UNICODE
+inline size_t ustrlen(const tchar* _p)
+{
+ if (_p == NULL) return 0;
+ const tchar *p = _p;
+ while (*p != 0)
+ {
+ p++;
+/*
+ if (p - _p == 20)
+ {
+ printf("ustrlen::String too long:");
+ for (int i = 0; i < 20; i++) printf("%c",_p[i]);
+ printf("\n");
+ }
+*/
+ }
+ return p - _p;
+}
+
+inline int ustrcmp(const tchar* _p1, const tchar* _p2)
+{
+ if (_p1 == 0) return 1;
+ if (_p2 == 0) return -1;
+ const tchar* p1 = _p1, *p2 = _p2;
+ while (*p1 != 0)
+ {
+/*
+ if (p1 - _p1 == 20)
+ {
+ printf("ustrcmp::String too long:");
+ for (int i = 0; i < 20; i++) printf("%c",_p1[i]);
+ printf("\n");
+ }
+*/
+ if (*p1 < *p2) return -1;
+ if (*p1 > *p2) return 1;
+ if (*p2 == 0) return 1;
+ p1++, p2++;
+ }
+ if (*p2 != 0) return -1;
+ return 0;
+}
+
+inline QString toQString(tchar *_p)
+{
+ if (_p == NULL) return 0;
+ int i = 0;
+ tchar *p = _p;
+ QString ret;
+ while (*p != 0) ret[i++] = *(p++);
+ return ret;
+}
+
+inline QString toQString(tchar *_p, unsigned int len)
+{
+ if (_p == NULL) return 0;
+ unsigned int i = 0;
+ tchar *p = _p;
+ QString ret;
+ while (*p != 0 && i < len) ret[i++] = *(p++);
+ return ret;
+}
+#else
+
+inline size_t ustrlen(const tchar* _p) { return strlen(_p); }
+inline int ustrcmp(const tchar* _p1, const tchar* _p2) { return strcmp(_p1, _p2); }
+
+#endif
diff --git a/noncore/apps/opie-reader/utypes.h b/noncore/apps/opie-reader/utypes.h
new file mode 100644
index 0000000..b7c59f3
--- a/dev/null
+++ b/noncore/apps/opie-reader/utypes.h
@@ -0,0 +1,14 @@
+/*
+ * Quelques types utiles
+ */
+
+#ifndef UTYPES_H
+
+#define UTYPES_H
+
+typedef unsigned char UCHAR;
+typedef unsigned short USHORT;
+typedef unsigned int UINT;
+
+#endif
+
diff --git a/noncore/apps/opie-reader/version.h b/noncore/apps/opie-reader/version.h
new file mode 100644
index 0000000..bd32e4d
--- a/dev/null
+++ b/noncore/apps/opie-reader/version.h
@@ -0,0 +1,3 @@
+#define MAJOR "0"
+#define MINOR "3r"
+#define RELEASE_TYPE "beta(U)"
diff --git a/noncore/apps/opie-reader/ztxt.cpp b/noncore/apps/opie-reader/ztxt.cpp
new file mode 100644
index 0000000..c30e4fd
--- a/dev/null
+++ b/noncore/apps/opie-reader/ztxt.cpp
@@ -0,0 +1,159 @@
+#include <stdio.h>
+#include <string.h>
+#include "ztxt.h"
+
+ztxt::ztxt() : bInit(false), expandedtextbuffer(NULL), compressedtextbuffer(NULL) { /*printf("constructing:%x\n",fin);*/ }
+
+
+int ztxt::openfile(const char *src)
+{
+ if (!Cpdb::openfile(src))
+ {
+ return -1;
+ }
+
+//printf("Okay %u\n", 4);
+
+ if (head.type != ZTXT_ID) return -1;
+
+ gotorecordnumber(0);
+ fread(&hdr0, 1, sizeof(hdr0), fin);
+//printf("Okay %u\n", 5);
+ buffersize = ntohl(hdr0.size);
+ compressedtextbuffer = new UInt8[buffersize];
+ expandedtextbuffer = new UInt8[buffersize];
+//printf("Okay %u\n", 6);
+
+ home();
+//printf("Okay %u\n", 7);
+
+// printf("Returning 0\n");
+
+ return 0;
+}
+
+int ztxt::getch()
+{
+ if (bufferpos >= buffercontent)
+ {
+ size_t reclen = recordlength(++bufferrec);
+ if (reclen == 0) return -1;
+ gotorecordnumber(bufferrec);
+ fread(compressedtextbuffer, reclen, sizeof(char), fin);
+
+ zstream.next_in = compressedtextbuffer;
+ zstream.next_out = expandedtextbuffer;
+ zstream.avail_out = buffersize;
+ zstream.avail_in = reclen;
+
+ int ret = inflate(&zstream, Z_SYNC_FLUSH);
+ buffercontent = buffersize - zstream.avail_out;
+ bufferpos = 0;
+
+ }
+ currentpos++;
+ return expandedtextbuffer[bufferpos++];
+}
+
+unsigned int ztxt::locate()
+{
+ return currentpos;
+}
+
+void ztxt::locate(unsigned int n)
+{
+
+ if (hasrandomaccess())
+ {
+ bufferrec = n / ntohs(hdr0.recordSize) + 1;
+ if (bufferrec == 1)
+ {
+ inflateEnd(&zstream);
+ }
+ size_t reclen = recordlength(bufferrec);
+ if (reclen == 0) return;
+ gotorecordnumber(bufferrec);
+ fread(compressedtextbuffer, reclen, sizeof(char), fin);
+
+ zstream.next_in = compressedtextbuffer;
+ zstream.next_out = expandedtextbuffer;
+ zstream.avail_out = buffersize;
+ zstream.avail_in = reclen;
+
+ if (bufferrec == 1)
+ {
+ zstream.zalloc = Z_NULL;
+ zstream.zfree = Z_NULL;
+ zstream.opaque = Z_NULL;
+
+ inflateInit(&zstream);
+ }
+
+
+ int ret = inflate(&zstream, Z_SYNC_FLUSH);
+ buffercontent = buffersize - zstream.avail_out;
+ bufferpos = 0;
+ currentpos = n - n % ntohs(hdr0.recordSize);
+ while (currentpos < n) getch();
+ }
+ else
+ {
+ home();
+ while (currentpos < n && getch() != EOF);
+ }
+}
+
+void ztxt::home()
+{
+ if (bInit)
+ {
+ inflateEnd(&zstream);
+ }
+ bInit = true;
+ size_t reclen = recordlength(1);
+ gotorecordnumber(1);
+ fread(compressedtextbuffer, reclen, sizeof(char), fin);
+
+ zstream.next_in = compressedtextbuffer;
+ zstream.next_out = expandedtextbuffer;
+ zstream.avail_out = buffersize;
+ zstream.avail_in = reclen;
+
+ zstream.zalloc = Z_NULL;
+ zstream.zfree = Z_NULL;
+ zstream.opaque = Z_NULL;
+
+// printf("Initialising\n");
+
+ inflateInit(&zstream);
+
+ int ret = inflate(&zstream, Z_SYNC_FLUSH);
+// printf("Inflate : %d\n", ret);
+ bufferpos = 0;
+ bufferrec = 1;
+ currentpos = 0;
+ buffercontent = buffersize - zstream.avail_out;
+// printf("buffercontent:%u\n", buffercontent);
+}
+
+CList<Bkmk>* ztxt::getbkmklist()
+{
+ UInt16 recno = ntohs(hdr0.bookmarkRecord);
+
+// printf("Bookmarks - record %d contains %d\n", recno, ntohs(hdr0.numBookmarks));
+
+ if (recno == 0) return NULL;
+
+ CList<Bkmk>* t = new CList<Bkmk>;
+ size_t cur = ftell(fin);
+ gotorecordnumber(recno);
+ for (int i = 0; i < ntohs(hdr0.numBookmarks); i++)
+ {
+ zTXTbkmk bkmk;
+ if (fread(&bkmk, sizeof(bkmk), 1, fin) != 1) break;
+// printf("Bookmark number:%d:%.20s\n", i, bkmk.title);
+ t->push_back(Bkmk(bkmk.title, ntohl(bkmk.offset)));
+ }
+ fseek(fin, cur, SEEK_SET);
+ return t;
+}
diff --git a/noncore/apps/opie-reader/ztxt.h b/noncore/apps/opie-reader/ztxt.h
new file mode 100644
index 0000000..b8ad29c
--- a/dev/null
+++ b/noncore/apps/opie-reader/ztxt.h
@@ -0,0 +1,102 @@
+#ifndef __ztxt_h
+#define __ztxt_h
+
+#include "CExpander.h"
+#include <zlib.h>
+#include "pdb.h"
+/*
+ * Stuff common to both Weasel Reader and makeztxt
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _WEASEL_COMMON_H_
+#define _WEASEL_COMMON_H_ 1
+
+
+/* Padding is no good */
+#if defined(__GNUC__) && defined(__UNIX__)
+# pragma pack(2)
+#endif
+
+/* The default creator is Weasel Reader 'GPlm' */
+#define GPLM_CREATOR_ID "GPlm"
+/* Databases of type 'zTXT' */
+#define ZTXT_TYPE_ID "zTXT"
+/* Size of one database record */
+#define RECORD_SIZE 8192
+/* Allow largest WBIT size for data. Lower with command line options
+ in makeztxt */
+#define MAXWBITS 15
+/* Max length for a bookmark/annotation title */
+#define MAX_BMRK_LENGTH 20
+
+
+/*****************************************************
+ * This is the zTXT document header (record #0) *
+ * ----zTXT version 1.42---- *
+ *****************************************************/
+typedef struct zTXT_record0Type {
+ UInt16 version; /* zTXT format version */
+ UInt16 numRecords; /* Number of data (TEXT) records */
+ UInt32 size; /* Size in bytes of uncomp. data */
+ UInt16 recordSize; /* Size of a single data record */
+ UInt16 numBookmarks; /* Number of bookmarks in DB */
+ UInt16 bookmarkRecord; /* Record containing bookmarks */
+ UInt16 numAnnotations; /* Number of annotation records */
+ UInt16 annotationRecord; /* Record # of annotation index */
+ UInt8 randomAccess; /* 1 if compressed w/Z_FULL_FLUSH */
+ UInt8 padding[0x20 - 19]; /* Pad to a size of 0x20 bytes */
+} zTXT_record0;
+
+struct zTXTbkmk
+{
+ UInt32 offset;
+ tchar title[MAX_BMRK_LENGTH];
+};
+
+#endif
+
+
+const UInt32 ZTXT_ID = 0x5458547a;
+
+class ztxt : public CExpander, Cpdb
+{
+ bool bInit;
+ UInt32 buffersize;
+ UInt32 buffercontent;
+ UInt8* expandedtextbuffer;
+ UInt8* compressedtextbuffer;
+ z_stream zstream;
+ size_t bufferpos;
+ UInt16 bufferrec;
+ zTXT_record0 hdr0;
+ size_t currentpos;
+ void home();
+ public:
+ virtual void sizes(unsigned long& _file, unsigned long& _text)
+ {
+ _file = file_length;
+ _text = ntohl(hdr0.size);
+ }
+ virtual bool hasrandomaccess() { return (hdr0.randomAccess != 0); }
+ virtual ~ztxt()
+ {
+ if (expandedtextbuffer != NULL) delete [] expandedtextbuffer;
+ if (compressedtextbuffer != NULL) delete [] compressedtextbuffer;
+ if (bInit)
+ {
+ inflateEnd(&zstream);
+ }
+ }
+ ztxt();
+ virtual int openfile(const char *src);
+ virtual int getch();
+ virtual unsigned int locate();
+ virtual void locate(unsigned int n);
+ virtual CList<Bkmk>* getbkmklist();
+};
+
+#endif
+