wxIScan
wxiscanframe.cpp
Go to the documentation of this file.
00001 /*************************************************************
00002  * Name:      wxiscanframe.cpp
00003  * Purpose:   Code for application frame (the main) window
00004  * Author:    Daniel Nell (daniel.nell@nellresearch.de)
00005  * Created:   2008-05-04
00006  * Copyright: Daniel Nell (www.nellresearch.de)
00007  * License:   GPL
00008  **************************************************************/
00009 
00010 // Include precompiled headers.
00011 #include "wx_pch.h"
00012 
00013 //(*InternalHeaders(wxIScanFrame)
00014 #include <wx/string.h>
00015 #include <wx/intl.h>
00016 #include <wx/bitmap.h>
00017 #include <wx/icon.h>
00018 #include <wx/image.h>
00019 #include <wx/artprov.h>
00020 //*)
00021 
00022 // wxWidgets headers
00023 #include <wx/accel.h>
00024 #include <wx/clipbrd.h>
00025 #include <wx/config.h>
00026 #include <wx/fileconf.h>
00027 #include <wx/filename.h>
00028 #if __WXPDFDOC__
00029 #   include <wx/pdfdoc.h>
00030 #endif // __WXPDFDOC__
00031 #include <wx/print.h>
00032 #include <wx/printdlg.h>
00033 #if __DEBUG__
00034 #   include <wx/stdpaths.h>
00035 #endif // __DEBUG__
00036 #include <wx/txtstrm.h>
00037 
00038 // Private headers
00039 #include "wxextprocess.h"
00040 #include "wxiscanabout.h"
00041 #include "wxiscanapp.h"
00042 #include "wxiscanframe.h"
00043 #include "wxiscanglobals.h"
00044 #if __WXLUASCRIPT__
00045 #   include "wxiscanluascript.h"
00046 #endif // __WXLUASCRIPT__
00047 #include "wxiscanresources.h"
00048 #include "wxchainlogtextctrl.h"
00049 #include "wxiviewprintout.h"
00050 #include "wxoptionsdialog.h"
00051 #include "wxtextctrlcolourizer.h"
00052 
00053 #if __WXLUASCRIPT__
00054 // Include Lua header file(s).
00055 #   include "lua5.1/lua.hpp"
00056 #endif // WXLUASCRIPT__
00057 
00058 // Resources
00059 //}
00060 
00061 //(*IdInit(wxIScanFrame)
00062 const long wxIScanFrame::ID_CANVAS = wxNewId();
00063 const long wxIScanFrame::ID_PAGES = wxNewId();
00064 const long wxIScanFrame::ID_VSPLITTERWINDOW = wxNewId();
00065 const long wxIScanFrame::ID_LOGTEXTCTRL = wxNewId();
00066 const long wxIScanFrame::ID_HSPLITTERWINDOW = wxNewId();
00067 const long wxIScanFrame::ID_FILESCANIMAGE = wxNewId();
00068 const long wxIScanFrame::ID_FILEOPEN = wxNewId();
00069 const long wxIScanFrame::ID_FILESAVEAS = wxNewId();
00070 const long wxIScanFrame::ID_FILEPRINT = wxNewId();
00071 const long wxIScanFrame::ID_FILEPRINTPREVIEW = wxNewId();
00072 const long wxIScanFrame::ID_FILEPRINTSETUP = wxNewId();
00073 const long wxIScanFrame::ID_FILEQUIT = wxNewId();
00074 const long wxIScanFrame::ID_EDITCOPY = wxNewId();
00075 const long wxIScanFrame::ID_EDITPASTE = wxNewId();
00076 const long wxIScanFrame::ID_EDITSETTINGS = wxNewId();
00077 const long wxIScanFrame::ID_EDITSETTINGSFILE = wxNewId();
00078 const long wxIScanFrame::ID_EDITSCANSCANNERS = wxNewId();
00079 const long wxIScanFrame::ID_EDITCLEARLOG = wxNewId();
00080 const long wxIScanFrame::ID_EDITCLEARHISTORY = wxNewId();
00081 const long wxIScanFrame::ID_VIEWFULLSCREEN = wxNewId();
00082 const long wxIScanFrame::ID_VIEWFITWIDTH = wxNewId();
00083 const long wxIScanFrame::ID_VIEWFITWINDOW = wxNewId();
00084 const long wxIScanFrame::ID_VIEWFULLSIZE = wxNewId();
00085 const long wxIScanFrame::ID_VIEWCUSTOMSIZE = wxNewId();
00086 const long wxIScanFrame::ID_VIEWZOOMIN = wxNewId();
00087 const long wxIScanFrame::ID_VIEWZOOMOUT = wxNewId();
00088 const long wxIScanFrame::ID_VIEWZOOMSELECTION = wxNewId();
00089 const long wxIScanFrame::ID_VIEWCLOSEDEBUGWINDOW = wxNewId();
00090 const long wxIScanFrame::ID_VIEWCLOSEPREVIEWPANEL = wxNewId();
00091 const long wxIScanFrame::ID_DOCUMENTCOPYTEXT = wxNewId();
00092 const long wxIScanFrame::ID_DOCUMENTREADTEXT = wxNewId();
00093 const long wxIScanFrame::ID_CMDSTOP = wxNewId();
00094 const long wxIScanFrame::ID_DOCUMENTFIRSTPAGE = wxNewId();
00095 const long wxIScanFrame::ID_DOCUMENTPREVIOUSPAGE = wxNewId();
00096 const long wxIScanFrame::ID_DOCUMENTNEXTPAGE = wxNewId();
00097 const long wxIScanFrame::ID_DOCUMENTLASTPAGE = wxNewId();
00098 const long wxIScanFrame::ID_DOCUMENTROTATE90LEFT = wxNewId();
00099 const long wxIScanFrame::ID_DOCUMENTROTATE90RIGHT = wxNewId();
00100 const long wxIScanFrame::ID_DOCUMENTCROP = wxNewId();
00101 const long wxIScanFrame::ID_DOCUMENTAPPLYPROFILE = wxNewId();
00102 const long wxIScanFrame::ID_MENUDOCUMENTPROFILES = wxNewId();
00103 const long wxIScanFrame::ID_PDFBEGINPDF = wxNewId();
00104 const long wxIScanFrame::ID_PDFADDPAGE = wxNewId();
00105 const long wxIScanFrame::ID_PDFSAVEASPDF = wxNewId();
00106 const long wxIScanFrame::ID_HELPABOUT = wxNewId();
00107 const long wxIScanFrame::ID_FILESCANIMAGE_TB = wxNewId();
00108 const long wxIScanFrame::ID_FILEOPEN_TB = wxNewId();
00109 const long wxIScanFrame::ID_FILESAVEAS_TB = wxNewId();
00110 const long wxIScanFrame::ID_FILEPRINT_TB = wxNewId();
00111 const long wxIScanFrame::ID_PDFBEGINPDF_TB = wxNewId();
00112 const long wxIScanFrame::ID_PDFADDPAGE_TB = wxNewId();
00113 const long wxIScanFrame::ID_PDFSAVEASPDF_TB = wxNewId();
00114 const long wxIScanFrame::ID_DOCUMENTFIRSTPAGE_TB = wxNewId();
00115 const long wxIScanFrame::ID_DOCUMENTPREVIOUSPAGE_TB = wxNewId();
00116 const long wxIScanFrame::ID_DOCUMENTNEXTPAGE_TB = wxNewId();
00117 const long wxIScanFrame::ID_DOCUMENTLASTPAGE_TB = wxNewId();
00118 const long wxIScanFrame::ID_DOCUMENTREADTEXT_TB = wxNewId();
00119 const long wxIScanFrame::ID_CMDSTOP_TB = wxNewId();
00120 //*)
00121 #if __WXLUASCRIPT__
00122 const long wxIScanFrame::ID_DOCUMENTREADTEXTSYNC= wxNewId();
00123 #endif // __WXLUASCRIPT__
00124 const long wxIScanFrame::ID_TEXTCTRLPAGE= wxNewId();
00125 #ifdef __WXSCANSANE__
00126 const long wxIScanFrame::ID_CHOICESCANNER= wxNewId();
00127 #endif // __WXSCANSANE__
00128 const long wxIScanFrame::ID_DOCUMENTPROFILE0= wxNewId();
00129 
00130 
00131 //////////////////////////////////////////////////////////
00132 // Strings and other (global) constants
00133 //
00134 static const wxString cstrwxFrame= wxT( "wxIScanFrame" );
00135 
00136 
00137 //////////////////////////////////////////////////////////
00138 // Class wxIScanFrame
00139 //
00140 // Event table
00141 //
00142 BEGIN_EVENT_TABLE( wxIScanFrame, wxFrame )
00143     //(*EventTable(wxIScanFrame)
00144     //*)
00145     // File history handling.
00146     EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, wxIScanFrame::OnMRUFiles )
00147 #if __WXLUASCRIPT__
00148     EVT_MENU_RANGE( ID_DOCUMENTPROFILE0 + 1000, ID_DOCUMENTPROFILE0 + 1999, wxIScanFrame::OnScriptStartScript )
00149     EVT_MENU( ID_DOCUMENTREADTEXTSYNC, wxIScanFrame::OnDocumentReadText )
00150 #endif // __WXLUASCRIPT__
00151     // File drop event
00152     EVT_EXTFILEDROP( wxIScanFrame::OnFileDrop )
00153     // Handle canvas size changes.
00154     EVT_IVIEWCANVASSIZE( wxIScanFrame::OnCanvasSize )
00155     // Handle canvas selection changes.
00156     EVT_IVIEWCANVASSELECTED( wxIScanFrame::OnCanvasSelected )
00157     // Handle process events.
00158     EVT_END_PROCESS( wxISCAN_PROCESS, wxIScanFrame::OnProcessTerminated )
00159     // Handle page number editor field events.
00160     EVT_TEXT_ENTER( ID_TEXTCTRLPAGE, wxIScanFrame::OnTextCtrlPageProcessEnter )
00161 #ifdef __WXSCANSANE__
00162     // Handle thread events.
00163     EVT_MENU( wxExtThread::ID_EXIT, wxIScanFrame::OnThreadExit )
00164 #endif // __WXSCANSANE__
00165 END_EVENT_TABLE()
00166 
00167 
00168 // Standard constructor.
00169 //
00170 wxIScanFrame::wxIScanFrame( wxWindow* parent, wxWindowID id )
00171   :
00172   m_bUILocked( false ),
00173   m_poScanner( NULL ),
00174   m_nScaleFactor( 1.0 ),
00175   m_nZoomFactor( 0.1 ),
00176   m_nProfileIndex( 0 ),
00177 #if __WXPDFDOC__
00178   m_poPdfDoc( NULL ),
00179   m_nPdfPages( 0 ),
00180   m_bPdfDirty( false ),
00181 #endif
00182 #if __WXLUASCRIPT__
00183   bLuaReturnFromEventHandler( true ),
00184 #endif // __WXLUASCRIPT__
00185   m_poRunningProcess( NULL ),
00186   m_oTextValidatorTextCtrlPage( wxFILTER_NUMERIC )
00187 {
00188     //(*Initialize(wxIScanFrame)
00189     wxMenuItem* poOnDocumentZoom;
00190     wxMenu* poMenuHelp;
00191     wxMenuItem* poMenuSavePdf;
00192     wxMenuItem* poViewCustomSize;
00193     wxMenuItem* poDocumentRotate90Left;
00194     wxMenuItem* poViewZoomOut;
00195     wxMenuItem* poMenuFileOpen;
00196     wxMenuItem* poMenuFileSaveAs;
00197     wxMenuItem* poHelpAbout;
00198     wxMenuItem* poMenuCmdStop;
00199     wxMenuItem* poFileQuit;
00200     wxMenuItem* poMenuPdfBeginPdf;
00201     wxMenuItem* poMenuFileScanImage;
00202     wxMenuItem* poViewFitWidth;
00203     wxMenuItem* poMenuDocumentPreviousPage;
00204     wxMenuItem* poEditSettingsFile;
00205     wxMenuItem* poMenuFilePrint;
00206     wxMenuItem* poViewFullSize;
00207     wxMenuItem* poOnDocumentCrop;
00208     wxMenuItem* poEditClearHistory;
00209     wxMenu* poMenuDocument;
00210     wxMenuItem* poMenuFilePrintPreview;
00211     wxStatusBar* poStatusBar;
00212     wxMenuItem* poViewClosePreviewPanel;
00213     wxMenuItem* poMenuDocumentLastPage;
00214     wxMenuItem* poMenuDocumentReadText;
00215     wxMenuItem* poViewFullScreen;
00216     wxMenuItem* poViewFitWindow;
00217     wxMenuItem* poMenuPdfAddPage;
00218     wxMenuItem* poViewZoomIn;
00219     wxMenuItem* poEditSettings;
00220     wxToolBar* poToolBar;
00221     wxMenu* poMenuDocumentProfiles;
00222     wxMenuItem* poViewCloseDebugWindow;
00223     wxMenuItem* poDocumentApplyProfile;
00224     wxMenuItem* poMenuDocumentCopyText;
00225     wxMenuItem* poEditCopy;
00226     wxMenu* poMenuFile;
00227     wxMenu* poMenuPdf;
00228     wxMenuBar* poMenuBar;
00229     wxMenu* poView;
00230     wxMenuItem* poMenuFilePrintSetup;
00231     wxMenuItem* poEditPaste;
00232     wxMenuItem* poEditClearLog;
00233     wxMenuItem* poDocumentRotate90Right;
00234     wxMenuItem* poMenuDocumentFirstPage;
00235     wxMenuItem* poEditScanScanners;
00236     wxMenuItem* poMenuDocumentNextPage;
00237 
00238     Create(parent, wxID_ANY, _("wxIScan"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("wxID_ANY"));
00239     {
00240         wxIcon FrameIcon;
00241         FrameIcon.CopyFromBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_NORMAL_FILE")),wxART_FRAME_ICON));
00242         SetIcon(FrameIcon);
00243     }
00244     m_poHSplitterWindow = new wxSplitterWindow(this, ID_HSPLITTERWINDOW, wxDefaultPosition, wxDefaultSize, wxSP_3D|wxSP_LIVE_UPDATE, _T("ID_HSPLITTERWINDOW"));
00245     m_poHSplitterWindow->SetMinSize(wxSize(1,1));
00246     m_poHSplitterWindow->SetMinimumPaneSize(1);
00247     m_poHSplitterWindow->SetSashGravity(0);
00248     m_poVSplitterWindow = new wxSplitterWindow(m_poHSplitterWindow, ID_VSPLITTERWINDOW, wxDefaultPosition, wxDefaultSize, wxSP_3D|wxSP_LIVE_UPDATE, _T("ID_VSPLITTERWINDOW"));
00249     m_poVSplitterWindow->SetMinSize(wxSize(1,1));
00250     m_poVSplitterWindow->SetMinimumPaneSize(1);
00251     m_poVSplitterWindow->SetSashGravity(0);
00252     m_poCanvas = new wxIViewCanvas(m_poVSplitterWindow, ID_CANVAS, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxVSCROLL|wxHSCROLL, _T("ID_CANVAS"));
00253     m_poPanelPages = new wxImagePanel(m_poVSplitterWindow, ID_PAGES, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxVSCROLL|wxHSCROLL, _T("ID_PAGES"));
00254     m_poVSplitterWindow->SplitVertically(m_poCanvas, m_poPanelPages);
00255     m_poVSplitterWindow->SetSashPosition(1);
00256     m_poLogTextCtrl = new wxTextCtrl(m_poHSplitterWindow, ID_LOGTEXTCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH|wxTE_AUTO_URL|wxTE_DONTWRAP, wxDefaultValidator, _T("ID_LOGTEXTCTRL"));
00257     m_poHSplitterWindow->SplitHorizontally(m_poVSplitterWindow, m_poLogTextCtrl);
00258     m_poHSplitterWindow->SetSashPosition(250);
00259     poMenuBar = new wxMenuBar();
00260     poMenuFile = new wxMenu();
00261     poMenuFileScanImage = new wxMenuItem(poMenuFile, ID_FILESCANIMAGE, _("Scan &Image\tCtrl+I"), _("Scan an image"), wxITEM_NORMAL);
00262     poMenuFile->Append(poMenuFileScanImage);
00263     poMenuFileScanImage= poMenuFile->Remove( ID_FILESCANIMAGE );
00264     poMenuFileScanImage->SetBitmap( filescanimagebmp_xpm );
00265     poMenuFile->Append( poMenuFileScanImage );
00266     poMenuFile->AppendSeparator();
00267     poMenuFileOpen = new wxMenuItem(poMenuFile, ID_FILEOPEN, _("&Open...\tCtrl+O"), _("Open an image file."), wxITEM_NORMAL);
00268     poMenuFileOpen->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_OPEN")),wxART_MENU));
00269     poMenuFile->Append(poMenuFileOpen);
00270     poMenuFileSaveAs = new wxMenuItem(poMenuFile, ID_FILESAVEAS, _("Save &as...\tCtrl+S"), _("Save scanned image to file."), wxITEM_NORMAL);
00271     poMenuFileSaveAs->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_SAVE_AS")),wxART_MENU));
00272     poMenuFile->Append(poMenuFileSaveAs);
00273     poMenuFileSaveAs->Enable(false);
00274     poMenuFile->AppendSeparator();
00275     poMenuFilePrint = new wxMenuItem(poMenuFile, ID_FILEPRINT, _("&Print...\tCtrl+P"), _("Print the current image."), wxITEM_NORMAL);
00276     poMenuFilePrint->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_PRINT")),wxART_MENU));
00277     poMenuFile->Append(poMenuFilePrint);
00278     poMenuFilePrint->Enable(false);
00279     poMenuFilePrintPreview = new wxMenuItem(poMenuFile, ID_FILEPRINTPREVIEW, _("Print pre&view\tCtrl+Alt+P"), _("Show a print preview of the current image."), wxITEM_NORMAL);
00280     poMenuFile->Append(poMenuFilePrintPreview);
00281     poMenuFilePrintPreview->Enable(false);
00282     poMenuFilePrintPreview= poMenuFile->Remove( ID_FILEPRINTPREVIEW );
00283     poMenuFilePrintPreview->SetBitmap( fileprintpreviewbmp_xpm );
00284     poMenuFile->Append( poMenuFilePrintPreview );
00285     poMenuFilePrintSetup = new wxMenuItem(poMenuFile, ID_FILEPRINTSETUP, _("Page setup"), _("Show page setup dialog."), wxITEM_NORMAL);
00286     poMenuFile->Append(poMenuFilePrintSetup);
00287     poMenuFilePrintSetup= poMenuFile->Remove( ID_FILEPRINTSETUP );
00288     poMenuFilePrintSetup->SetBitmap( fileprintsetupbmp_xpm );
00289     poMenuFile->Append( poMenuFilePrintSetup );
00290     poMenuFile->AppendSeparator();
00291     poFileQuit = new wxMenuItem(poMenuFile, ID_FILEQUIT, _("&Quit\tCtrl+Q"), _("Quit the application"), wxITEM_NORMAL);
00292     poFileQuit->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_QUIT")),wxART_MENU));
00293     poMenuFile->Append(poFileQuit);
00294     poMenuBar->Append(poMenuFile, _("&File"));
00295     poMenuEdit = new wxMenu();
00296     poEditCopy = new wxMenuItem(poMenuEdit, ID_EDITCOPY, _("&Copy\tCtrl+C"), _("Copy image to clipboard"), wxITEM_NORMAL);
00297     poEditCopy->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_COPY")),wxART_MENU));
00298     poMenuEdit->Append(poEditCopy);
00299     poEditCopy->Enable(false);
00300     poEditPaste = new wxMenuItem(poMenuEdit, ID_EDITPASTE, _("&Paste\tCtrl-V"), _("Inserts the content of the clipboard."), wxITEM_NORMAL);
00301     poEditPaste->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_PASTE")),wxART_TOOLBAR));
00302     poMenuEdit->Append(poEditPaste);
00303     poMenuEdit->AppendSeparator();
00304     poEditSettings = new wxMenuItem(poMenuEdit, ID_EDITSETTINGS, _("&Settings...\tCtrl-Alt-O"), _("Edit (most) settings in a dialog window."), wxITEM_NORMAL);
00305     poEditSettings->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_EXECUTABLE_FILE")),wxART_MENU));
00306     poMenuEdit->Append(poEditSettings);
00307     poEditSettingsFile = new wxMenuItem(poMenuEdit, ID_EDITSETTINGSFILE, _("Edit settings &file"), _("Edit settings file in a text editor."), wxITEM_NORMAL);
00308     poEditSettingsFile->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_HELP_SETTINGS")),wxART_MENU));
00309     poMenuEdit->Append(poEditSettingsFile);
00310     poMenuEdit->AppendSeparator();
00311     poEditScanScanners = new wxMenuItem(poMenuEdit, ID_EDITSCANSCANNERS, _("Scan for scanne&rs\tF4"), _("Scan for available scanning devices (USB, network etc.)."), wxITEM_NORMAL);
00312     poMenuEdit->Append(poEditScanScanners);
00313     poEditScanScanners= poMenuEdit->Remove( ID_EDITSCANSCANNERS );
00314     poEditScanScanners->SetBitmap( filescanimagebmp_xpm );
00315     poMenuEdit->Append( poEditScanScanners );
00316     poMenuEdit->AppendSeparator();
00317     poEditClearLog = new wxMenuItem(poMenuEdit, ID_EDITCLEARLOG, _("Clear &log\tF5"), _("Clear log window."), wxITEM_NORMAL);
00318     poEditClearLog->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_MENU));
00319     poMenuEdit->Append(poEditClearLog);
00320     poEditClearHistory = new wxMenuItem(poMenuEdit, ID_EDITCLEARHISTORY, _("Clear file &history"), _("Clear the file history."), wxITEM_NORMAL);
00321     poEditClearHistory->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DEL_BOOKMARK")),wxART_MENU));
00322     poMenuEdit->Append(poEditClearHistory);
00323     poMenuBar->Append(poMenuEdit, _("&Edit"));
00324     poView = new wxMenu();
00325     poViewFullScreen = new wxMenuItem(poView, ID_VIEWFULLSCREEN, _("&Full screen\tF12"), _("View in full screen mode (no frame, no caption etc.)"), wxITEM_CHECK);
00326     poView->Append(poViewFullScreen);
00327     poView->AppendSeparator();
00328     poViewFitWidth = new wxMenuItem(poView, ID_VIEWFITWIDTH, _("Fit image to window w&idth\tI"), _("Zoom image to fit the window width."), wxITEM_CHECK);
00329     poView->Append(poViewFitWidth);
00330     poViewFitWindow = new wxMenuItem(poView, ID_VIEWFITWINDOW, _("Fit image to &window\tW"), _("Zoom image to fit the window size."), wxITEM_CHECK);
00331     poView->Append(poViewFitWindow);
00332     poViewFullSize = new wxMenuItem(poView, ID_VIEWFULLSIZE, _("View image in &original size\tO"), _("Show image in its original size (without any zooming)."), wxITEM_CHECK);
00333     poView->Append(poViewFullSize);
00334     poViewCustomSize = new wxMenuItem(poView, ID_VIEWCUSTOMSIZE, _("View image in &custom size\tC"), _("Zoom image to an explicit given (fixed) zoom factor."), wxITEM_CHECK);
00335     poView->Append(poViewCustomSize);
00336     poView->AppendSeparator();
00337     poViewZoomIn = new wxMenuItem(poView, ID_VIEWZOOMIN, _("Zoom &in\t+"), _("Zoom into the image."), wxITEM_NORMAL);
00338     poView->Append(poViewZoomIn);
00339     poViewZoomOut = new wxMenuItem(poView, ID_VIEWZOOMOUT, _("Zoom &out\t-"), _("Zoom out of the image."), wxITEM_NORMAL);
00340     poView->Append(poViewZoomOut);
00341     poOnDocumentZoom = new wxMenuItem(poView, ID_VIEWZOOMSELECTION, _("&Zoom selection\tZ"), _("Zoom the image along selection rectangle."), wxITEM_NORMAL);
00342     poView->Append(poOnDocumentZoom);
00343     poOnDocumentZoom->Enable(false);
00344     poView->AppendSeparator();
00345     poViewCloseDebugWindow = new wxMenuItem(poView, ID_VIEWCLOSEDEBUGWINDOW, _("Close the &debug window\tF2"), _("Close the debug window."), wxITEM_NORMAL);
00346     poView->Append(poViewCloseDebugWindow);
00347     poViewClosePreviewPanel = new wxMenuItem(poView, ID_VIEWCLOSEPREVIEWPANEL, _("Close the preview &panel\tF3"), _("Close the PDF preview panel."), wxITEM_NORMAL);
00348     poView->Append(poViewClosePreviewPanel);
00349     poMenuBar->Append(poView, _("&View"));
00350     poMenuDocument = new wxMenu();
00351     poMenuDocumentCopyText = new wxMenuItem(poMenuDocument, ID_DOCUMENTCOPYTEXT, _("Copy &text\tCtrl-Alt-C"), _("Copies via OCR detected text to the clipboard."), wxITEM_NORMAL);
00352     poMenuDocumentCopyText->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_COPY")),wxART_MENU));
00353     poMenuDocument->Append(poMenuDocumentCopyText);
00354     poMenuDocumentCopyText->Enable(false);
00355     poMenuDocumentReadText = new wxMenuItem(poMenuDocument, ID_DOCUMENTREADTEXT, _("&Read out document\tCtrl+Alt+R"), _("Reads the document through TTS."), wxITEM_NORMAL);
00356     poMenuDocument->Append(poMenuDocumentReadText);
00357     poMenuDocumentReadText->Enable(false);
00358     poMenuDocumentReadText= poMenuDocument->Remove( ID_DOCUMENTREADTEXT );
00359     poMenuDocumentReadText->SetBitmap( documentreadtext_xpm );
00360     poMenuDocument->Append( poMenuDocumentReadText );
00361     poMenuCmdStop = new wxMenuItem(poMenuDocument, ID_CMDSTOP, _("&Stop\tCtrl-Alt-E"), _("Stop background action."), wxITEM_NORMAL);
00362     poMenuDocument->Append(poMenuCmdStop);
00363     poMenuCmdStop->Enable(false);
00364     poMenuCmdStop= poMenuDocument->Remove( ID_CMDSTOP );
00365     poMenuCmdStop->SetBitmap( cmdstop_xpm );
00366     poMenuDocument->Append( poMenuCmdStop );
00367     poMenuDocument->AppendSeparator();
00368     poMenuDocumentFirstPage = new wxMenuItem(poMenuDocument, ID_DOCUMENTFIRSTPAGE, _("&First page\tCtrl+Home"), _("Go to first document page."), wxITEM_NORMAL);
00369     poMenuDocument->Append(poMenuDocumentFirstPage);
00370     poMenuDocumentFirstPage->Enable(false);
00371     poMenuDocumentFirstPage= poMenuDocument->Remove( ID_DOCUMENTFIRSTPAGE );
00372     poMenuDocumentFirstPage->SetBitmap( documentfirstpage_xpm );
00373     poMenuDocument->Append( poMenuDocumentFirstPage );
00374     poMenuDocumentPreviousPage = new wxMenuItem(poMenuDocument, ID_DOCUMENTPREVIOUSPAGE, _("&Previous page\tCtrl+PageUp"), _("Go to previous document page."), wxITEM_NORMAL);
00375     poMenuDocument->Append(poMenuDocumentPreviousPage);
00376     poMenuDocumentPreviousPage->Enable(false);
00377     poMenuDocumentPreviousPage= poMenuDocument->Remove( ID_DOCUMENTPREVIOUSPAGE );
00378     poMenuDocumentPreviousPage->SetBitmap( documentpreviouspage_xpm );
00379     poMenuDocument->Append( poMenuDocumentPreviousPage );
00380     poMenuDocumentNextPage = new wxMenuItem(poMenuDocument, ID_DOCUMENTNEXTPAGE, _("&Next page\tCtrl+PageDown"), _("Go to next document page."), wxITEM_NORMAL);
00381     poMenuDocument->Append(poMenuDocumentNextPage);
00382     poMenuDocumentNextPage->Enable(false);
00383     poMenuDocumentNextPage= poMenuDocument->Remove( ID_DOCUMENTNEXTPAGE );
00384     poMenuDocumentNextPage->SetBitmap( documentnextpage_xpm );
00385     poMenuDocument->Append( poMenuDocumentNextPage );
00386     poMenuDocumentLastPage = new wxMenuItem(poMenuDocument, ID_DOCUMENTLASTPAGE, _("&Last page\tCtrl+End"), _("Go to last document page."), wxITEM_NORMAL);
00387     poMenuDocument->Append(poMenuDocumentLastPage);
00388     poMenuDocumentLastPage->Enable(false);
00389     poMenuDocumentLastPage= poMenuDocument->Remove( ID_DOCUMENTLASTPAGE );
00390     poMenuDocumentLastPage->SetBitmap( documentlastpage_xpm );
00391     poMenuDocument->Append( poMenuDocumentLastPage );
00392     poMenuDocument->AppendSeparator();
00393     poDocumentRotate90Left = new wxMenuItem(poMenuDocument, ID_DOCUMENTROTATE90LEFT, _("Rotate 90 degress &left\tL"), _("Rotate 90 degress left"), wxITEM_NORMAL);
00394     poDocumentRotate90Left->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_UNDO")),wxART_MENU));
00395     poMenuDocument->Append(poDocumentRotate90Left);
00396     poDocumentRotate90Left->Enable(false);
00397     poDocumentRotate90Right = new wxMenuItem(poMenuDocument, ID_DOCUMENTROTATE90RIGHT, _("Rotate 90 degress &right\tR"), _("Rotate 90 degress right"), wxITEM_NORMAL);
00398     poDocumentRotate90Right->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_REDO")),wxART_MENU));
00399     poMenuDocument->Append(poDocumentRotate90Right);
00400     poDocumentRotate90Right->Enable(false);
00401     poOnDocumentCrop = new wxMenuItem(poMenuDocument, ID_DOCUMENTCROP, _("&Crop selection\tCtrl+Y"), _("Crop the image along selection rectangle."), wxITEM_NORMAL);
00402     poOnDocumentCrop->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_CUT")),wxART_MENU));
00403     poMenuDocument->Append(poOnDocumentCrop);
00404     poOnDocumentCrop->Enable(false);
00405     poMenuDocument->AppendSeparator();
00406     poDocumentApplyProfile = new wxMenuItem(poMenuDocument, ID_DOCUMENTAPPLYPROFILE, _("&Apply profile\tp"), _("Apply the current selected image profile to the image."), wxITEM_NORMAL);
00407     poMenuDocument->Append(poDocumentApplyProfile);
00408     poDocumentApplyProfile->Enable(false);
00409     poMenuDocumentProfiles = new wxMenu();
00410     poMenuDocumentProfiles->AppendSeparator();
00411     poMenuDocument->Append(ID_MENUDOCUMENTPROFILES, _("&Profiles"), poMenuDocumentProfiles, wxEmptyString);
00412     poMenuBar->Append(poMenuDocument, _("&Document"));
00413     poMenuPdf = new wxMenu();
00414     poMenuPdfBeginPdf = new wxMenuItem(poMenuPdf, ID_PDFBEGINPDF, _("&Begin PDF\tCtrl+Alt+N"), _("Start a new PDF document."), wxITEM_NORMAL);
00415     poMenuPdfBeginPdf->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_NEW")),wxART_MENU));
00416     poMenuPdf->Append(poMenuPdfBeginPdf);
00417     poMenuPdfBeginPdf->Enable(false);
00418     poMenuPdfAddPage = new wxMenuItem(poMenuPdf, ID_PDFADDPAGE, _("&Add Page\tCtrl++"), _("Add image as new page to the PDF document."), wxITEM_NORMAL);
00419     poMenuPdfAddPage->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_ADD_BOOKMARK")),wxART_MENU));
00420     poMenuPdf->Append(poMenuPdfAddPage);
00421     poMenuPdfAddPage->Enable(false);
00422     poMenuPdf->AppendSeparator();
00423     poMenuSavePdf = new wxMenuItem(poMenuPdf, ID_PDFSAVEASPDF, _("Save &PDF...\tCtrl+Shift+S"), _("Save image as PDF file."), wxITEM_NORMAL);
00424     poMenuSavePdf->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_SAVE")),wxART_MENU));
00425     poMenuPdf->Append(poMenuSavePdf);
00426     poMenuSavePdf->Enable(false);
00427     poMenuBar->Append(poMenuPdf, _("&PDF"));
00428     poMenuHelp = new wxMenu();
00429     poHelpAbout = new wxMenuItem(poMenuHelp, ID_HELPABOUT, _("&About\tCtrl-Alt-I"), _("Show info about this application"), wxITEM_NORMAL);
00430     poHelpAbout->SetBitmap(wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_INFORMATION")),wxART_MENU));
00431     poMenuHelp->Append(poHelpAbout);
00432     poMenuBar->Append(poMenuHelp, _("&Help"));
00433     SetMenuBar(poMenuBar);
00434     poStatusBar = new wxStatusBar(this, wxID_ANY, 0, _T("wxID_ANY"));
00435     int __wxStatusBarWidths_1[4] = { -3, 80, 80, -2 };
00436     int __wxStatusBarStyles_1[4] = { wxSB_FLAT, wxSB_FLAT, wxSB_FLAT, wxSB_FLAT };
00437     poStatusBar->SetFieldsCount(4,__wxStatusBarWidths_1);
00438     poStatusBar->SetStatusStyles(4,__wxStatusBarStyles_1);
00439     SetStatusBar(poStatusBar);
00440     poToolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_VERTICAL|wxNO_BORDER, _T("wxID_ANY"));
00441     ToolBarItem1 = poToolBar->AddTool(ID_FILESCANIMAGE_TB, _("Scan"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_MISSING_IMAGE")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Scan"), _("Scan an image"));
00442     poToolBar->AddSeparator();
00443     ToolBarItem2 = poToolBar->AddTool(ID_FILEOPEN_TB, _("Open"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_OPEN")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Open file"), _("Open an image file."));
00444     ToolBarItem3 = poToolBar->AddTool(ID_FILESAVEAS_TB, _("Save as"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_SAVE_AS")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Save as"), _("Save scanned image to file."));
00445     ToolBarItem4 = poToolBar->AddTool(ID_FILEPRINT_TB, _("Print"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_PRINT")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Print"), _("Print the current image."));
00446     poToolBar->AddSeparator();
00447     ToolBarItem5 = poToolBar->AddTool(ID_PDFBEGINPDF_TB, _("Begin PDF"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_NEW")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Begin PDF"), _("Start a new PDF document."));
00448     ToolBarItem6 = poToolBar->AddTool(ID_PDFADDPAGE_TB, _("Add Page"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_ADD_BOOKMARK")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Add PDF Page"), _("Add image as new page to the PDF document."));
00449     ToolBarItem7 = poToolBar->AddTool(ID_PDFSAVEASPDF_TB, _("Save PDF"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_SAVE_AS")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Save PDF"), _("Save image as PDF file."));
00450     poToolBar->AddSeparator();
00451     ToolBarItem8 = poToolBar->AddTool(ID_DOCUMENTFIRSTPAGE_TB, _("First page"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_GO_BACK")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("First page"), _("Go To first document page."));
00452     ToolBarItem9 = poToolBar->AddTool(ID_DOCUMENTPREVIOUSPAGE_TB, _("Previous page"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_GO_BACK")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Previous page"), _("Go to previous document page."));
00453     ToolBarItem10 = poToolBar->AddTool(ID_DOCUMENTNEXTPAGE_TB, _("Next page"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_GO_FORWARD")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Next page"), _("Go to next document page."));
00454     ToolBarItem11 = poToolBar->AddTool(ID_DOCUMENTLASTPAGE_TB, _("Last page"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_GO_FORWARD")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Last page"), _("Go to last document page."));
00455     poToolBar->AddSeparator();
00456     ToolBarItem12 = poToolBar->AddTool(ID_DOCUMENTREADTEXT_TB, _("Read out"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_HELP_BOOK")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Read out document via TTS."), _("Read out document via text-to-speach system."));
00457     ToolBarItem13 = poToolBar->AddTool(ID_CMDSTOP_TB, _("Stop"), wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_ERROR")),wxART_TOOLBAR), wxNullBitmap, wxITEM_NORMAL, _("Stop background action."), _("Stop background action."));
00458     poToolBar->Realize();
00459     SetToolBar(poToolBar);
00460 
00461     Connect(ID_FILESCANIMAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFileScanImage);
00462     Connect(ID_FILEOPEN,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFileOpen);
00463     Connect(ID_FILESAVEAS,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFileSaveAs);
00464     Connect(ID_FILEPRINT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFilePrint);
00465     Connect(ID_FILEPRINTPREVIEW,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFilePrintPreview);
00466     Connect(ID_FILEPRINTSETUP,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFilePrintSetup);
00467     Connect(ID_FILEQUIT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnFileQuit);
00468     Connect(ID_EDITCOPY,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditCopy);
00469     Connect(ID_EDITPASTE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditPaste);
00470     Connect(ID_EDITSETTINGS,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditSettings);
00471     Connect(ID_EDITSETTINGSFILE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditSettingsFile);
00472     Connect(ID_EDITSCANSCANNERS,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditScanScanners);
00473     Connect(ID_EDITCLEARLOG,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditClearLog);
00474     Connect(ID_EDITCLEARHISTORY,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnEditClearHistory);
00475     Connect(ID_VIEWFULLSCREEN,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFullScreen);
00476     Connect(ID_VIEWFITWIDTH,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00477     Connect(ID_VIEWFITWINDOW,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00478     Connect(ID_VIEWFULLSIZE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00479     Connect(ID_VIEWCUSTOMSIZE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00480     Connect(ID_VIEWZOOMIN,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00481     Connect(ID_VIEWZOOMOUT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewFit);
00482     Connect(ID_VIEWZOOMSELECTION,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentZoom);
00483     Connect(ID_VIEWCLOSEDEBUGWINDOW,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewCloseDebugWindow);
00484     Connect(ID_VIEWCLOSEPREVIEWPANEL,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnViewClosePreviewPanel);
00485     Connect(ID_DOCUMENTCOPYTEXT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentCopyText);
00486     Connect(ID_DOCUMENTREADTEXT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentReadText);
00487     Connect(ID_CMDSTOP,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnCmdStop);
00488     Connect(ID_DOCUMENTFIRSTPAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentFirstPage);
00489     Connect(ID_DOCUMENTPREVIOUSPAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentPreviousPage);
00490     Connect(ID_DOCUMENTNEXTPAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentNextPage);
00491     Connect(ID_DOCUMENTLASTPAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentLastPage);
00492     Connect(ID_DOCUMENTROTATE90LEFT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentRotate90Left);
00493     Connect(ID_DOCUMENTROTATE90RIGHT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentRotate90Right);
00494     Connect(ID_DOCUMENTCROP,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentCrop);
00495     Connect(ID_DOCUMENTAPPLYPROFILE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentApplyProfile);
00496     Connect(ID_PDFBEGINPDF,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnPdfBeginPdf);
00497     Connect(ID_PDFADDPAGE,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnPdfAddPage);
00498     Connect(ID_PDFSAVEASPDF,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnPdfSavePdf);
00499     Connect(ID_HELPABOUT,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&wxIScanFrame::OnHelpAbout);
00500     Connect(ID_FILESCANIMAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnFileScanImage);
00501     Connect(ID_FILEOPEN_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnFileOpen);
00502     Connect(ID_FILESAVEAS_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnFileSaveAs);
00503     Connect(ID_FILEPRINT_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnFilePrint);
00504     Connect(ID_PDFBEGINPDF_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnPdfBeginPdf);
00505     Connect(ID_PDFADDPAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnPdfAddPage);
00506     Connect(ID_PDFSAVEASPDF_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnPdfSavePdf);
00507     Connect(ID_DOCUMENTFIRSTPAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentFirstPage);
00508     Connect(ID_DOCUMENTPREVIOUSPAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentPreviousPage);
00509     Connect(ID_DOCUMENTNEXTPAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentNextPage);
00510     Connect(ID_DOCUMENTLASTPAGE_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentLastPage);
00511     Connect(ID_DOCUMENTREADTEXT_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnDocumentReadText);
00512     Connect(ID_CMDSTOP_TB,wxEVT_COMMAND_TOOL_CLICKED,(wxObjectEventFunction)&wxIScanFrame::OnCmdStop);
00513     Connect(wxID_ANY,wxEVT_CLOSE_WINDOW,(wxObjectEventFunction)&wxIScanFrame::OnClose);
00514     //*)
00515 
00516     // Custom tool bar icons.
00517     GetToolBar()->SetToolNormalBitmap( ID_CMDSTOP_TB,              wxBitmap( cmdstop_xpm              ) );
00518     GetToolBar()->SetToolNormalBitmap( ID_DOCUMENTREADTEXT_TB,     wxBitmap( documentreadtext_xpm     ) );
00519     GetToolBar()->SetToolNormalBitmap( ID_DOCUMENTFIRSTPAGE_TB,    wxBitmap( documentfirstpage_xpm    ) );
00520     GetToolBar()->SetToolNormalBitmap( ID_DOCUMENTPREVIOUSPAGE_TB, wxBitmap( documentpreviouspage_xpm ) );
00521     GetToolBar()->SetToolNormalBitmap( ID_DOCUMENTNEXTPAGE_TB,     wxBitmap( documentnextpage_xpm     ) );
00522     GetToolBar()->SetToolNormalBitmap( ID_DOCUMENTLASTPAGE_TB,     wxBitmap( documentlastpage_xpm     ) );
00523     GetToolBar()->SetToolNormalBitmap( ID_FILESCANIMAGE_TB,        wxBitmap( filescanimagebmp_xpm     ) );
00524 
00525     // Insert a text editor control to switch to a given page.
00526     m_poTextCtrlPage= new wxTextCtrl( GetToolBar(), ID_TEXTCTRLPAGE,
00527                                       wxEmptyString, wxDefaultPosition,
00528                                       wxSize( GetToolBar()->IsVertical() ? 22 : 44, -1 ),
00529                                       wxTE_PROCESS_ENTER,
00530                                       m_oTextValidatorTextCtrlPage );
00531     GetToolBar()->InsertControl( 12, m_poTextCtrlPage );
00532     GetToolBar()->SetToolShortHelp( ID_TEXTCTRLPAGE, _( "Current page" ) );
00533 
00534 #if __WXSCANSANE__
00535     // Insert a wxChoice object to change the scanning device in the toolbar.
00536     m_poChoiceScanner= new wxChoice( GetToolBar(), ID_CHOICESCANNER,
00537                                      wxDefaultPosition,
00538                                      wxSize( GetToolBar()->IsVertical() ? 22 : 150, -1 ) );
00539     GetToolBar()->InsertControl( 1, m_poChoiceScanner );
00540     GetToolBar()->SetToolShortHelp( ID_CHOICESCANNER, _( "Select a scanner" ) );
00541 #endif // __WXSCANSANE__
00542 
00543     // Validate the toolbar.
00544     GetToolBar()->Realize();
00545 
00546     // Custom splitter window (sash) configuration.
00547     m_poHSplitterWindow->SetSashGravity( 1.0 );
00548     m_poVSplitterWindow->SetSashGravity( 1.0 );
00549 
00550 //    // Custom key accelerators.
00551 //    wxAcceleratorEntry aoAcceleratorEntries[1];
00552 //    aoAcceleratorEntries[0].Set( wxACCEL_NORMAL, 'a', ID_CMDSTOP_TB );
00553 //    wxAcceleratorTable oAcceleratorTable( WXSIZEOF( aoAcceleratorEntries ),
00554 //                                          aoAcceleratorEntries );
00555 //    SetAcceleratorTable( oAcceleratorTable );
00556 
00557     // Custom Initializations:
00558     //
00559     m_poCanvas->SetOptions(   wxIViewCanvas::wxICANVAS_MOUSE_SCROLL
00560                             | wxIViewCanvas::wxICANVAS_MOUSEWHEEL_SCROLL
00561                             | wxIViewCanvas::wxICANVAS_MOUSE_SELECTION );
00562 
00563     // Reset the image count, the page number and the image filename.
00564     ResetFileName();
00565 
00566 #if defined( __WXPDFDOC__ ) && __WXPDFDOC__ >= 1
00567     // Initialize a new pdf document object.
00568     if( !CreateNewPdfDocument() )
00569     {
00570         wxLogFatalError( _( "Failed to create wxPdfDocument object." ) );
00571     }
00572 #endif
00573 
00574     // Complete status bar information.
00575     SetStatusText( cstrStatusCopyRight, 3 );
00576 
00577     // Give the window an icon.
00578     SetIcon( wxiscanico_xpm );
00579 
00580     // Restore (most) settings.
00581     RestoreSettings();
00582 
00583     // Restore some additional settings (which should not be initialized twice).
00584     wxConfigBase *poConfig = wxConfigBase::Get();
00585     poConfig->SetRecordDefaults();
00586     poConfig->SetPath( wxT( "/" )  );
00587     poConfig->SetPath( cstrwxFrame );
00588 
00589     // Set style attributes to log text control:
00590     //
00591     // Read the font size from config file, ...
00592     int nFontSize= poConfig->Read( wxT( "FontSize" ), 8 );
00593 
00594     // ... get default text style parameters, and ...
00595     wxTextAttr oStyle( m_poLogTextCtrl->GetDefaultStyle() );
00596 
00597     // ... set some styling options (e. g. font).
00598     wxFont oFont( nFontSize, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL );
00599 
00600     oStyle.SetFont( oFont );
00601     m_poLogTextCtrl->SetDefaultStyle( oStyle );
00602 
00603     // Redirect logging to text control.
00604     int nMaxLogLevel= poConfig->Read( wxT( "MaxLogLevel" ), 2 );
00605     new wxChainLogTextCtrl( m_poLogTextCtrl, nMaxLogLevel );
00606 
00607     // Output a program version info to the log.
00608     wxLogMessage( wxT( "%s %s" ), cstrAppName.c_str(), cstrVersionString.c_str() );
00609     wxLogMessage( wxT( "----------------------------------------------------------" ) );
00610 
00611     // Restore profile settings.
00612     int nProfileIndex= poConfig->Read( wxT( "ProfileIndex" ), (long)0 );
00613 
00614     for( int i= 0; i < 999; i++ )
00615     {
00616         wxString strMenuItemText;
00617         wxString strProfileConfigPath= wxString::Format( wxT( "/Profile/%d" ), i );
00618 
00619         if( !poConfig->Exists( strProfileConfigPath ) )
00620         {
00621             break;
00622         }
00623 
00624         poConfig->SetPath( strProfileConfigPath );
00625 
00626         wxString strProfileName= poConfig->Read( wxT( "ProfileName" ), wxString::Format( wxT( "%d" ), i ) );
00627 
00628         if( i <= 9 )
00629         {
00630             strMenuItemText= wxString::Format( wxT( "&%d " ), i ) + strProfileName + wxString::Format( wxT( "\tCtrl+%d" ), i );
00631         }
00632         else
00633         {
00634             strMenuItemText= wxString::Format( wxT( "%d " ), i ) + strProfileName;
00635         }
00636 
00637         int nMenuID= ID_DOCUMENTPROFILE0 + i;
00638 
00639         poMenuDocumentProfiles->AppendCheckItem( nMenuID, strMenuItemText );
00640         Connect( nMenuID, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&wxIScanFrame::OnDocumentProfilesChooseProfile );
00641     }
00642     SetProfile( nProfileIndex );
00643 
00644 #if __WXLUASCRIPT__
00645     GetMenuBar()->Insert( wxISCAN_SCRIPTMENUPOS, new wxMenu, _( "&Scripts" ) );
00646 
00647     // Restore scripting settings.
00648     m_nLuaCount= 0;
00649     for( int i= 0; i < 999; i++ )
00650     {
00651         if( !poConfig->Exists( wxString::Format( wxT( "/Script/%d" ), i ) ) )
00652         {
00653             break;
00654         }
00655 
00656         // Switch to the scripting sub section.
00657         poConfig->SetPath( wxString::Format( wxT( "/Script/%d" ), i ) );
00658 
00659         // Get the string for the menu entry and its help string.
00660         wxString strMenuItemText= poConfig->Read( wxT( "MenuEntry" ), wxString::Format( wxT( "Script%d" ), i ) );
00661         wxString strMenuItemHelpText= poConfig->Read( wxT( "MenuEntryHelp" ), wxEmptyString );
00662 
00663         // Get the menu from config file where the new menu entry should appear, ...
00664         wxString strMenuPosition= poConfig->Read( wxT( "MenuPosition" ), wxT( "&Scripts" ) );
00665 
00666         // ... get its position number in the menu bar, ...
00667         int nMenuPos= GetMenuBar()->FindMenu( ::wxGetTranslation( strMenuPosition ) );
00668 
00669         // ... check its existence, ...
00670         if( nMenuPos == wxNOT_FOUND )
00671         {
00672             wxLogError( _( "Cannot find menu '%s'. "
00673                              "The according script will not be reachable by menu entry '%s'." ),
00674                           strMenuPosition.c_str(),
00675                           strMenuItemText.c_str()
00676                         );
00677             break;
00678         }
00679 
00680         // ... gets the position of the menu item after it, and ..
00681         int nMenuItem= poConfig->Read( wxT( "MenuItem" ), 0L );
00682 
00683         // ... gets its menu ID.
00684         int nMenuID= ID_DOCUMENTPROFILE0 + 1000 + i;
00685 
00686         // Create the menu entry and connect its ID to the scripting event handler.
00687         GetMenuBar()->GetMenu( nMenuPos )->Insert( nMenuItem, nMenuID, strMenuItemText, strMenuItemHelpText );
00688         Connect( nMenuID, wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&wxIScanFrame::OnScriptStartScript );
00689 
00690         // Adjust script number counter.
00691         m_nLuaCount++;
00692     }
00693 #endif // __WXLUASCRIPT__
00694 
00695     // Reset file history.
00696     poConfig->SetPath( wxT( "/Files" ) );
00697     m_oFileHistory.Load( *poConfig );
00698 
00699     // Delete file history entries of files that do not exist.
00700     for( int i= m_oFileHistory.GetCount() - 1; i >= 0; i-- )
00701     {
00702         wxString strFileName= m_oFileHistory.GetHistoryFile( i );
00703 
00704         if( !::wxFileExists( strFileName ) )
00705         {
00706             m_oFileHistory.RemoveFileFromHistory( i );
00707         }
00708     }
00709 
00710     // Add file history to the 'files' menu.
00711     m_oFileHistory.AddFilesToMenu( poMenuFile );
00712     m_oFileHistory.UseMenu( poMenuFile );
00713 
00714     // Set drop target.
00715     SetDropTarget( new wxExtFileDropTarget( this ) );
00716 
00717 #if __WXSCANSANE__
00718     // Scan for scanning devices and create a scanner object.
00719     //
00720     // Note: A new wxScan object is created and EnableControls() called
00721     //       implicidly in an independent thread by ScanForScanners().
00722     //       So we don't have to do it here again.
00723     ScanForScanners( true );
00724 #else
00725     // Create a scanner object.
00726     m_poScanner= new wxScan;
00727 
00728     // Switch (mostly disable) controls.
00729     EnableControls();
00730 #endif // __WXSCANSANE__
00731 }
00732 
00733 // Destructor.
00734 //
00735 wxIScanFrame::~wxIScanFrame()
00736 {
00737     // Destroy an existing scanner object.
00738     if( m_poScanner )
00739     {
00740         delete m_poScanner;
00741         m_poScanner= NULL;
00742     }
00743 
00744     // Terminate a possibly running concurrent process.
00745     if( m_poRunningProcess )
00746     {
00747         m_poRunningProcess->Kill( wxSIGTERM, wxKILL_CHILDREN );
00748         delete m_poRunningProcess;
00749         m_poRunningProcess= NULL;
00750     }
00751 
00752 #if __WXPDFDOC__
00753     // Destroy pending PDF documents.
00754     if( m_poPdfDoc )
00755     {
00756         delete m_poPdfDoc;
00757         m_poPdfDoc= NULL;
00758     }
00759 #endif // __WXPDFDOC__
00760 
00761     // Save configuration data.
00762     SaveSettings();
00763 
00764     //(*Destroy(wxIScanFrame)
00765     //*)
00766 
00767     // Save the log to a text file.
00768     if( m_poLogTextCtrl )
00769     {
00770         wxFileName oFileName( wxStandardPaths::Get().GetDocumentsDir(), ::wxGetApp().GetAppName(), wxT( "log" ) );
00771 
00772         m_poLogTextCtrl->SaveFile( oFileName.GetFullPath() );
00773     }
00774 }
00775 
00776 // Event handlers.
00777 //
00778 /// \brief Handle window closing requests.
00779 //
00780 void wxIScanFrame::OnClose( wxCloseEvent& oEvent )
00781 {
00782     // Check if the content is "dirty" and veto closing
00783     // (if it is not forbidden).
00784     if( CanClose( oEvent.CanVeto() ) )
00785     {
00786         this->Destroy();
00787     }
00788     else
00789     {
00790         if( oEvent.CanVeto() )
00791         {
00792             oEvent.Veto();
00793         }
00794         else
00795         {
00796             this->Destroy();
00797         }
00798     }
00799 }
00800 
00801 // Handle file dropping events (by opening the given file name).
00802 //
00803 void wxIScanFrame::OnFileDrop( wxExtFileDropEvent &oEvent )
00804 {
00805     // Open file.
00806     OpenImage( oEvent.GetFileName() );
00807 }
00808 
00809 /// \brief Handle menu command "File|Scan image".
00810 //
00811 void wxIScanFrame::OnFileScanImage( wxCommandEvent& oEvent )
00812 {
00813     // Show hourglass cursor.
00814     wxBusyCursor oWait;
00815 
00816     // Scan image.
00817 #if __WXLUASCRIPT__
00818     bLuaReturnFromEventHandler= ScanImage();
00819 #else
00820     ScanImage();
00821 #endif // __WXLUASCRIPT__
00822 
00823     // Enable (additional) menu options after the 1st scan.
00824     EnableControls();
00825 }
00826 
00827 /// \brief Handle menu command "File|Open...".
00828 //
00829 void wxIScanFrame::OnFileOpen( wxCommandEvent& oEvent )
00830 {
00831     // Open an "Open file" dialog an let the user choose a filename.
00832     wxFileDialog oDlg( this,
00833                        _( "Open file" ),
00834                        wxT( "" ),
00835                        wxT( "" ),
00836                        ::wxGetApp().GetImageFilter(),
00837 #if wxCHECK_VERSION( 2, 9, 0 )
00838                        wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
00839 #else
00840                        wxOPEN | wxFILE_MUST_EXIST | wxCHANGE_DIR );
00841 #endif // wxCHECK_VERSION
00842 
00843     if( oDlg.ShowModal() == wxID_OK )
00844     {
00845         // Open file.
00846         OpenImage( oDlg.GetPath() );
00847     }
00848 }
00849 
00850 /// \brief Handle menu command "File|Save as...".
00851 //
00852 void wxIScanFrame::OnFileSaveAs( wxCommandEvent& oEvent )
00853 {
00854     // Open a "Save file" dialog and let the user choose a filename.
00855     wxFileDialog oDlg( this,
00856                        _( "Save as" ),
00857                        wxT( "" ),
00858                        m_strImageFileName,
00859                        ::wxGetApp().GetImageFilter(),
00860 #if wxCHECK_VERSION( 2, 9, 0 )
00861                        wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxFD_CHANGE_DIR );
00862 #else
00863                        wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR );
00864 #endif // wxCHECK_VERSION
00865 
00866     if( oDlg.ShowModal() == wxID_OK )
00867     {
00868         // Show hourglass cursor.
00869         wxBusyCursor oWait;
00870 
00871         // Save file.
00872         if( !GetImageSelection().SaveFile( oDlg.GetPath() ) )
00873         {
00874             // On error warn the user.
00875             wxLogError( wxT( "Image cannot be written to file '%s'." ), oDlg.GetPath().c_str() );
00876             return;
00877         }
00878 
00879         // Save the filename.
00880         m_strImageFileName= oDlg.GetPath();
00881         SetTitle( m_strImageFileName + wxT( " - " ) + cstrAppName );
00882     }
00883 }
00884 
00885 /// \brief Handle menu command "File|Print".
00886 //
00887 void wxIScanFrame::OnFilePrint( wxCommandEvent& oEvent )
00888 {
00889     // ...
00890     AdjustOrientation();
00891 
00892     // Data object representing the print dialog's values.
00893     wxPrintDialogData oPrintDialogData( m_oPrintData );
00894 
00895     // Set the printer dialog's maximal page.
00896     oPrintDialogData.SetMaxPage( m_nImageCount );
00897 
00898     // Printer object.
00899     wxPrinter oPrinter( &oPrintDialogData );
00900 
00901     // ...
00902     wxIViewPrintout oPrintout( this, m_strImageFileName, false, m_nResolution, m_nResolution );
00903 
00904     // Create cancel dialog.
00905     oPrinter.CreateAbortWindow( this, &oPrintout );
00906 
00907     // Print.
00908     if( oPrinter.Print( this, &oPrintout, true ) )
00909     {
00910         m_oPrintData= oPrinter.GetPrintDialogData().GetPrintData();
00911     }
00912     else
00913     {
00914         if( wxPrinter::GetLastError() == wxPRINTER_ERROR )
00915         {
00916             wxLogError( _( "An error occured while printing." ) );
00917 #if __WXLUASCRIPT__
00918             // Signal error to Lua.
00919             bLuaReturnFromEventHandler= false;
00920 #endif // __WXLUASCRIPT__
00921         }
00922     }
00923 
00924     // Destroy the print image (for to release MBs of memory).
00925     m_oPrintImage.Destroy();
00926 }
00927 
00928 /// \brief Handle menu command "File|Print Preview".
00929 //
00930 void wxIScanFrame::OnFilePrintPreview( wxCommandEvent& oEvent )
00931 {
00932     // ...
00933     AdjustOrientation();
00934 
00935     // Data object representing the print dialog's values.
00936     wxPrintDialogData oPrintDialogData( m_oPrintData );
00937 
00938     // Pass two printout objects: for preview, and possible printing.
00939     wxPrintPreview *poPreview = new wxPrintPreview(
00940         new wxIViewPrintout( this, m_strImageFileName, false, m_nResolution, m_nResolution ),
00941         new wxIViewPrintout( this, m_strImageFileName, false, m_nResolution, m_nResolution ),
00942         &oPrintDialogData );
00943 
00944     if ( !poPreview || !poPreview->Ok() )
00945     {
00946         if( poPreview )
00947         {
00948             delete poPreview;
00949         }
00950         wxLogError( _( "An error occured while creating print preview object.") );
00951         return;
00952     }
00953 
00954     // Set the zoom factor to 100%.
00955     poPreview->SetZoom( 100 );
00956 
00957     int x, y, w, h;
00958 
00959     // Get the frame window position and size and create a print preview
00960     // window with the same postion and size.
00961     GetSize( &w, &h );
00962     GetPosition( &x, &y );
00963     wxIViewPreviewFrame *poPreviewFrame= new wxIViewPreviewFrame(
00964                                           poPreview,
00965                                           this,
00966                                           _( "Print Preview" ),
00967                                           wxPoint( x, y ),
00968                                           wxSize( w, h ) );
00969     if( !poPreviewFrame )
00970     {
00971         delete poPreview;
00972         wxLogError( _( "An error occured while creating print preview window.") );
00973         return;
00974     }
00975     poPreviewFrame->Initialize();
00976     poPreviewFrame->Show();
00977 
00978     // Destory the print image (for to save MBs memory).
00979     m_oPrintImage.Destroy();
00980 }
00981 
00982 /// \brief Handle menu command "File|Page Setup ".
00983 //
00984 void wxIScanFrame::OnFilePrintSetup( wxCommandEvent& oEvent )
00985 {
00986     // ...
00987     AdjustOrientation();
00988 
00989     wxPageSetupDialogData oPageSetupData( m_oPrintData );
00990 
00991     oPageSetupData.EnableOrientation( false );
00992 
00993     wxPageSetupDialog oPageSetupDialog( this, &oPageSetupData );
00994 
00995     if( oPageSetupDialog.ShowModal() == wxID_OK )
00996     {
00997         m_oPrintData= oPageSetupDialog.GetPageSetupData().GetPrintData();
00998     }
00999 }
01000 
01001 /// \brief Handle menu command "File|Quit".
01002 //
01003 void wxIScanFrame::OnFileQuit( wxCommandEvent& oEvent )
01004 {
01005     Close();
01006 }
01007 
01008 // Handle menu command "File|[MOST RECENTLY USED FILE #X]".
01009 //
01010 void wxIScanFrame::OnMRUFiles( wxCommandEvent &oEvent )
01011 {
01012     // Get the filename from history menu index, ...
01013     int nId= oEvent.GetId() - wxID_FILE1;
01014     wxString strFilename = m_oFileHistory.GetHistoryFile( nId );
01015 
01016     // ... check if it is valid, and reopen the image file.
01017     if( strFilename.IsEmpty() || !::wxFileExists( strFilename ) || !OpenImage( strFilename ) )
01018     {
01019         // Otherwise remove the file from the file name history, ...
01020         m_oFileHistory.RemoveFileFromHistory( nId );
01021 
01022         // and signal an error.
01023         wxLogError( wxString::Format( _( "File '%s' does not exist (any more) or cannot be opened." ),
01024                                         strFilename.c_str() ) );
01025     }
01026 }
01027 
01028 /// \brief Begin an new (empty) PDF document.
01029 //
01030 void wxIScanFrame::OnPdfBeginPdf( wxCommandEvent& oEvent )
01031 {
01032 #if defined( __WXPDFDOC__ ) && __WXPDFDOC__ >= 1
01033     if( !CanClose() )
01034     {
01035         return;
01036     }
01037 
01038     if( !CreateNewPdfDocument() )
01039     {
01040         return;
01041     }
01042 
01043     // Remove all thumbs from the the pages panel.
01044     m_poPanelPages->Reset();
01045 
01046     // Enable (additional) menu options.
01047     EnableControls();
01048 #else
01049     wxLogError( _( "PDF support is not enabled." ) );
01050 #endif
01051 }
01052 
01053 /// \brief Add the current image as a new page to the current PDF
01054 ///        document.
01055 //
01056 void wxIScanFrame::OnPdfAddPage( wxCommandEvent& oEvent )
01057 {
01058 #if defined( __WXPDFDOC__ ) && __WXPDFDOC__ >= 1
01059     bool bAddAllPages= false;
01060 
01061     // On multipage images ask for permission to add all pages.
01062     if( ( m_nImageCount > 1 ) && ( m_nPage == 0 ) )
01063     {
01064 
01065         switch( ::wxMessageBox( _( "This is a multipage image. Do you want to "
01066                                    "add all image pages to the PDF file?" ),
01067                                 ::wxGetApp().GetAppName(),
01068                                 wxYES_DEFAULT | wxYES_NO | wxCANCEL | wxICON_QUESTION  ) )
01069         {
01070             case wxYES    : bAddAllPages= true;
01071                             break;
01072             case wxCANCEL : return;
01073         }
01074     }
01075 
01076     // Show busy cursor (until the automatic variable is destroyed).
01077     wxBusyCursor oWait;
01078 
01079     // Apply a profile automatically after loading a page from a
01080     // multi page file.
01081     if( bAddAllPages and m_bAutoApplyProfileOnMultiPage )
01082     {
01083         ApplyProfile();
01084     }
01085 
01086     // Add page to PDF document.
01087     AddPdfPage();
01088 
01089     // Add the following pages (if wished).
01090     if( bAddAllPages )
01091     {
01092         while( m_nPage < ( m_nImageCount - 1 ) )
01093         {
01094             // Load next image page.
01095             OnDocumentNextPage( oEvent );
01096 
01097             // Optionally apply a profile automatically after loading
01098             // a page from a multi page file.
01099             if( m_bAutoApplyProfileOnMultiPage )
01100             {
01101                 ApplyProfile();
01102             }
01103 
01104             // Add page to PDF document.
01105             AddPdfPage();
01106         }
01107     }
01108 
01109     // Enable (additional) menu options.
01110     EnableControls();
01111 #else
01112     wxLogError( _( "PDF support is not enabled." ) );
01113 #endif
01114 }
01115 
01116 /// \brief Save the current PDF document as a PDF file.
01117 //
01118 void wxIScanFrame::OnPdfSavePdf( wxCommandEvent& oEvent )
01119 {
01120 #if defined( __WXPDFDOC__ ) && __WXPDFDOC__ >= 1
01121     if( !m_poPdfDoc )
01122     {
01123         wxLogError( _( "wxPdfDocument is NULL" ) );
01124         return;
01125     }
01126 
01127     // Open a "Save file" dialog and let the user choose a filename.
01128     wxFileDialog oDlg( this,
01129                        _( "Save as" ),
01130                        wxT( "" ),
01131                        _( "unknown.pdf" ),
01132                        _( "PDF file" ) + wxString( wxT( " (*.pdf)|*.pdf|" ) )
01133                        + _( "All files" ) + wxString( wxT( "|*.*" ) ),
01134 #if wxCHECK_VERSION( 2, 9, 0 )
01135                        wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxFD_CHANGE_DIR );
01136 #else
01137                        wxSAVE | wxOVERWRITE_PROMPT | wxCHANGE_DIR );
01138 #endif // wxCHECK_VERSION( 2, 9, 0 )
01139 
01140     if( oDlg.ShowModal() == wxID_OK )
01141     {
01142         // Show busy cursor (until the automatic variable is destroyed).
01143         wxBusyCursor oWait;
01144 
01145         // Save file.
01146         //
01147         // NOTE: At the moment there is no error checking on writing the
01148         //       PDF file. Does anyone know a (real) workaround?
01149         m_poPdfDoc->SaveAsFile( oDlg.GetPath() );
01150 
01151         // Mark PDF document as 'clean'.
01152         m_bPdfDirty= false;
01153 
01154         // Create a new PDF document.
01155         OnPdfBeginPdf( oEvent );
01156     }
01157 #else
01158     wxLogError( _( "PDF support is not enabled." ) );
01159 #endif
01160 }
01161 
01162 /// \brief Copy the (selected part of the) image to the system
01163 ///        clipboard.
01164 //
01165 void wxIScanFrame::OnEditCopy( wxCommandEvent& oEvent )
01166 {
01167     // Show hourglass cursor.
01168     wxBusyCursor oWait;
01169 
01170     // Copy the (selected part of the) image to the system clipboard.
01171     ::CopyImage2Clipboard( GetImageSelection() );
01172 }
01173 
01174 /// \brief Replace the image by the content of the system clipboard.
01175 //
01176 void wxIScanFrame::OnEditPaste( wxCommandEvent& oEvent )
01177 {
01178     // Show hourglass cursor.
01179     wxBusyCursor oWait;
01180 
01181     wxBitmapDataObject oBitmapData;
01182 
01183     // Open the clipboard.
01184     //
01185     // Note: There is a global object ::wxTheClipboard.
01186     //
01187     if( !wxTheClipboard->Open() )
01188     {
01189         wxLogError( wxString( wxT( "wxIScanFrame::CopyImage2Clipboard -- " ) )
01190               + _( "Failed to open clipboard." ) );
01191     }
01192 
01193     // If there is bitmap data in the clipboard get it.
01194     if( wxTheClipboard->GetData( oBitmapData ) )
01195     {
01196         // Get the image from the bitmap data in the clipboard.
01197         wxBitmap oBitmap= oBitmapData.GetBitmap();
01198 
01199         m_oImage= oBitmap.ConvertToImage();
01200         UpdateBitmap();
01201 
01202         // Enable/disable menu options according to the actual state.
01203         EnableControls();
01204     }
01205 
01206     // Close the clipboard.
01207     wxTheClipboard->Close();
01208 
01209     // Reset the filename.
01210     ResetFileName();
01211 }
01212 
01213 /// \brief Edit program settings (using an wxOptionsDialog window).
01214 //
01215 void wxIScanFrame::OnEditSettings( wxCommandEvent& oEvent )
01216 {
01217     // Get the global configuration object.
01218     wxConfigBase *poConfig = wxConfigBase::Get();
01219     poConfig->SetPath( wxT( "/Global" ) );
01220 
01221     // Get internationalization state flag directly from configuration.
01222     bool bI18n= (bool)poConfig->Read( wxT( "I18n" ), (long)true );
01223 
01224     // Get splashscreen state flag directly from configuration.
01225     bool bSplashscreen= (bool)poConfig->Read( wxT( "Splashscreen" ), (long)true );
01226 
01227     // Create, setup and display the options dialog (as a modal dialog).
01228 #if __NOTYETRELEASED__ >= 2
01229     wxOptionsBookDialog oDialog( this, wxT( "Common" ) );
01230 #else // __NOTYETRELEASED__
01231     wxOptionsDialog oDialog( this );
01232 #endif // __NOTYETRELEASED__
01233 
01234     // Create, setup and display the options dialog (as a modal dialog).
01235     oDialog.AppendOption( new wxOptionCheckBox( _( "Use internationalization on next program start." ), &bI18n ) );
01236     oDialog.AppendOption( new wxOptionCheckBox( _( "Show splashscreen at program startup." ), &bSplashscreen ) );
01237 #if __WXLUASCRIPT__
01238     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable Lua scripting." ), &m_bLua ) );
01239 #endif // __WXLUASCRIPT__
01240     oDialog.AppendOption( new wxOptionCheckBox( _( "Automatically apply profile after scanning." ), &m_bAutoApplyProfile ) );
01241     oDialog.AppendOption( new wxOptionCheckBox( _( "Automatically apply profile after loading a page from a multi page file." ), &m_bAutoApplyProfileOnMultiPage ) );
01242     oDialog.AppendOption( new wxOptionComboBox( _( "Mime type of image exported:" ), &m_strBitmapMimeType, 150 ) );
01243     oDialog.AppendOption( new wxOptionStaticLine );
01244 #if __WXPDFDOC__
01245     oDialog.AppendOption( new wxOptionCheckBox( _( "Use OCR when adding text to a PDF page." ), &m_bOCR ) );
01246     oDialog.AppendOption( new wxOptionComboBox( _( "Mime type of image exported to a PDF page:" ), &m_strPdfBitmapMimeType, 150 ) );
01247     oDialog.AppendOption( new wxOptionStaticLine );
01248 #endif // __WXPDFDOC__
01249     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable OCR command." ), &m_bCmdOcrEnable ) );
01250     oDialog.AppendOption( new wxOptionComboBox( _( "OCR command:" ), &m_strCmdOcr ) );
01251     oDialog.AppendOption( new wxOptionComboBox( _( "Output extension of the extracted text:" ), &m_strOcrOutputExtension, 150 ) );
01252     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable hOCR processing." ), &m_bHocrEnable ) );
01253     oDialog.AppendOption( new wxOptionComboBox( _( "OCR command to create hOCR output:" ), &m_strCmdOcrUseHocr ) );
01254     oDialog.AppendOption( new wxOptionComboBox( _( "Output extension of the hOCR output file:" ), &m_strOcrOutputExtensionHocr, 150 ) );
01255     oDialog.AppendOption( new wxOptionComboBox( _( "hOCR class in HOCR file to extract:" ), &m_strHocrClass, 150 ) );
01256     oDialog.AppendOption( new wxOptionCheckBox( _( "Use smart hOCR processing." ), &m_bSmartHocrEnable ) );
01257     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable HTML to XHTML conversion." ), &m_bCmdHtml2XhtmlEnable ) );
01258     oDialog.AppendOption( new wxOptionComboBox( _( "HTML to XHTML conversion command:" ), &m_strCmdHtml2Xhtml ) );
01259     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable image convertion command." ), &m_bCmdConvertEnable ) );
01260     oDialog.AppendOption( new wxOptionComboBox( _( "Bitmap conversion command:" ), &m_strCmdConvert ) );
01261     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable clean up command." ), &m_bCmdCleanUpEnable ) );
01262     oDialog.AppendOption( new wxOptionComboBox( _( "Clean up command:" ), &m_strCmdCleanUp ) );
01263     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable additional clean up after hOCR processing." ), &m_bCmdHocrCleanUpEnable ) );
01264     oDialog.AppendOption( new wxOptionComboBox( _( "Additional clean up command after hOCR processing:" ), &m_strCmdHocrCleanUp ) );
01265     oDialog.AppendOption( new wxOptionStaticLine );
01266     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable TTS command." ), &m_bCmdTtsEnable ) );
01267     oDialog.AppendOption( new wxOptionComboBox( _( "TTS command:" ), &m_strCmdTts, 500 ) );
01268     oDialog.AppendOption( new wxOptionStaticLine );
01269     oDialog.AppendOption( new wxOptionCheckBox( _( "Enable editor command." ), &m_bCmdEditEnable ) );
01270     oDialog.AppendOption( new wxOptionComboBox( _( "Editor command:" ), &m_strCmdEdit ) );
01271     // ... (Add another options.)
01272 
01273     oDialog.SetupDialog();
01274 
01275     if( oDialog.ShowModal() == wxID_OK )
01276     {
01277         // Get the global configuration object and set the config path.
01278         //
01279         // NOTE: We do this because wxConfigBase::Get() returns a global object
01280         //       that could have been changed by the option dialog itself.
01281         //
01282         poConfig= wxConfigBase::Get();
01283         poConfig->SetPath( wxT( "/Global" ) );
01284 
01285         // Set i18n flag state directly in configuration (file or registry).
01286         poConfig->Write( wxT( "I18n" ), (long)bI18n );
01287 
01288         // Set splashscreen flag state directly in configuration (file or registry).
01289         poConfig->Write( wxT( "Splashscreen" ), (long)bSplashscreen );
01290 
01291         // ... (Handle another options.)
01292 
01293         // Adjust control states.
01294         EnableControls();
01295     }
01296 }
01297 
01298 /// \brief Start the configured editor to edit the configuration file.
01299 //
01300 void wxIScanFrame::OnEditSettingsFile( wxCommandEvent& oEvent )
01301 {
01302     // Save programme settings.
01303     SaveSettings();
01304 
01305     // Open settings editor.
01306     wxFileConfig *poConfig = (wxFileConfig *)wxConfigBase::Get();
01307     wxString strConfigFilename= wxFileConfig::GetLocalFileName( poConfig->GetAppName() );
01308     wxString strCommand= wxString::Format( m_strCmdEdit, strConfigFilename.c_str() );
01309 
01310 #if __DEBUG__
01311     wxLogMessage( wxT( "wxIScanFrame::OnEditSettings - strCommand == '%s'" ), strCommand.c_str() );
01312 #endif
01313     Execute( strCommand );
01314 
01315     // Restore settings (from file).
01316     RestoreSettings();
01317 }
01318 
01319 /// \brief Scan for scanning devices and fill the corresponding
01320 ///        wxChoice control in the toolbar.
01321 //
01322 void wxIScanFrame::OnEditScanScanners(wxCommandEvent& event)
01323 {
01324 #ifdef __WXSCANSANE__
01325     // Scan for scanning devices.
01326     ScanForScanners( true );
01327 #endif // __WXSCANSANE__
01328 }
01329 
01330 /// \brief Wipe out the log window.
01331 //
01332 void wxIScanFrame::OnEditClearLog( wxCommandEvent& oEvent )
01333 {
01334     m_poLogTextCtrl->Clear();
01335 }
01336 
01337 /// \brief Wipe out the file name history (under file menu).
01338 //
01339 void wxIScanFrame::OnEditClearHistory( wxCommandEvent& oEvent )
01340 {
01341     // Delete file history entries.
01342     for( int i= m_oFileHistory.GetCount() - 1; i >= 0; i-- )
01343     {
01344         m_oFileHistory.RemoveFileFromHistory( i );
01345     }
01346 }
01347 
01348 /// \brief Do OCR on the loaded/scanned image and copy the text
01349 ///        to the system clipboard.
01350 //
01351 void wxIScanFrame::OnDocumentCopyText( wxCommandEvent& oEvent )
01352 {
01353     // Save image in a temporary JPEG file.
01354     wxString strTempFileName= wxFileName::CreateTempFileName( wxT( "" ) );
01355 
01356     GetImageSelection().SaveFile( strTempFileName, m_strBitmapMimeType );
01357 
01358     // Do OCR (and get the file name of the generated text file).
01359     wxString strOcrTextFileName= OCR( strTempFileName );
01360 
01361     // Remove the temporary JPEG file.
01362     ::wxRemoveFile( strTempFileName );
01363 
01364     // Get the text and copy it to the clipboard.
01365     if( !strOcrTextFileName.IsEmpty() )
01366     {
01367         // Copy text (from text file) to clipboard.
01368         ::CopyText2Clipboard( ::GetTextFromFile( strOcrTextFileName ) );
01369 
01370         // Remove the temporary text file
01371         ::wxRemoveFile( strOcrTextFileName );
01372     }
01373 #if __WXLUASCRIPT__
01374     else
01375     {
01376         // Signal error to Lua.
01377         bLuaReturnFromEventHandler= false;
01378     }
01379 #endif // __WXLUASCRIPT__
01380 }
01381 
01382 /// \brief Do OCR on the loaded/scanned image and read the text
01383 ///        out loud.
01384 //
01385 void wxIScanFrame::OnDocumentReadText( wxCommandEvent& oEvent )
01386 {
01387 #if __WXLUASCRIPT__
01388     bLuaReturnFromEventHandler= ReadOut( oEvent.GetId() != ID_DOCUMENTREADTEXTSYNC );
01389 #else
01390     ReadOut();
01391 #endif // __WXLUASCRIPT__
01392 
01393     // Enable/disable menu options according to the actual state.
01394     EnableControls();
01395 }
01396 
01397 /// \brief Go to first page of a multipage document.
01398 //
01399 void wxIScanFrame::OnDocumentFirstPage( wxCommandEvent& oEvent )
01400 {
01401     m_nPage= 0;
01402     OnDocumentPageChanged();
01403 }
01404 
01405 /// \brief Go to previous page of a multipage document.
01406 //
01407 void wxIScanFrame::OnDocumentPreviousPage( wxCommandEvent& oEvent )
01408 {
01409     if( m_nPage > 0 )
01410     {
01411         m_nPage--;
01412         OnDocumentPageChanged();
01413     }
01414 #if __WXLUASCRIPT__
01415     else
01416     {
01417             // Signal error to Lua.
01418             bLuaReturnFromEventHandler= false;
01419     }
01420 #endif // __WXLUASCRIPT__
01421 }
01422 
01423 /// \brief Go to next page of a multipage document.
01424 //
01425 void wxIScanFrame::OnDocumentNextPage( wxCommandEvent& oEvent )
01426 {
01427     if( m_nPage < ( m_nImageCount - 1 ) )
01428     {
01429         m_nPage++;
01430         OnDocumentPageChanged();
01431     }
01432 #if __WXLUASCRIPT__
01433     else
01434     {
01435             // Signal error to Lua.
01436             bLuaReturnFromEventHandler= false;
01437     }
01438 #endif // __WXLUASCRIPT__
01439 }
01440 
01441 /// \brief Go to last page of a multipage document.
01442 //
01443 void wxIScanFrame::OnDocumentLastPage( wxCommandEvent& oEvent )
01444 {
01445     m_nPage= m_nImageCount - 1;
01446     OnDocumentPageChanged();
01447 }
01448 
01449 /// \brief Crop the image to the selected rectangle.
01450 //
01451 void wxIScanFrame::OnDocumentCrop( wxCommandEvent& oEvent )
01452 {
01453     // Show hourglass cursor.
01454     wxBusyCursor oWait;
01455 
01456     // Get the selected subimage.
01457     m_oImage= GetImageSelection();
01458 
01459     // Replace the image by the selected subimage.
01460     UpdateBitmap();
01461 
01462     // Set the file name to unknown (because the main image changed).
01463     ResetFileName();
01464 
01465     // Enable/disable menu options according to the actual state.
01466     EnableControls();
01467 }
01468 
01469 /// \brief Zoom the image to the selected rectangle to fit the
01470 ///        canvas size.
01471 //
01472 void wxIScanFrame::OnDocumentZoom( wxCommandEvent& oEvent )
01473 {
01474     // If there is nothing selected there is nothing to do at all.
01475     if( !m_poCanvas->IsSelected() )
01476     {
01477         // So just return.
01478         return;
01479     }
01480 
01481     // Show hourglass cursor.
01482     wxBusyCursor oWait;
01483 
01484     // Calculate the new zoom factor.
01485     wxRect oSelection= m_poCanvas->GetSelection();
01486     wxSize oWindowSize= m_poCanvas->GetClientSize();
01487     double nScaleFactorX= (double)oWindowSize.GetWidth()  / (double)oSelection.GetWidth();
01488     double nScaleFactorY= (double)oWindowSize.GetHeight() / (double)oSelection.GetHeight();
01489     double nScaleFactor= ( nScaleFactorX < nScaleFactorY ) ? nScaleFactorX : nScaleFactorY;
01490 
01491     // Scale old zoom factor by the new one.
01492     m_nScaleFactor *= nScaleFactor;
01493 
01494     // Set zooming to fixed size.
01495     m_nFit= wxCANVASCUSTOMSIZE;
01496 
01497     // Rezoom the image.
01498     UpdateBitmap();
01499 
01500     // Scroll left upper corner of selection to the beginning of
01501     // the visuable part of the canvas.
01502     int nXUnit, nYUnit;
01503     m_poCanvas->GetScrollPixelsPerUnit( &nXUnit, &nYUnit );
01504     m_poCanvas->Scroll( (double)oSelection.GetX() * nScaleFactor / (double)nXUnit,
01505                         (double)oSelection.GetY() * nScaleFactor / (double)nYUnit );
01506 
01507     // Enable/disable menu options according to the actual state.
01508     EnableControls();
01509 }
01510 
01511 /// \brief Rotate image by 90° to the left.
01512 //
01513 void wxIScanFrame::OnDocumentRotate90Left( wxCommandEvent& oEvent )
01514 {
01515     // Show hourglass cursor.
01516     wxBusyCursor oWait;
01517 
01518     // Rotate image and change image orientation.
01519     m_oImage= m_oImage.Rotate90( false );
01520     UpdateBitmap();
01521 }
01522 
01523 /// \brief Rotate image by 90° to the right.
01524 //
01525 void wxIScanFrame::OnDocumentRotate90Right( wxCommandEvent& oEvent )
01526 {
01527     // Show hourglass cursor.
01528     wxBusyCursor oWait;
01529 
01530     // Rotate image and change image orientation.
01531     m_oImage= m_oImage.Rotate90( true );
01532     UpdateBitmap();
01533 }
01534 
01535 /// \brief Apply a previously selected profile to the image.
01536 //
01537 void wxIScanFrame::OnDocumentApplyProfile( wxCommandEvent& oEvent )
01538 {
01539     // Apply an image profile (crop, convert to monochrome etc.), and ...
01540     ApplyProfile();
01541 
01542     // ... reset the image on the canvas window.
01543     UpdateBitmap();
01544 }
01545 
01546 /// \brief Select a profile from the corresponding sub menu.
01547 //
01548 void wxIScanFrame::OnDocumentProfilesChooseProfile( wxCommandEvent& oEvent )
01549 {
01550     SetProfile( oEvent.GetId() - ID_DOCUMENTPROFILE0 );
01551 }
01552 
01553 /// \brief Select an image fitting option.
01554 //
01555 void wxIScanFrame::OnViewFit( wxCommandEvent& oEvent )
01556 {
01557     // Save the old fitting state and the old scalation
01558     // factor (for optimizing see below).
01559     int nFitOld= m_nFit;
01560     double nScaleFactorOld= m_nScaleFactor;
01561 
01562     // Transform the given event into an option value.
01563     if( oEvent.GetId() == ID_VIEWFITWIDTH )
01564     {
01565         m_nFit= wxCANVASFITWIDTH;
01566     }
01567     else if( oEvent.GetId() == ID_VIEWFITWINDOW )
01568     {
01569         m_nFit= wxCANVASFITWINDOW;
01570     }
01571     else if( oEvent.GetId() == ID_VIEWFULLSIZE )
01572     {
01573         m_nFit= wxCANVASFULLSIZE;
01574     }
01575     else if( oEvent.GetId() == ID_VIEWCUSTOMSIZE )
01576     {
01577         m_nFit= wxCANVASCUSTOMSIZE;
01578     }
01579     else if( oEvent.GetId() == ID_VIEWZOOMIN )
01580     {
01581         m_nFit= wxCANVASCUSTOMSIZE;
01582         m_nScaleFactor *= ( 1.0 + m_nZoomFactor );
01583     }
01584     else if( oEvent.GetId() == ID_VIEWZOOMOUT )
01585     {
01586         m_nFit= wxCANVASCUSTOMSIZE;
01587         m_nScaleFactor /= ( 1.0 + m_nZoomFactor );
01588     }
01589 
01590     // Optimization: If the fitting state and the scalation
01591     // factor hasn't changed just do nothing.
01592     if( ( nFitOld != m_nFit ) || ( nScaleFactorOld != m_nScaleFactor ) )
01593     {
01594         // Otherwise (re)zoom the image.
01595         UpdateBitmap();
01596     }
01597 
01598     // Enable/disable menu options according to the actual state.
01599     EnableControls();
01600 }
01601 
01602 /// \brief Toggle full screen mode.
01603 //
01604 void wxIScanFrame::OnViewFullScreen( wxCommandEvent& oEvent )
01605 {
01606     // Toggle full screen mode.
01607     ToggleFullScreen();
01608 }
01609 
01610 /// \brief Close the debug window.
01611 //
01612 void wxIScanFrame::OnViewCloseDebugWindow( wxCommandEvent& oEvent )
01613 {
01614     // Close the debug window by moving the the sash downwards.
01615     m_poHSplitterWindow->SetSashPosition( -1 );
01616 }
01617 
01618 /// \brief Close the preview panel window.
01619 //
01620 void wxIScanFrame::OnViewClosePreviewPanel( wxCommandEvent& oEvent )
01621 {
01622     // Close the preview panel window by moving the the sash right.
01623     m_poVSplitterWindow->SetSashPosition( -1 );
01624 }
01625 
01626 #if __WXLUASCRIPT__
01627 // Handle menu command "Scrips|[SCRIPT NAME]".
01628 //
01629 void wxIScanFrame::OnScriptStartScript( wxCommandEvent& oEvent )
01630 {
01631     // Show hourglass cursor.
01632     wxBusyCursor oWait;
01633 
01634     // Let the system do the showing the hourglass cursor.
01635     ::wxSafeYield();
01636 
01637     // Get the script index, ...
01638     int nIndex= oEvent.GetId() - ( ID_DOCUMENTPROFILE0 + 1000 );
01639 
01640     // ... and get the filename and the start up ("main") function.
01641     wxConfigBase *poConfig= wxConfigBase::Get();
01642 
01643     poConfig->SetPath( wxString::Format( wxT( "/Script/%d" ), nIndex ) );
01644 
01645     wxString strScriptStartupFunction= poConfig->Read( wxT( "Function" ), wxT( "" ) );
01646     wxString strScriptFileName= poConfig->Read( wxT( "Script" ), wxT( "" ) );
01647 
01648     if( strScriptStartupFunction.IsEmpty() )
01649     {
01650         // Signal error.
01651         wxLogError( wxString( wxT( "wxIScanFrame::OnScriptStartScript -- " ) )
01652                       + _( "Script startup function is empty." ) );
01653         return;
01654     }
01655     else
01656     {
01657         // Run script
01658         StartScript( strScriptStartupFunction, strScriptFileName );
01659     }
01660 
01661     // Enable/disable menu options according to the actual state.
01662     EnableControls();
01663 }
01664 #endif // __WXLUASCRIPT__
01665 
01666 /// \brief Handle (sub-)process killing.
01667 //
01668 void wxIScanFrame::OnCmdStop( wxCommandEvent& oEvent )
01669 {
01670     // Check if the (sub-)process is running.
01671     if( m_poRunningProcess )
01672     {
01673         // Log process's output.
01674         LogProcessOutput( m_poRunningProcess );
01675 
01676         // Try to terminate the (sub-)process.
01677         //
01678         // NOTE: In case the process is not terminated properly
01679         //       it is at least detached and released from the
01680         //       the main process.
01681         m_poRunningProcess->Kill( wxSIGTERM, wxKILL_CHILDREN );
01682         m_poRunningProcess->Detach();
01683 
01684         // Mark (sub-)process pointer as "clean".
01685         m_poRunningProcess= NULL;
01686    }
01687 
01688    // Enable/disable menu options according to the actual state.
01689    EnableControls();
01690 }
01691 
01692 /// \brief Handle menu command "Help|About...".
01693 //
01694 void wxIScanFrame::OnHelpAbout( wxCommandEvent& oEvent )
01695 {
01696     // Create an show the program's about box.
01697     wxIScanAbout oAboutBox( this );
01698 
01699     oAboutBox.ShowModal();
01700 }
01701 
01702 // Handle bitmap resizing introduced by canvas resizing.
01703 //
01704 void wxIScanFrame::OnCanvasSize( wxIViewCanvasSizeEvent & WXUNUSED( oEvent ) )
01705 {
01706     if( ( m_nFit == wxCANVASFITWIDTH ) || ( m_nFit == wxCANVASFITWINDOW ) )
01707     {
01708         UpdateBitmap();
01709     }
01710 }
01711 
01712 // Handle canvas selection events.
01713 //
01714 void wxIScanFrame::OnCanvasSelected( wxIViewCanvasSelectedEvent& oEvent )
01715 {
01716     // Check if the CTRL key was pressed when the selection was finished.
01717     if( oEvent.m_bCtrl )
01718     {
01719         wxCommandEvent oDummyEvent;
01720 
01721         // Zoom the selected rect to fit in the canvas window.
01722         OnDocumentZoom( oDummyEvent );
01723     }
01724 
01725     // Check if the ALT key was pressed when the selection was finished.
01726     else if( oEvent.m_bAlt )
01727     {
01728         wxCommandEvent oDummyEvent;
01729 
01730         // Crop the selected rect.
01731         OnDocumentCrop( oDummyEvent );
01732     }
01733 
01734 #if __NOTYETRELEASED__
01735     // Check if the SHIFT key was pressed when the selection was finished.
01736     else if( oEvent.m_bShift )
01737     {
01738         // ...
01739 double nHeight= (double)( oEvent.m_oSelection.GetTop() - oEvent.m_oSelection.GetBottom() );//oEvent.m_oSelection.GetHeight();
01740 double nWidth= (double)oEvent.m_oSelection.GetWidth();
01741 double nAngle= asin( nHeight / sqrt( nHeight * nHeight + nWidth * nWidth ) );
01742 m_oImage= ::RotateImage( m_oImage, nAngle );
01743 
01744         // ...
01745         UpdateBitmap();
01746     }
01747 #endif // __NOTYETRELEASED__
01748 }
01749 
01750 // Handle process termination.
01751 //
01752 void wxIScanFrame::OnProcessTerminated( wxProcessEvent & WXUNUSED( oEvent ) )
01753 {
01754     if( m_poRunningProcess )
01755     {
01756         // Log process's output.
01757         LogProcessOutput( m_poRunningProcess );
01758 
01759         // Delete the process and set its pointer to NULL.
01760         delete m_poRunningProcess;
01761         m_poRunningProcess= NULL;
01762     }
01763 
01764     // Enable/disable menu options according to the actual state.
01765     EnableControls();
01766 }
01767 
01768 // Handle page number editor field events.
01769 //
01770 void wxIScanFrame::OnTextCtrlPageProcessEnter( wxCommandEvent & WXUNUSED( oEvent ) )
01771 {
01772     long nNewPage;
01773 
01774     if( m_poTextCtrlPage->GetValue().ToLong( &nNewPage )
01775         && ( 0 < nNewPage )
01776         && ( nNewPage <=  m_nImageCount ) )
01777     {
01778         m_nPage= nNewPage - 1;
01779         OnDocumentPageChanged();
01780     }
01781 }
01782 
01783 // Handle window closing requests.
01784 //
01785 bool wxIScanFrame::CanClose( bool bCanVeto )
01786 {
01787 #if __WXPDFDOC__
01788     if( IsPdfDirty() )
01789     {
01790         switch( ::wxMessageBox( _( "The changes to the current PDF document have not yet been saved. "
01791                                    "Do you want to save the PDF document now?" ),
01792                                 ::wxGetApp().GetAppName(),
01793                                 wxYES_NO | ( bCanVeto ? wxCANCEL : 0 ) | wxICON_QUESTION ) )
01794         {
01795             case wxYES: {
01796                             wxCommandEvent oDummyEvent( wxEVT_COMMAND_MENU_SELECTED, ID_PDFSAVEASPDF );
01797 
01798                             OnPdfSavePdf  ( oDummyEvent );
01799                         }
01800                         return !IsPdfDirty();
01801             case wxNO : return true;
01802             default:    return false;
01803         }
01804     }
01805     else
01806     {
01807         return true;
01808     }
01809 #else
01810     return true;
01811 #endif
01812 }
01813 
01814 // Helper functions.
01815 //
01816 // Open an image using the given name.
01817 //
01818 bool wxIScanFrame::OpenImage( const wxString &strFileName, bool bSetFileName )
01819 {
01820     // Show hourglass cursor.
01821     wxBusyCursor oWait;
01822 
01823     // Save the filename.
01824     wxFileName oFileName( strFileName );
01825     oFileName.Normalize();
01826     wxString strFileNameFullPath= oFileName.GetFullPath();
01827 
01828     // Open file.
01829     if( !m_oImage.LoadFile( strFileNameFullPath ) )
01830     {
01831         // Signal error;
01832         return false;
01833     }
01834 
01835     // Set filename to new one (if indicated).
01836     if( bSetFileName )
01837     {
01838         m_strImageFileName= strFileNameFullPath;
01839         SetTitle( m_strImageFileName + wxT( " - " ) + cstrAppName );
01840     }
01841 
01842     // Get the image count and reset the page number.
01843     m_nImageCount= m_oImage.GetImageCount( m_strImageFileName );
01844     m_nPage= 0;
01845 
01846     // Update the page number info in the statusbar and in the toolbar.
01847     UpdatePageNumber();
01848 
01849     // Get the image resolution (or use the resolution value of the last
01850     // acquired/loaded image by not changing the resolution).
01851     if( m_oImage.HasOption( wxIMAGE_OPTION_RESOLUTION ) )
01852     {
01853         m_nResolution= m_oImage.GetOptionInt( wxIMAGE_OPTION_RESOLUTION );
01854     }
01855     else if( m_oImage.HasOption( wxIMAGE_OPTION_RESOLUTIONX ) )
01856     {
01857         m_nResolution= m_oImage.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONX );
01858     }
01859     else if( m_oImage.HasOption( wxIMAGE_OPTION_RESOLUTIONY ) )
01860     {
01861         m_nResolution= m_oImage.GetOptionInt( wxIMAGE_OPTION_RESOLUTIONY );
01862     }
01863 
01864     // Show the image on the canvas window.
01865     UpdateBitmap();
01866 
01867     // Enable (additional) menu options after the 1st scan.
01868     EnableControls();
01869 
01870     // Add filename to file history.
01871     m_oFileHistory.AddFileToHistory( m_strImageFileName );
01872 
01873     // Signal success.
01874     return true;
01875 }
01876 
01877 // (Re)loads the (zero based) page number given in m_nPage.
01878 //
01879 bool wxIScanFrame::OnDocumentPageChanged()
01880 {
01881     // Show hourglass cursor.
01882     wxBusyCursor oWait;
01883 
01884     // Load the image by name and page number.
01885     if( !m_oImage.LoadFile( m_strImageFileName, wxBITMAP_TYPE_ANY, m_nPage ) )
01886     {
01887         // Signal error.
01888         return false;
01889     }
01890 
01891     // Get the image direction.
01892 //    m_bPortrait= ( m_oImage.GetHeight() > m_oImage.GetWidth() );
01893 
01894     // Update the page number info in the statusbar and in the toolbar.
01895     UpdatePageNumber();
01896 
01897     // Show the image
01898     UpdateBitmap();
01899 
01900     // Update the menu and toolbar controls.
01901     EnableControls();
01902 
01903     // Signal success.
01904     return true;
01905 }
01906 
01907 // Update the canvas bitmap.
01908 //
01909 void wxIScanFrame::UpdateBitmap()
01910 {
01911     // Some little optimization for empty images.
01912     if( !m_oImage.IsOk() )
01913     {
01914         return;
01915     }
01916 
01917     // Resize image (if necessary).
01918     switch( m_nFit )
01919     {
01920         case wxCANVASFITWIDTH   : {
01921                                       int x, nDummy;
01922 
01923                                       m_poCanvas->GetClientSize( &x, &nDummy );
01924 
01925                                       m_nScaleFactor= (double)x / (double)m_oImage.GetWidth();
01926                                   }
01927                                   break;
01928         case wxCANVASFITWINDOW  : {
01929                                       int x, y;
01930 
01931                                       m_poCanvas->GetClientSize( &x, &y );
01932 
01933                                       double nScaleFactorX= (double)x / (double)m_oImage.GetWidth();
01934                                       double nScaleFactorY= (double)y / (double)m_oImage.GetHeight();
01935 
01936                                       m_nScaleFactor= nScaleFactorX > nScaleFactorY ? nScaleFactorY : nScaleFactorX;
01937                                   }
01938                                   break;
01939         case wxCANVASCUSTOMSIZE : break;
01940         default                 : m_nScaleFactor= 1.0;
01941                                   break;
01942     }
01943 
01944     // Some little optimization:
01945     //  - A scalation factor of 1.0 means there is no scalation at all.
01946     if( m_nScaleFactor == 1.0 )
01947     {
01948         m_poCanvas->SetBitmap( m_oImage );
01949     }
01950     else
01951     {
01952         // Show busy cursor (until the automatic variable is destroyed).
01953         wxBusyCursor oWait;
01954 
01955         m_poCanvas->SetBitmap( m_oImage.Scale(
01956             (int)( (double)m_oImage.GetWidth()  * m_nScaleFactor ),
01957             (int)( (double)m_oImage.GetHeight() * m_nScaleFactor ),
01958             wxIMAGE_QUALITY_HIGH ) );
01959     }
01960 }
01961 
01962 // Get the selected sub image.
01963 //
01964 wxImage wxIScanFrame::GetImageSelection()
01965 {
01966     if( m_poCanvas->IsSelected() )
01967     {
01968         wxRect oSelection= m_poCanvas->GetSelection();
01969 
01970         oSelection.x     = int( (double)oSelection.x      / m_nScaleFactor );
01971         oSelection.y     = int( (double)oSelection.y      / m_nScaleFactor );
01972         oSelection.width = int( (double)oSelection.width  / m_nScaleFactor );
01973         oSelection.height= int( (double)oSelection.height / m_nScaleFactor );
01974 
01975         int nWidth= m_oImage.GetWidth();
01976         if( nWidth < ( oSelection.x + oSelection.width ) )
01977         {
01978             oSelection.width= nWidth - oSelection.x;
01979         }
01980 
01981         int nHeight= m_oImage.GetHeight();
01982         if( nHeight < ( oSelection.y + oSelection.height ) )
01983         {
01984             oSelection.height= nHeight - oSelection.y;
01985         }
01986 
01987         return m_oImage.GetSubImage( oSelection );
01988     }
01989     else
01990     {
01991         return m_oImage;
01992     }
01993 }
01994 
01995 // Get an image from scanner.
01996 //
01997 bool wxIScanFrame::ScanImage()
01998 {
01999 #ifdef __WXSCANSANE__
02000     // Enter critical section to protect m_poScanner.
02001     m_oCriticalSectionScanner.Enter();
02002 
02003     // ...
02004     if( !m_poScanner->SetDeviceIndex( m_poChoiceScanner->GetSelection() ) )
02005     {
02006         wxLogWarning( ( m_poScanner->GetDeviceCount() ? _( "The selected scanning device is invald." )
02007                                                         : _( "No scanning device found." ) )
02008                         + wxString( wxT( " " ) )
02009                         + _( "Rescanning for scanning devices..." ) );
02010 
02011         // Leave the critical section that protects m_poScanner.
02012         //
02013         // Note: We do this because ScanForScanners() enters the
02014         //       the same critical section.
02015         //
02016         m_oCriticalSectionScanner.Leave();
02017 
02018         // Rescan for scanning devices.
02019         ScanForScanners();
02020 
02021         if( !m_poScanner->SetDeviceIndex( m_poChoiceScanner->GetSelection() ) )
02022         {
02023             wxLogError( m_poScanner->GetDeviceCount() ? _( "The selected scanning device is invald." )
02024                                                         : _( "No scanning device found." ) );
02025             return false;
02026         }
02027 
02028         // Reenter critical section to protect m_poScanner.
02029         m_oCriticalSectionScanner.Enter();
02030     }
02031 #endif // __WXSCANSANE__
02032 
02033     // Check if the scanner object initialization was successful.
02034     if( !m_poScanner->IsOk() )
02035     {
02036         wxLogError( _( "Cannot initialize scanner object." ) );
02037         return false;
02038     }
02039 
02040     // Scan an image, ...
02041     if( !m_poScanner->ScanImage( m_oImage ) )
02042     {
02043         wxLogError( _( "An error occured while scanning." ) );
02044         return false;
02045     }
02046 
02047     // ... get its resolution, ...
02048     m_nResolution= m_poScanner->GetResolution();
02049 
02050 #ifdef __WXSCANSANE__
02051     // Leave the critical section that protects m_poScanner.
02052     m_oCriticalSectionScanner.Leave();
02053 #endif // __WXSCANSANE__
02054 
02055     // ... apply an image profile (crop, convert to monochrome etc.), and ...
02056     if( m_bAutoApplyProfile )
02057     {
02058         ApplyProfile();
02059     }
02060 
02061     // ... show the image on the canvas window.
02062     UpdateBitmap();
02063 
02064     // Reset the image count, the page number and the image filename.
02065     ResetFileName();
02066 
02067     // Signal success.
02068     return true;
02069 }
02070 
02071 #ifdef __WXSCANSANE__
02072 // Scan for existing SANE scanners an fill the according wxChoice
02073 // object in the tool bar.
02074 //
02075 void wxIScanFrame::ScanForScanners( bool bAsync )
02076 {
02077     // Enter critical section to protect m_poScanner.
02078     //
02079     // Note: The corresponding ScanForScannersThreadExit().Leave() call
02080     //       is included in wxIScanFrame::ScanForScannersThreadEntry().
02081     //
02082     m_oCriticalSectionScanner.Enter();
02083 
02084     // If there is a current scanner object destroy it.
02085     if( m_poScanner )
02086     {
02087         delete m_poScanner;
02088         m_poScanner= NULL;
02089     }
02090 
02091     // Empty the wxChoice object for scanners.
02092     m_poChoiceScanner->Clear();
02093 
02094     // Enable/disable menu options according to the actual state.
02095     EnableControls();
02096 
02097     // Switch between asynchronous and synchronous version of
02098     // creating a new scanner object and filling the choice object.
02099     if( bAsync )
02100     {
02101         // Create a new thread that creates a new scanner object
02102         // (and scans therefore for available scanners).
02103         wxIScanFrameScanForScannersThread * poThread= new wxIScanFrameScanForScannersThread( this );
02104 
02105         poThread->Create();
02106         poThread->Run();
02107     }
02108     else
02109     {
02110         // Show hourglass cursor.
02111         wxBusyCursor oWait;
02112 
02113         // Create a new scanner object (and scan for scanning devices)
02114         ScanForScannersThreadEntry();
02115 
02116         // Fill the wxChoice object for scanners with a list of
02117         // available scanning devices.
02118         ScanForScannersThreadExit();
02119     }
02120 }
02121 
02122 // Create a new scanner object and scan for scanning devices.
02123 //
02124 // Note: This function should not be called directly.
02125 //
02126 void wxIScanFrame::ScanForScannersThreadEntry()
02127 {
02128     // Create a new scanner object (and scan for scanning devices)
02129     m_poScanner= new wxScan;
02130 }
02131 
02132 // Fill the wxChoice object for scanners with a list of available
02133 // scanning devices.
02134 //
02135 // Note: This function should not be called directly.
02136 //
02137 void wxIScanFrame::ScanForScannersThreadExit()
02138 {
02139     // Check...
02140     if( !m_poScanner )
02141     {
02142         // Log an error message and leave.
02143         wxLogError( _( "Cannot create a scanning device object (wxScan)." ) );
02144     }
02145 
02146     // Fill the wxChoice object for scanners with a list of
02147     // available scanning devices.
02148     else if( m_poScanner->IsOk() )
02149     {
02150         int nCount= m_poScanner->GetDeviceCount();
02151 
02152         if( nCount > 0 )
02153         {
02154             for( int i= 0; i < nCount; i++ )
02155             {
02156                 m_poChoiceScanner->Append(
02157                                            m_poScanner->GetDeviceModel( i )
02158                                            + wxT( " (" )
02159                                            + m_poScanner->GetDeviceName( i )
02160                                            + wxT( ")" )
02161                                          );
02162             }
02163             m_poChoiceScanner->SetSelection( m_poScanner->GetDeviceIndex() );
02164         }
02165         else
02166         {
02167             wxLogWarning( _( "No scanning device found." ) );
02168         }
02169     }
02170 
02171     // Leave the critical section that protects m_poScanner.
02172     m_oCriticalSectionScanner.Leave();
02173 
02174     // Enable/disable menu options according to the actual state.
02175     EnableControls();
02176 }
02177 #endif // __WXSCANSANE__
02178 
02179 // Select a profile (by number).
02180 //
02181 void wxIScanFrame::SetProfile( int nProfileIndex )
02182 {
02183     GetMenuBar()->Check( ID_DOCUMENTPROFILE0 + m_nProfileIndex, false );
02184     m_nProfileIndex= nProfileIndex;
02185     GetMenuBar()->Check( ID_DOCUMENTPROFILE0 + m_nProfileIndex, true  );
02186 }
02187 
02188 // Apply the selected profile to the image.
02189 //
02190 void wxIScanFrame::ApplyProfile()
02191 {
02192     // Show hourglass cursor.
02193     wxBusyCursor oWait;
02194 
02195     // Get profile configuration.
02196     wxConfigBase *poConfig= wxConfigBase::Get();
02197 
02198     poConfig->SetRecordDefaults();
02199     poConfig->SetPath( wxString::Format( wxT( "/Profile/%d" ), m_nProfileIndex ) );
02200 
02201 #if __WXLUASCRIPT__
02202     wxString strScriptStartupFunction= poConfig->Read( wxT( "Function" ), wxT( "" ) );
02203 
02204     if( m_bLua && !strScriptStartupFunction.IsEmpty() )
02205     {
02206         wxString strScriptFileName= poConfig->Read( wxT( "Script" ), wxT( "" ) );
02207 
02208         StartScript( strScriptStartupFunction, strScriptFileName );
02209     }
02210     else
02211 #endif // __WXLUASCRIPT__
02212     {
02213         // Crop image to the corresponding image rect.
02214         bool bCrop= (bool)poConfig->Read( wxT( "Crop" ), (long)false );
02215 
02216         if( bCrop )
02217         {
02218             int x= poConfig->Read( wxT( "x" ), 0L );
02219             int y= poConfig->Read( wxT( "y" ), 0L );
02220             int w= poConfig->Read( wxT( "w" ), (long)( 210.0 / 25.4 * (double)m_nResolution ) );
02221             int h= poConfig->Read( wxT( "h" ), (long)( 297.0 / 25.4 * (double)m_nResolution ) );
02222 
02223             m_oImage= ::CropImage( m_oImage, x, y, w, h );
02224         }
02225 
02226         // Convert the image to greyscale.
02227         bool bGreyScale= (bool)poConfig->Read( wxT( "GreyScale" ), (long)false );
02228 
02229         if( bGreyScale )
02230         {
02231             m_oImage= ::Image2Grey( m_oImage );
02232         }
02233 
02234         // Convert the image to mono chrome.
02235         bool bMonoChrome= (bool)poConfig->Read( wxT( "MonoChrome" ), (long)false );
02236 
02237         if( bMonoChrome )
02238         {
02239             int nMonoThreshold= poConfig->Read( wxT( "MonoThreshold" ), 128L );
02240 
02241             m_oImage= ::Image2Mono( m_oImage, nMonoThreshold);
02242         }
02243 
02244         // Rotate the image 90° to the right (multiple times).
02245         int nRotate90Right= poConfig->Read( wxT( "Rotate90Right" ), 0L );
02246 
02247         for( int i= 0; i < nRotate90Right; i++ )
02248         {
02249             m_oImage= m_oImage.Rotate90();
02250         }
02251     }
02252 }
02253 
02254 // Call an external OCR software and return the filename
02255 // of the resulting text file.
02256 //
02257 wxString wxIScanFrame::OCR( const wxString &strTempFileName, bool bUseHocr )
02258 {
02259     wxString strCommand;            // Command line to execute as an external process.
02260     wxString strReturnFileName;     // ...
02261 
02262     // Check if OCR command is enabled.
02263     if( !m_bCmdOcrEnable )
02264     {
02265 #if __DEBUG__
02266         wxLogWarning( wxString( wxT( "wxIScanFrame::OCR - " ) )
02267                         + _( "OCR command is disabled by option." ) );
02268 #endif
02269         return wxEmptyString;
02270     }
02271 
02272     // Convert image to a monochrome version, ...
02273     if( m_bCmdConvertEnable )
02274     {
02275         // ... either by using an external command, ...
02276         strCommand.Printf( m_strCmdConvert,
02277                            strTempFileName.c_str(),
02278                            strTempFileName.c_str() );
02279 #if __DEBUG__
02280         wxLogMessage( wxT( "wxIScanFrame::OCR - strCommand == '%s'" ), strCommand.c_str() );
02281 #endif
02282         if( !Execute( strCommand ) )
02283         {
02284             wxLogError( wxString( wxT( "wxIScanFrame::OCR - " ) )
02285                           + _( "Monochrome file creation failed." ) );
02286             strReturnFileName.Empty();
02287             goto leave;
02288         }
02289     }
02290     else
02291     {
02292         // ... or by using an internal function (Image2Mono()).
02293         //
02294         // Note: Image2Mono() replaces the image in place, i. e.
02295         //       the monochrome image shows on the screen, too.
02296         //
02297         ::Image2Mono( GetImageSelection() ).SaveFile( strTempFileName, m_strBitmapMimeType );
02298     }
02299 
02300     // Do OCR using an external command.
02301     strCommand.Printf( bUseHocr ? m_strCmdOcrUseHocr : m_strCmdOcr,
02302                        strTempFileName.c_str(),
02303                        strTempFileName.c_str() );
02304 #if __DEBUG__
02305     wxLogMessage( wxT( "wxIScanFrame::OCR - strCommand == '%s'" ), strCommand.c_str() );
02306 #endif
02307     if( !Execute( strCommand ) )
02308     {
02309         wxLogError( wxString( wxT( "wxIScanFrame::OCR - " ) )
02310                       + _( "OCR failed." ) );
02311         strReturnFileName.Empty();
02312         goto leave;
02313     }
02314 
02315     strReturnFileName= strTempFileName + wxT( "." ) + ( bUseHocr ? m_strOcrOutputExtensionHocr : m_strOcrOutputExtension );
02316 
02317 leave:
02318     // Clean up temporary image file.
02319     if(m_bCmdCleanUpEnable )
02320     {
02321 
02322         // Clean up.
02323         strCommand.Printf( m_strCmdCleanUp,
02324                            strTempFileName.c_str(),
02325                            strTempFileName.c_str() );
02326 #if __DEBUG__
02327         wxLogMessage( wxT( "wxIScanFrame::OCR - strCommand == '%s'" ), strCommand.c_str() );
02328 #endif
02329         Execute( strCommand );
02330     }
02331 
02332     // Clean up temporary hOCR file(s).
02333     if( bUseHocr && m_bCmdHocrCleanUpEnable )
02334     {
02335 
02336         // Clean up.
02337         strCommand.Printf( m_strCmdHocrCleanUp,
02338                            strTempFileName.c_str(),
02339                            strTempFileName.c_str() );
02340 #if __DEBUG__
02341         wxLogMessage( wxT( "wxIScanFrame::OCR - strCommand == '%s'" ), strCommand.c_str() );
02342 #endif
02343         Execute( strCommand );
02344     }
02345 
02346     // Return filename of the created text file (or an empty string on errors).
02347     return strReturnFileName;
02348 }
02349 
02350 // Do OCR and read out the returned text.
02351 //
02352 bool wxIScanFrame::ReadOut( bool bAsync )
02353 {
02354     // Save image in a temporary JPEG file.
02355     wxString strTempFileName= wxFileName::CreateTempFileName( wxT( "" ) );
02356 
02357     GetImageSelection().SaveFile( strTempFileName, m_strBitmapMimeType );
02358 
02359     // Do OCR, and get the temporary text file name.
02360     wxString strTempTextFileName= OCR( strTempFileName );
02361 
02362     // Remove temporary JPEG file.
02363     ::wxRemoveFile( strTempFileName );
02364 
02365     // Read the text using a custom command (if it is not the empty string).
02366     if( strTempTextFileName.IsEmpty() )
02367     {
02368         // Signal error.
02369         return false;
02370     }
02371 
02372     wxString strCommand= wxString::Format( m_strCmdTts, strTempTextFileName.c_str() );
02373 
02374 #if __DEBUG__
02375     wxLogMessage( wxT( "wxIScanFrame::ReadText - strCommand == '%s'" ), strCommand.c_str() );
02376 #endif
02377 
02378     // Execute the read out process.
02379     return Execute( strCommand, bAsync, strTempTextFileName );
02380 }
02381 
02382 // Fork an external process.
02383 //
02384 bool wxIScanFrame::Execute( const wxString &strCommand, bool bAsync, const wxString &strTempTextFileName )
02385 {
02386     if( bAsync )
02387     {
02388         // Check if an asynchronous process is still running.
02389         if( m_poRunningProcess )
02390         {
02391             // Log an error message.
02392             wxLogError( wxString( wxT( "wxIScanFrame::Execute - " ) )
02393                           + _( "Cannot create new asynchronous process. An old one is still running. "
02394                                "Please wait until it stops or press the STOP button in the taskbar." ) );
02395 
02396             // Signal error.
02397             return false;
02398         }
02399 
02400         // Create an asynchronous running process, ...
02401         if( strTempTextFileName.IsEmpty() )
02402         {
02403             m_poRunningProcess= new wxExtProcess( this, wxISCAN_PROCESS );
02404         }
02405         else
02406         {
02407             m_poRunningProcess= new wxExtProcessDelTempFile( this, wxISCAN_PROCESS, strTempTextFileName );
02408         }
02409 
02410         // ... check if is was created correctly, ...
02411         if( !m_poRunningProcess )
02412         {
02413             // Log an error message.
02414             wxLogError( wxString( wxT( "wxIScanFrame::Execute - " ) )
02415                           + _( "Cannot create process object." ) );
02416 
02417             // Signal error.
02418             return false;
02419         }
02420 
02421         // ... redirect its output, ...
02422 //        m_poRunningProcess->Redirect();
02423 
02424         // ... and execute it.
02425         if( !m_poRunningProcess->Execute( strCommand, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER ) )
02426         {
02427             // Log an error message.
02428             wxLogError( wxString( wxT( "wxIScanFrame::Execute - " ) )
02429                           + wxString::Format( _( "Cannot start asynchronous process [%s]." ),
02430                                               strCommand.c_str() ) );
02431 
02432             // Signal error.
02433             return false;
02434         }
02435     }
02436     else
02437     {
02438         // Create a process, ...
02439         wxProcess oProcess( this );
02440 
02441         // ... redirect its output, ...
02442         oProcess.Redirect();
02443 
02444         // ... execute it synchronous, and await its ending.
02445         long nExitCode= ::wxExecute( strCommand, wxEXEC_SYNC, &oProcess );
02446 
02447        // Log process's output.
02448         LogProcessOutput( &oProcess );
02449 
02450         if( nExitCode )
02451         {
02452             // Log an error message.
02453             wxLogError( wxString( wxT( "wxIScanFrame::Execute - " ) )
02454                           + wxString::Format( _( "An error occured on synchronous process [%s]." ),
02455                                               strCommand.c_str() ) );
02456 
02457             // Signal error.
02458             return false;
02459         }
02460     }
02461 
02462     // Signal success.
02463     return true;
02464 }
02465 
02466 // Reset the filename to "unknown.jpg" etc.
02467 //
02468 void wxIScanFrame::ResetFileName()
02469 {
02470     // Reset the file name.
02471     m_strImageFileName= _( "unknown.jpg" );
02472     SetTitle( cstrAppName );
02473 
02474     // Reset the image count, the page number and the image filename.
02475     m_nImageCount= 1;
02476     m_nPage= 0;
02477 
02478     // Update the page number info in the statusbar and in the toolbar.
02479     UpdatePageNumber();
02480 }
02481 
02482 // Write a sub process's stdout and stderr output to the program's log.
02483 //
02484 void wxIScanFrame::LogProcessOutput( wxProcess *poProcess )
02485 {
02486     // Save the log text control's default colour.
02487     wxTextAttr oStyle( m_poLogTextCtrl->GetDefaultStyle() );
02488     wxColour oOldColor( oStyle.GetTextColour() );
02489 
02490     // Check if there is text on the process's stdout and stderr stream
02491     // and log it.
02492     //
02493     // Process's stdout in light blue:
02494     wxTextInputStream oIn( *poProcess->GetInputStream() );
02495 
02496     oStyle.SetTextColour( wxColour( 64, 64, 255 ) );
02497     m_poLogTextCtrl->SetDefaultStyle( oStyle );
02498     while( poProcess->IsInputAvailable() )
02499     {
02500         wxLogMessage( oIn.ReadLine() );
02501     }
02502 
02503     // Process's stderr in light violet:
02504     wxTextInputStream oErr( *poProcess->GetErrorStream() );
02505 
02506     oStyle.SetTextColour( wxColour( 192, 96, 192 ) );
02507     m_poLogTextCtrl->SetDefaultStyle( oStyle );
02508     while( poProcess->IsErrorAvailable() )
02509     {
02510         wxLogMessage( oErr.ReadLine() );
02511     }
02512 
02513     // Restore the log text control's default colour.
02514     oStyle.SetTextColour( oOldColor );
02515     m_poLogTextCtrl->SetDefaultStyle( oStyle );
02516 }
02517 
02518 // Update the page number info in the statusbar and in the toolbar.
02519 //
02520 void wxIScanFrame::UpdatePageNumber()
02521 {
02522     SetStatusText( wxString::Format( wxT( "%d/%d" ),  m_nPage + 1, m_nImageCount ), 2 );
02523     m_poTextCtrlPage->SetValue( wxString::Format( wxT( "%d" ),  m_nPage + 1 ) );
02524 }
02525 
02526 // Enable or disable controls according to the actual progam state.
02527 //
02528 void wxIScanFrame::EnableControls()
02529 {
02530     // Enable/disable menu items (on first call).
02531     bool bImageOk= !m_bUILocked && m_oImage.IsOk();
02532 
02533     GetMenuBar()->Enable(     ID_FILESAVEAS,                bImageOk );
02534     GetToolBar()->EnableTool( ID_FILESAVEAS_TB,             bImageOk );
02535     GetMenuBar()->Enable(     ID_FILEPRINT,                 bImageOk );
02536     GetToolBar()->EnableTool( ID_FILEPRINT_TB,              bImageOk );
02537     GetMenuBar()->Enable(     ID_FILEPRINTPREVIEW,          bImageOk );
02538     GetMenuBar()->Enable(     ID_FILEPRINTSETUP,            bImageOk );
02539     GetMenuBar()->Enable(     ID_EDITCOPY,                  bImageOk );
02540     GetMenuBar()->Enable(     ID_VIEWZOOMIN,                bImageOk );
02541     GetMenuBar()->Enable(     ID_VIEWZOOMOUT,               bImageOk );
02542     GetMenuBar()->Enable(     ID_VIEWZOOMSELECTION,         bImageOk );
02543 #if __WXPDFDOC__
02544     GetMenuBar()->Enable(     ID_PDFBEGINPDF,               true     );
02545     GetToolBar()->EnableTool( ID_PDFBEGINPDF_TB,            true     );
02546     GetMenuBar()->Enable(     ID_PDFADDPAGE,                bImageOk );
02547     GetToolBar()->EnableTool( ID_PDFADDPAGE_TB,             bImageOk );
02548 #else
02549     GetMenuBar()->Enable(     ID_PDFBEGINPDF,               false    );
02550     GetToolBar()->EnableTool( ID_PDFBEGINPDF_TB,            false    );
02551     GetMenuBar()->Enable(     ID_PDFADDPAGE,                false    );
02552     GetToolBar()->EnableTool( ID_PDFADDPAGE_TB,             false    );
02553 #endif // __WXPDFDOC__
02554     GetMenuBar()->Enable(     ID_DOCUMENTROTATE90LEFT,      bImageOk );
02555     GetMenuBar()->Enable(     ID_DOCUMENTROTATE90RIGHT,     bImageOk );
02556     GetMenuBar()->Enable(     ID_DOCUMENTCROP,              bImageOk );
02557     GetMenuBar()->Enable(     ID_DOCUMENTAPPLYPROFILE,      bImageOk );
02558 
02559 #if __WXPDFDOC__
02560     // Enable/disable PDF file save controls.
02561     bool bCanSavePdfFile= !m_bUILocked && ( m_nPdfPages > 0 );
02562 
02563     GetMenuBar()->Enable(     ID_PDFSAVEASPDF,              bCanSavePdfFile );
02564     GetToolBar()->EnableTool( ID_PDFSAVEASPDF_TB,           bCanSavePdfFile );
02565 #else
02566     GetMenuBar()->Enable(     ID_PDFSAVEASPDF,              false );
02567     GetToolBar()->EnableTool( ID_PDFSAVEASPDF_TB,           false );
02568 #endif // __WXPDFDOC__
02569 
02570     // ...
02571     bool bCopyText= bImageOk && m_bCmdOcrEnable;
02572 
02573     GetMenuBar()->Enable(     ID_DOCUMENTCOPYTEXT,         bCopyText );
02574 
02575     // ...
02576     GetMenuBar()->Enable(     ID_EDITSETTINGSFILE ,        m_bCmdEditEnable );
02577 
02578     // Enable text-to-speach controls
02579     bool bTTS= bImageOk
02580                 && m_bCmdOcrEnable
02581                 && m_bCmdTtsEnable
02582                 && ( m_poRunningProcess ? false : true );
02583 
02584     GetMenuBar()->Enable(     ID_DOCUMENTREADTEXT,          bTTS );
02585     GetToolBar()->EnableTool( ID_DOCUMENTREADTEXT_TB,       bTTS );
02586 
02587     // Enable/disable page controls
02588     bool bNotFirstPage= ( m_nPage > 0 );
02589     bool bNotLastPage=  ( m_nPage < ( m_nImageCount - 1 ) );
02590 
02591     GetMenuBar()->Enable(     ID_DOCUMENTFIRSTPAGE,         bImageOk && bNotFirstPage );
02592     GetToolBar()->EnableTool( ID_DOCUMENTFIRSTPAGE_TB,      bImageOk && bNotFirstPage );
02593     GetMenuBar()->Enable(     ID_DOCUMENTPREVIOUSPAGE,      bImageOk && bNotFirstPage );
02594     GetToolBar()->EnableTool( ID_DOCUMENTPREVIOUSPAGE_TB,   bImageOk && bNotFirstPage );
02595     GetMenuBar()->Enable(     ID_DOCUMENTNEXTPAGE,          bImageOk && bNotLastPage  );
02596     GetToolBar()->EnableTool( ID_DOCUMENTNEXTPAGE_TB,       bImageOk && bNotLastPage  );
02597     GetMenuBar()->Enable(     ID_DOCUMENTLASTPAGE,          bImageOk && bNotLastPage  );
02598     GetToolBar()->EnableTool( ID_DOCUMENTLASTPAGE_TB,       bImageOk && bNotLastPage  );
02599     GetToolBar()->EnableTool( ID_TEXTCTRLPAGE,              bImageOk                  );
02600 
02601     // Enable process killer.
02602     GetMenuBar()->Enable(     ID_CMDSTOP,                   m_poRunningProcess );
02603     GetToolBar()->EnableTool( ID_CMDSTOP_TB,                m_poRunningProcess );
02604 
02605     // Enable scanning.
02606     bool bScanEnabled= !m_bUILocked && m_poScanner && m_poScanner->IsOk();
02607 
02608     GetMenuBar()->Enable(     ID_FILESCANIMAGE,             bScanEnabled );
02609     GetToolBar()->EnableTool( ID_FILESCANIMAGE_TB,          bScanEnabled );
02610 #ifdef __WXSCANSANE__
02611     GetMenuBar()->Enable(     ID_EDITSCANSCANNERS ,         !m_bUILocked && m_poScanner /*bScanEnabled*/ );
02612     GetToolBar()->EnableTool( ID_CHOICESCANNER,             bScanEnabled );
02613 #else // __WXSCANSANE__
02614     GetMenuBar()->Enable(     ID_EDITSCANSCANNERS ,         false );
02615 #endif // __WXSCANSANE__
02616 
02617     // Lock ...
02618     GetMenuBar()->Enable(     ID_FILEOPEN,                  !m_bUILocked );
02619     GetToolBar()->EnableTool( ID_FILEOPEN_TB,               !m_bUILocked );
02620     GetMenuBar()->Enable(     ID_EDITPASTE,                 !m_bUILocked );
02621 
02622     // Check the active viewing (fitting) option.
02623     GetMenuBar()->Check( ID_VIEWFITWIDTH,   false );
02624     GetMenuBar()->Check( ID_VIEWFITWINDOW,  false );
02625     GetMenuBar()->Check( ID_VIEWFULLSIZE,   false );
02626     GetMenuBar()->Check( ID_VIEWCUSTOMSIZE, false );
02627     switch( m_nFit )
02628     {
02629         case wxCANVASFITWIDTH   : GetMenuBar()->Check( ID_VIEWFITWIDTH,   true );
02630                                   break;
02631         case wxCANVASFITWINDOW  : GetMenuBar()->Check( ID_VIEWFITWINDOW,  true );
02632                                   break;
02633         case wxCANVASFULLSIZE   : GetMenuBar()->Check( ID_VIEWFULLSIZE,   true );
02634                                   break;
02635         case wxCANVASCUSTOMSIZE : GetMenuBar()->Check( ID_VIEWCUSTOMSIZE, true );
02636                                   break;
02637     }
02638 
02639     // ... file history... .
02640     for( unsigned i= 0; i <  m_oFileHistory.GetCount(); i++ )
02641     {
02642         GetMenuBar()->Enable( m_oFileHistory.GetBaseId() + i, !m_bUILocked );
02643     }
02644 
02645 #if __WXLUASCRIPT__
02646     // Enable/disable Lua script menu.
02647     GetMenuBar()->EnableTop( wxISCAN_SCRIPTMENUPOS, m_bLua );
02648     for( int i= 0; i < m_nLuaCount; i++ )
02649     {
02650         GetMenuBar()->Enable( ID_DOCUMENTPROFILE0 + 1000 + i, m_bLua );
02651     }
02652 #endif // __WXLUASCRIPT__
02653 
02654     // Disable (by compiler option) not implemented controls .
02655 #if defined( __WXPDFDOC__ ) && __WXPDFDOC__ >= 1
02656     GetMenuBar()->Enable(     ID_PDFBEGINPDF,               !m_bUILocked );
02657     GetToolBar()->EnableTool( ID_PDFBEGINPDF_TB,            !m_bUILocked );
02658 #else
02659     GetMenuBar()->Enable(     ID_PDFBEGINPDF,               false );
02660     GetToolBar()->EnableTool( ID_PDFBEGINPDF_TB,            false );
02661 #endif
02662 }
02663 
02664 #if __WXPDFDOC__
02665 // PDF creation functions.
02666 //
02667 // Create (and initialize) a new PDF document.
02668 //
02669 bool wxIScanFrame::CreateNewPdfDocument()
02670 {
02671     // Delete any old PDF documents.
02672     if( m_poPdfDoc  )
02673     {
02674         delete m_poPdfDoc;
02675     }
02676     SetStatusText( wxString( wxT( "PDF: " ) ) + _( "empty" ), 1 );
02677 
02678     // Create a new PDF document in portrait mode on A4 paper using mm
02679     // as measurement unit.
02680     m_poPdfDoc= new wxPdfDocument( wxPORTRAIT,
02681                                    wxString( _T( "mm" ) ),
02682                                    m_oPrintData.GetPaperId() );
02683     m_nPdfPages= 0;
02684     m_bPdfDirty= false;
02685     if( !m_poPdfDoc )
02686     {
02687         wxLogError( _( "Cannot create wxPdfDocument." ) );
02688     }
02689     m_poPdfDoc->SetCreator( ::wxGetApp().GetAppName() );
02690     m_poPdfDoc->SetAutoPageBreak( false );
02691     m_poPdfDoc->SetCompression( true );
02692     return true;
02693 }
02694 
02695 // Add a new image/OCR text page to the existing PDF document.
02696 //
02697 bool wxIScanFrame::AddPdfPage()
02698 {
02699     if( !m_poPdfDoc )
02700     {
02701         wxLogError( wxString( wxT( "wxIScanFrame::AddPdfPage - " ) )
02702                       + _( "wxPdfDocument is NULL" ) );
02703         return false;
02704     }
02705 
02706     // Save image in a temporary file.
02707     wxString strTempFileName= wxFileName::CreateTempFileName( wxEmptyString );
02708 
02709     m_oImage.SaveFile( strTempFileName, m_strPdfBitmapMimeType );
02710 
02711 #if defined( __WXSCANDEBUG__ ) && __WXSCANDEBUG__ >= 1
02712     wxLogMessage( wxT( "PDF PARAMETERS" ) );
02713     wxLogMessage( wxT( "\tGetPageWidth == %.2f mm (%f)"  ), m_poPdfDoc->GetPageWidth(),  m_poPdfDoc->GetPageWidth()  / m_oImage.GetWidth() );
02714     wxLogMessage( wxT( "\tGetPageHeight == %.2f mm (%f)" ), m_poPdfDoc->GetPageHeight(), m_poPdfDoc->GetPageHeight() / m_oImage.GetHeight() );
02715     wxLogMessage( wxT( "\tGetImageScale == %f (new: %f)" ), m_poPdfDoc->GetImageScale(), (double)m_nResolution / 72.0 );
02716     wxLogMessage( wxT( "\tGetScaleFactor == %f" ), m_poPdfDoc->GetScaleFactor() );
02717     wxLogMessage( wxT( "\tm_nResolution == %.2f DPI (%.2f/mm)" ), (double)m_nResolution, (double)m_nResolution / 25.4 );
02718     wxLogMessage( wxT( "============" ) );
02719     ::wxSafeYield();
02720 #endif
02721 
02722     // Add a page, ...
02723     m_poPdfDoc->AddPage( IsPortrait() ? wxPORTRAIT : wxLANDSCAPE );
02724 
02725     // ... do some OCR and include the recognized text if enabled, and ...
02726     if( m_bOCR )
02727     {
02728         wxString strOcrTextFileName= OCR( strTempFileName, m_bHocrEnable );
02729 
02730         if( !strOcrTextFileName.IsEmpty() )
02731         {
02732             m_poPdfDoc->SetFont( wxT( "Times" ), wxPDF_FONTSTYLE_REGULAR, 8 );
02733             m_poPdfDoc->SetTextRenderMode( wxPDF_TEXT_RENDER_INVISIBLE );
02734 
02735             if( m_bHocrEnable )
02736             {
02737                 wxXmlDocument oXmlDoc;
02738 
02739                 // Try to load the OCR result file as XML (XHTML).
02740                 {
02741                     // Suppress the error message if wxXmlDocument::Load(...) fails.
02742                     //
02743                     // Note: We want to suppress only the logging of
02744                     //       wxXmlDocument::Load(...). Therefore we use a local
02745                     //       variable oLogNull in an additional inner context
02746                     //       which is automatically destroyed after leaving this
02747                     //       context.
02748                     //
02749                     wxLogNull oLogNull;
02750 
02751                     // Load the XML file.
02752                     //
02753                     // Note: We need the flag wxXMLDOC_KEEP_WHITESPACE_NODES
02754                     //       because we need the whitespace for flushing!
02755                     oXmlDoc.Load( strOcrTextFileName, wxT( "UTF-8" ), wxXMLDOC_KEEP_WHITESPACE_NODES );
02756                 }
02757 
02758                 // If this was not successfull convert try to convert from HTML to XHTML.
02759                 if( !oXmlDoc.IsOk() && m_bCmdHtml2XhtmlEnable )
02760                 {
02761                     // Try to convert the file from HTML to XHTML.
02762                     wxString strCommand= wxString::Format( m_strCmdHtml2Xhtml, strOcrTextFileName.c_str() );
02763 #if __DEBUG__
02764                     wxLogMessage( wxT( "wxIScanFrame::AddPdfPage - strCommand == '%s'" ), strCommand.c_str() );
02765 #endif
02766                     Execute( strCommand );
02767 
02768                     // Retry to load the file as XHTML file.
02769                     {
02770                         // Suppress the error message if wxXmlDocument::Load(...)
02771                         // fails.
02772                         wxLogNull oLogNull;
02773 
02774                         // Load the XML file.
02775                         //
02776                         // Note: We need the flag wxXMLDOC_KEEP_WHITESPACE_NODES
02777                         //       because we need the whitespace for flushing!
02778                         oXmlDoc.Load( strOcrTextFileName, wxT( "UTF-8" ), wxXMLDOC_KEEP_WHITESPACE_NODES );
02779                     }
02780 
02781                     // In case of an error use the fallback action.
02782                     if( !oXmlDoc.IsOk() )
02783                     {
02784                         // Do a fallback by treating the file as unformated text.
02785                         goto FallBack;
02786                     }
02787                 }
02788 
02789                 // Traverse DOM tree and draw the text on the PDF document.
02790                 if( m_bSmartHocrEnable )
02791                 {
02792                     wxIScanSmartHocr2Pdf oHocr2Pdf( &oXmlDoc, m_poPdfDoc, m_nResolution, m_strHocrClass );
02793 
02794                     oHocr2Pdf.Run();
02795                 }
02796                 else
02797                 {
02798                     wxIScanHocr2Pdf oHocr2Pdf( &oXmlDoc, m_poPdfDoc, m_nResolution, m_strHocrClass );
02799 
02800                     oHocr2Pdf.Run();
02801                 }
02802 
02803                 // On success leave out the fall back code.
02804                 goto GoOn;
02805             }
02806 
02807 FallBack:
02808             // Handle unformated text file (non-hocr-files).
02809             //
02810             m_poPdfDoc->MultiCell( 0, 3, ::GetTextFromFile( strOcrTextFileName ), wxPDF_BORDER_NONE, wxPDF_ALIGN_LEFT, 1 );
02811 
02812 GoOn:
02813             // Remove the text file created by the OCR program.
02814             ::wxRemoveFile( strOcrTextFileName );
02815         }
02816     }
02817 
02818     // ... put the image onto the current PDF page.
02819     m_poPdfDoc->SetImageScale(  (double)m_nResolution / 72.0 );
02820     m_poPdfDoc->Image( strTempFileName, 0 , 0, 0, 0, m_strPdfBitmapMimeType );
02821 
02822     // Remove temporary file.
02823     ::wxRemoveFile( strTempFileName );
02824 
02825     // Incremement the page counter and mark the PDF document as 'dirty'.;
02826     m_nPdfPages++;
02827     m_bPdfDirty= true;
02828     SetStatusText( wxString::Format( wxT( "PDF: %d" ), m_nPdfPages ), 1 );
02829 
02830     // Add a thumb to the pages panel.
02831     m_poPanelPages->AddImage( m_oImage );
02832 
02833     // Signal success.
02834     return true;
02835 }
02836 #endif // __WXPDFDOC__
02837 
02838 #if __WXLUASCRIPT__
02839 // Start a Lua script from a given file.
02840 //
02841 void wxIScanFrame::StartScript( const wxString &strScriptStartupFunction, wxString strScriptFileName )
02842 {
02843     // Create the final script ...
02844     wxString strScriptCode; // Contains the Lua script code.
02845 
02846     if( strScriptFileName.IsEmpty() )
02847     {
02848         // ... by using the given main function call(s) (chunk).
02849         strScriptCode= strScriptStartupFunction + wxT( "\n" );
02850     }
02851     else
02852     {
02853         // Search for the directory containing the script file:
02854         //
02855         // Check...
02856         if( !::wxFileExists( strScriptFileName ) )
02857         {
02858             // If the script file does not exist replace its directory part by the
02859             // user's home directory.
02860             //
02861             // Signal a warning.
02862             wxLogWarning( wxString( wxT( "wxIScanFrame::StartScript -- " ) )
02863                             + _( "Script file does not exist. I try searching in the home directory." ) );
02864 
02865             // Replace the directory part of the script file name
02866             // by the user's home directory.
02867             wxFileName oScriptFileName( strScriptFileName );
02868 
02869             strScriptFileName= oScriptFileName.GetFullName();
02870             oScriptFileName.AssignHomeDir();
02871             oScriptFileName.SetFullName( strScriptFileName );
02872 
02873             strScriptFileName= oScriptFileName.GetFullPath();
02874     #if __DEBUG__
02875             wxLogWarning( wxT( "wxIScanFrame::StartScript -- strScriptFileName == '%s'" ),
02876                             strScriptFileName.c_str() );
02877     #endif // __DEBUG
02878 
02879                 // Check...
02880             if( !::wxFileExists( strScriptFileName ) )
02881             {
02882                 // If the script file does not exist replace its directory
02883                 // part by the data directory.
02884                 //
02885                 // Display (log) a warning.
02886                 wxLogWarning( wxString( wxT( "wxIScanFrame::StartScript -- " ) )
02887                                 + _( "Script file does not exist. I try searching in the data directory." ) );
02888 
02889                 // Replace the directory part of the script file name
02890                 // by the program's data directory.
02891                 wxFileName oScriptFileName( strScriptFileName );
02892 
02893                 strScriptFileName= oScriptFileName.GetFullName();
02894                 oScriptFileName.AssignDir( wxStandardPaths::Get().GetDataDir() );
02895                 oScriptFileName.SetFullName( strScriptFileName );
02896 
02897                 strScriptFileName= oScriptFileName.GetFullPath();
02898     #if __DEBUG__
02899                 wxLogWarning( wxT( "wxIScanFrame::StartScript -- strScriptFileName == '%s'" ),
02900                                 strScriptFileName.c_str() );
02901     #endif // __DEBUG
02902             }
02903         }
02904 
02905         // ... by concatinating the file content and the main
02906         // function call(s) (chunk).
02907         strScriptCode= ::GetTextFromFile( strScriptFileName ) + wxT( "\n\n" ) +
02908                        strScriptStartupFunction + wxT( "\n" );
02909     }
02910 
02911     // Create the Lua scripting object, ...
02912     wxIScanLuaScript oScript( strScriptCode, this, cstrAppName, &bLuaReturnFromEventHandler );
02913 
02914 #if __WXLUASCRIPT_DYNAMIC__
02915     // Check if the script object is initialized correctly. This is only done
02916     // on dynamic loading of the Lua library because only there the library
02917     // may not be loaded correctly.
02918     if( !oScript.IsOk() )
02919     {
02920         // Log an error message, ...
02921         wxLogError( wxString( wxT( "wxIScanFrame::StartScript -- " ) )
02922                       + _( "Cannot initialize wxIScanLuaScript object." ) );
02923 
02924         // ... and leave.
02925         return;
02926     }
02927 #endif // __WXLUASCRIPT_DYNAMIC__
02928 
02929     // ..., register menu id constants, ...
02930     oScript.RegisterConstant( wxT( "ID_FILESCANIMAGE" ), ID_FILESCANIMAGE );
02931     oScript.RegisterConstant( wxT( "ID_FILEOPEN" ), ID_FILEOPEN );
02932     oScript.RegisterConstant( wxT( "ID_FILESAVEAS" ), ID_FILESAVEAS );
02933     oScript.RegisterConstant( wxT( "ID_FILEPRINT" ), ID_FILEPRINT );
02934     oScript.RegisterConstant( wxT( "ID_FILEPRINTPREVIEW" ), ID_FILEPRINTPREVIEW );
02935     oScript.RegisterConstant( wxT( "ID_FILEPRINTSETUP" ), ID_FILEPRINTSETUP );
02936     oScript.RegisterConstant( wxT( "ID_FILEQUIT" ), ID_FILEQUIT );
02937     oScript.RegisterConstant( wxT( "ID_EDITCOPY" ), ID_EDITCOPY );
02938     oScript.RegisterConstant( wxT( "ID_EDITPASTE" ), ID_EDITPASTE );
02939     oScript.RegisterConstant( wxT( "ID_EDITSETTINGS" ), ID_EDITSETTINGS );
02940     oScript.RegisterConstant( wxT( "ID_EDITSETTINGSFILE" ), ID_EDITSETTINGSFILE );
02941     oScript.RegisterConstant( wxT( "ID_VIEWFITWIDTH" ), ID_VIEWFITWIDTH );
02942     oScript.RegisterConstant( wxT( "ID_VIEWFITWINDOW" ), ID_VIEWFITWINDOW );
02943     oScript.RegisterConstant( wxT( "ID_VIEWFULLSIZE" ), ID_VIEWFULLSIZE );
02944     oScript.RegisterConstant( wxT( "ID_VIEWCUSTOMSIZE" ), ID_VIEWCUSTOMSIZE );
02945     oScript.RegisterConstant( wxT( "ID_VIEWFULLSCREEN" ), ID_VIEWFULLSCREEN );
02946     oScript.RegisterConstant( wxT( "ID_DOCUMENTCOPYTEXT" ), ID_DOCUMENTCOPYTEXT );
02947     oScript.RegisterConstant( wxT( "ID_DOCUMENTREADTEXT" ), ID_DOCUMENTREADTEXT );
02948     oScript.RegisterConstant( wxT( "ID_DOCUMENTREADTEXT" ), ID_DOCUMENTREADTEXT );
02949     oScript.RegisterConstant( wxT( "ID_DOCUMENTREADTEXTSYNC" ), ID_DOCUMENTREADTEXTSYNC );
02950     oScript.RegisterConstant( wxT( "ID_DOCUMENTPREVIOUSPAGE" ), ID_DOCUMENTPREVIOUSPAGE );
02951     oScript.RegisterConstant( wxT( "ID_DOCUMENTNEXTPAGE" ), ID_DOCUMENTNEXTPAGE );
02952     oScript.RegisterConstant( wxT( "ID_DOCUMENTLASTPAGE" ), ID_DOCUMENTLASTPAGE );
02953     oScript.RegisterConstant( wxT( "ID_DOCUMENTCROP" ), ID_DOCUMENTCROP );
02954     oScript.RegisterConstant( wxT( "ID_DOCUMENTROTATE90LEFT" ), ID_DOCUMENTROTATE90LEFT );
02955     oScript.RegisterConstant( wxT( "ID_DOCUMENTROTATE90RIGHT" ), ID_DOCUMENTROTATE90RIGHT );
02956     oScript.RegisterConstant( wxT( "ID_DOCUMENTAPPLYPROFILE" ), ID_DOCUMENTAPPLYPROFILE );
02957 #if __WXPDFDOC__
02958     oScript.RegisterConstant( wxT( "ID_PDFBEGINPDF" ), ID_PDFBEGINPDF );
02959     oScript.RegisterConstant( wxT( "ID_PDFADDPAGE" ), ID_PDFADDPAGE );
02960     oScript.RegisterConstant( wxT( "ID_PDFSAVEASPDF" ), ID_PDFSAVEASPDF );
02961 #endif // __WXPDFDOC__
02962     oScript.RegisterConstant( wxT( "ID_HELPABOUT" ), ID_HELPABOUT );
02963     oScript.RegisterConstant( wxT( "ID_CMDSTOP" ), ID_CMDSTOP );
02964 
02965     // ..., register variables, ...
02966     oScript.RegisterVariable( wxT( "Resolution" ), &m_nResolution );
02967     oScript.RegisterVariable( wxT( "Page" ), &m_nPage );
02968     oScript.RegisterVariable( wxT( "ImageCount" ), &m_nImageCount );
02969     oScript.RegisterVariable( wxT( "PdfPages" ), &m_nPdfPages );
02970     oScript.RegisterVariable( wxT( "ProfileIndex" ), &m_nProfileIndex );
02971     oScript.RegisterVariable( wxT( "ImageFileName" ), &m_strImageFileName );
02972     oScript.RegisterVariable( wxT( "BitmapMimeType" ), &m_strBitmapMimeType );
02973     oScript.RegisterVariable( wxT( "ScaleFactor" ), &m_nScaleFactor );
02974     oScript.RegisterVariable( wxT( "ZoomFactor" ), &m_nZoomFactor );
02975     oScript.RegisterVariable( wxT( "AutoApplyProfile" ), &m_bAutoApplyProfile );
02976     oScript.RegisterVariable( wxT( "AutoApplyProfileOnMultiPage" ), &m_bAutoApplyProfileOnMultiPage );
02977     oScript.RegisterVariable( wxT( "OCR" ), &m_bOCR );
02978     oScript.RegisterVariable( wxT( "CmdConvertEnable" ), &m_bCmdConvertEnable );
02979     oScript.RegisterVariable( wxT( "CmdConvert" ), &m_strCmdConvert );
02980     oScript.RegisterVariable( wxT( "CmdOcrEnable" ), &m_bCmdOcrEnable );
02981     oScript.RegisterVariable( wxT( "CmdOcr" ), &m_strCmdOcr );
02982     oScript.RegisterVariable( wxT( "CmdCleanUpEnable" ), &m_bCmdCleanUpEnable );
02983     oScript.RegisterVariable( wxT( "CmdCleanUp" ), &m_strCmdCleanUp );
02984     oScript.RegisterVariable( wxT( "HocrEnable" ), &m_bHocrEnable );
02985     oScript.RegisterVariable( wxT( "HocrClass" ), &m_strHocrClass );
02986     oScript.RegisterVariable( wxT( "SmartHocrEnable" ), &m_bSmartHocrEnable );
02987     oScript.RegisterVariable( wxT( "CmdOcrUseHocr" ), &m_strCmdOcrUseHocr );
02988     oScript.RegisterVariable( wxT( "CmdHtml2XhtmlEnable" ), &m_bCmdHtml2XhtmlEnable );
02989     oScript.RegisterVariable( wxT( "CmdHtml2Xhtml" ), &m_strCmdHtml2Xhtml );
02990     oScript.RegisterVariable( wxT( "CmdHocrCleanUpEnable" ), &m_bCmdHocrCleanUpEnable );
02991     oScript.RegisterVariable( wxT( "CmdHocrCleanUp" ), &m_strCmdHocrCleanUp );
02992     oScript.RegisterVariable( wxT( "CmdTtsEnable" ), &m_bCmdTtsEnable );
02993     oScript.RegisterVariable( wxT( "CmdTts" ), &m_strCmdTts );
02994     oScript.RegisterVariable( wxT( "CmdEditEnable" ), &m_bCmdEditEnable );
02995     oScript.RegisterVariable( wxT( "CmdEdit" ), &m_strCmdEdit );
02996     oScript.RegisterVariable( wxT( "PdfDirty" ), &m_bPdfDirty );
02997 #if __WXPDFDOC__
02998     oScript.RegisterVariable( wxT( "PdfBitmapMimeType" ), &m_strPdfBitmapMimeType );
02999 #endif // __WXPDFDOC__
03000 
03001     // ... and run the script.
03002 #if __DEBUG__
03003     wxLogMessage( wxT( "wxIScanFrame::StartScript - " )
03004                     + wxString::Format( _( "Running Lua Script '%s' starting function '%s'." ),
03005                                         strScriptFileName.c_str(),
03006                                         strScriptStartupFunction.c_str() ) );
03007 #endif // __DEBUG__
03008     oScript.Run();
03009 }
03010 #endif // __WXLUASCRIPT__
03011 
03012 // Setting functions.
03013 //
03014 // Restore program settings from config file.
03015 //
03016 void wxIScanFrame::RestoreSettings()
03017 {
03018     // Reset window settings.
03019     wxConfigBase *poConfig = wxConfigBase::Get();
03020     poConfig->SetRecordDefaults();
03021     poConfig->SetPath( wxT( "/" )  );
03022     poConfig->SetPath( cstrwxFrame );
03023 
03024     int x= poConfig->Read( wxT( "x" ),   5 );
03025     int y= poConfig->Read( wxT( "y" ),   5 );
03026     int w= poConfig->Read( wxT( "w" ), 630 );
03027     int h= poConfig->Read( wxT( "h" ), 470 );
03028     bool bMaximized= (bool)poConfig->Read( wxT( "Maximized"  ), (long)false );
03029     bool bIconized= (bool)poConfig->Read( wxT( "Iconized"  ), (long)false );
03030     bool bFullScreen= (bool)poConfig->Read( wxT( "FullScreen"  ), (long)false );
03031 
03032     // Reset window position, size, maximization and full screen state.
03033     Move( x, y );
03034     SetSize( w, h );
03035     Maximize( bMaximized );
03036     Iconize( bIconized );
03037     if( bFullScreen )
03038     {
03039         ToggleFullScreen();
03040     }
03041 
03042     // Reset ...
03043     m_oPrintData.SetPaperId( (wxPaperSize)poConfig->Read( wxT( "PaperSize" ), (long)wxPAPER_A4 ) );
03044     m_nFit= poConfig->Read( wxT( "Fit" ), wxCANVASFITWINDOW );
03045     poConfig->Read( wxT( "ScaleFactor" ), &m_nScaleFactor );
03046     poConfig->Read( wxT( "ZoomFactor" ), &m_nZoomFactor );
03047 
03048     // Reset bitmap mimetype for everything but pdf export.
03049     m_strBitmapMimeType= poConfig->Read( wxT( "BitmapMimeType" ), wxT( "image/tiff" ) );
03050 
03051 #if __WXPDFDOC__
03052     // Reset bitmap mimetype for pdf export.
03053     m_strPdfBitmapMimeType= poConfig->Read( wxT( "PdfBitmapMimeType" ), wxT( "image/png" ) );
03054 #endif // __WXPDFDOC__
03055 
03056     // Get OCR and tts configuration.
03057     m_bAutoApplyProfile= (bool)poConfig->Read( wxT( "AutoApplyProfile" ), (long)false );
03058     m_bAutoApplyProfileOnMultiPage= (bool)poConfig->Read( wxT( "AutoApplyProfileOnMultiPage" ), (long)false );
03059     m_strOcrOutputExtension= poConfig->Read( wxT( "OcrOutputExtension" ), wxT( "txt" ) );
03060     m_bCmdConvertEnable= poConfig->Read( wxT( "CmdConvertEnable" ), (long)false );
03061     m_strCmdConvert= poConfig->Read( wxT( "CmdConvert" ), wxT( "convert %s -compress Group4 %s.tif" ) );
03062     m_bCmdOcrEnable= poConfig->Read( wxT( "CmdOcrEnable" ), (long)false );
03063     m_strCmdOcr= poConfig->Read( wxT( "CmdOcr" ), wxT( "cuneiform -f text -o %s.txt %s.tif" ) );
03064     m_bOCR= (bool)poConfig->Read( wxT( "OCR" ), (long)false );
03065 #if __WXLUASCRIPT__
03066     m_bLua= (bool)poConfig->Read( wxT( "Lua" ), (long)false );
03067 #endif // __WXLUASCRIPT__
03068     m_bCmdCleanUpEnable= poConfig->Read( wxT( "CmdCleanUpEnable" ), (long)false );
03069     m_strCmdCleanUp= poConfig->Read( wxT( "CmdCleanUp" ), wxT( "rm %s.tif" ) );
03070     m_bCmdTtsEnable= poConfig->Read( wxT( "CmdTtsEnable" ), (long)false );
03071     m_strCmdTts= poConfig->Read( wxT( "CmdTts" ), wxT( "espeak -f %s" ) );
03072     m_bCmdEditEnable= poConfig->Read( wxT( "CmdEditEnable" ), (long)false );
03073     m_strCmdEdit= poConfig->Read( wxT( "CmdEdit" ), wxT( "scite %s" ) );
03074     m_bHocrEnable= poConfig->Read( wxT( "HocrEnable" ), (long)false );
03075     m_strHocrClass= poConfig->Read( wxT( "HocrClass" ), wxT( "ocr_line" ) );
03076     m_bSmartHocrEnable= poConfig->Read( wxT( "SmartHocrEnable" ), (long)false );
03077     m_strCmdOcrUseHocr= poConfig->Read( wxT( "CmdOcrUseHocr" ), wxT( "cuneiform -f hocr -o %s.html %s.tif" ) );
03078     m_strOcrOutputExtensionHocr= poConfig->Read( wxT( "OcrOutputExtensionHocr" ), wxT( "html" ) );
03079     m_bCmdHtml2XhtmlEnable= poConfig->Read( wxT( "CmdHtml2XhtmlEnable" ), (long)false );
03080     m_strCmdHtml2Xhtml= poConfig->Read( wxT( "CmdHtml2Xhtml" ), wxT( "tidy -q -m -numeric -asxhtml -utf8 %s" ) );
03081     m_bCmdHocrCleanUpEnable= poConfig->Read( wxT( "CmdHocrCleanUpEnable" ), (long)false );
03082     m_strCmdHocrCleanUp= poConfig->Read( wxT( "CmdHocrCleanUp" ), wxT( "rm -r %s_files" ) );
03083 
03084     // Restore the standard resolution.
03085     m_nResolution= poConfig->Read( wxT( "Resolution" ), 300 );
03086 
03087     // Reset sash positions and splitting options.
03088     RestoreSashSettings();
03089 }
03090 
03091 // Restore sash settings from config file.
03092 //
03093 void wxIScanFrame::RestoreSashSettings()
03094 {
03095     // Reset window settings.
03096     wxConfigBase *poConfig = wxConfigBase::Get();
03097     poConfig->SetRecordDefaults();
03098     poConfig->SetPath( wxT( "/" )  );
03099     poConfig->SetPath( cstrwxFrame );
03100 
03101     // Reset sash positions and splitting options.
03102     int nHSashPos= poConfig->Read( wxT( "HSashPos" ), -1 );
03103     int nVSashPos= poConfig->Read( wxT( "VSashPos" ), -1 );
03104 
03105     m_poHSplitterWindow->SetSashPosition( nHSashPos );
03106     m_poVSplitterWindow->SetSashPosition( nVSashPos );
03107 }
03108 
03109 // Save program settings in config file.
03110 //
03111 void wxIScanFrame::SaveSettings()
03112 {
03113     // Save configuration data.
03114     wxConfigBase *poConfig= wxConfigBase::Get();
03115 
03116     poConfig->SetPath( wxT( "/" ) );
03117     poConfig->SetPath( cstrwxFrame );
03118 
03119     // Save iconifization state.
03120     poConfig->Write( wxT( "Iconized" ),  (long)IsIconized() );
03121     if( IsIconized() )
03122     {
03123         Iconize( false );
03124     }
03125 
03126     // Save maximization state.
03127     poConfig->Write( wxT( "Maximized" ),  (long)IsMaximized() );
03128     if( IsMaximized() )
03129     {
03130         Maximize( false );
03131         ::wxSafeYield();
03132         ::wxSafeYield();
03133     }
03134 
03135     // Save full screen state.
03136     poConfig->Write( wxT( "FullScreen" ),  (long)IsFullScreen() );
03137     if( IsFullScreen() )
03138     {
03139         ToggleFullScreen();
03140         ::wxSafeYield();
03141         ::wxSafeYield();
03142         ::wxSafeYield();
03143     }
03144 
03145     // Save window position and size.
03146     //
03147     int x, y, w, h;
03148 
03149     GetSize( &w, &h );
03150     GetPosition( &x, &y );
03151     poConfig->Write( wxT( "x" ), (long)x );
03152     poConfig->Write( wxT( "y" ), (long)y );
03153     poConfig->Write( wxT( "w" ), (long)w );
03154     poConfig->Write( wxT( "h" ), (long)h );
03155 
03156     // Save the sash positions.
03157     poConfig->Write( wxT( "HSashPos" ), (long)m_poHSplitterWindow->GetSashPosition() );
03158     poConfig->Write( wxT( "VSashPos" ), (long)m_poVSplitterWindow->GetSashPosition() );
03159 
03160     // Save the resolution as standard resolution.
03161     poConfig->Write( wxT( "Resolution" ), (long)m_nResolution );
03162 
03163     // ...
03164     poConfig->Write( wxT( "PaperSize" ), (long)m_oPrintData.GetPaperId() );
03165     poConfig->Write( wxT( "Fit" ), (long)m_nFit );
03166     poConfig->Write( wxT( "ScaleFactor" ), m_nScaleFactor );
03167     poConfig->Write( wxT( "ZoomFactor" ), m_nZoomFactor );
03168 
03169     // ...
03170     poConfig->Write( wxT( "BitmapMimeType" ), m_strBitmapMimeType );
03171 
03172 #if __WXPDFDOC__
03173     // ...
03174     poConfig->Write( wxT( "PdfBitmapMimeType" ), m_strPdfBitmapMimeType );
03175 #endif // __WXPDFDOC__
03176 
03177     // ...
03178     poConfig->Write( wxT( "AutoApplyProfile" ), (long)m_bAutoApplyProfile );
03179     poConfig->Write( wxT( "AutoApplyProfileOnMultiPage" ), (long)m_bAutoApplyProfileOnMultiPage );
03180     poConfig->Write( wxT( "OCR" ), (long)m_bOCR );
03181 #if __WXLUASCRIPT__
03182     poConfig->Write( wxT( "Lua" ), (long)m_bLua );
03183 #endif // __WXLUASCRIPT__
03184     poConfig->Write( wxT( "CmdConvertEnable" ), (long)m_bCmdConvertEnable );
03185     poConfig->Write( wxT( "CmdConvert" ), m_strCmdConvert );
03186     poConfig->Write( wxT( "CmdOcrEnable" ), (long)m_bCmdOcrEnable );
03187     poConfig->Write( wxT( "CmdOcr" ), m_strCmdOcr );
03188     poConfig->Write( wxT( "OcrOutputExtension" ), m_strOcrOutputExtension );
03189     poConfig->Write( wxT( "CmdCleanUpEnable" ), (long)m_bCmdCleanUpEnable );
03190     poConfig->Write( wxT( "CmdCleanUp" ), m_strCmdCleanUp );
03191     poConfig->Write( wxT( "CmdTtsEnable" ), (long)m_bCmdTtsEnable );
03192     poConfig->Write( wxT( "CmdTts" ), m_strCmdTts );
03193     poConfig->Write( wxT( "CmdEditEnable" ), (long)m_bCmdEditEnable );
03194     poConfig->Write( wxT( "CmdEdit" ), m_strCmdEdit );
03195     poConfig->Write( wxT( "HocrEnable" ), (long)m_bHocrEnable );
03196     poConfig->Write( wxT( "HocrClass" ), m_strHocrClass );
03197     poConfig->Write( wxT( "SmartHocrEnable" ), (long)m_bSmartHocrEnable );
03198     poConfig->Write( wxT( "CmdOcrUseHocr" ), m_strCmdOcrUseHocr );
03199     poConfig->Write( wxT( "OcrOutputExtensionHocr" ), m_strOcrOutputExtensionHocr );
03200     poConfig->Write( wxT( "CmdHtml2XhtmlEnable" ), (long)m_bCmdHtml2XhtmlEnable );
03201     poConfig->Write( wxT( "CmdHtml2Xhtml" ), m_strCmdHtml2Xhtml );
03202     poConfig->Write( wxT( "CmdHocrCleanUpEnable" ), (long)m_bCmdHocrCleanUpEnable );
03203     poConfig->Write( wxT( "CmdHocrCleanUp" ), m_strCmdHocrCleanUp );
03204 
03205     // ...
03206     poConfig->Write( wxT( "ProfileIndex" ), m_nProfileIndex );
03207 
03208     // Save file history to config file.
03209     poConfig->SetPath( wxT( "/Files" ) );
03210     m_oFileHistory.Save( *poConfig );
03211 }
03212 
03213 // Printing support.
03214 //
03215 // Paints the image while printing or print previewing.
03216 //
03217 // NOTE: The painting on the screen is done by void wxIViewCanvas::Paint( wxDC& oDc )!
03218 //
03219 bool wxIScanFrame::Paint( wxDC& oDc )
03220 {
03221     // If there is a bitmap connected to this canvas window (re)paint it.
03222 #if wxCHECK_VERSION( 2, 9, 0 )
03223     if( oDc.IsOk() && m_oPrintImage.Ok() )
03224 #else
03225     if( oDc.Ok() && m_oPrintImage.Ok() )
03226 #endif // wxCHECK_VERSION( 2, 9, 0 )
03227 
03228     {
03229         // Repaint the bitmap.
03230         oDc.DrawBitmap( wxBitmap( m_oPrintImage ), 0, 0 );
03231         return true;
03232     }
03233     else
03234     {
03235         return false;
03236     }
03237 }
03238 
03239 // Calculates the image extents in mm while printing or print previewing.
03240 //
03241 bool wxIScanFrame::GetPageSizeMM( int *pnWidth, int *pnHeight )
03242 {
03243      if( m_oPrintImage.Ok() )
03244      {
03245          (*pnWidth)=  (int)( (double)m_oPrintImage.GetWidth()  / (double)m_nResolution * 25.4 );
03246          (*pnHeight)= (int)( (double)m_oPrintImage.GetHeight() / (double)m_nResolution * 25.4 );
03247          return true;
03248      }
03249      else
03250      {
03251          return false;
03252      }
03253 }
03254 
03255 // Go to a given printer page.
03256 //
03257 bool wxIScanFrame::GotoPage( int nPage )
03258 {
03259     // NOTE: The wxPrintOut object passes pages one-based. We need it
03260     //        zero-based. Therefore we decrement the page number by 1.
03261     //
03262     nPage--;
03263 
03264     // Avoid loading an already loaded image.
03265     if( nPage == m_nPage )
03266     {
03267         m_oPrintImage= m_oImage;
03268         return true;
03269     }
03270     else
03271     {
03272         return m_oPrintImage.LoadFile( m_strImageFileName, wxBITMAP_TYPE_ANY, nPage );
03273     }
03274 }