Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

BuffDoc.cpp

Go to the documentation of this file.
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   //  //qDebug("BuffDoc:locating:%u",n);
00051     lastword.empty();
00052   lastsizes[0] = laststartline = n;
00053 #ifdef NEWLINEBREAK
00054     lastispara = false;
00055 #else
00056     lastispara = false;
00057 #endif
00058   //    tchar linebuf[1024];
00059   if (exp != NULL) filt->locate(n);
00060   //  //qDebug("BuffDoc:Located");
00061 }
00062 
00063 void BuffDoc::resetPos()
00064 {
00065   //  //qDebug("BuffDoc:locating:%u",n);
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   // Cyrillic letters
00080   if (0x400 <= c && c <= 0x52F) return true;
00081   return false;
00082 }
00083 
00084 static bool isvowel(unsigned short c) // Only want lower case vowels
00085 {
00086   switch (c)
00087     {
00088     case 'a':
00089     case 'e':
00090     case 'i':
00091     case 'o':
00092     case 'u':
00093       // Cyrillic vowels
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       // Some cyrillic letters are neither vowels, nor consonants, or otherwise
00141       // the letters no word can start from.
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 // should do a backward search for spaces, first.
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                         //                      ((*buff)[i] == '-' && !(((*buff)[i-1] == '-') || ((*buff)[i+1] == '-')))
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                         //                      buff->resize();
00270                         for (int j = 0; j < lastword.length(); j++)
00271                         {
00272                             lastsizes[j] = lastsizes[j+i+1];
00273                         }
00274                         return true;
00275                     }
00276 
00277                     //if (hyphenate && (m_hyphenthreshold+1)*i < m_hyphenthreshold*len)
00278                     // We end up with i+1 characters instead of len-1
00279                     // Thus we are removing len - 1 - (i + 1) = len-i-2
00280                     // The space characters will be stretched to cover
00281                     // nospaces to nospaces + len - i - 2
00282                     // The stretch factor is hence
00283                     // (nospaces+len-i-2)/nospaces
00284                     if (hyphenate && !isCentred && ( 100*(nospaces+len-i-2) > (100+m_hyphenthreshold)*nospaces ))
00285                       {
00286                         /*
00287                         if (m_customhyphen)
00288                           {
00289                             for (int k = lastk; k >= i && k >= 2; k--)
00290                               {
00291                                 if (
00292                                     isletter((*buff)[k+3])
00293                                     &&
00294                                     isletter((*buff)[k+2])
00295                                     &&
00296                                     isvowel((*buff)[k+1])
00297                                     &&
00298                                     isconsonant((*buff)[k])
00299                                     &&
00300                                     isletter((*buff)[k-1])
00301                                     &&
00302                                     isletter((*buff)[k-2])
00303                                     )
00304                                   {
00305                                     (*buff)[len] = 0;
00306                                     lastword.setright(*buff, k+1);
00307                                     buff->truncate(k+2);
00308                                     (*buff)[k+1] = '-';
00309                                     (*buff)[k+2] = '\0';
00310                                     laststartline = lastsizes[k+1];
00311                                     buff->resize();
00312                                     for (int j = 0; j < lastword.length(); j++)
00313                                       {
00314                                         lastsizes[j] = lastsizes[j+k+1];
00315                                       }
00316                                     return true;
00317                                   }
00318                               }
00319                           }
00320                         else
00321                         */
00322                           {
00323                             for (int k = lastk; k >= i && k >= 1; k--)
00324                               {
00325                                 if (
00326                                     /*
00327                                       (
00328                                       k < len-3
00329                                       &&
00330                                       k >= 1
00331                                       &&
00332                                       isletter((*buff)[k+3])
00333                                       &&
00334                                       isletter((*buff)[k+2])
00335                                       &&
00336                                       isconsonant((*buff)[k+1])
00337                                       &&
00338                                       ((*buff)[k+1] != 'y')
00339                                       &&
00340                                       ((*buff)[k+1] != 'h')
00341                                       &&
00342                                       isconsonant((*buff)[k])
00343                                       &&
00344                                       ((*buff)[k] != 'h')
00345                                       &&
00346                                       isletter((*buff)[k-1])
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                                      && // Do not hyphenate when the first part ends with a vowel,
00365                                      // and the second starts with the two consonants.
00366                                      // Examples: "co-nsona-nts" -> "con-sonants",
00367                                      // "hy-phenation" -> "hyp-henation" etc.
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                                     //                              buff->resize();
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                         //                      buff->resize();
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     //    buff->resize();
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 //      (*buff)[0] = '\0';
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 //  //qDebug("Buff:%s Lastword:%s", (const char*)toQString(buff->data()), (const char*)toQString(lastword.data()));
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 //      lastword = buff->data() + len - 1;
00454       laststartline = lastsizes[len-1];
00455       for (int i = 0; i < buff->length(); i++) lastsizes[i] = lastsizes[i+len-1];
00456 //      (*buff)[len-1] = '-';
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       //      buff->resize();
00471       return true;
00472     }
00473   if (lastispara)
00474     {
00475       lastispara = false;
00476 //      lastword[0] = '\0';
00477       lastword.empty();
00478       len = buff->length();
00479       while (buff->width(availht, len) > w) len--;
00480 //      (*buff)[len] = '\0';
00481       buff->truncate(len);
00482       laststartline = exp->locate();
00483       //      buff->resize();
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 //  lastword = buff->data()+lastcheck;
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 //      (*buff)[lastcheck-1] = '\0';
00531       buff->truncate(lastcheck-1);
00532   }
00533   else
00534   {
00535       laststartline = (lastcheck == len) ? exp->locate() : allsizes[lastcheck+1];
00536 //      (*buff)[lastcheck] = '\0';
00537       buff->truncate(lastcheck);
00538   }
00539 //  buff->frig();
00540 //  buff->resize();
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     //    buff->resize();
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     if (ret != 0)
00600     {
00601         delete exp;
00602         exp = new ebookcodec("Aportis");
00603         ret = exp->openfile(src);
00604         if (ret == 0) qDebug("Aportis format");
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         //qDebug("Trying ppms");
00650         exp = new CReb;
00651         ret = exp->openfile(src);
00652     }
00653     if (ret != 0)
00654     {
00655         delete exp;
00656         //qDebug("Trying ppms");
00657         exp = new ppm_expander;
00658         ret = exp->openfile(src);
00659     }
00660     if (ret != 0)
00661     {
00662         delete exp;
00663         exp = new Text;
00664 //              //qDebug("Trying text");
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     //        //qDebug("Doing final open:%x:%x",exp,filt);
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 );      // create list iterator
00695       QFileInfo *fi;                          // pointer for traversing
00696   
00697       int ret = -1;
00698       while ( ret != 0 && (fi=it.current()) )
00699         {           // for each file...
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 }

Generated on Sat Nov 5 16:16:53 2005 for OPIE by  doxygen 1.4.2