%% options copyright owner = Dirk Krause copyright year = 2011-xxxx license = bsd %% header /** Worker thread for wxbmeps. */ class DkWxBmepsThread : public wxThread { protected: /** Conversion options. */ dk3_bm_eps_options_t bmeo; /** Communication object to communicate with main thread. */ DkWxCommunicator *pComm; /** Localized messages, wxChar strings. */ wxChar const * const *sTexts; /** Localized messages, dkChar strings. */ dkChar const * const *msg; /** Directory or file name. */ wxChar const *sDirectory; /** Application helper. */ DkWxAppHelper *pHelper; /** Encoding for wxChar strings. */ int wxenc; /** Encoding for dkChar strings. */ int dkenc; public: /** Constructor. @param pc Communication object. @param st Localized messages, wxChar strings. @param m Localized messages, dkChar strings. @param sd Directory or file name. @param ph Application helper. @param wxe Encoding for wxChar strings. @param dke Encoding for dkChar strings. @param bmeoptr Conversion options. */ DkWxBmepsThread( DkWxCommunicator *pc, wxChar const * const *st, dkChar const * const *m, wxChar const *sd, DkWxAppHelper *ph, int wxe, int dke, dk3_bm_eps_options_t *bmeoptr ); /** Destructor. */ ~DkWxBmepsThread(); /** Check setup (memory allocations succeeded). @return Test result, true on success, false on error. */ bool checkSetup(); /** Thread function. @return A pointer which is ignored. */ virtual void * Entry(); /** Function executed at end of thread, does nothing. */ virtual void OnExit(); /** Run for one file. @param fn File name. @param ming Minimum value for progress bar. @param maxg Maximum value for progress bar. */ void runForFile(wxChar const *fn, int ming, int maxg); /** Run for one directory. @param dn Directory name. */ void runForDirectory(wxChar const *dn); /** Check whether we must run for a file. @param sfn Source file name. @return true for must run, false for not necessary. */ bool checkMustRun(wxChar const *sfn); /** Get short file name. @param longName Full file name. @return Pointer to short file name on success, NULL on error. */ wxChar const * shortFileName(wxChar const *longName); }; %% module #include "wxbmeps.h" $!trace-include /** File name separator. */ static wxChar const dkwxbmeps_fnsep[] = { DK3_WX_CHAR_SEP , wxT('\0') }; static wxChar const * const dkwxbmeps_output_suffixes[] = { wxT(".ps"), wxT(".eps"), wxT(".pdf"), wxT(".bb") }; /** Non-localized keywords used by this module. */ static wxChar const * const dkwxbmeps_thread_kw[] = { $!string-table macro=wxT # # 0: File specification. # *.* $!end }; /** File suffixes we can handle. */ static wxChar const * const dkwxbmeps_thread_suffixes[] = { #if DK3_HAVE_PNG_H wxT(".png"), #endif #if DK3_HAVE_JPEGLIB_H wxT(".jpg"), wxT(".jpeg"), #endif #if DK3_HAVE_TIFF_H wxT(".tif"), wxT(".tiff"), #endif NULL }; DkWxBmepsThread::DkWxBmepsThread( DkWxCommunicator *pc, wxChar const * const *st, dkChar const * const *m, wxChar const *sd, DkWxAppHelper *ph, int wxe, int dke, dk3_bm_eps_options_t *bmeoptr ) { $? "+ DkWxBmepsThread::DkWxBmepsThread" pComm = pc; sTexts = st; msg = m; sDirectory = dk3wxs_dup_app(sd, ph->getApp()); pHelper = ph; wxenc = wxe; dkenc = dke; dk3mem_cpy((void *)(&bmeo), (void *)bmeoptr, sizeof(dk3_bm_eps_options_t)); bmeo.to_stdout = 0; $? "- DkWxBmepsThread::DkWxBmepsThread" } bool DkWxBmepsThread::checkSetup() { bool back = false; $? "+ DkWxBmepsThread::checkSetup" if(sDirectory) { back = true; } $? "- DkWxBmepsThread::checkSetup %d", (back ? 1 : 0) return back; } DkWxBmepsThread::~DkWxBmepsThread() { $? "+ DkWxBmepsThread::~DkWxBmepsThread" dk3_release(sDirectory); $? "- DkWxBmepsThread::~DkWxBmepsThread" } void * DkWxBmepsThread::Entry() { #if 0 /* Simple test thread without practical use. */ int i = 0; int cc = 1; int numbreak = -1; do { this->Sleep(100); i++; if(i >= 10) { cc = 0; } pComm->setUpdates(wxT("test-file"), (100*i)); if(pComm->getCanContinue() == 0) { if(numbreak == -1) { numbreak = i; } else { if(i >= numbreak + 15) { cc = 0; } } } pComm->addWxText(wxT("Test mit einer ganz ganz ganz ganz langen Zeile\n")); } while(cc); pComm->setRunning(0); #else $? "+ DkWxBmepsThread::Entry" if(wxFileName::DirExists(sDirectory)) { $? ". handle directory" runForDirectory(sDirectory); } else { $? ". check for single file" if(wxFileName::FileExists(sDirectory)) { $? ". file" runForFile(sDirectory, 0, 1000); } else { $? "! no such file" /* ##### ERROR: No such file or directory! */ } } pComm->setRunning(0); $? "- DkWxBmepsThread::Entry" #endif return NULL; } void DkWxBmepsThread::OnExit() { /* Doing nothing. */ $? "= DkWxBmepsThread::OnExit" } /** Compare two wxChar file names. @param l Left file name. @param r Right file name. @param cr Comparison criteria (ignored). @return Comparison result. */ static int dkwxbmeps_compare_filenames(void const *l, void const *r, int cr) { int back = 0; if(l) { if(r) { #if DK3_HAVE_FNCASEINS back = dk3wxs_casecmp((wxChar const *)l, (wxChar const *)r); #else back = dk3wxs_cmp((wxChar const *)l, (wxChar const *)r); #endif if(back < -1) back = -1; if(back > 1) back = 1; } else { back = 1; } } else { if(r) { back = -1; } } return back; } void DkWxBmepsThread::runForFile(wxChar const *fn, int ming, int maxg) { dkChar sfn[DK3_MAX_PATH]; wxChar const *shortname; $? "+ DkWxBmepsThread::runForFile \"%ls\"", fn shortname = shortFileName(fn); if(dk3wxs_to_dkstr( sfn, DK3_SIZEOF(sfn,dkChar), pHelper->getDkEncoding(), fn, pHelper->getWxEncoding() ) ) { /* PROGRESS MESSAGE Start */ pComm->addWxText(sTexts[114]); pComm->addWxText(shortname); pComm->addWxText(sTexts[115]); pComm->addWxText(sTexts[110]); (void)dk3bm_process_file_name( &bmeo, sfn, DK3_BIF_IMAGE_TYPE_UNKNOWN, ming, maxg, (void *)pComm ); /* PROGRESS MESSAGE Finished */ #if 0 pComm->addWxText(sTexts[116]); pComm->addWxText(shortname); pComm->addWxText(sTexts[117]); pComm->addWxText(sTexts[110]); #endif pComm->addWxText(sTexts[110]); } else { $? "! failed to convert file name to dkChar string" /* ERROR: Failed to convert file name! */ pComm->addWxText(sTexts[118]); pComm->addWxText(shortname); pComm->addWxText(sTexts[119]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } pComm->setUpdates(NULL, maxg); $? "- DkWxBmepsThread::runForFile" } void DkWxBmepsThread::runForDirectory(wxChar const *dn) { wxChar namein[DK3_MAX_PATH]; wxChar const *currentfn; wxChar const *cfilename; wxChar *suffix; dk3_sto_t *sFiles; dk3_sto_it_t *iFiles; size_t fnlgt; int namesFound; int i; int promille; int cc; $? "+ DkWxBmepsThread::runForDirectory \"%ls\"", dn pComm->addWxText(sTexts[106]); pComm->addWxText(dn); pComm->addWxText(sTexts[107]); pComm->addWxText(sTexts[110]); pComm->addWxText(sTexts[110]); sFiles = dk3sto_open_app(pHelper->getApp()); if(sFiles) { dk3sto_set_comp(sFiles, dkwxbmeps_compare_filenames, 0); iFiles = dk3sto_it_open(sFiles); if(iFiles) { /* Find all input filename candidates. */ namesFound = 0; { wxLogNull lognull; bool canContinue; wxDir directory(sDirectory); if(directory.IsOpened()) { wxString filename; canContinue = directory.GetFirst( &filename, dkwxbmeps_thread_kw[0], wxDIR_FILES ); while(canContinue) { cfilename = filename.c_str(); if(cfilename) { if(dk3wxs_len(cfilename) < DK3_SIZEOF(namein,wxChar)) { dk3wxs_cpy(namein, cfilename); suffix = dk3wxs_get_suffix(namein); if(suffix) { if(dk3wxs_array_index(dkwxbmeps_thread_suffixes,suffix,0) > -1 ) { suffix = dk3wxs_dup_app(namein, pHelper->getApp()); if(suffix) { if(dk3sto_add(sFiles, suffix)) { namesFound++; $? ". registered \"%ls\"", suffix } else { /* ERROR: Memory */ dk3_release(suffix); pComm->addWxText(sTexts[105]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } } else { /* ERROR: Memory */ pComm->addWxText(sTexts[105]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } } } } else { /* ERROR: Name too long! */ pComm->addWxText(sTexts[111]); pComm->addWxText(cfilename); pComm->addWxText(sTexts[112]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } } canContinue = directory.GetNext(&filename); } } } pComm->setUpdates(NULL, 50); /* Process all input file name candidates. */ if(namesFound > 0) { dk3sto_it_reset(iFiles); i = 0; #if VERSION_BEFORE_20150821 /* Immediately set to 0 at loop begin */ cc = 1; #endif do { cc = 0; cfilename = (wxChar const *)dk3sto_it_next(iFiles); if(cfilename) { cc = 1; promille = 50 + (950 * i )/namesFound; if(promille >= 1000) { promille = 999; } pComm->setUpdates(cfilename, promille); $? ". file \"%ls\"", cfilename fnlgt = dk3wxs_len(sDirectory); fnlgt += dk3wxs_len(cfilename); fnlgt += 1; if(fnlgt < DK3_SIZEOF(namein,wxChar)) { dk3wxs_cpy(namein, sDirectory); dk3wxs_cat(namein, dkwxbmeps_fnsep); dk3wxs_cat(namein, cfilename); if(checkMustRun(namein)) { runForFile( namein, 50 + (950 * i )/namesFound, 50 + (950 * (i + 1))/namesFound ); } } else { /* ERROR: File name too long for buffer */ pComm->addWxText(sTexts[111]); pComm->addWxText(sDirectory); pComm->addWxText(dkwxbmeps_fnsep); pComm->addWxText(cfilename); pComm->addWxText(sTexts[112]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } i++; promille = 50 + (950 * i )/namesFound; if(promille >= 1000) { promille = 999; } pComm->setUpdates(cfilename, promille); if(!(pComm->getCanContinue())) { cc = 0; } } } while(cc); pComm->setUpdates(cfilename, 1000); } else { /* ERROR: No names found! */ pComm->addWxText(sTexts[113]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } /* Release the file names. */ dk3sto_it_reset(iFiles); while((currentfn = (wxChar const *)dk3sto_it_next(iFiles)) != NULL) { dk3_release(currentfn); } dk3sto_it_close(iFiles); } else { pComm->addWxText(sTexts[105]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } dk3sto_close(sFiles); } else { pComm->addWxText(sTexts[105]); pComm->addWxText(sTexts[110]); pComm->setLogLevel(DK3_LL_ERROR); } pComm->addWxText(sTexts[108]); pComm->addWxText(dn); pComm->addWxText(sTexts[109]); pComm->addWxText(sTexts[110]); $? "- DkWxBmepsThread::runForDirectory" } bool DkWxBmepsThread::checkMustRun(wxChar const *sfn) { wxChar nameout[DK3_MAX_PATH]; wxChar *suffix; wxChar const *nsuffix; bool back = true; if(bmeo.make) { dk3wxs_cpy(nameout, sfn); suffix = dk3wxs_get_suffix(nameout); if(suffix) { *suffix = wxT('\0'); nsuffix = NULL; switch(bmeo.dr) { case DK3_BMEPS_DRIVER_PS: { nsuffix = dkwxbmeps_output_suffixes[0]; } break; case DK3_BMEPS_DRIVER_EPS: { nsuffix = dkwxbmeps_output_suffixes[1]; } break; case DK3_BMEPS_DRIVER_PDF: { nsuffix = dkwxbmeps_output_suffixes[2]; } break; case DK3_BMEPS_DRIVER_BB: { nsuffix = dkwxbmeps_output_suffixes[3]; } break; } if(nsuffix) { if((dk3wxs_len(nameout) + dk3wxs_len(nsuffix)) < DK3_SIZEOF(nameout,wxChar) ) { dk3wxs_cat(nameout, nsuffix); if(wxFileName::FileExists(sfn)) { if(wxFileName::FileExists(nameout)) { wxFileName fni(sfn); wxFileName fno(nameout); if(fno.GetModificationTime() > fni.GetModificationTime()) { back = false; } } } else { /* ##### BUG: Source file does not exist, should not happen. */ } } else { /* ##### ERROR: Name too long! */ } } else { $? "! Bug, illegal output driver" /* BUG: Illegal output driver, should not happen. */ } } } return back; } wxChar const * DkWxBmepsThread::shortFileName(wxChar const *longName) { wxChar const *back = NULL; wxChar const *ptr; if(longName) { ptr = longName; while(*ptr) { if(*ptr == DK3_WX_CHAR_SEP) { back = ptr; } ptr++; } if(back) { back++; } else { back = longName; } } return back; }