From 59222a752fa4c8a1e8c2a00ee2f9e22855f12bb2 Mon Sep 17 00:00:00 2001 From: llornkcor Date: Mon, 01 Jul 2002 23:24:08 +0000 Subject: initial --- (limited to 'noncore/apps/opie-reader') 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 +#include +#include "Aportis.h" + +Aportis::Aportis() { /*printf("constructing:%x\n",fin);*/ } + +CList* Aportis::getbkmklist() +{ + if (bCompressed != 4) return NULL; + CList* t = new CList; + 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<= 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* 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 +#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 +#include + +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* 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 +#include +#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 +#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& bl) + { + if (f != NULL) + { + for (CList::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* readall() + { + CList* bl = NULL; + if (f != NULL) + { + bl = new CList; + 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* 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 +#include +#include +#include //for sprintf +#include +#include +#include +#include +#include + +#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 +#include +#include + +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::Iterator it; + +// QValueList 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 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 +#include +#include +#include "CBuffer.h" +#include "my_list.h" +#include "BuffDoc.h" +#include + +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* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //getenv +#include +#include +#include +#include + +#include "cbkmkselector.h" +#include "infowin.h" + +//#include + +#include +#include + +#include "QTReaderApp.h" +#include "fileBrowser.h" + + +unsigned long QTReaderApp::m_uid = 0; + +void QTReaderApp::setScrollState(bool _b) { m_scrollButton->setOn(_b); } + +#include +#include +#include + +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; +#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; + 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::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; + 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; +#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 +#include "QTReader.h" +#include +#include +#include +#include +#include +#include +#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* 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* 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 + +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 CQueue : public CList +{ + 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 +#include +#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 +#include +#include + +#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 + +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 +#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 +#include +#include +#include + +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 + +#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 +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include + +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 +#include +#include +#include + +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 +//#include +#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 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 +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 +#include + +/* 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 +#include +#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 (hhdr.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;ihdr.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 (phdr.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;ihdr.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;ihdr.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=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_maxhdr.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=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;ihdr.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 +//#include +#include +#include +#include + +/*************************************************************************** + * 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 + + +#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 + +#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 +#include +#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* ztxt::getbkmklist() +{ + UInt16 recno = ntohs(hdr0.bookmarkRecord); + +// printf("Bookmarks - record %d contains %d\n", recno, ntohs(hdr0.numBookmarks)); + + if (recno == 0) return NULL; + + CList* t = new CList; + 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 +#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* getbkmklist(); +}; + +#endif + -- cgit v0.9.0.2