"Fossies" - the Fresh Open Source Software Archive

Member "tea-47.1.0/tio.cpp" (4 May 2019, 21715 Bytes) of package /linux/privat/tea-47.1.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tio.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 46.3.0_vs_47.0.0.

    1 /*
    2 
    3 DJVU read code taken fromdvutxt.c:  
    4 
    5 //C- DjVuLibre-3.5
    6 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
    7 //C- Copyright (c) 2001  AT&T
    8 
    9 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
   10 //C- Lizardtech Software.  Lizardtech Software has authorized us to
   11 //C- replace the original DjVu(r) Reference Library notice by the following
   12 //C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
   13 //C-
   14 //C-  ------------------------------------------------------------------
   15 //C- | DjVu (r) Reference Library (v. 3.5)
   16 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
   17 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
   18 //C- | 6,058,214 and patents pending.
   19 //C- |
   20 //C- | This software is subject to, and may be distributed under, the
   21 //C- | GNU General Public License, either Version 2 of the license,
   22 //C- | or (at your option) any later version. The license should have
   23 //C- | accompanied the software or you may obtain a copy of the license
   24 //C- | from the Free Software Foundation at http://www.fsf.org .
   25 //C- |
   26 //C- | The computer code originally released by LizardTech under this
   27 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
   28 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
   29 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
   30 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
   31 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
   32 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
   33 //C- | General Public License.   This grant only confers the right to 
   34 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
   35 //C- | the extent such infringement is reasonably necessary to enable 
   36 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
   37 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
   38 //C- | any greater extent that may be necessary to utilize further 
   39 //C- | modifications or combinations.
   40 //C- |
   41 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
   42 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
   43 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
   44 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
   45 //C- +------------------------------------------------------------------
   46 */
   47 
   48 #include <QXmlStreamReader>
   49 #include <QTextStream>
   50 #include <QDebug>
   51 #include <iostream>
   52 
   53 //FIXME: not good with cmake, cmake just use Qt5 here
   54 #if defined (POPPLER_ENABLE) || defined(Q_OS_OS2)
   55 #if QT_VERSION >= 0x050000
   56 #include <poppler-qt5.h>
   57 #else
   58 #include <poppler-qt4.h>
   59 #endif
   60 #endif
   61 
   62 
   63 #if defined (DJVU_ENABLE) || defined(Q_OS_OS2)
   64 #include <stddef.h>
   65 #include <stdlib.h>
   66 #include <stdio.h>
   67 #include <string.h>
   68 #include <locale.h>
   69 #include <fcntl.h>
   70 #include <errno.h>
   71 #include <libdjvu/miniexp.h>
   72 #include <libdjvu/ddjvuapi.h>
   73 #endif
   74 
   75 
   76 #include "tio.h"
   77 #include "utils.h"
   78 #include "tzipper.h"
   79 #include "textproc.h"
   80 
   81 
   82 QString extract_text_from_xml (const QString &string_data, const QStringList &tags)
   83 {
   84   QString data;
   85   QXmlStreamReader xml (string_data);
   86 
   87   bool tt = false;
   88 
   89   while (! xml.atEnd())
   90         {
   91          xml.readNext();
   92 
   93          QString tag_name = xml.qualifiedName().toString().toLower();
   94 
   95          foreach (QString ts, tags)
   96                 {
   97                  if (xml.isStartElement() && tag_name == ts)
   98                     tt = true;
   99 
  100                  if (xml.isEndElement() && tag_name == ts) 
  101                     tt = false; 
  102                  }
  103 
  104          if (tt && xml.isCharacters())
  105             {
  106              QString s = xml.text().toString();
  107              if (! s.isEmpty())
  108                {
  109                 data.append (s);
  110                 data.append("\n");
  111                }
  112              }
  113         }
  114 
  115    if (xml.hasError())
  116       qDebug() << "xml parse error";
  117 
  118   return data;
  119 }
  120 
  121 
  122 bool CTioPlainText::load (const QString &fname)
  123 {
  124   QFile feol_detector (fname);
  125 
  126   if (! feol_detector.open (QFile::ReadOnly))
  127      {
  128       error_string = feol_detector.errorString();
  129       return false;
  130      }
  131 
  132   QByteArray block = feol_detector.read (4096);
  133 
  134   eol = "\n";
  135 
  136   if (block.indexOf ("\r\n") != -1)
  137      eol = "\r\n";
  138   else
  139   if (block.indexOf ('\n') != -1)
  140      eol = "\n";
  141   else
  142   if (block.indexOf ('\r') != -1)
  143      eol = "\r";
  144 
  145 /*
  146    if (eol == "\n")
  147      qDebug() << "LF";
  148    if (eol == "\r\n")
  149      qDebug() << "CRLF";
  150    if (eol == "\r")
  151      qDebug() << "CR";
  152 */
  153 
  154   feol_detector.close();
  155 
  156   QFile file (fname);
  157 
  158   if (! file.open (QFile::ReadOnly/* | QFile::Text)*/))
  159      {
  160       error_string = file.errorString();
  161       return false;
  162      }
  163 
  164   QTextStream in (&file);
  165   in.setCodec (charset.toUtf8().data());
  166   data = in.readAll();
  167 
  168   if (eol == "\r\n")
  169      data.replace (eol, "\n");
  170   else
  171   if (eol == "\r")
  172      data.replace (eol, "\n");
  173 
  174   return true;
  175 }
  176 
  177 
  178 bool CTioPlainText::save (const QString &fname)
  179 {
  180   QFile file (fname);
  181   if (! file.open (QFile::WriteOnly))
  182      {
  183       error_string = file.errorString();
  184       return false;
  185      }
  186 
  187   QTextStream out (&file);
  188   out.setCodec (charset.toUtf8().data());
  189   out << data;
  190 
  191   return true;
  192 }
  193 
  194 
  195 CTioHandler::CTioHandler()
  196 {
  197   default_handler = new CTioPlainText;
  198 
  199   list.append (default_handler);
  200   list.append (new CTioGzip);
  201   list.append (new CTioXMLZipped);
  202   list.append (new CTioODT);
  203   list.append (new CTioABW);
  204   list.append (new CTioFB2);
  205   list.append (new CTioRTF);
  206   list.append (new CTioEpub);
  207 
  208 #if defined (POPPLER_ENABLE) || defined(Q_OS_OS2)
  209 //#ifdef POPPLER_ENABLE
  210   list.append (new CTioPDF);
  211 #endif
  212 
  213 #if defined (DJVU_ENABLE) || defined(Q_OS_OS2)
  214 //#ifdef DJVU_ENABLE
  215   list.append (new CTioDJVU);
  216 #endif
  217 }
  218 
  219 
  220 CTioHandler::~CTioHandler()
  221 {
  222   while (! list.isEmpty())
  223        delete list.takeFirst();
  224 }
  225 
  226 
  227 CTio* CTioHandler::get_for_fname (const QString &fname)
  228 {
  229   CTio *instance;
  230   QString ext = file_get_ext (fname).toLower();
  231 
  232   for (int i = 0; i < list.size(); i++)
  233       {
  234        instance = list.at (i);
  235        if (instance->extensions.indexOf (ext) != -1)
  236           return instance;
  237       }
  238 
  239   return default_handler;
  240 }
  241 
  242 
  243 CTioPlainText::CTioPlainText()
  244 {
  245   ronly = false;
  246 }
  247 
  248 
  249 CTioGzip::CTioGzip()
  250 {
  251   ronly = true;
  252   extensions.append ("gz");
  253 }
  254 
  255 
  256 bool CTioGzip::load (const QString &fname)
  257 {
  258   QByteArray a = gzip_deflateFile (fname);
  259   data = a.data();
  260   return true;
  261 }
  262 
  263 
  264 bool CTioReadOnly::save (const QString &fname)
  265 {
  266   error_string = tr ("Saving for this format is not supported");
  267   return false;
  268 }
  269 
  270 
  271 CTioABW::CTioABW()
  272 {
  273   ronly = true;
  274   extensions.append ("abw");
  275 }
  276 
  277 
  278 bool CTioABW::load (const QString &fname)
  279 {
  280   QString temp = qstring_load (fname);
  281 
  282   QStringList tags;
  283   tags.append ("p");
  284   
  285   data = extract_text_from_xml (temp, tags);
  286 
  287   return true;
  288 }
  289 
  290 
  291 bool CTioODT::load (const QString &fname)
  292 {
  293   data.clear();
  294   
  295   CZipper zipper;
  296   
  297   if (! zipper.read_as_utf8 (fname, "content.xml"))
  298      {
  299       qDebug() << "cannot read content.xml";
  300       return false;
  301      }
  302    
  303   QXmlStreamReader xml (zipper.string_data);
  304  
  305   bool tt = false;
  306   while (! xml.atEnd()) 
  307         {
  308          xml.readNext();
  309 
  310          QString tag_name = xml.qualifiedName().toString().toLower();
  311          
  312          if (xml.isStartElement()) 
  313             {
  314              if (tag_name == "text:s")
  315                 {
  316                  QXmlStreamAttributes attrs = xml.attributes();
  317                  if (attrs.hasAttribute("text:c"))
  318                     {
  319                      QString av = attrs.value ("text:c").toString();
  320                      QString fillval;
  321                      fillval = fillval.fill (' ', av.toInt());
  322                      data.append (fillval);
  323                     }
  324                  }   
  325             }
  326               
  327          if (xml.isEndElement()) 
  328             {
  329              if (tag_name.startsWith ("text") && tag_name != "text:span")
  330                 tt = true;
  331             }
  332          
  333          if (xml.isCharacters() && tt)
  334             {
  335              tt = false;
  336              data.append (xml.text().toString());
  337              data.append ("\n");
  338             }
  339         }
  340     
  341    if (xml.hasError()) 
  342       qDebug() << "xml parse error";
  343    
  344   return true;
  345 }
  346 
  347 
  348 CTioODT::CTioODT()
  349 {
  350   ronly = true;
  351 
  352   extensions.append ("odt");
  353   extensions.append ("sxw");
  354 }
  355 
  356 
  357 CTioXMLZipped::CTioXMLZipped()
  358 {
  359   ronly = true;
  360 
  361   extensions.append ("kwd");
  362   extensions.append ("docx");
  363 }
  364 
  365 
  366 bool CTioXMLZipped::load (const QString &fname)
  367 {
  368   data.clear();
  369     
  370   QString source_fname;
  371   QString ts;  
  372   
  373   QString ext = file_get_ext (fname);
  374 
  375   if (ext == "kwd")
  376      {
  377       source_fname = "maindoc.xml";
  378       ts = "text";
  379      } 
  380   else
  381   if (ext == "docx")
  382      {
  383       source_fname = "word/document.xml";
  384       ts = "w:t";  
  385      }
  386  
  387   
  388   CZipper zipper;
  389   if (! zipper.read_as_utf8 (fname, source_fname))
  390       return false;
  391  
  392   QStringList tags;
  393   tags.append (ts);
  394   
  395   data = extract_text_from_xml (zipper.string_data, tags);
  396  
  397   return true;
  398 }
  399 
  400 
  401 CCharsetMagic::CCharsetMagic()
  402 {
  403   QStringList fnames = read_dir_entries (":/encsign");
  404   
  405   CSignaturesList *koi8u = NULL;
  406   CSignaturesList *koi8r= NULL;
  407   
  408   foreach (QString fn, fnames)
  409           {
  410            QString fname = ":/encsign";
  411            fname.append ("/"); 
  412            fname.append (fn); 
  413            
  414            QByteArray a = file_load (fname);     
  415            QList<QByteArray> bsl = a.split ('\n'); 
  416   
  417            CSignaturesList *sl = new CSignaturesList;
  418            sl->encname = fn;
  419            
  420            if (fn == "KOI8-R")
  421               koi8r = sl;
  422 
  423            if (fn == "KOI8-U")
  424               koi8u = sl;
  425            
  426            for (int i = 0; i < bsl.count(); i++) 
  427                sl->words.append (bsl[i]);        
  428                       
  429            signatures.append (sl);          
  430           }
  431           
  432   int ku = signatures.indexOf (koi8u);
  433   int kr = signatures.indexOf (koi8r);
  434           
  435   signatures.swap (ku, kr);      
  436 }
  437 
  438 
  439 CCharsetMagic::~CCharsetMagic()  
  440 {
  441   for (int i = 0; i < signatures.count(); i++)
  442       delete signatures.at (i);
  443 }
  444 
  445 
  446 QString CCharsetMagic::guess_for_file (const QString &fname)
  447 {
  448   QString enc = "UTF-8";
  449 
  450   QByteArray bafile = file_load (fname);
  451   QString ext = file_get_ext (fname);
  452    
  453   if (ext == "html" || 
  454       ext == "htm" || 
  455       ext == "xhtml")
  456      {
  457       QTextCodec *defcodec = QTextCodec::codecForName ("UTF-8");
  458       QTextCodec *codec = QTextCodec::codecForHtml (bafile, defcodec);
  459       return codec->name(); 
  460      }
  461 
  462   for (int i = 0; i < signatures.count(); i++)
  463        for (int x = 0; x < signatures[i]->words.count(); x++)
  464            {
  465             if (bafile.contains (signatures[i]->words[x]))
  466                {
  467                 enc = signatures[i]->encname;
  468                 return enc;
  469                }           
  470            }
  471   
  472   return enc;
  473 }
  474 
  475 
  476 CTioFB2::CTioFB2()
  477 {
  478   ronly = true;
  479   extensions.append ("fb2");
  480 }
  481 
  482 
  483 bool CTioFB2::load (const QString &fname)
  484 {
  485   data.clear();
  486 
  487   QByteArray ba = file_load (fname);
  488   if (ba.isEmpty())
  489      return false;
  490 
  491   //read encoding:
  492 
  493   QString enc = string_between (QString (ba), "encoding=\"", "\"");
  494 
  495   if (enc.isEmpty())
  496      enc = "UTF-8";
  497 
  498   QTextCodec *codec = QTextCodec::codecForName (enc.toLatin1().data());
  499   QString temp = codec->toUnicode (ba);
  500 
  501   QString ts = "p";
  502 
  503   QXmlStreamReader xml (temp);
  504 
  505   bool tt = false;
  506  // bool title = false;
  507  // bool section = false;
  508 
  509   while (! xml.atEnd())
  510         {
  511          xml.readNext();
  512 
  513          QString tag_name = xml.qualifiedName().toString().toLower();
  514 
  515          if (xml.isStartElement())
  516             {
  517              if (tag_name == ts)
  518                 tt = true;
  519 
  520    //          if (tag_name == "title")
  521      //           title = true;
  522 
  523    //          if (tag_name == "section")
  524      //           section = true;
  525             }
  526 
  527          if (xml.isEndElement())
  528             {
  529              if (tag_name == ts)
  530                  tt = false;
  531 
  532              if (tag_name == "title")
  533                 {
  534        //          title = false;
  535                  data.append ("\n");
  536                 }
  537 
  538              if (tag_name == "section")
  539                 {
  540        //          section = false;
  541                  data.append ("\n");
  542                 }
  543              }
  544 
  545          if (tt && xml.isCharacters())
  546             {
  547              QString s = xml.text().toString();
  548              if (! s.isEmpty())
  549                 {
  550                  data.append ("   ");
  551                  data.append (s);
  552                  data.append ("\n");
  553                 }
  554             }
  555         }
  556 
  557   if (xml.hasError())
  558     qDebug() << "xml parse error";
  559 
  560   return true;
  561 }
  562 
  563 
  564 //www.codeguru.com/forum/archive/index.php/t-201658.html
  565 //rewritten by Peter Semiletov
  566 QString rtf_strip (const QString &rtf)
  567 {
  568   int length = rtf.size();
  569 
  570   if (length < 4)
  571      return QString();
  572 
  573   int start = 0;
  574 
  575   start = rtf.indexOf ("\\pard");
  576   if ( start < 1)
  577      return QString();
  578 
  579   QString strCopy;
  580   strCopy.reserve (length);
  581 
  582   int k = 0;
  583 
  584   bool slash = false; //is backslash followed by the space
  585   bool figure_opened = false; //is opening figure brace followed by the space
  586   bool figure_closed = false; //is closing brace followed by the space
  587   bool first_space = false; //else spaces are in plain text and must be included to the result
  588 
  589   QChar ch;
  590   for (int j = start; j < length; j++)
  591       {
  592 
  593        ch = rtf.at (j);
  594 
  595        if (ch == '\\')//we are looking at the backslash
  596           {
  597            first_space = true;
  598            slash = true;
  599           }
  600        else
  601        if (ch == '{')
  602           {
  603            first_space = true;
  604            figure_opened = true;
  605           }
  606       else
  607       if (ch == '}')
  608          {
  609           first_space = true;
  610           figure_closed = true;
  611          }
  612       else
  613       if (ch == ' ')// &&
  614           //(rtf.indexOf ("\\datafield", j - 10) + 10) != j)
  615          {
  616           slash = false;
  617           figure_opened = false;
  618           figure_closed = false;
  619          }
  620 
  621       if ( ch == '\\')
  622          {
  623           QChar chr = rtf.at (j + 1);
  624 
  625           if (chr == '{') //if the text contains symbol '{'
  626            {
  627             slash = false;
  628             figure_opened = false;
  629             figure_closed = false;
  630             first_space = false;
  631             strCopy += '{';
  632             j++;
  633             k++;
  634             continue;
  635            }
  636 
  637       if (chr == '}') //if the text contains symbol '}'
  638          {
  639           slash = false;
  640           figure_opened = false;
  641           figure_closed = false;
  642           first_space = false;
  643           strCopy += '}';
  644           j++;
  645           k++;
  646           continue;
  647          }
  648 
  649       if (chr == '\\')//if the text contains symbol '\'
  650          {
  651           slash = false;
  652           figure_opened = false;
  653           figure_closed = false;
  654           first_space = false;
  655           strCopy += '\\';
  656           j++;
  657           continue;
  658          }
  659     }
  660 
  661     if (rtf.at (j) == '\\' &&
  662         rtf.at (j + 1) == 'p' &&
  663         rtf.at (j + 2) == 'a' &&
  664         rtf.at (j + 3) == 'r' &&
  665         rtf.at (j + 4) != 'd')
  666        {
  667         slash = false;
  668         figure_opened = false;
  669         figure_closed = false;
  670         first_space = false;
  671         strCopy += '\n';
  672         j += 4;
  673         continue;
  674        }
  675 
  676     if (slash == false &&
  677         figure_opened == false &&
  678         figure_closed == false &&
  679         ch != '\n')
  680         {
  681          if (! first_space)
  682             strCopy += ch;
  683          else
  684             first_space = false;
  685         }
  686    }
  687 
  688   return strCopy;
  689 }
  690 
  691 
  692 CTioRTF::CTioRTF()
  693 {
  694   ronly = true;
  695   extensions.append ("rtf");
  696 }
  697 
  698 
  699 bool CTioRTF::load (const QString &fname)
  700 {
  701   QByteArray ba = file_load (fname);
  702 
  703   QString text;
  704   text.reserve (ba.size());
  705 
  706   int i = 0;
  707   int l = ba.size();
  708 
  709   QString ansicgp;
  710   int n = ba.indexOf ("ansicpg");
  711   if (n != -1)
  712      {
  713       int m = ba.indexOf ('\\', n);
  714       n += 7;
  715       ansicgp = ba.mid (n, m - n);
  716      }
  717 
  718   if (ansicgp.isEmpty()) //assuming unicode
  719      {
  720       while (i < l)
  721              if ((ba.at(i) == '\\') && (ba.at(i + 1) == 'u'))
  722                 {
  723                  QByteArray ta = ba.mid (i, 7);
  724                  ta = ta.mid (2, 4);
  725                  QChar c (ta.toInt());
  726                  text.append (c);
  727                  i += 7 + 3;
  728                 }
  729              else
  730                  {
  731                   text.append (ba.at(i));
  732                   i++;
  733                  }
  734      }
  735   else
  736       {
  737        ansicgp.prepend ("CP");
  738 
  739        QTextCodec *codec = QTextCodec::codecForName (ansicgp.toUtf8().data());
  740        qDebug() << "not unicode!";
  741 
  742        while (i < l)
  743        if ((ba.at(i) == '\\') && (ba.at(i + 1) == '\''))
  744           {
  745            QByteArray ta = ba.mid (i, 4);
  746            ta = ta.mid (2, 2);
  747            QByteArray bh = ta.fromHex (ta);
  748            text.append (codec->toUnicode (bh));
  749            i += 4;
  750           }
  751        else
  752            {
  753             text.append (ba.at(i));
  754             i++;
  755            }
  756        }
  757 
  758   data = rtf_strip (text);
  759 
  760   return true;
  761 }
  762 
  763 #if defined (POPPLER_ENABLE) || defined(Q_OS_OS2)
  764 //#ifdef POPPLER_ENABLE
  765 
  766 CTioPDF::CTioPDF()
  767 {
  768   ronly = true;
  769   extensions.append ("pdf");
  770 }
  771 
  772 
  773 bool CTioPDF::load (const QString &fname)
  774 {
  775   Poppler::Document *d = Poppler::Document::load (fname);
  776   
  777   if (! d)
  778      return false;
  779 
  780   if (d->isLocked()) 
  781      {
  782       delete d;
  783       return false;
  784      }
  785      
  786      
  787   int pages_count = d->numPages();   
  788   
  789   for (int i = 0; i < pages_count; i++)
  790       {
  791        Poppler::Page *p = d->page (i);
  792       
  793        QList<Poppler::TextBox*> tb = p->textList();
  794        
  795        for (int j = 0; j < tb.size(); j++)
  796            {
  797             data += tb[j]->text();
  798             //if (tb[j]->hasSpaceAfter())
  799             data += " ";
  800           
  801             delete tb[j];
  802            }
  803       }
  804      
  805   delete d;
  806   return true;
  807 }
  808 
  809 #endif
  810 
  811 
  812 //#ifdef DJVU_ENABLE
  813 #if defined (DJVU_ENABLE) || defined(Q_OS_OS2)
  814 
  815 
  816 const char *detail = 0;
  817 int escape = 0;
  818 
  819 QString temp_data_s;
  820 
  821 ddjvu_context_t *ctx;
  822 ddjvu_document_t *doc;
  823 
  824 
  825 void djvumsg_handle()
  826 {
  827   const ddjvu_message_t *msg;
  828 
  829   if (! ctx)
  830     return;
  831     
  832   msg = ddjvu_message_wait (ctx);
  833     
  834   while ((msg = ddjvu_message_peek (ctx)))
  835         {
  836          if (msg->m_any.tag == DDJVU_ERROR)
  837             {
  838              qDebug() << msg->m_error.message;              
  839              qDebug() << msg->m_error.filename << ":" << msg->m_error.lineno;
  840              return;
  841             }
  842                 
  843          ddjvu_message_pop(ctx);
  844         }
  845 }
  846 
  847 
  848 void dopage (int pageno)
  849 {
  850   miniexp_t r = miniexp_nil;
  851   
  852   const char *lvl = (detail) ? detail : "page";
  853   
  854   while ((r = ddjvu_document_get_pagetext (doc, pageno, lvl)) == miniexp_dummy)
  855          djvumsg_handle();
  856 
  857   if ((r = miniexp_nth (5, r)) && miniexp_stringp (r))
  858      {
  859       const char *s = miniexp_to_str (r); 
  860       if (s)
  861          {
  862           temp_data_s.append (s);
  863           temp_data_s.append ('\n');  
  864          } 
  865      }
  866 }
  867 
  868 
  869 CTioDJVU::CTioDJVU()
  870 {
  871   ronly = true;
  872   extensions.append ("djvu");
  873 }
  874 
  875 
  876 bool CTioDJVU::load (const QString &fname)
  877 {
  878   if (! (ctx = ddjvu_context_create ("tea")))
  879      return false;
  880      
  881   if (! (doc = ddjvu_document_create_by_filename (ctx, fname.toUtf8().data(), TRUE)))
  882      return false;
  883 
  884     
  885   while (! ddjvu_document_decoding_done (doc))
  886         djvumsg_handle();
  887 
  888   int n = ddjvu_document_get_pagenum (doc);
  889   
  890   for (int i = 0; i < n; i++)
  891       dopage (i);
  892    
  893   if (doc)
  894     ddjvu_document_release (doc);
  895     
  896   if (ctx)
  897     ddjvu_context_release (ctx);
  898 
  899   data = temp_data_s;
  900   return true;
  901 }
  902 
  903 #endif
  904 
  905 
  906 CTioEpub::CTioEpub()
  907 {
  908   ronly = true;
  909 
  910   extensions.append ("epub");
  911 }
  912 
  913 
  914 bool CTioEpub::load (const QString &fname)
  915 {
  916   data.clear();
  917   
  918   QStringList html_files;
  919     
  920   QString source_fname;
  921   QString ts;  
  922   
  923   CZipper zipper;
  924   if (! zipper.read_as_utf8 (fname, "META-INF/container.xml"))
  925        return false;
  926   
  927   
  928   QString opf_fname;
  929   QString opf_dir;
  930   
  931   int start = zipper.string_data.indexOf ("full-path=\"");
  932   int end = zipper.string_data.indexOf ("\"", start + 11);
  933   
  934   opf_fname = zipper.string_data.mid (start + 11, end - start - 11);
  935   opf_dir = opf_fname.left (opf_fname.indexOf ("/"));
  936    
  937   //std::cout << opf_fname.toStdString() << std::endl;
  938   //std::cout << opf_dir.toStdString() << std::endl;
  939 
  940   //READ FILES LIST. PARSE OPF FILE
  941   
  942   if (! zipper.read_as_utf8 (fname, opf_fname))
  943        return false;
  944   
  945   
  946   QXmlStreamReader xml (zipper.string_data);
  947   
  948   while (! xml.atEnd()) 
  949         {
  950          xml.readNext();
  951 
  952          QString tag_name = xml.qualifiedName().toString().toLower();
  953          if (tag_name == "item")
  954             {
  955              QString attr_href = xml.attributes().value ("href").toString();
  956              QString ext = file_get_ext (attr_href);
  957              if (ext == "html" || ext == "htm" || ext == "xml")
  958                 html_files.append (opf_dir + "/" + attr_href);
  959              //std::cout << attr_href.toStdString() << std::endl;
  960             }
  961         } 
  962     
  963   if (xml.hasError()) 
  964       qDebug() << "xml parse error";
  965 
  966 
  967   foreach (QString fn, html_files)
  968           {
  969            if (! zipper.read_as_utf8 (fname, fn))
  970               return false;
  971               
  972            //QString t = strip_html (zipper.string_data);
  973            QStringList tags;
  974            tags.append ("p");
  975           // tags.append ("h2");
  976           
  977            QString t = extract_text_from_xml (zipper.string_data, tags);
  978           
  979            data += t;
  980            data += "\n";
  981           }
  982    
  983   return true;
  984 }
  985 
  986 
  987 QStringList CTioHandler::get_supported_exts()
  988 {
  989   QStringList l;
  990 
  991   foreach (CTio *t, list)
  992           {
  993            for (int i = 0; i < t->extensions.size(); i++)
  994                l.append (t->extensions[i]); 
  995           }
  996 
  997    
  998   l.append ("txt");
  999 //  qstring_list_print (l);
 1000 
 1001   return l;
 1002 }