home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / eikon / searchstate.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  9.0 KB  |  369 lines

  1. // SearchState.cpp
  2. //
  3. // Copyright (c) 1999-2000 Sander van der Wal.  All rights reserved.
  4. //
  5. // $Id: searchstate.cpp 1.1 2000-09-17 13:18:14+02 svdwal Exp svdwal $
  6. //
  7. // $Log: searchstate.cpp $
  8. // Revision 1.1  2000-09-17 13:18:14+02  svdwal
  9. // Initial checkin
  10. //
  11.  
  12. #include "SearchState.h"
  13.  
  14. // --o EIKON
  15. #include <eikfindd.h> // SEdwinFindModel
  16. #include <eiklabel.h>
  17. //#include <eikon.rsg>
  18. #include <eikdialg.hrh>
  19.  
  20. // Engine
  21. // --o PDFLib
  22. #include "PDFDoc.h"
  23. #include "TextOutputDev.h"
  24.  
  25. #include "Pdf.hrh"
  26. #include "Pdf.rsg"
  27.  
  28. // Profiling
  29. #include "PROFILE.H"
  30.  
  31.  
  32. //
  33. // Global const
  34. //
  35. static inline TInt round(double x) { return TInt(x+0.5); };
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38. //
  39. // CSearchingDialog
  40. //
  41. //////////////////////////////////////////////////////////////////////////////
  42. class CSearchingDialog: public CEikDialog, 
  43.                         public MSearchStateObserver
  44. {
  45. public:
  46.   CSearchingDialog(CSearchState& iSearchState);
  47.  
  48. // --0 CEikDialog
  49. private:
  50.   void PreLayoutDynInitL();
  51.   void PostLayoutDynInitL();
  52.   TBool OkToExitL(TInt /*aButtonId*/);
  53.  
  54. // --o MSearchStateObserver
  55. private: 
  56.   void NotifyFound();
  57.   void NotifyError(TInt aError);
  58.   void NotifyPage(TInt aPage);
  59.  
  60. private:
  61.   CSearchState& iSearchState;
  62. };
  63.  
  64. CSearchingDialog::CSearchingDialog(CSearchState& aSearchState)
  65. : iSearchState(aSearchState)
  66. {
  67.   iSearchState.SetObserver(this);
  68. }
  69.  
  70.  
  71. void CSearchingDialog::PreLayoutDynInitL()
  72. {
  73.   // use MaxPage() to get enough room for the biggest page number
  74.   TBuf<10> buf;
  75.   buf.Num(iSearchState.MaxPage());
  76.   CEikLabel* label=((CEikLabel*)Control(ESearchingDialogPage));
  77.   label->iAlignment=EHRightVCenter;
  78.   label->SetTextL(buf);
  79. }
  80.  
  81.  
  82. void CSearchingDialog::PostLayoutDynInitL()
  83. {
  84.   TBuf<10> buf;
  85.   buf.Num(iSearchState.Page());
  86.   CEikLabel* label=((CEikLabel*)Control(ESearchingDialogPage));
  87.   label->iAlignment=EHLeftVCenter;
  88.   label->SetTextL(buf);
  89.  
  90.   iSearchState.StartSearchingL();
  91. }
  92.  
  93.  
  94. TBool CSearchingDialog::OkToExitL(TInt /* aButtonId */ )
  95. {
  96.   iSearchState.CancelSearch();
  97.   return(ETrue);
  98. }
  99.  
  100.  
  101. void CSearchingDialog::NotifyFound()
  102. {
  103.   TryExitL(EEikBidOk);// this doesn't leave in this case. 
  104. }
  105.  
  106.  
  107. void CSearchingDialog::NotifyError(TInt anErrorCode)
  108. {
  109.   if (anErrorCode!=KErrCancel)
  110.     delete(this);
  111.   else
  112.     TryExitL(EEikBidCancel);
  113. }
  114.  
  115.  
  116. void CSearchingDialog::NotifyPage(TInt aPage)
  117. {
  118.   TBuf<10> buf;
  119.   buf.Num(aPage);
  120.   TRAPD(ret, SetLabelL(ESearchingDialogPage, buf));
  121. }
  122.  
  123.  
  124. /////////////////////////////////////////////////////////////////////////////
  125. //
  126. // CSearchState
  127. //
  128. //////////////////////////////////////////////////////////////////////////////
  129. CSearchState::CSearchState(PDFDoc* aDoc, TInt aStartPage, SEdwinFindModel* aFindModel)
  130. : iState(EDone), iDoc(aDoc), iFindModel(aFindModel), iStartPage(aStartPage)
  131. {
  132.   iMin.iX = iMin.iY = iMax.iX = iMax.iY = 0;
  133.   iSelection = TRect(0,0,0,0);
  134.  
  135.   // search current page starting at top of page
  136.   iPage      = iStartPage;
  137.   iTop       = gTrue;
  138. }
  139.  
  140.  
  141. void CSearchState::ConstructL()
  142. {
  143.   // search following pages
  144.   iTextOut = new(ELeave) TextOutputDev();
  145.   iTextOut->ConstructL(0, gFalse /* useEUCJP */, gFalse);
  146.   if (!iTextOut->isOk()) {
  147.     delete iTextOut;
  148.     iTextOut = 0;
  149.   }
  150.   else
  151.     iState = EStart;
  152. }
  153.  
  154.  
  155. CSearchState::~CSearchState()
  156. {
  157.   if (iActivePage) {
  158.     iActivePage->Cancel();
  159.     delete iActivePage;
  160.   }
  161.   delete iTextOut;
  162. }
  163.  
  164.  
  165. void CSearchState::SetObserver(MSearchStateObserver* aObserver)
  166. {
  167.  iObserver = aObserver;
  168. }
  169.  
  170.  
  171. TInt CSearchState::MaxPage() const { return iDoc->getNumPages(); }
  172.  
  173.  
  174. void CSearchState::NotifyPageFinishedL(TInt aError)
  175. {
  176.   if (aError == KErrNone)
  177.     // reenter the state engine until it has found something
  178.     while (!StepL());
  179.   else if (iObserver)
  180.     iObserver->NotifyError(aError);
  181. }
  182.  
  183.  
  184. TBool CSearchState::FindNextL()
  185. {
  186.   // if result is fast to find, return directly
  187.   // else start a dialog with a cancel button and the active page 
  188.  
  189.   iObserver = 0;
  190.   TBool fast = StepL();
  191.   if (!fast) {
  192.     CSearchingDialog* dialog = new(ELeave) CSearchingDialog(*this);
  193.     dialog->ExecuteLD(R_SEARCHING_DIALOG);
  194.   }
  195.   return iFound;
  196. }
  197.  
  198.  
  199. void CSearchState::StartSearchingL()
  200. {
  201.   if (iState != EDone) {
  202.     iActivePage = CActivePage::NewL(10, this);
  203.     StepL();
  204.   }
  205.   else if (iObserver)
  206.     iObserver->NotifyError(KErrCancel);
  207.   return;
  208. }
  209.  
  210.  
  211. TBool CSearchState::StepL()
  212. {
  213.   iFound = EFalse;
  214.   for (;;) {
  215.     switch (iState) {
  216.     
  217.     case EStart: // start searching by rendering the chars on the first page
  218.       iNumSeen = 0;
  219.       iPg = iStartPage;
  220.       iState = ENextPage;
  221.       return EFalse;
  222.     
  223.     case EStartAtSelection: // search current page starting at current selection or top of page
  224.       iXMin1=0;
  225.       iYMin1=0;
  226.       iXMax1=0;
  227.       iYMax1=0;
  228.       if (iSelection.iTl.iX < iSelection.iBr.iX && iSelection.iTl.iY < iSelection.iBr.iY) {
  229.         iMin.iX = iSelection.iBr.iX;
  230.         iMin.iY = (iSelection.iTl.iY + iSelection.iBr.iY) / 2;
  231.         iTop = gFalse;
  232.       } 
  233.       else
  234.         iTop = gTrue;
  235.       
  236.       iXMin1 = iMin.iX;
  237.       iYMin1 = iMin.iY;
  238.       if (iTextOut->findText((char*)iFindModel->iText.PtrZ(), iTop, gTrue, &iXMin1, &iYMin1, &iXMax1, &iYMax1,
  239.                              (iFindModel->iFlags & EFindCaseSensitive) ? gTrue : gFalse))
  240.         iState = EFound;
  241.       else if (iNumSeen < iDoc->getNumPages()) {
  242.         iTop = gTrue;
  243.         iPg = iPage + 1;
  244.         iState = ENextPage;
  245.         return EFalse;
  246.       }
  247.       else
  248.         iState = ENotFound;
  249.       break;
  250.  
  251.     case ENextPage: // search following pages
  252.       if (iPg > iDoc->getNumPages()) {
  253.         iTop = gTrue;
  254.         iState = EPrevPage;
  255.         iPg = 1;
  256.       }
  257.       else {
  258.         iActivePage->StartRenderingL(iTextOut, iDoc, iPg, 72, 0);
  259.         if (iObserver)
  260.           iObserver->NotifyPage(iPg);
  261.         iNumSeen++;
  262.         iState = EDisplayingNextPage;
  263.         return ETrue;
  264.       }
  265.       break;
  266.  
  267.     case EDisplayingNextPage:
  268.       if (iTextOut->findText((char*)iFindModel->iText.PtrZ(), gTrue, gTrue, &iXMin1, &iYMin1, &iXMax1, &iYMax1,
  269.                              (iFindModel->iFlags & EFindCaseSensitive)?gTrue:gFalse))
  270.         iState = EFoundPage;
  271.       else {
  272.         iPg++;
  273.         iState = ENextPage;
  274.         return EFalse;
  275.       }
  276.       break;
  277.  
  278.     case EPrevPage: // search previous pages
  279.       if (iPg >= iStartPage)
  280.         iState = EStopAtSelection;
  281.       else {
  282.         iActivePage->StartRenderingL(iTextOut, iDoc, iPg, 72, 0);
  283.         if (iObserver)
  284.           iObserver->NotifyPage(iPg);
  285.         iNumSeen++;
  286.         iState = EDisplayingPrevPage;
  287.         return ETrue;
  288.       }
  289.       break;
  290.  
  291.     case EDisplayingPrevPage:
  292.       if (iTextOut->findText((char*)iFindModel->iText.PtrZ(), gTrue, gTrue, &iXMin1, &iYMin1, &iXMax1, &iYMax1,
  293.                              (iFindModel->iFlags & EFindCaseSensitive)?gTrue:gFalse))
  294.         iState = EFoundPage;
  295.       else {
  296.         iPg++;
  297.         iState = EPrevPage;
  298.         return EFalse;
  299.       }
  300.       break;
  301.  
  302.     case EStopAtSelection: // search current page ending at current selection
  303.       if (iSelection.iTl.iX < iSelection.iBr.iX && iSelection.iTl.iY < iSelection.iBr.iY) {
  304.         iMax.iX = iSelection.iTl.iX;
  305.         iMax.iY = (iSelection.iTl.iY + iSelection.iBr.iY) / 2;
  306.         if (iTextOut->findText((char*)iFindModel->iText.PtrZ(), gTrue, gFalse, &iXMin1, &iYMin1, &iXMax1, &iYMax1,
  307.                                (iFindModel->iFlags & EFindCaseSensitive)?gTrue:gFalse))
  308.           iState = EFound;
  309.         else
  310.           iState = ENotFound;
  311.       }
  312.       else
  313.         iState = ENotFound;
  314.       break;
  315.  
  316.     case ENotFound:
  317.       CancelSearch();
  318.       delete iTextOut;
  319.       iTextOut = 0;
  320.       iState = EDone;
  321.       if (iObserver)
  322.         iObserver->NotifyError(KErrCancel);
  323.       return ETrue;
  324.  
  325.     case EFoundPage: // found on a different page, which becomes the current page
  326.       iPage = iPg;
  327.       iState = EFound;
  328.       break;
  329.  
  330.     case EFound: // found: change the selection
  331.       CancelSearch();
  332.       iFound = ETrue;
  333.       iSelection = TRect(round(iXMin1), round(iYMin1), round(iXMax1), round(iYMax1));
  334.       iState = EStartAtSelection;
  335.       if (iObserver)
  336.         iObserver->NotifyFound();
  337.       return ETrue;
  338.  
  339.     case EDone:
  340.       return ETrue;
  341.  
  342.     } // switch
  343.   } // for
  344.  
  345.  
  346. void CSearchState::CancelSearch()
  347. {
  348.   if (iActivePage) {
  349.     iActivePage->Cancel();
  350.     delete iActivePage;
  351.     iActivePage = 0;
  352.   }
  353. }
  354.  
  355. TRect CSearchState::Selection() const
  356. {
  357.   TReal selXMin, selYMin;
  358.   iTextOut->cvtDevToUser(iSelection.iTl.iX, iSelection.iTl.iY, &selXMin, &selYMin);
  359.  
  360.   TReal selXMax, selYMax;
  361.   iTextOut->cvtDevToUser(iSelection.iBr.iX, iSelection.iBr.iY, &selXMax, &selYMax);
  362.  
  363.   TRect res(round(KTwipsPerPoint*selXMin), round(KTwipsPerPoint*selYMin), 
  364.             round(KTwipsPerPoint*selXMax), round(KTwipsPerPoint*selYMax));
  365.   res.Normalize();
  366.  
  367.   return res;
  368. }