summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-reader/BuffDoc.cpp
Side-by-side diff
Diffstat (limited to 'noncore/apps/opie-reader/BuffDoc.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/apps/opie-reader/BuffDoc.cpp428
1 files changed, 363 insertions, 65 deletions
diff --git a/noncore/apps/opie-reader/BuffDoc.cpp b/noncore/apps/opie-reader/BuffDoc.cpp
index 68391b8..22934f9 100644
--- a/noncore/apps/opie-reader/BuffDoc.cpp
+++ b/noncore/apps/opie-reader/BuffDoc.cpp
@@ -1,26 +1,43 @@
+#include "static.h"
+#include "names.h"
#define NEWLINEBREAK
+#define INCREMENTALWIDTH
+#include "useqpe.h"
+#include "usenef.h"
#include "BuffDoc.h"
-//#include <FL/fl_draw.h>
+#include "config.h"
+#include "CDrawBuffer.h"
+#include "ZText.h"
+#include "ebookcodec.h"
+
+#ifdef __STATIC
+#include "Aportis.h"
+#include "CHM.h"
+#include "ppm_expander.h"
+#include "ztxt.h"
#include "plucker.h"
#ifdef USENEF
#include "nef.h"
#include "arrierego.h"
#endif
+#include "iSilo.h"
+#endif
+
-linkType BuffDoc::hyperlink(unsigned int n, QString& wrd)
+linkType BuffDoc::hyperlink(unsigned int n, unsigned int noff, QString& wrd, QString& nm)
{
linkType bRet = eNone;
if (exp != NULL)
{
- bRet = exp->hyperlink(n, wrd);
- if (bRet == eLink)
+ bRet = filt->hyperlink(n, noff, wrd, nm);
+ if ((bRet & eLink) != 0)
{
lastword.empty();
lastsizes[0] = laststartline = n;
#ifdef NEWLINEBREAK
- lastispara = true;
+ lastispara = false;
#else
lastispara = false;
#endif
@@ -32,25 +49,107 @@ linkType BuffDoc::hyperlink(unsigned int n, QString& wrd)
void BuffDoc::locate(unsigned int n)
{
- // //odebug << "BuffDoc:locating:" << n << "" << oendl;
+ // //qDebug("BuffDoc:locating:%u",n);
lastword.empty();
lastsizes[0] = laststartline = n;
#ifdef NEWLINEBREAK
- lastispara = true;
+ lastispara = false;
#else
lastispara = false;
#endif
// tchar linebuf[1024];
- if (exp != NULL) exp->locate(n);
- // //odebug << "BuffDoc:Located" << oendl;
+ if (exp != NULL) filt->locate(n);
+ // //qDebug("BuffDoc:Located");
+}
+
+static bool isletter(unsigned short c)
+{
+ if ('a' <= c && c <= 'z') return true;
+ if ('A' <= c && c <= 'Z') return true;
+ // Cyrillic letters
+ if (0x400 <= c && c <= 0x52F) return true;
+ return false;
+}
+
+static bool isvowel(unsigned short c) // Only want lower case vowels
+{
+ switch (c)
+ {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u':
+ // Cyrillic vowels
+ case 0x430:
+ case 0x435:
+ case 0x438:
+ case 0x43E:
+ case 0x443:
+ case 0x44B:
+ case 0x44D:
+ case 0x44E:
+ case 0x44F:
+ case 0x451:
+
+ case 0x450:
+ case 0x454:
+ case 0x456:
+ case 0x457:
+ case 0x45D:
+
+ case 0x463:
+
+ case 0x4AF:
+ case 0x4B1:
+ case 0x4D1:
+ case 0x4D3:
+
+ case 0x4D5:
+ case 0x4D7:
+ case 0x4E3:
+ case 0x4E5:
+ case 0x4E7:
+ case 0x4E9:
+ case 0x4EB:
+ case 0x4ED:
+ case 0x4EF:
+ case 0x4F1:
+ case 0x4F3:
+ case 0x4F9:
+ return true;
+ default:
+ return ((0xe0 <= c) && (c <= 0xfc) && (c != 0xf1) && (c != 0xf7) && (c != 0xe7));
+ }
+}
+
+inline bool isconsonant(unsigned short c)
+{
+ switch( c )
+ {
+ // Some cyrillic letters are neither vowels, nor consonants, or otherwise
+ // the letters no word can start from.
+ case 0x439:
+ case 0x44A:
+ case 0x44C:
+
+ case 0x45E:
+
+ return false;
+
+ default:
+ return (isletter(c) && !isvowel(c));
+ }
+ return (isletter(c) && !isvowel(c));
}
#ifdef NEWLINEBREAK
-bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
+bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned short _lborder, unsigned short _rborder, bool hyphenate, int availht)
{
bool moreleft = true;
bool margindone = false;
- int w = wth-2*_border;
+ int isCentred = -1;
+ int w = wth-(_lborder+_rborder);
tchar ch = 32;
CStyle cs;
buff->empty();
@@ -63,6 +162,10 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
int len = 0;
if (lastword.length() > 0)
{
+ if (isCentred < 0)
+ {
+ isCentred = (lastword.firststyle().getJustify() == m_AlignCentre) ? 1 : 0;
+ }
*buff = lastword;
cs = lastword.laststyle();
w -= buff->leftMargin() + buff->rightMargin();
@@ -71,19 +174,24 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
}
else buff->empty();
lastword.empty();
- unsigned int slen = buff->width(len);
+ unsigned int slen = buff->width(availht, len);
if (lastispara) buff->setstartpara();
+ int nospaces = 0;
while (1)
{
- lastsizes[len] = exp->locate();
- getch(ch, cs);
+ getch(ch, cs, lastsizes[len]);
+ if (isCentred < 0)
+ {
+ isCentred = (cs.getJustify() == m_AlignCentre) ? 1 : 0;
+ }
if (ch == 10 && len == 0 && !lastispara)
{
- lastsizes[len] = exp->locate();
- getch(ch, cs);
+ getch(ch, cs, lastsizes[len]);
+ buff->setstartpara();
}
if (ch == UEOF)
{
+ buff->setendpara(cs);
if (len == 0)
{
buff->setEof();
@@ -94,20 +202,36 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
}
if (ch == 10)
{
- buff->setendpara();
+ buff->setendpara(cs);
+ lastispara = true;
+ laststartline = exp->locate();
+ break;
+ }
+ if (ch == 6)
+ {
+ buff->setendpara(cs);
+ buff->setBop();
lastispara = true;
laststartline = exp->locate();
break;
}
lastispara = false;
buff->addch(ch, cs);
+ if (ch == ' ')
+ {
+ nospaces++;
+ }
len++;
if (!margindone)
{
w -= buff->leftMargin() + buff->rightMargin();
margindone = true;
}
- if ((slen = buff->width(len)) > w)
+#ifdef INCREMENTALWIDTH
+ if ((slen += buff->charwidth(len-1, cs)) > w)
+#else
+ if ((slen = buff->width(availht, len)) > w)
+#endif
{
if (ch == ' ' || len == 1)
{
@@ -117,30 +241,149 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
}
else // should do a backward search for spaces, first.
{
+ int lastk = len-4;
for (int i = len-2; i > 0; i--)
{
- if ((*buff)[i] == ' ')
+ if (
+ (((*buff)[i] == 0x2014) && isletter((*buff)[i+1]))
+ ||
+ ((*buff)[i] == '-')
+ // ((*buff)[i] == '-' && !(((*buff)[i-1] == '-') || ((*buff)[i+1] == '-')))
+)
{
(*buff)[len] = 0;
lastword.setright(*buff, i+1);
- buff->truncate(i);
- (*buff)[i] = '\0';
+ buff->truncate(i+1);
+ (*buff)[i+1] = '\0';
laststartline = lastsizes[i+1];
- buff->resize();
+ // buff->resize();
for (int j = 0; j < lastword.length(); j++)
{
lastsizes[j] = lastsizes[j+i+1];
}
return true;
}
- if ((*buff)[i] == '-' && !(((*buff)[i-1] == '-') || ((*buff)[i+1] == '-')))
+
+ //if (hyphenate && (m_hyphenthreshold+1)*i < m_hyphenthreshold*len)
+ // We end up with i+1 characters instead of len-1
+ // Thus we are removing len - 1 - (i + 1) = len-i-2
+ // The space characters will be stretched to cover
+ // nospaces to nospaces + len - i - 2
+ // The stretch factor is hence
+ // (nospaces+len-i-2)/nospaces
+ if (hyphenate && !isCentred && ( 100*(nospaces+len-i-2) > (100+m_hyphenthreshold)*nospaces ))
+ {
+ /*
+ if (m_customhyphen)
+ {
+ for (int k = lastk; k >= i && k >= 2; k--)
+ {
+ if (
+ isletter((*buff)[k+3])
+ &&
+ isletter((*buff)[k+2])
+ &&
+ isvowel((*buff)[k+1])
+ &&
+ isconsonant((*buff)[k])
+ &&
+ isletter((*buff)[k-1])
+ &&
+ isletter((*buff)[k-2])
+ )
+ {
+ (*buff)[len] = 0;
+ lastword.setright(*buff, k+1);
+ buff->truncate(k+2);
+ (*buff)[k+1] = '-';
+ (*buff)[k+2] = '\0';
+ laststartline = lastsizes[k+1];
+ buff->resize();
+ for (int j = 0; j < lastword.length(); j++)
+ {
+ lastsizes[j] = lastsizes[j+k+1];
+ }
+ return true;
+ }
+ }
+ }
+ else
+ */
+ {
+ for (int k = lastk; k >= i && k >= 1; k--)
+ {
+ if (
+ /*
+ (
+ k < len-3
+ &&
+ k >= 1
+ &&
+ isletter((*buff)[k+3])
+ &&
+ isletter((*buff)[k+2])
+ &&
+ isconsonant((*buff)[k+1])
+ &&
+ ((*buff)[k+1] != 'y')
+ &&
+ ((*buff)[k+1] != 'h')
+ &&
+ isconsonant((*buff)[k])
+ &&
+ ((*buff)[k] != 'h')
+ &&
+ isletter((*buff)[k-1])
+ )
+ ||
+ */
+ (
+ isletter((*buff)[k+3])
+ &&
+ isletter((*buff)[k+2])
+ &&
+ isconsonant((*buff)[k+1])
+ &&
+ ((*buff)[k+1] != 'y')
+ &&
+ isletter((*buff)[k])
+ &&
+ ((*buff)[k] != 'h')
+ &&
+ isletter((*buff)[k-1])
+ && // Do not hyphenate when the first part ends with a vowel,
+ // and the second starts with the two consonants.
+ // Examples: "co-nsona-nts" -> "con-sonants",
+ // "hy-phenation" -> "hyp-henation" etc.
+ !( isvowel( (*buff)[k] ) && isconsonant( (*buff)[k+2] ) )
+ )
+ )
+ {
+ (*buff)[len] = 0;
+ lastword.setright(*buff, k+1);
+ buff->truncate(k+2);
+ (*buff)[k+1] = '-';
+ (*buff)[k+2] = '\0';
+ laststartline = lastsizes[k+1];
+ // buff->resize();
+ for (int j = 0; j < lastword.length(); j++)
+ {
+ lastsizes[j] = lastsizes[j+k+1];
+ }
+ return true;
+ }
+ }
+ }
+ lastk = i;
+ }
+ if ((*buff)[i] == ' ')
{
(*buff)[len] = 0;
lastword.setright(*buff, i+1);
- buff->truncate(i+1);
- (*buff)[i+1] = '\0';
+ buff->truncate(i);
+ (*buff)[i] = '\0';
laststartline = lastsizes[i+1];
- buff->resize();
+ // buff->resize();
for (int j = 0; j < lastword.length(); j++)
{
lastsizes[j] = lastsizes[j+i+1];
@@ -162,14 +405,14 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
}
}
(*buff)[len] = '\0';
- buff->resize();
+ // buff->resize();
return moreleft;
}
#else
-bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
+bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned short _lborder, unsigned short _rborder)
{
bool margindone = false;
- int w = wth-2*_border;
+ int w = wth-(_lborder+_rborder);
tchar ch = 32;
CStyle cs;
buff->empty();
@@ -188,14 +431,14 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
margindone = true;
}
else buff->empty();
-// //odebug << "Buff:" << toQString(buff->data()) << " Lastword:" << toQString(lastword.data()) << "" << oendl;
+// //qDebug("Buff:%s Lastword:%s", (const char*)toQString(buff->data()), (const char*)toQString(lastword.data()));
lastcheck = len = buff->length();
- unsigned int slen = buff->width(len);
+ unsigned int slen = buff->width(availht, len);
if (slen > w)
{
for ( ; len > 1; len--)
{
- if (buff->width(len) < w) break;
+ if (buff->width(availht, len) < w) break;
}
// lastword = buff->data() + len - 1;
laststartline = lastsizes[len-1];
@@ -214,7 +457,7 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
lastword.empty();
(*buff)[len] = '\0';
}
- buff->resize();
+ // buff->resize();
return true;
}
if (lastispara)
@@ -223,11 +466,11 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
// lastword[0] = '\0';
lastword.empty();
len = buff->length();
- while (buff->width(len) > w) len--;
+ while (buff->width(availht, len) > w) len--;
// (*buff)[len] = '\0';
buff->truncate(len);
laststartline = exp->locate();
- buff->resize();
+ // buff->resize();
return true;
}
lastispara = false;
@@ -235,17 +478,15 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
while (slen < w)
{
lastcheck = len;
- allsizes[len] = exp->locate();
- getch(ch, cs);
+ getch(ch, cs, allsizes[len]);
while (ch != ' ' && ch != '\012' && ch != UEOF && len < 128)
{
len++;
buff->addch(ch,cs);
- allsizes[len] = exp->locate();
- getch(ch, cs);
+ getch(ch, cs, allsizes[len]);
}
(*buff)[len] = 0;
- slen = buff->width(len);
+ slen = buff->width(availht, len);
len++;
buff->addch(' ', cs);
if (!margindone)
@@ -286,7 +527,7 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
buff->truncate(lastcheck);
}
// buff->frig();
- buff->resize();
+// buff->resize();
if (ch == UEOF && buff->length() == 0)
{
buff->setEof();
@@ -296,9 +537,9 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned char _border)
}
#endif
-bool BuffDoc::getline(CDrawBuffer* buff, int wth, int cw, unsigned char _border)
+bool BuffDoc::getline(CDrawBuffer* buff, int wth, int cw, unsigned short _lborder, unsigned short _rborder, int availht)
{
- int w = wth-2*_border;
+ int w = wth-(_lborder+_rborder);
buff->empty();
if (exp == NULL)
{
@@ -307,36 +548,27 @@ bool BuffDoc::getline(CDrawBuffer* buff, int wth, int cw, unsigned char _border)
tchar ch;
CStyle cs;
int i = 1;
- while (i*cw < w-buff->offset(w,0))
+ int offset = buff->offset(w,0,0,availht);
+ while (i*cw < w-offset)
{
- getch(ch, cs);
+ unsigned long dummy;
+ getch(ch, cs, dummy);
if (ch == '\12' || ch == UEOF) break;
buff->addch(ch,cs);
i++;
}
buff->truncate(i);
laststartline = exp->locate();
- buff->resize();
+ // buff->resize();
return (ch != UEOF);
}
int BuffDoc::openfile(QWidget* _parent, const char *src)
{
- // //odebug << "BuffDoc:Openfile:" << src << "" << oendl;
- // //odebug << "Trying aportis " << exp << "" << oendl;
if (exp != NULL) delete exp;
- lastword.empty();
- lastsizes[0] = laststartline = 0;
-#ifdef NEWLINEBREAK
- lastispara = true;
-#else
- lastispara = false;
-#endif
- /*
- exp = new Text;
- int ret = exp->openfile(src);
- */
+ exp = NULL;
+#ifdef __STATIC
exp = new Aportis;
int ret = exp->openfile(src);
if (ret == -1)
@@ -352,6 +584,16 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
exp = new ztxt;
ret = exp->openfile(src);
}
+ /*
+ }
+ if (ret != 0)
+ {
+ delete exp;
+ exp = new ebookcodec("Aportis");
+ ret = exp->openfile(src);
+ if (ret == 0) qDebug("Aportis format");
+ }
+ */
#ifdef USENEF
if (ret != 0)
{
@@ -359,6 +601,7 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
delete exp;
exp = new CArriere;
ret = exp->openfile(src);
+ if (ret == 0) qDebug("Arriere format");
}
if (ret != 0)
{
@@ -366,6 +609,7 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
delete exp;
exp = new CNEF;
ret = exp->openfile(src);
+ if (ret == 0) qDebug("NEF format");
}
#endif
if (ret != 0)
@@ -377,8 +621,22 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
}
if (ret != 0)
{
+
delete exp;
- //odebug << "Trying ppms" << oendl;
+ exp = new CHM;
+ ret = exp->openfile(src);
+ }
+ if (ret != 0)
+ {
+
+ delete exp;
+ exp = new iSilo;
+ ret = exp->openfile(src);
+ }
+ if (ret != 0)
+ {
+ delete exp;
+ //qDebug("Trying ppms");
exp = new ppm_expander;
ret = exp->openfile(src);
}
@@ -386,8 +644,9 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
{
delete exp;
exp = new Text;
-// //odebug << "Trying text" << oendl;
+// //qDebug("Trying text");
ret = exp->openfile(src);
+ if (ret == 0) qDebug("Text format");
}
if (ret != 0)
@@ -396,17 +655,56 @@ int BuffDoc::openfile(QWidget* _parent, const char *src)
QMessageBox::information(_parent, PROGNAME, "Unknown file compression type","Try another file");
return ret;
}
- // //odebug << "Doing final open:" << exp << ":" << filt << "" << oendl;
+ // //qDebug("Doing final open:%x:%x",exp,filt);
+#else
+ QString codecpath(QTReaderUtil::getPluginPath());
+ QDir d(codecpath, "*.so");
+
+ if (d.exists())
+ {
+ const QFileInfoList *list = d.entryInfoList();
+ QFileInfoListIterator it( *list ); // create list iterator
+ QFileInfo *fi; // pointer for traversing
+
+ int ret = -1;
+ while ( ret != 0 && (fi=it.current()) )
+ { // for each file...
+ if (exp != NULL) delete exp;
+ qDebug("Trying %s", (const char*)fi->fileName());
+ exp = new ebookcodec(fi->fileName());
+ ret = exp->openfile(src);
+ ++it;
+ }
+ qDebug("Buffdoc:Finished opening");
+ if (ret != 0)
+ {
+ if (exp != NULL) delete exp;
+ exp = new Text;
+ ret = exp->openfile(src);
+ }
+ }
+ else
+ {
+ if (exp != NULL) delete exp;
+ exp = new Text;
+ exp->openfile(src);
+ }
+#endif
lastword.empty();
lastsizes[0] = laststartline = 0;
#ifdef NEWLINEBREAK
- lastispara = true;
+ lastispara = false;
#else
lastispara = false;
#endif
- exp->locate(0);
+ exp->locate(exp->getHome());
filt->setsource(exp);
- // //odebug << "BuffDoc:file opened" << oendl;
+ qDebug("BuffDoc:file opened");
return 0;
}
+
+QString BuffDoc::about()
+{
+ return QString("Buffered Decompressor (c) Tim Wentford\nHyphenation algorithm (c) Tim Wentford\n (Cyrillic support by Konstantin Isakov\n")+filt->about();
+}