%% options # __CHANGE__ 001: Correct copyright owner if necessary. copyright owner = Dirk Krause # __CHANGE__ 003: Correct copyright year(s) if necessary. copyright year = 2013-xxxx # __CHANGE__ 002: Correct license type if necessary. # Use "bsd", "gpl", "lgpl", or "commercial". license = bsd %% wx-gui type = frame contents = mainSizer icon = winprint_icon tool bar = tbMain status bar = 1 sTexts[8] menu bar = mbMain [wxToolBar tbMain] contents = bRun contents = bExit [wxToolBarToolBase bRun] text = sTexts[15] bitmap = xpm_run_conversion id = WinprintFrame_Print tip = sTexts[16] [wxToolBarToolBase bExit] text = sTexts[1] bitmap = xpm_exit_program id = WinprintFrame_Quit tip = sTexts[2] [wxMenuBar mbMain] contents = menuFile contents = menuHelp [wxMenu menuFile] text = sTexts[0] contents = miFilePrint contents = miFileExit [wxMenuItem miFilePrint] id = WinprintFrame_Print text = sTexts[15] tip = sTexts[16] [wxMenuItem miFileExit] id = WinprintFrame_Quit text = sTexts[1] tip = sTexts[2] [wxMenu menuHelp] text = sTexts[3] contents = miHelpAbout contents = miHelpContents [wxMenuItem miHelpAbout] id = WinprintFrame_Help_About text = sTexts[4] tip = sTexts[5] [wxMenuItem miHelpContents] id = WinprintFrame_Help_Contents text = sTexts[6] tip = sTexts[7] [wxBoxSizer mainSizer] direction = horizontal contents = $space(10) contents = verticalSizer contents = $space(10) [wxBoxSizer verticalSizer] direction = vertical grow = yes proportion = 1 contents = $space(10) contents = contentsSizer contents = $space(10) [wxGridBagSizer contentsSizer] grid = 5 5 # __CHANGE__ 015: The dummy label was added to have at least # one GUI element in the sizer. # Remove tStatus (next 4 lines) and add the real # window contents here. contents = tStatus 0 0 1 1 left [wxStaticText tStatus] text = sTexts[13] %% header start #ifdef DK3_USE_WX #undef DK3_USE_WX #endif /** Use wxWidgets libraries to build GUI programs. */ #define DK3_USE_WX 1 %% class start class WinprintFrame : public DkWxFrame { private: /** Event table for frame. */ DECLARE_EVENT_TABLE() protected: /** Black color for status label. */ wxColour cBlack; /** Green color for status label. */ wxColour cGreen; /** Red color for status label. */ wxColour cRed; /** Printer names. */ DK3_PCWXCHAR *pNames; /** Printer names as wxString array. */ wxString *wxsNames; /** Size of printer names array. */ size_t nNames; /** Index of default printer in array. */ int nDefPrinter; /** File dialog x position. */ int fdx; /** File dialog y position. */ int fdy; /** Printer chooser dialog x position. */ int pcx; /** Printer chooser dialog y position. */ int pcy; /** Localized texts. */ wxChar const * const *sTexts; /** Non-localized texts. */ wxChar const * const *sNlWx; /** Non-localized texts. */ dkChar const * const *sNlDk; /** Print configuration. */ dk3_print_conf_t *pc; /** Use default printer. */ BOOL bUseDefaultPrinter; /** Use named printer. */ wxChar const *sNamedPrinter; /** Named file to process. */ wxChar const *sNamedFile; /** Communicator object. */ DkWxCommunicator *pComm; /** Time to close the application. */ dk3_time_t timeClose; /** Flag: Closing the application is scheduled. */ BOOL bCloseScheduled; /** Flag: Autostart wanted. */ BOOL bAutostartWanted; %% class end public: /** Constructor. @param wxid Window ID. @param applicationHelper Application helper object. @param hc Help controller for online help. @param argc Number of command line arguments. @param argv Command line arguments array. @param localizedTexts Localized wxChar texts. @param nlWx Non-localized wxChar texts. @param nlDk Non-localized dkChar texts. @param pPrintConf Print configuration. */ WinprintFrame( int wxid, DkWxAppHelper *applicationHelper, DkWxHelpController *hc, int argc, wxChar **argv, wxChar const * const *localizedTexts, wxChar const * const *nlWx, dkChar const * const *nlDk, dk3_print_conf_t *pPrintConf, DK3_PCWXCHAR *printerNames, size_t numberOfPrinters, int defaultPrinterIndex ); /** Destructor. */ ~WinprintFrame(); /** Check whether we can close the window. @param isLast Flag: Last main window to close. */ bool canClose(bool isLast); /** Handler for File/Exit. @param event Event to process. */ void OnQuit(wxCommandEvent & event); /** Handler for Help/About. @param event Event to process. */ void OnAbout(wxCommandEvent & event); /** Handler for Help/Contents. @param event Event to process. */ void OnHelpContents(wxCommandEvent & event); /** Handler for print menu item. @param event Event to process. */ void OnPrint(wxCommandEvent & event); /* __CHANGE__ 008: Remove OnIdle if no idle processing required. */ /** Handler for idle events. */ void OnIdle(wxIdleEvent & event); /* __CHANGE__ 017: Event handlers for further events. */ /* __CHANGE__ 014: Add further methods. */ /** Run for a print job. */ int runJob(void); /** Set error status. @param txt Error message text. @param filename Current filename to process. */ void setErrorStatus(wxChar const *txt, wxChar const *filename); }; %% header end %% module start #include "winprint.h" #if 0 #include "dkt-version.h" #endif #include "dk4verswx.h" #include "dk4verswx.h" #include "run-conversion.xpm" #include "exit-program.xpm" #if !defined(__WXMSW__) #include "winprint.xpm" #endif $!trace-include /* __CHANGE__ 017: Add further events. */ /* __CHANGE__ 008: Remove OnIdle if no idle processing required. */ BEGIN_EVENT_TABLE(WinprintFrame, wxFrame) EVT_MENU(WinprintFrame_Quit, WinprintFrame::OnQuit) EVT_MENU(WinprintFrame_Print, WinprintFrame::OnPrint) EVT_MENU(WinprintFrame_Help_About, WinprintFrame::OnAbout) EVT_MENU(WinprintFrame_Help_Contents, WinprintFrame::OnHelpContents) EVT_IDLE(WinprintFrame::OnIdle) END_EVENT_TABLE() static const wxCmdLineEntryDesc winprint_cmd_line_desc[] = { { wxCMD_LINE_OPTION, wxT_2("P"), wxT_2("printer"), wxT_2("choose printer"), wxCMD_LINE_VAL_STRING }, { wxCMD_LINE_SWITCH, wxT_2("d"), wxT_2("default"), wxT_2("Use default printer") }, { wxCMD_LINE_PARAM, NULL, NULL, wxT_2("input file"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_NONE } }; %% constructor start WinprintFrame::WinprintFrame( int wxid, DkWxAppHelper *applicationHelper, DkWxHelpController *hc, int argc, wxChar **argv, wxChar const * const *localizedTexts, wxChar const * const *nlWx, dkChar const * const *nlDk, dk3_print_conf_t *pPrintConf, DK3_PCWXCHAR *printerNames, size_t numberOfPrinters, int defaultPrinterIndex ) : DkWxFrame(nlWx[0], applicationHelper, hc, wxid), cBlack(0, 0, 0), cGreen(0, 127, 0), cRed(127, 0, 0) { /* __CHANGE__ 012: Add further local variables. */ size_t i; /* Traverse pNames when creating wxsNames. */ /* __CHANGE__ 012: Initialize further local variables. */ fdx = -1; fdy = -1; pcx = -1; pcy = -1; wxsNames = NULL; pNames = printerNames; nNames = numberOfPrinters; nDefPrinter = defaultPrinterIndex; pComm = NULL; bCloseScheduled = false; bAutostartWanted = false; timeClose = (dk3_time_t)0UL; sNamedFile = NULL; sNamedPrinter = NULL; bUseDefaultPrinter = false; sTexts = localizedTexts; sNlWx = nlWx; sNlDk = nlDk; pc = pPrintConf; #if defined(__WXMSW__) wxIcon winprint_icon(sNlWx[4]); #else wxIcon winprint_icon(winprint_xpm); #endif /* __CHANGE__ 011: Initialize further class members. */ %% constructor end if(dkctGUILayoutOK) { SetTitle(nlWx[0]); #if 0 restorePosition(); #endif } if((pNames) && (nNames > 0)) { wxsNames = new wxString[nNames]; if(wxsNames) { for(i = 0; i < nNames; i++) { wxsNames[i] = wxString(pNames[i]); } } } pComm = new DkWxCommunicator( applicationHelper->getWxEncoding(), applicationHelper->getDkEncoding() ); if(argc > 1) { bAutostartWanted = true; { wxChar const *ptr; int res = -1; wxCmdLineParser parser(winprint_cmd_line_desc, argc, argv); { wxLogNull log; res = parser.Parse(false); } if(0 == res) { wxString sPrinter(wxT("")); if(pComm) { pComm->autostartEnable(true); } if(parser.Found(wxT("d"))) { /* Use default printer */ bUseDefaultPrinter = true; } else { if(parser.Found(wxT("P"), &sPrinter)) { /* Use named printer */ ptr = sPrinter.c_str(); if(ptr) { if(sNamedPrinter) { dk3_release(sNamedPrinter); } sNamedPrinter = dk3wxs_dup(ptr); } } } if(parser.GetParamCount() > 0) { wxString cmdfn; wxString fullPath; /* Print named file(s) */ cmdfn = parser.GetParam(0); wxFileName fn(cmdfn); fn.Normalize( wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE ); fullPath = fn.GetFullPath(); ptr = fullPath.c_str(); if(ptr) { if(sNamedFile) { dk3_release(sNamedFile); } sNamedFile = dk3wxs_dup(ptr); } } } } } } %% module end WinprintFrame::~WinprintFrame() { size_t i; /* Index of current string to delete. */ /* __CHANGE__ 011: Release resources allocated by further class members. */ if(wxsNames) { for(i = 0; i < nNames; i++) { wxsNames[i] = wxString(wxT("")); } delete [] wxsNames; } dk3_cpp_release(pComm); if(sNamedPrinter) { dk3_release(sNamedPrinter); sNamedPrinter = NULL; } if(sNamedFile) { dk3_release(sNamedFile); sNamedFile = NULL; } } bool WinprintFrame::canClose(bool isLast) { bool back = true; /* __CHANGE__ 013: Check for unsaved data. */ return back; } void WinprintFrame::OnQuit(wxCommandEvent & event) { Close(); } void WinprintFrame::OnAbout(wxCommandEvent & event) { wxString text(wxT("")); /* Text to show. */ wxString title(wxT("")); /* Windows title. */ /* Construct message text. */ text.Append(sNlWx[0]); text.Append(sNlWx[7]); #if 0 text.Append(sNlWx[1]); #else text.Append( DKT_VERSION_WX ); #endif text.Append(sNlWx[8]); text.Append(sTexts[9]); text.Append(sNlWx[2]); text.Append(sNlWx[8]); text.Append(sNlWx[8]); text.Append(sTexts[11]); text.Append(sNlWx[8]); text.Append(sNlWx[9]); text.Append(sNlWx[8]); text.Append(sNlWx[8]); text.Append(sTexts[12]); text.Append(sNlWx[8]); text.Append(sNlWx[10]); text.Append(sNlWx[8]); text.Append(sNlWx[11]); text.Append(sNlWx[8]); text.Append(sNlWx[12]); text.Append(sNlWx[8]); text.Append(sNlWx[13]); text.Append(sNlWx[8]); text.Append(sNlWx[14]); text.Append(sNlWx[8]); text.Append(sNlWx[15]); text.Append(sNlWx[8]); /* Construct dialog box title. */ title.Append(sTexts[10]); title.Append(sNlWx[0]); /* Show dialog box. */ wxMessageBox(text, title, wxOK, this); /* __CHANGE__ 019: Create better about box. */ } void WinprintFrame::OnHelpContents(wxCommandEvent & event) { openHelp(); } /* __CHANGE__ 017: Event handlers for further events. */ void WinprintFrame::OnPrint(wxCommandEvent & event) { (void)runJob(); } /* __CHANGE__ 014: Implementation of further methods. */ /* __CHANGE__ 008: Remove OnIdle if no idle processing required. */ void WinprintFrame::OnIdle(wxIdleEvent & event) { static BOOL firstIdle = true; /* Flag: First idle event of application. */ dk3_time_t ct; /* Current time. */ int res; /* Operation result. */ $? "+ WinprintFrame::OnIdle" /* __CHANGE__ */ if(firstIdle) { $? ". first idle event" firstIdle = false; tStatus->SetLabel(wxT("")); Refresh(); Update(); /* For autostart */ event.RequestMore(); } else { $? ". not the first idle event" if(!bCloseScheduled) { $? ". no close scheduled" if(pComm) { $? ". pComm" if((bAutostartWanted) && (pComm->autostartCanRun())) { $? ". autostart wanted and possible" res = runJob(); if(res > 0) { $? ". request more" event.RequestMore(); } } else { $? ". autostart not wanted or not possible" if(pComm->autostartIsFinished()) { $? ". autostart finished" if(!(timeClose)) { $? ". no close time yet" if(pComm->getLogLevel() > DK3_LL_WARNING) { $? ". can close" dk3sf_time(&timeClose); $? ". close time scheduled" event.RequestMore(); tStatus->SetLabel(sTexts[14]); $? ". tStatus 14" tStatus->SetForegroundColour(cGreen); Refresh(); Update(); } else { tStatus->SetLabel(pComm->getText()); $? ". tStatus pComm" tStatus->SetForegroundColour(cRed); Refresh(); Update(); wxMessageBox( pComm->getText(), sTexts[29], (wxICON_ERROR | wxOK), this ); dk3sf_time(&timeClose); $? ". can close" event.RequestMore(); } } } if(timeClose) { $? ". found scheduled close time" dk3sf_time(&ct); if(ct > (timeClose + (dk3_time_t)1UL)) { $? ". close now" timeClose = (dk3_time_t)0UL; bCloseScheduled = true; Show(false); Close(); } else { $? ". can not yet close" event.RequestMore(); } } } } else { $? "! pComm" /* ERROR: No communicator */ if(timeClose) { dk3sf_time(&ct); if(ct > (timeClose * (dk3_time_t)1UL)) { timeClose = (dk3_time_t)0UL; bCloseScheduled = true; Show(false); Close(); } else { event.RequestMore(); } } } } else { $? ". close scheduled" } } event.Skip(); $? "- WinprintFrame::OnIdle" } int WinprintFrame::runJob(void) { wxChar prbuf[512]; /* Printer name in system enc. */ wxString path; /* File path. */ wxChar const *filename = NULL; /* File name. */ wxChar const *printername = NULL; /* Printer name. */ int res; /* Operation result. */ int ok = 0; /* Flag: Success. */ int back = 0; $? "+ WinprintFrame::runJob" tStatus->SetLabel(sTexts[17]); $? ". tStatus 17" tStatus->SetForegroundColour(cBlack); Refresh(); Update(); if(sNamedFile) { $? ". named file" filename = sNamedFile; } else { $? ". no named file" wxString s(wxT("")); s.Append(wxT("Print files (*.prn)|*.prn")); s.Append(wxT("|All files (*.*)|*.*")); #if wxCHECK_VERSION(2, 9, 0) wxFileDialog dlg(this, sTexts[18], wxT("."), wxT(""), s, wxFD_OPEN); #else wxFileDialog dlg(this, sTexts[18], wxT("."), wxT(""), s, wxOPEN); #endif pHelper->setRelatedPosition(this, &dlg, &fdx, &fdy); if(wxID_OK == dlg.ShowModal()) { path = dlg.GetPath(); filename = path.c_str(); } else { /* Aborted by user */ setErrorStatus(sTexts[19], NULL); $? ". setErrorStatus 19" } dlg.GetPosition(&fdx, &fdy); } if(filename) { $? ". have file" if(bUseDefaultPrinter) { $? ". use default printer" if(pc) { $? ". have print conf" if(pc->defPrinter) { $? ". default printer" if((pc->defPrinter->name)) { $? ". default printer name ok" res = dk3wxs_from_dkstr( prbuf, DK3_SIZEOF(prbuf,wxChar), pHelper->getWxEncoding(), (pc->defPrinter)->name, pHelper->getDkEncoding() ); if(res) { $? ". name conversion ok" printername = prbuf; } else { $? "! name conversion failed" /* ERROR: Failed to convert printer name! */ setErrorStatus(sTexts[24], filename); $? ". setErrorStatus 24" } } else { $? "! no default printer name" /* ERROR: No default printer name */ setErrorStatus(sTexts[25], filename); $? ". setErrorStatus 25" } } else { $? "! no default printer" /* ERROR: No default printer */ setErrorStatus(sTexts[25], filename); $? ". setErrorStatus 25" } } else { $? "! no print conf" /* ERROR: No print configuration */ setErrorStatus(sTexts[26], filename); $? ". setErrorStatus 26" } } else { $? ". non-default printer" if(sNamedPrinter) { $? ". named printer" printername = sNamedPrinter; } else { $? ". choose printer" if((pNames) && (wxsNames) && (nNames > 0)) { $? ". variables" WinprintChooserDialog dlg(this, sTexts[30], sTexts, wxsNames, nNames); dlg.setCurrentPrinter(nDefPrinter); pHelper->setRelatedPosition(this, &dlg, &pcx, &pcy); if(wxID_OK == dlg.ShowModal()) { $? ". dialog ok" nDefPrinter = dlg.getCurrentPrinter(); if((nDefPrinter >= 0) && (nDefPrinter < (int)nNames)) { $? ". ok" printername = pNames[nDefPrinter]; } else { $? "! wrong index" /* BUG: Illegal return value from dialog */ setErrorStatus(sTexts[26], filename); $? ". setErrorStatus 26" } } else { $? ". aborted by user" /* ERROR: Aborted by user */ setErrorStatus(sTexts[19], filename); $? ". setErrorStatus 19" } dlg.GetPosition(&pcx, &pcy); } else { $? "! variables" /* ERROR: No printer configuration */ setErrorStatus(sTexts[26], filename); $? ". setErrorStatus 26" } } } } else { $? "! no file name" } if((filename) && (printername)) { $? ". both names ok" /* wxMessageBox(filename, printername); */ if(pComm) { $? ". communicator ok" DkWxProgressDialog *pd; pComm->prepareRun(); pd = new DkWxProgressDialog( (DkWxFrame *)this, pComm, NULL, sTexts[20], filename, sTexts[21], sTexts[22], sTexts[23] ); if(pd) { $? ". pd" WinprintThread *pt; pt = new WinprintThread( pComm, sTexts, pHelper, pc, filename, printername ); if(pt) { $? ". pt" if(wxTHREAD_NO_ERROR == pt->Create()) { $? ". pt->Create" pt->SetPriority(WXTHREAD_DEFAULT_PRIORITY); pt->Run(); pd->chooseModalPosition(); pd->ShowModal(); ok = 1; if(pComm->getLogLevel() <= DK3_LL_WARNING) { $? "! warning" /* ERRORS occured */ tStatus->SetLabel(pComm->getText()); $? ". tStatus pComm" tStatus->SetForegroundColour(cRed); } else { $? ". success" /* Transfer succeeeded */ if(!(bAutostartWanted)) { tStatus->SetLabel(sTexts[37]); $? ". tStatus 37" tStatus->SetForegroundColour(cGreen); } } Refresh(); Update(); back = 1; } else { $? "! pt->Create" /* ERROR: Create method failed! */ setErrorStatus(sTexts[27], filename); $? ". setErrorStatus 27" } } else { $? "! pt" /* ERROR: Failed to create thread */ setErrorStatus(sTexts[27], filename); $? ". setErrorStatus 27" } pd->Destroy(); } else { $? "! pd" /* ERROR: Failed to create progress dialog */ setErrorStatus(sTexts[28], filename); $? ". setErrorStatus 28" } } else { $? "! communicator" /* ###### ERROR: No communicator */ } } else { $? "! name missing" if(pComm) { if(!(filename)) { } if(!(printername)) { } } else { /* ##### ERROR: No communicator */ } } $? "- WinprintFrame::runJob %d", back return back; } void WinprintFrame::setErrorStatus(wxChar const *txt, wxChar const *filename) { if(pComm) { pComm->prepareRun(); pComm->addWxText(txt); pComm->setLogLevel(DK3_LL_ERROR); pComm->setUpdates(((filename) ? filename : wxT("")), 1000); pComm->setRunning(0); } tStatus->SetLabel(txt); tStatus->SetForegroundColour(cRed); Refresh(); Update(); }