00001 #include <qmap.h>
00002 #include <qfileinfo.h>
00003 #include <qtextstream.h>
00004 #include <qdir.h>
00005
00006 #ifdef USEQPE
00007 #include <qpe/global.h>
00008 #endif
00009 #include "CDrawBuffer.h"
00010 #include "CFilter.h"
00011 #include "hrule.h"
00012
00013 #include <qregexp.h>
00014 #include <qimage.h>
00015 #include <qpixmap.h>
00016
00017
00018
00019 void textfmt::mygetch(tchar& ch, CStyle& sty, unsigned long& pos)
00020 {
00021 if (uselast)
00022 {
00023 ch = lastchar;
00024 uselast = false;
00025 }
00026 else
00027 {
00028 parent->getch(ch, sty, pos);
00029 }
00030 }
00031
00032 void textfmt::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00033 {
00034 mygetch(ch, sty, pos);
00035 do
00036 {
00037 sty = currentstyle;
00038 switch (ch)
00039 {
00040 case 10:
00041 currentstyle.unset();
00042 sty = currentstyle;
00043 break;
00044
00045 case '-':
00046
00047 mygetch(ch, sty, pos);
00048 if (ch == '-')
00049 {
00050 ch = 0x2014;
00051 }
00052 else
00053 {
00054 lastchar = ch;
00055 uselast = true;
00056 ch = '-';
00057 }
00058 break;
00059 case '*':
00060 if (currentstyle.isBold())
00061 {
00062
00063
00064
00065
00066 if (lastchar != '*')
00067 {
00068 currentstyle.unsetBold();
00069 CStyle dummy;
00070
00071 mygetch(ch, dummy, pos);
00072 }
00073 }
00074 else
00075 {
00076
00077 CStyle dummy;
00078
00079 mygetch(ch, dummy, pos);
00080 QChar c(ch);
00081 if ((ch != '*') && (c.isPunct() || c.isLetterOrNumber()))
00082 {
00083 currentstyle.setBold();
00084 }
00085 else
00086 {
00087 lastchar = ch;
00088 uselast = true;
00089 ch = '*';
00090 }
00091
00092 }
00093 break;
00094 case '_':
00095 if (currentstyle.isItalic())
00096 {
00097
00098
00099
00100
00101 if (lastchar != '_')
00102 {
00103 currentstyle.unsetItalic();
00104 CStyle dummy;
00105
00106 mygetch(ch, dummy, pos);
00107 }
00108 }
00109 else
00110 {
00111
00112 CStyle dummy;
00113
00114 mygetch(ch, dummy, pos);
00115 QChar c(ch);
00116 if ((ch != '_') && (c.isPunct() || c.isLetterOrNumber()))
00117 {
00118 currentstyle.setItalic();
00119 }
00120 else
00121 {
00122 lastchar = ch;
00123 uselast = true;
00124 ch = '_';
00125 }
00126
00127 }
00128 break;
00129 }
00130 }
00131 while (sty != currentstyle);
00132 if (!uselast) lastchar = ch;
00133 return;
00134 }
00135
00136 void remap::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00137 {
00138 if (q[offset] != 0)
00139 {
00140 q[offset++];
00141 sty = currentstyle;
00142 return;
00143 }
00144 parent->getch(ch, sty, pos);
00145 switch (ch)
00146 {
00147 case 0x201a:
00148 ch = '\'';
00149 break;
00150 case 0x0192:
00151 ch = 'f';
00152 break;
00153 case 0x201e:
00154 ch = '"';
00155 break;
00156 case 0x2026:
00157 offset = 0;
00158 q[0] = '.';
00159 q[1] = '.';
00160 q[2] = 0;
00161 ch = '.';
00162 break;
00163 case 0x0160:
00164 ch = 'S';
00165 break;
00166 case 0x2039:
00167 ch = '<';
00168 break;
00169 case 0x0152:
00170 offset = 0;
00171 q[0] = 'E';
00172 q[1] = 0;
00173 ch = 'O';
00174 break;
00175 case 0x017d:
00176 ch = 'Z';
00177 break;
00178 case 0x2018:
00179 ch = '\'';
00180 break;
00181 case 0x2019:
00182 ch = '\'';
00183 break;
00184 case 0x201c:
00185 ch = '"';
00186 break;
00187 case 0x201d:
00188 ch = '"';
00189 break;
00190 case 0x2022:
00191 ch = '>';
00192 break;
00193 case 0x2013:
00194 ch = '-';
00195 break;
00196 case 0x2014:
00197 offset = 0;
00198 q[0] = '-';
00199 q[1] = 0;
00200 ch = '-';
00201 break;
00202 case 0x02dc:
00203 ch = '~';
00204 break;
00205 case 0x0161:
00206 ch = 's';
00207 break;
00208 case 0x203a:
00209 ch = '>';
00210 break;
00211 case 0x0153:
00212 offset = 0;
00213 q[0] = 'e';
00214 q[1] = 0;
00215 ch = 'o';
00216 break;
00217
00218
00219
00220
00221
00222
00223
00224
00225 case 0x017e:
00226 ch = 'z';
00227 break;
00228 case 0x0178:
00229 ch = 'Y';
00230 break;
00231 }
00232 currentstyle = sty;
00233 }
00234
00235 void PeanutFormatter::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00236 {
00237 CStyle dummy;
00238 currentstyle.setColour(0,0,0);
00239 parent->getch(ch, dummy, pos);
00240 while (ch == '\\')
00241 {
00242 parent->getch(ch, dummy, pos);
00243 if (ch == '\\') break;
00244 switch(ch)
00245 {
00246 case 'a':
00247 {
00248 int code = 0;
00249 for (int i = 0; i < 3; i++)
00250 {
00251 parent->getch(ch, dummy, pos);
00252 code = 10*code + ch - '0';
00253 }
00254 ch = code;
00255 }
00256 break;
00257 case 'v':
00258 {
00259 while (1)
00260 {
00261 parent->getch(ch, dummy, pos);
00262 if (ch == '\\')
00263 {
00264 parent->getch(ch, dummy, pos);
00265 if (ch == 'v')
00266 {
00267 parent->getch(ch, dummy, pos);
00268 break;
00269 }
00270 }
00271 }
00272 }
00273 break;
00274 case 's':
00275 case 'n':
00276 currentstyle.setFontSize(0);
00277 parent->getch(ch,dummy, pos);
00278 break;
00279 case 'p':
00280 currentstyle.unset();
00281
00282 ch = 10;
00283 break;
00284 case 'l':
00285 if (currentstyle.getFontSize() == 1)
00286 {
00287 currentstyle.setFontSize(0);
00288 }
00289 else
00290 {
00291 currentstyle.setFontSize(1);
00292 }
00293 parent->getch(ch, dummy, pos);
00294 break;
00295 case 'x':
00296 if (currentstyle.getFontSize() == 0)
00297 {
00298
00299
00300 currentstyle.setFontSize(1);
00301 }
00302 else
00303 {
00304 currentstyle.unset();
00305 }
00306
00307 ch = 10;
00308 break;
00309 case 'i':
00310 if (currentstyle.isItalic())
00311 {
00312 currentstyle.unsetItalic();
00313 }
00314 else
00315 {
00316 currentstyle.setItalic();
00317 }
00318 parent->getch(ch, dummy, pos);
00319 break;
00320 case 'b':
00321 case 'B':
00322 if (currentstyle.isBold())
00323 {
00324 currentstyle.unsetBold();
00325 }
00326 else
00327 {
00328 currentstyle.setBold();
00329 }
00330 parent->getch(ch, dummy, pos);
00331 break;
00332 case 'c':
00333 if (currentstyle.getJustify() == m_AlignCentre)
00334 {
00335 currentstyle.setLeftJustify();
00336 }
00337 else
00338 {
00339 currentstyle.setCentreJustify();
00340 }
00341 parent->getch(ch, dummy, pos);
00342 break;
00343 case 'r':
00344 if (currentstyle.getJustify() == m_AlignRight)
00345 {
00346 currentstyle.setLeftJustify();
00347 }
00348 else
00349 {
00350 currentstyle.setRightJustify();
00351 }
00352 parent->getch(ch, dummy, pos);
00353 break;
00354 default:
00355 currentstyle.setColour(255,0,0);
00356 }
00357 }
00358 sty = currentstyle;
00359 }
00360
00361 void OnePara::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00362 {
00363 parent->getch(ch, sty, pos);
00364 if (m_lastchar == 10)
00365 {
00366 while (ch == 10) parent->getch(ch, sty, pos);
00367 }
00368 m_lastchar = ch;
00369 }
00370
00371 void repalm::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00372 {
00373 parent->getch(ch, sty, pos);
00374 switch (ch)
00375 {
00376 case 0x80:
00377 ch = 0x20ac;
00378 break;
00379 case 0x82:
00380 ch = 0x201a;
00381 break;
00382 case 0x83:
00383 ch = 0x0192;
00384 break;
00385 case 0x84:
00386 ch = 0x201e;
00387 break;
00388 case 0x85:
00389 ch = 0x2026;
00390 break;
00391 case 0x86:
00392 ch = 0x2020;
00393 break;
00394 case 0x87:
00395 ch = 0x2021;
00396 break;
00397 case 0x88:
00398 ch = 0x02c6;
00399 break;
00400 case 0x89:
00401 ch = 0x2030;
00402 break;
00403 case 0x8a:
00404 ch = 0x0160;
00405 break;
00406 case 0x8b:
00407 ch = 0x2039;
00408 break;
00409 case 0x8c:
00410 ch = 0x0152;
00411 break;
00412
00413
00414
00415
00416
00417 case 0x91:
00418 ch = 0x2018;
00419 break;
00420 case 0x92:
00421 ch = 0x2019;
00422 break;
00423 case 0x93:
00424 ch = 0x201c;
00425 break;
00426 case 0x94:
00427 ch = 0x201d;
00428 break;
00429 case 0x95:
00430 ch = 0x2022;
00431 break;
00432 case 0x96:
00433 ch = 0x2013;
00434 break;
00435 case 0x97:
00436 ch = 0x2014;
00437 break;
00438 case 0x98:
00439 ch = 0x02dc;
00440 break;
00441 case 0x99:
00442 ch = 0x2122;
00443 break;
00444 case 0x9a:
00445 ch = 0x0161;
00446 break;
00447 case 0x9b:
00448 ch = 0x203a;
00449 break;
00450 case 0x9c:
00451 ch = 0x0153;
00452 break;
00453 case 0x9e:
00454 ch = 0x017e;
00455 break;
00456 case 0x9f:
00457 ch = 0x0178;
00458 break;
00459 case 0x18:
00460 ch = 0x2026;
00461 break;
00462 case 0x19:
00463 ch = 0x2007;
00464 break;
00465 case 0x8d:
00466 ch = 0x2662;
00467 break;
00468 case 0x8e:
00469 ch = 0x2663;
00470 break;
00471 case 0x8f:
00472 ch = 0x2661;
00473 break;
00474 case 0x90:
00475 ch = 0x2660;
00476 break;
00477 default:
00478 break;
00479 }
00480 }
00481
00482
00483
00484
00485 void DePluck::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00486 {
00487 if (m_buffed > 0)
00488 {
00489 sty = m_laststyle;
00490 ch = nextpart[m_current++];
00491 if (m_current == m_buffed)
00492 {
00493 m_current = m_buffed = 0;
00494 }
00495 }
00496 else
00497 {
00498 if (m_buffer != 0)
00499 {
00500 ch = m_buffer;
00501 m_buffer = 0;
00502 return;
00503 }
00504 unsigned long lnk, lnkoff;
00505 do
00506 {
00507 if (nextpart[m_buffed] == 0) break;
00508 parent->getch(ch, sty, pos);
00509 m_laststyle = sty;
00510 if (sty.getLink())
00511 {
00512 lnk = sty.getData();
00513 lnkoff = sty.getOffset();
00514 }
00515 } while (ch == nextpart[m_buffed] && sty.getLink() && ++m_buffed);
00516 m_current = 0;
00517 if (nextpart[m_buffed] == 0)
00518 {
00519 m_buffed = 0;
00520 QString dmy, dmy2;
00521 parent->hyperlink(lnk, lnkoff, dmy, dmy2);
00522 do
00523 {
00524 parent->getch(ch, sty, pos);
00525 }
00526 while (ch != 10);
00527 parent->getch(ch, sty, pos);
00528 }
00529 else if (m_buffed > 0)
00530 {
00531 m_buffer = ch;
00532 ch = nextpart[0];
00533 if (m_buffed == 1)
00534 {
00535 m_buffed = 0;
00536 }
00537 else m_current = 1;
00538 }
00539 }
00540
00541 return;
00542 }
00543
00544 HighlightFilter::HighlightFilter(QTReader* _p) : pReader(_p), lastpos(0), nextpos(0), red(255), green(255), blue(255)
00545 {
00546 }
00547
00548 #include "Bkmks.h"
00549 #include "QTReader.h"
00550
00551 void HighlightFilter::refresh(unsigned long pos)
00552 {
00553 bkmks = pReader->Bkmklist();
00554
00555 red = green = blue = 255;
00556
00557 if (bkmks == NULL)
00558 {
00559 lastpos = 0;
00560 nextpos = 0xffffffff;
00561 }
00562 else
00563 {
00564 lastpos = 0;
00565 nextpos = 0xffffffff;
00566 for (CList<Bkmk>::iterator i = bkmks->begin(); i != bkmks->end(); i++)
00567 {
00568 if ((*i).value() <= pos && pos < (*i).value2())
00569 {
00570 red = i->red();
00571 green = i->green();
00572 blue = i->blue();
00573 lastpos = (*i).value();
00574 nextpos = (*i).value2();
00575 break;
00576 }
00577 if ((*i).value() > pos)
00578 {
00579 nextpos = (*i).value();
00580 break;
00581 }
00582 lastpos = (*i).value();
00583 }
00584 }
00585 }
00586
00587 void HighlightFilter::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00588 {
00589 parent->getch(ch, sty, pos);
00590 if (bkmks != pReader->Bkmklist() || pos <= lastpos || pos >= nextpos)
00591 {
00592
00593 refresh(pos);
00594
00595 }
00596 int r = sty.bRed(), g = sty.bGreen(), b = sty.bBlue();
00597 if (r == 255 && g == 255 && b == 255)
00598 {
00599 sty.setBackground(red, green, blue);
00600 }
00601 }
00602
00603 void kern::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00604 {
00605 if (uselast)
00606 {
00607 ch = lastchar;
00608 sty = laststy;
00609 uselast = false;
00610 return;
00611 }
00612 else
00613 {
00614 parent->getch(ch, sty, pos);
00615 }
00616 switch (ch)
00617 {
00618 case 'f':
00619 {
00620 tchar savedchar = 'f';
00621 parent->getch(ch, sty, pos);
00622 switch (ch)
00623 {
00624 case 'i':
00625 ch = (251 << 8) + 1;
00626 break;
00627 case 'l':
00628 ch = (251 << 8) + 2;
00629 break;
00630 default:
00631 lastchar = ch;
00632 uselast = true;
00633 laststy = sty;
00634 ch = savedchar;
00635 }
00636 }
00637 break;
00638 default:
00639 break;
00640 }
00641 }
00642
00643 class ErrorFilter : public CFilter
00644 {
00645 QString error;
00646 int currentpos;
00647 public:
00648 ErrorFilter(const QString& _s) : error(_s), currentpos(0) {}
00649 ~ErrorFilter() {}
00650 void getch(tchar& ch, CStyle& sty, unsigned long& pos)
00651 {
00652 if (currentpos == error.length())
00653 {
00654 ch = UEOF;
00655 currentpos = 0;
00656 }
00657 else
00658 {
00659 ch = error[currentpos++].unicode();
00660 }
00661 }
00662 QString about() { return parent->about(); }
00663 };
00664
00665 #ifndef __STATIC
00666 ExternFilter::ExternFilter(const QString& nm, const QString& optional) : filt(NULL), handle(NULL)
00667 {
00668 #ifdef USEQPE
00669 #ifdef OPIE
00670 QString filterpath(getenv("OPIEDIR"));
00671 #else
00672 QString filterpath(getenv("QTDIR"));
00673 #endif
00674 filterpath += "/plugins/reader/filters/lib";
00675 #else
00676 QString filterpath(getenv("READERDIR"));
00677 filterpath += "/filters/lib";
00678 #endif
00679 filterpath += nm;
00680 filterpath += ".so";
00681 if (QFile::exists(filterpath))
00682 {
00683 qDebug("Filter:%s", (const char*)filterpath);
00684 handle = dlopen(filterpath, RTLD_LAZY);
00685 if (handle == 0)
00686 {
00687 qDebug("Can't find filter:%s", dlerror());
00688
00689 filt = new ErrorFilter(QString("Can't find plugin:")+nm);
00690 return;
00691 }
00692 CFilter* (*newfilter)(const QString&);
00693 newfilter = (CFilter* (*)(const QString&))dlsym(handle, "newfilter");
00694 if (newfilter == NULL)
00695 {
00696 qDebug("Can't find newfilter");
00697 filt = new ErrorFilter(QString("Can't find entry point in plugin:")+nm);
00698 return;
00699 }
00700 filt = (*newfilter)(optional);
00701 }
00702 else
00703 {
00704 qDebug("No filter path:%s", (const char*)filterpath);
00705 filt = new ErrorFilter(QString("No filter plugins installed:")+nm);
00706 }
00707 if (filt == NULL)
00708 {
00709 qDebug("Can't do newfilter");
00710 filt = new ErrorFilter(QString("Filter creation failed:")+nm);
00711 return;
00712 }
00713 }
00714 #endif
00715
00716 void makeInverse::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00717 {
00718 parent->getch(ch, sty, pos);
00719 int r,g,b;
00720 r = 255 - sty.Red(), g = 255 - sty.Green(), b = 255 - sty.Blue();
00721 sty.setColour(r,g,b);
00722 r = 255 - sty.bRed(), g = 255 - sty.bGreen(), b = 255 - sty.bBlue();
00723 sty.setBackground(r,g,b);
00724 r = 255 - sty.pRed(), g = 255 - sty.pGreen(), b = 255 - sty.pBlue();
00725 sty.setPaper(r,g,b);
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 void setbg::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00747 {
00748 parent->getch(ch, sty, pos);
00749 int r = sty.pRed(), g = sty.pGreen(), b = sty.pBlue();
00750 if (r == 255 && g == 255 && b == 255)
00751 {
00752 sty.setPaper(m_r,m_g,m_b);
00753 }
00754 else
00755 {
00756 qDebug("We have background [%x%x%x]", r, g, b);
00757 }
00758 r = sty.bRed(), g = sty.bGreen(), b = sty.bBlue();
00759 if (r == 255 && g == 255 && b == 255)
00760 {
00761 sty.setBackground(m_r,m_g,m_b);
00762 }
00763 else
00764 {
00765 qDebug("We have background [%x%x%x]", r, g, b);
00766 }
00767 }
00768
00769 void setfg::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00770 {
00771 parent->getch(ch, sty, pos);
00772 int r = sty.Red(), g = sty.Green(), b = sty.Blue();
00773 if (r == 0 && g == 0 && b == 0)
00774 {
00775 sty.setColour(m_r,m_g,m_b);
00776 }
00777 }
00778
00779 #include "CRegExp.h"
00780
00781 repara::repara(const QString& pat) : tch(0)
00782 {
00783
00784 flt = new CRegExpFilt(pat, false);
00785 qDebug("Construction done");
00786 }
00787
00788 repara::~repara()
00789 {
00790 delete flt;
00791 }
00792
00793 void repara::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00794 {
00795 if (flt->empty())
00796 {
00797 while (flt->empty())
00798 {
00799 parent->getch(ch, sty, pos);
00800 flt->addch(ch);
00801 }
00802 }
00803 ch = flt->pop();
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 return;
00824 }
00825
00826 void tableLink::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00827 {
00828 if (offset >= (int)text.length())
00829 {
00830 offset = -1;
00831 sty.setColour(m_r, m_g, m_b);
00832 do
00833 {
00834 parent->getch(ch, sty, pos);
00835 }
00836 while (sty.isTable());
00837 return;
00838 }
00839 if (offset >= 0)
00840 {
00841 ch = text[offset++].unicode();
00842 return;
00843 }
00844 parent->getch(ch, sty, pos);
00845 if (sty.isTable())
00846 {
00847 offset = 1;
00848 ch = text[0].unicode();
00849 m_r = sty.Red(), m_g = sty.Green(), m_b = sty.Blue();
00850 sty.setColour(255, 0, 0);
00851 }
00852 return;
00853 }
00854
00855 void underlineLink::getch(tchar& ch, CStyle& sty, unsigned long& pos)
00856 {
00857 parent->getch(ch, sty, pos);
00858 if (sty.getLink()) sty.setUnderline();
00859
00860
00861 }