00001 #include "CHM.h"
00002 #include "chm_lib.h"
00003 #include <qstring.h>
00004 #include <qstringlist.h>
00005 #include <stdio.h>
00006 #include <qimage.h>
00007 #include <qpixmap.h>
00008 #ifdef USEQPE
00009 #include <qpe/global.h>
00010 #endif
00011
00012 #ifndef __STATIC
00013 extern "C"
00014 {
00015 CExpander* newcodec() { return new CHM; }
00016 }
00017 #endif
00018
00019 static int _print_ui_index(struct chmFile *h, struct chmUnitInfo *ui,
00020 void *context)
00021 {
00022 CHM *chm = (CHM *)context;
00023 QString temp = "<tr>";
00024 char buff[1024];
00025 sprintf( buff,"<td align=right>%8d\n</td><td><a href=\"%s\">%s</a></td></tr>",(int)ui->length, ui->path, ui->path);
00026 temp += buff;
00027 chm->addContent(temp);
00028 return CHM_ENUMERATOR_CONTINUE;
00029 }
00030
00031 static int _get_hhc (struct chmFile *h, struct chmUnitInfo *ui,
00032 void *context)
00033 {
00034 CHM *chm = (CHM *)context;
00035 QString PathName = ui->path;
00036 if (PathName.find(".hhc") > -1) {
00037 chm->setPath(PathName);
00038 }
00039 return CHM_ENUMERATOR_CONTINUE;
00040 }
00041
00042 CHM::CHM() {
00043 chmFile = NULL;
00044 chmPath = "";
00045 chmHHCPath = "";
00046 chmBuffer = "";
00047 bufpos = 0;
00048 }
00049
00050 CHM::~CHM() {
00051 if (chmFile != NULL)
00052 chm_close(chmFile);
00053 }
00054
00055 void CHM::suspend() {
00056 #ifdef USEQPE
00057 bSuspended = true;
00058
00059 chm_close(chmFile);
00060 chmFile = NULL;
00061 sustime = time(NULL);
00062 #endif
00063 }
00064
00065 void CHM::unsuspend() {
00066 #ifdef USEQPE
00067 if (bSuspended)
00068 {
00069 bSuspended = false;
00070 int delay = time(NULL) - sustime;
00071 if (delay < 10)
00072 {
00073 Global::statusMessage("Stalling");
00074 sleep(10-delay);
00075 }
00076 chmFile = chm_open(fname);
00077 for (int i = 0; chmFile == NULL && i < 5; i++) {
00078 Global::statusMessage("Stalling");
00079 sleep(5);
00080 chmFile = chm_open(fname);
00081 }
00082 if (chmFile == NULL) {
00083 QMessageBox::warning(NULL, PROGNAME, "Couldn't reopen file");
00084 exit(0);
00085 }
00086
00087 }
00088 #endif
00089 }
00090
00091 void CHM::addContent(QString content) {
00092 chmBuffer += content;
00093 }
00094
00095 void CHM::FillHomeContent() {
00096 unsuspend();
00097 if (chmHHCPath != "") {
00098 const char *ext;
00099 char buffer[65536];
00100 unsigned int swath, offset;
00101 QString tmp="";
00102 QString HTML="";
00103
00104 const char *filename = (const char *)chmHHCPath;
00105 if (chm_resolve_object(chmFile, filename, &m_ui) != CHM_RESOLVE_SUCCESS)
00106 {
00107 chmBuffer = "HELP";
00108 fsize = chmBuffer.length();
00109 return;
00110 }
00111 m_homestart = m_ui.start;
00112 m_homeend = m_homestart + m_ui.length;
00113 swath = 65536;
00114 offset = 0;
00115 fsize = m_ui.length;
00116 while (offset < m_ui.length)
00117 {
00118 if ((m_ui.length - offset) < 65536)
00119 swath = m_ui.length - offset;
00120 else
00121 swath = 65536;
00122 swath = (int)chm_retrieve_object(chmFile, &m_ui, (unsigned char *) buffer, offset, swath);
00123 tmp += buffer;
00124 offset += swath;
00125 }
00126 HTML +="<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN>\r\n";
00127 HTML +="<HTML>\r\n";
00128 HTML +="<BODY>\r\n";
00129 HTML +="<h2>Home Page</h2>\r\n";
00130 HTML +="<h3>\r\n";
00131 QStringList qsl = QStringList::split("\r\n",tmp);
00132 QString NameFind ="<param name=\"Name\" value=\"";
00133 QString LocalFind = "<param name=\"Local\" value=\"";
00134 QString ULOpenFind = "<UL>";
00135 QString LIOpenFind = "<LI>";
00136 QString ULCloseFind = "</UL>";
00137 QString Name = "";
00138 QString Local = "";
00139 for ( QStringList::Iterator it = qsl.begin(); it != qsl.end(); ++it ) {
00140 QString Line = (*it);
00141 int NamePos = Line.find( NameFind);
00142 int LocalPos = Line.find( LocalFind);
00143 if (NamePos > -1) {
00144 Name = Line.mid(NamePos+NameFind.length(),Line.length());
00145 Name = Name.left(Name.length() - 2);
00146 }
00147 if (LocalPos > -1) {
00148 Local = Line.mid(LocalPos+LocalFind.length(),Line.length());
00149 Local = Local.left(Local.length() - 2);
00150 if (Name != "") {
00151 HTML += "<br>\r\n<a href=";
00152 HTML += Local;
00153 HTML += ">";
00154 HTML += Name;
00155 HTML += "</a>\r\n";
00156 Name = "";
00157 }
00158 }
00159 }
00160 HTML +="</h3>";
00161 HTML +="</BODY>\r\n";
00162 HTML +="</HTML>\r\n";
00163 chmHomeBuffer = HTML;
00164 chmBuffer = HTML;
00165 fsize = chmBuffer.length();
00166 m_currentstart = m_ui.start;
00167 m_currentend = m_currentstart+chmBuffer.length();
00168 }
00169 }
00170
00171 bool CHM::FillBuffer()
00172 {
00173 unsuspend();
00174 bool bRetVal = false;
00175 char buffer[65536];
00176 int swath, offset;
00177 chmBuffer = "";
00178 swath = 65536;
00179 offset = 0;
00180 fsize = m_ui.length;
00181 while (offset < m_ui.length)
00182 {
00183 if ((m_ui.length - offset) < 65536)
00184 swath = m_ui.length - offset;
00185 else
00186 swath = 65536;
00187 swath = (int)chm_retrieve_object(chmFile, &m_ui, (unsigned char *) buffer, offset, swath);
00188 chmBuffer += buffer;
00189 offset += swath;
00190 }
00191
00192 QString temp = chmBuffer.lower();
00193 int lpos = temp.find("</html");
00194 if (lpos > -1) {
00195 chmBuffer.truncate(lpos);
00196 chmBuffer = chmBuffer+"</HTML>";
00197 }
00198 fsize = chmBuffer.length();
00199
00200 bufpos = 0;
00201 bRetVal = true;
00202 m_currentstart = m_ui.start;
00203 m_currentend = m_currentstart+chmBuffer.length();
00204 return bRetVal;
00205 }
00206
00207 bool CHM::FillContent() {
00208 unsuspend();
00209 bool bRetVal = false;
00210 if (chmPath != "") {
00211
00212 const char *filename = (const char *)chmPath;
00213 if (chm_resolve_object(chmFile, filename, &m_ui) != CHM_RESOLVE_SUCCESS)
00214 {
00215 fsize = chmBuffer.length();
00216 return bRetVal;
00217 }
00218
00219 char buffer[65536];
00220 int swath, offset;
00221 chmBuffer = "";
00222 swath = 65536;
00223 offset = 0;
00224 fsize = m_ui.length;
00225 while (offset < m_ui.length)
00226 {
00227 if ((m_ui.length - offset) < 65536)
00228 swath = m_ui.length - offset;
00229 else
00230 swath = 65536;
00231 swath = (int)chm_retrieve_object(chmFile, &m_ui, (unsigned char *) buffer, offset, swath);
00232 chmBuffer += buffer;
00233 offset += swath;
00234 }
00235
00236 QString temp = chmBuffer.lower();
00237 int lpos = temp.find("</html");
00238 if (lpos > -1) {
00239 chmBuffer.truncate(lpos);
00240 chmBuffer = chmBuffer+"</HTML>";
00241 }
00242 fsize = chmBuffer.length();
00243
00244 bufpos = 0;
00245 m_currentstart = m_ui.start;
00246 m_currentend = m_currentstart+chmBuffer.length();
00247 bRetVal = true;
00248 }
00249 return bRetVal;
00250 }
00251
00252 bool CHM::getFile(const QString& _href, const QString& ) {
00253 QString href = "/" + _href;
00254 qDebug("Got:%s", (const char*)href);
00255 bool bRetVal = false;
00256 QString temp = chmPath;
00257 chmPath = href;
00258 if (FillContent()) {
00259 qDebug("Got it");
00260 bRetVal = true;
00261 } else {
00262 qDebug("Missed");
00263 chmPath = temp;
00264 FillContent();
00265 }
00266 return bRetVal;
00267 }
00268
00269 QImage *CHM::getPicture(const QString& href) {
00270 QImage *img = NULL;
00271 QString PicRef = "/"+href;
00272 struct chmUnitInfo ui;
00273 const char *ext;
00274
00275 const char *filename = (const char *)PicRef;
00276 if (chm_resolve_object(chmFile, filename, &ui) != CHM_RESOLVE_SUCCESS)
00277 {
00278 qDebug ("Could not resolve image");
00279 return img;
00280 }
00281 if (ui.length > 0) {
00282 char *temp = new char[ui.length];
00283 char buffer[65536];
00284 int swath, offset;
00285 swath = 65536;
00286 offset = 0;
00287
00288 while (offset < ui.length)
00289 {
00290 if ((ui.length - offset) < 65536)
00291 swath = ui.length - offset;
00292 else
00293 swath = 65536;
00294 swath = (int)chm_retrieve_object(chmFile, &ui, (unsigned char *) buffer, offset, swath);
00295 memcpy( (void *) (temp + offset), (void *)&buffer, swath );
00296 offset += swath;
00297 }
00298 QByteArray qba;
00299 qba.setRawData( (const char *)temp, ui.length);
00300 QPixmap qpm(qba);
00301 img = new QImage(qpm.convertToImage());
00302 qba.resetRawData((const char *)temp, ui.length);
00303 delete[] temp;
00304 }
00305
00306 return img;
00307 }
00308
00309 int CHM::OpenFile(const char *src) {
00310 if (chmFile != NULL) chm_close(chmFile);
00311 struct stat _stat;
00312 stat(src,&_stat);
00313 fsize = _stat.st_size;
00314 chmFile = chm_open(src);
00315 if (chmFile != NULL) {
00316 chm_enumerate(chmFile,
00317 CHM_ENUMERATE_ALL,
00318 _get_hhc,
00319 (void *)this);
00320 if ( chmPath != "") {
00321 setHomePath(chmPath);
00322 FillHomeContent();
00323 }
00324 }
00325 m_homepos = locate();
00326 qDebug("Home:%u", m_homepos);
00327 return (chmFile==NULL);
00328 }
00329
00330 int CHM::getch() {
00331 if ( (bufpos+1) >= chmBuffer.length() )
00332 return EOF;
00333 #ifdef _WINDOWS
00334 QChar letter = chmBuffer.at(bufpos++);
00335 #else
00336 QChar letter = chmBuffer[bufpos++];
00337 #endif
00338 return (int)(char)letter;
00339 }
00340
00341 void CHM::getch(tchar& ch, CStyle& sty)
00342 {
00343 int ich = getch();
00344 ch = (ich == EOF) ? UEOF : ich;
00345 }
00346
00347 void CHM::start2endSection()
00348 {
00349 m_currentstart = m_ui.start;
00350 m_currentend = m_currentstart+chmBuffer.length();
00351 }
00352
00353 unsigned int CHM::locate() {
00354 return m_currentstart+bufpos;
00355 }
00356
00357 void CHM::locate(unsigned int n) {
00358 if (n == 0) n = m_homepos;
00359 if (n >= m_homestart && n < m_homeend)
00360 {
00361 FillHomeContent();
00362 bufpos = n - m_homestart;
00363 start2endSection();
00364 qDebug("Home:%u:<%u, %u, %u>", m_ui.start, m_currentstart, n, m_currentend);
00365 }
00366 else if (n >= m_currentstart && n < m_currentend)
00367 {
00368 bufpos = n - m_currentstart;
00369 }
00370 else if (CHM_RESOLVE_FAILURE == chm_resolve_location(chmFile, n/4, &m_ui))
00371 {
00372 qDebug("Resolve failure");
00373 FillHomeContent();
00374 bufpos = 0;
00375 start2endSection();
00376 qDebug("Home:%u:<%u, %u, %u>", m_ui.start, m_currentstart, n, m_currentend);
00377 }
00378 else
00379 {
00380 qDebug("Resolve success");
00381 FillBuffer();
00382 start2endSection();
00383 bufpos=n-m_currentstart;
00384 qDebug("Not Home:%u:<%u, %u, %u>", m_ui.start, m_currentstart, n, m_currentend);
00385 }
00386 }
00387
00388 void CHM::sizes(unsigned long& _file, unsigned long& _text) {
00389 _text = _file = fsize;
00390 }