00001 #include "names.h"
00002
00003 #define NEWLINEBREAK
00004 #define INCREMENTALWIDTH
00005
00006 #include "BuffDoc.h"
00007 #include "config.h"
00008 #include "CDrawBuffer.h"
00009 #include "ZText.h"
00010 #include "ebookcodec.h"
00011
00012 #ifdef __STATIC
00013 #include "Aportis.h"
00014 #include "CHM.h"
00015 #include "ppm_expander.h"
00016 #include "ztxt.h"
00017 #include "plucker.h"
00018 #ifdef USENEF
00019 #include "nef.h"
00020 #include "arrierego.h"
00021 #endif
00022 #include "iSilo.h"
00023 #include "Reb.h"
00024 #endif
00025
00026
00027 linkType BuffDoc::hyperlink(unsigned int n, unsigned int noff, QString& wrd, QString& nm)
00028 {
00029 linkType bRet = eNone;
00030 if (exp != NULL)
00031 {
00032 bRet = filt->hyperlink(n, noff, wrd, nm);
00033 if ((bRet & eLink) != 0)
00034 {
00035 lastword.empty();
00036 lastsizes[0] = laststartline = n;
00037 #ifdef NEWLINEBREAK
00038 lastispara = false;
00039 #else
00040 lastispara = false;
00041 #endif
00042 lastsizes[0] = laststartline = exp->locate();
00043 }
00044 }
00045 return bRet;
00046 }
00047
00048 void BuffDoc::locate(unsigned int n)
00049 {
00050
00051 lastword.empty();
00052 lastsizes[0] = laststartline = n;
00053 #ifdef NEWLINEBREAK
00054 lastispara = false;
00055 #else
00056 lastispara = false;
00057 #endif
00058
00059 if (exp != NULL) filt->locate(n);
00060
00061 }
00062
00063 void BuffDoc::resetPos()
00064 {
00065
00066 lastword.empty();
00067 lastsizes[0] = laststartline = exp->locate();
00068 #ifdef NEWLINEBREAK
00069 lastispara = false;
00070 #else
00071 lastispara = false;
00072 #endif
00073 }
00074
00075 static bool isletter(unsigned short c)
00076 {
00077 if ('a' <= c && c <= 'z') return true;
00078 if ('A' <= c && c <= 'Z') return true;
00079
00080 if (0x400 <= c && c <= 0x52F) return true;
00081 return false;
00082 }
00083
00084 static bool isvowel(unsigned short c)
00085 {
00086 switch (c)
00087 {
00088 case 'a':
00089 case 'e':
00090 case 'i':
00091 case 'o':
00092 case 'u':
00093
00094 case 0x430:
00095 case 0x435:
00096 case 0x438:
00097 case 0x43E:
00098 case 0x443:
00099 case 0x44B:
00100 case 0x44D:
00101 case 0x44E:
00102 case 0x44F:
00103 case 0x451:
00104
00105 case 0x450:
00106 case 0x454:
00107 case 0x456:
00108 case 0x457:
00109 case 0x45D:
00110
00111 case 0x463:
00112
00113 case 0x4AF:
00114 case 0x4B1:
00115 case 0x4D1:
00116 case 0x4D3:
00117
00118 case 0x4D5:
00119 case 0x4D7:
00120 case 0x4E3:
00121 case 0x4E5:
00122 case 0x4E7:
00123 case 0x4E9:
00124 case 0x4EB:
00125 case 0x4ED:
00126 case 0x4EF:
00127 case 0x4F1:
00128 case 0x4F3:
00129 case 0x4F9:
00130 return true;
00131 default:
00132 return ((0xe0 <= c) && (c <= 0xfc) && (c != 0xf1) && (c != 0xf7) && (c != 0xe7));
00133 }
00134 }
00135
00136 inline bool isconsonant(unsigned short c)
00137 {
00138 switch( c )
00139 {
00140
00141
00142 case 0x439:
00143 case 0x44A:
00144 case 0x44C:
00145
00146 case 0x45E:
00147
00148 return false;
00149
00150 default:
00151 return (isletter(c) && !isvowel(c));
00152 }
00153 return (isletter(c) && !isvowel(c));
00154 }
00155
00156 #ifdef NEWLINEBREAK
00157 bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned short _lborder, unsigned short _rborder, bool hyphenate, int availht)
00158 {
00159 bool moreleft = true;
00160 bool margindone = false;
00161 int isCentred = -1;
00162 int w = wth-(_lborder+_rborder);
00163 tchar ch = 32;
00164 CStyle cs;
00165 buff->empty();
00166 if (exp == NULL)
00167 {
00168 buff->empty();
00169 buff->setEof();
00170 return false;
00171 }
00172 int len = 0;
00173 if (lastword.length() > 0)
00174 {
00175 if (isCentred < 0)
00176 {
00177 isCentred = (lastword.firststyle().getJustify() == m_AlignCentre) ? 1 : 0;
00178 }
00179 *buff = lastword;
00180 cs = lastword.laststyle();
00181 w -= buff->leftMargin() + buff->rightMargin();
00182 margindone = true;
00183 len = lastword.length();
00184 }
00185 else buff->empty();
00186 lastword.empty();
00187 unsigned int slen = buff->width(availht, len);
00188 if (lastispara) buff->setstartpara();
00189 int nospaces = 0;
00190 while (1)
00191 {
00192 getch(ch, cs, lastsizes[len]);
00193 if (isCentred < 0)
00194 {
00195 isCentred = (cs.getJustify() == m_AlignCentre) ? 1 : 0;
00196 }
00197 if (ch == 10 && len == 0 && !lastispara)
00198 {
00199 getch(ch, cs, lastsizes[len]);
00200 buff->setstartpara();
00201 }
00202 if (ch == UEOF)
00203 {
00204 buff->setendpara(cs);
00205 if (len == 0)
00206 {
00207 buff->setEof();
00208 moreleft = false;
00209 }
00210 laststartline = exp->locate();
00211 break;
00212 }
00213 if (ch == 10)
00214 {
00215 buff->setendpara(cs);
00216 lastispara = true;
00217 laststartline = exp->locate();
00218 break;
00219 }
00220 if (ch == 6)
00221 {
00222 buff->setendpara(cs);
00223 buff->setBop();
00224 lastispara = true;
00225 laststartline = exp->locate();
00226 break;
00227 }
00228 lastispara = false;
00229 buff->addch(ch, cs);
00230 if (ch == ' ')
00231 {
00232 nospaces++;
00233 }
00234 len++;
00235 if (!margindone)
00236 {
00237 w -= buff->leftMargin() + buff->rightMargin();
00238 margindone = true;
00239 }
00240 #ifdef INCREMENTALWIDTH
00241 if ((slen += buff->charwidth(len-1, cs)) > w)
00242 #else
00243 if ((slen = buff->width(availht, len)) > w)
00244 #endif
00245 {
00246 if (ch == ' ' || len == 1)
00247 {
00248 if (ch == ' ') buff->truncate(len-1);
00249 laststartline = exp->locate();
00250 break;
00251 }
00252 else
00253 {
00254 int lastk = len-4;
00255 for (int i = len-2; i > 0; i--)
00256 {
00257 if (
00258 (((*buff)[i] == 0x2014) && isletter((*buff)[i+1]))
00259 ||
00260 ((*buff)[i] == '-')
00261
00262 )
00263 {
00264 (*buff)[len] = 0;
00265 lastword.setright(*buff, i+1);
00266 buff->truncate(i+1);
00267 (*buff)[i+1] = '\0';
00268 laststartline = lastsizes[i+1];
00269
00270 for (int j = 0; j < lastword.length(); j++)
00271 {
00272 lastsizes[j] = lastsizes[j+i+1];
00273 }
00274 return true;
00275 }
00276
00277
00278
00279
00280
00281
00282
00283
00284 if (hyphenate && !isCentred && ( 100*(nospaces+len-i-2) > (100+m_hyphenthreshold)*nospaces ))
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 {
00323 for (int k = lastk; k >= i && k >= 1; k--)
00324 {
00325 if (
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 (
00351 isletter((*buff)[k+3])
00352 &&
00353 isletter((*buff)[k+2])
00354 &&
00355 isconsonant((*buff)[k+1])
00356 &&
00357 ((*buff)[k+1] != 'y')
00358 &&
00359 isletter((*buff)[k])
00360 &&
00361 ((*buff)[k] != 'h')
00362 &&
00363 isletter((*buff)[k-1])
00364 &&
00365
00366
00367
00368 !( isvowel( (*buff)[k] ) && isconsonant( (*buff)[k+2] ) )
00369 )
00370 )
00371 {
00372 (*buff)[len] = 0;
00373 lastword.setright(*buff, k+1);
00374 buff->truncate(k+2);
00375 (*buff)[k+1] = '-';
00376 (*buff)[k+2] = '\0';
00377 laststartline = lastsizes[k+1];
00378
00379 for (int j = 0; j < lastword.length(); j++)
00380 {
00381 lastsizes[j] = lastsizes[j+k+1];
00382 }
00383 return true;
00384 }
00385 }
00386 }
00387 lastk = i;
00388 }
00389 if ((*buff)[i] == ' ')
00390 {
00391 (*buff)[len] = 0;
00392 lastword.setright(*buff, i+1);
00393 buff->truncate(i);
00394 (*buff)[i] = '\0';
00395 laststartline = lastsizes[i+1];
00396
00397 for (int j = 0; j < lastword.length(); j++)
00398 {
00399 lastsizes[j] = lastsizes[j+i+1];
00400 }
00401 return true;
00402 }
00403 }
00404 laststartline = lastsizes[len-1];
00405 (*buff)[len] = 0;
00406 lastword.setright(*buff, len - 1);
00407 buff->truncate(len-1);
00408 buff->addch('-', cs);
00409 for (int j = 0; j < lastword.length(); j++)
00410 {
00411 lastsizes[j] = lastsizes[j+len];
00412 }
00413 break;
00414 }
00415 }
00416 }
00417 (*buff)[len] = '\0';
00418
00419 return moreleft;
00420 }
00421 #else
00422 bool BuffDoc::getline(CDrawBuffer* buff, int wth, unsigned short _lborder, unsigned short _rborder)
00423 {
00424 bool margindone = false;
00425 int w = wth-(_lborder+_rborder);
00426 tchar ch = 32;
00427 CStyle cs;
00428 buff->empty();
00429 if (exp == NULL)
00430 {
00431
00432 buff->empty();
00433 return false;
00434 }
00435 int len = 0, lastcheck = 0;
00436 if (lastword.length() > 0)
00437 {
00438 *buff = lastword;
00439 cs = lastword.laststyle();
00440 w -= buff->leftMargin() + buff->rightMargin();
00441 margindone = true;
00442 }
00443 else buff->empty();
00444
00445 lastcheck = len = buff->length();
00446 unsigned int slen = buff->width(availht, len);
00447 if (slen > w)
00448 {
00449 for ( ; len > 1; len--)
00450 {
00451 if (buff->width(availht, len) < w) break;
00452 }
00453
00454 laststartline = lastsizes[len-1];
00455 for (int i = 0; i < buff->length(); i++) lastsizes[i] = lastsizes[i+len-1];
00456
00457 if (len > 2)
00458 {
00459 lastword.setright(*buff, len - 1);
00460 buff->truncate(len-1);
00461 buff->addch('-', cs);
00462 (*buff)[len] = '\0';
00463 }
00464
00465 else
00466 {
00467 lastword.empty();
00468 (*buff)[len] = '\0';
00469 }
00470
00471 return true;
00472 }
00473 if (lastispara)
00474 {
00475 lastispara = false;
00476
00477 lastword.empty();
00478 len = buff->length();
00479 while (buff->width(availht, len) > w) len--;
00480
00481 buff->truncate(len);
00482 laststartline = exp->locate();
00483
00484 return true;
00485 }
00486 lastispara = false;
00487 for (int i = 0; i < len; i++) allsizes[i] = lastsizes[i];
00488 while (slen < w)
00489 {
00490 lastcheck = len;
00491 getch(ch, cs, allsizes[len]);
00492 while (ch != ' ' && ch != '\012' && ch != UEOF && len < 128)
00493 {
00494 len++;
00495 buff->addch(ch,cs);
00496 getch(ch, cs, allsizes[len]);
00497 }
00498 (*buff)[len] = 0;
00499 slen = buff->width(availht, len);
00500 len++;
00501 buff->addch(' ', cs);
00502 if (!margindone)
00503 {
00504 w -= buff->leftMargin() + buff->rightMargin();
00505 margindone = true;
00506 }
00507 allsizes[len] = exp->locate();
00508 if (slen < w && ch != ' ')
00509 {
00510 lastcheck = len;
00511 break;
00512 }
00513 lastispara = (ch == '\012');
00514 }
00515 (*buff)[len] = '\0';
00516
00517 #ifdef _WINDOWS
00518 lastword.setright(*buff, (lastcheck > 0) ? lastcheck : 1);
00519 {
00520 int i;
00521 for (i = 0; i < lastword.length(); i++) lastsizes[i] = allsizes[i+lastcheck];
00522 }
00523 #else
00524 lastword.setright(*buff, (lastcheck > 0) ? lastcheck : 1);
00525 for (int i = 0; i < lastword.length(); i++) lastsizes[i] = allsizes[i+lastcheck];
00526 #endif
00527 if (lastcheck > 0)
00528 {
00529 laststartline = allsizes[lastcheck];
00530
00531 buff->truncate(lastcheck-1);
00532 }
00533 else
00534 {
00535 laststartline = (lastcheck == len) ? exp->locate() : allsizes[lastcheck+1];
00536
00537 buff->truncate(lastcheck);
00538 }
00539
00540
00541 if (ch == UEOF && buff->length() == 0)
00542 {
00543 buff->setEof();
00544 return false;
00545 }
00546 return true;
00547 }
00548 #endif
00549
00550 bool BuffDoc::getline(CDrawBuffer* buff, int wth, int cw, unsigned short _lborder, unsigned short _rborder, int availht)
00551 {
00552 int w = wth-(_lborder+_rborder);
00553 buff->empty();
00554 if (exp == NULL)
00555 {
00556 return false;
00557 }
00558 tchar ch;
00559 CStyle cs;
00560 int i = 1;
00561 int offset = buff->offset(w,0,0,availht);
00562 while (i*cw < w-offset)
00563 {
00564 unsigned long dummy;
00565 getch(ch, cs, dummy);
00566 if (ch == '\12' || ch == UEOF) break;
00567 buff->addch(ch,cs);
00568 i++;
00569 }
00570 buff->truncate(i);
00571 laststartline = exp->locate();
00572
00573 return (ch != UEOF);
00574 }
00575
00576 int BuffDoc::openfile(QWidget* _parent, const char *src)
00577 {
00578 if (exp != NULL) delete exp;
00579 exp = NULL;
00580
00581 #ifdef __STATIC
00582 exp = new Aportis;
00583 int ret = exp->openfile(src);
00584 if (ret == -1)
00585 {
00586 delete exp;
00587 exp = NULL;
00588 return ret;
00589 }
00590 if (ret == -2)
00591 {
00592
00593 delete exp;
00594 exp = new ztxt;
00595 ret = exp->openfile(src);
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 #ifdef USENEF
00608 if (ret != 0)
00609 {
00610
00611 delete exp;
00612 exp = new CArriere;
00613 ret = exp->openfile(src);
00614 if (ret == 0) qDebug("Arriere format");
00615 }
00616 if (ret != 0)
00617 {
00618
00619 delete exp;
00620 exp = new CNEF;
00621 ret = exp->openfile(src);
00622 if (ret == 0) qDebug("NEF format");
00623 }
00624 #endif
00625 if (ret != 0)
00626 {
00627
00628 delete exp;
00629 exp = new CPlucker;
00630 ret = exp->openfile(src);
00631 }
00632 if (ret != 0)
00633 {
00634
00635 delete exp;
00636 exp = new CHM;
00637 ret = exp->openfile(src);
00638 }
00639 if (ret != 0)
00640 {
00641
00642 delete exp;
00643 exp = new iSilo;
00644 ret = exp->openfile(src);
00645 }
00646 if (ret != 0)
00647 {
00648 delete exp;
00649
00650 exp = new CReb;
00651 ret = exp->openfile(src);
00652 }
00653 if (ret != 0)
00654 {
00655 delete exp;
00656
00657 exp = new ppm_expander;
00658 ret = exp->openfile(src);
00659 }
00660 if (ret != 0)
00661 {
00662 delete exp;
00663 exp = new Text;
00664
00665 ret = exp->openfile(src);
00666 if (ret == 0) qDebug("Text format");
00667 }
00668
00669 if (ret != 0)
00670 {
00671 delete exp;
00672 QMessageBox::information(_parent, PROGNAME, "Unknown file compression type","Try another file");
00673 return ret;
00674 }
00675
00676 #else
00677 #ifdef USEQPE
00678 #ifdef OPIE
00679 QString codecpath(getenv("OPIEDIR"));
00680 #else
00681 QString codecpath(getenv("QTDIR"));
00682 #endif
00683 codecpath += "/plugins/reader/codecs";
00684 #else
00685 QString codecpath(getenv("READERDIR"));
00686 codecpath += "/codecs";
00687 #endif
00688 QDir d(codecpath, "*.so");
00689
00690 if (d.exists())
00691 {
00692
00693 const QFileInfoList *list = d.entryInfoList();
00694 QFileInfoListIterator it( *list );
00695 QFileInfo *fi;
00696
00697 int ret = -1;
00698 while ( ret != 0 && (fi=it.current()) )
00699 {
00700 if (exp != NULL) delete exp;
00701 qDebug("Trying %s", (const char*)fi->fileName());
00702 exp = new ebookcodec(fi->fileName());
00703 ret = exp->openfile(src);
00704 ++it;
00705 }
00706 qDebug("Buffdoc:Finished opening");
00707 if (ret != 0)
00708 {
00709 if (exp != NULL) delete exp;
00710 exp = new Text;
00711 ret = exp->openfile(src);
00712 }
00713 }
00714 else
00715 {
00716 if (exp != NULL) delete exp;
00717 exp = new Text;
00718 exp->openfile(src);
00719 }
00720 #endif
00721 lastword.empty();
00722 lastsizes[0] = laststartline = 0;
00723 #ifdef NEWLINEBREAK
00724 lastispara = false;
00725 #else
00726 lastispara = false;
00727 #endif
00728 exp->locate(exp->getHome());
00729 filt->setsource(exp);
00730 qDebug("BuffDoc:file opened");
00731 return 0;
00732 }
00733
00734 QString BuffDoc::about()
00735 {
00736 return QString("Buffered Decompressor (c) Tim Wentford\nHyphenation algorithm (c) Tim Wentford\n (Cyrillic support by Konstantin Isakov\n")+filt->about();
00737 }
00738
00739 int BuffDoc::getsentence(CBuffer& buff)
00740 {
00741 tchar ch;
00742 int i = 0;
00743 bool intext = false;
00744 while ((ch = getch()) != 10 && ch != UEOF)
00745 {
00746 buff[i++] = ch;
00747 if (ch == '"' || ch == '\'' || ch == 0x2018 || ch == 0x2019 ||
00748 ch == 0x201a || ch == 0x201b || ch == 0x201c || ch == 0x201d)
00749 {
00750 intext = !intext;
00751 }
00752 if (!intext && (ch == '.' || ch == '!' || ch == '?')) break;
00753 }
00754
00755 buff[i] = '\0';
00756 if (i == 0 && ch == UEOF) i = -1;
00757 laststartline = exp->locate();
00758 return i;
00759 }