%% options copyright owner = Dirk Krause copyright year = 2018-xxxx SPDX-License-Identifier: BSD-3-Clause %% header /** @file Bmpp4App.h The Bmpp4App class. */ /* The program may be invoked in 2 variants wxbmpp [] * NO -l OPTION SPECIFIED, RUN AS NORMAL GUI APPLICATION * Restore all settings made in the GUI previously * Restore directory if not specified on command line * Do not run automatically * Save directory if not specified on command line * Save all settings made in the GUI * When running retrieve current settings from GUI wxbmpp -l[.language],... [] * WITH -l OPTION AUTOMATICALLY START CONVERSION FOR SPECIFIED FILE * Do not restore settings * Apply settings in the -l option * Run automatically, exit after running * Do not save settings * Do not save file * Use settings from the -l option */ /** Application class, derived from wxApp, one instance per program. */ class Bmpp4App : public wxApp { protected: /** Helper object. */ Dk4WxApplicationHelper *pAh; /** Controller fr online help. */ Dk4WxHelpController *pHc; /* __CHANGE__ 009: Add further members here. */ /** Graphics output configuration. */ dk4_gra_conf_t graconf; /** Array of known paper sizes. */ dk4_paper_size_t *pPaperSizes; /** Paper size names correspondig to the pPaperSizes items. */ wxArrayString *pasPaperSizes; /** Directory name, allocated. */ wxChar *pDirname; /** Number of paper sizes in pasPaperSizes. */ size_t szPaperSizes; /** Restore and save graphics conversion settings. */ bool bRestoreGx; /** Restore and save Make mode setting. */ bool bRestoreMake; /** Restore and save location to process. */ bool bRestoreLocation; /** Make mode setting from options, if not restored. */ bool bMakeMode; /** Automatically start. */ bool bAutorun; protected: /** Show error message if there is not enough memory available. */ void ShowMemoryErrorMessage(void); /** Process command line arguments and initialize components. @return True on success (can continue), false on error (abort). */ bool ProcessOptionsAndInitializeComponents( wxChar const * const *localizedTexts ); /** Process command line arguments. @return True on success (can continue), false on error (abort). */ bool ProcessOptions( dk4_app_t *app, wxChar const * const *localizedTexts ); public: /** Application initialization. @return true on success, false on error. */ virtual bool OnInit(); /** Application shutdown. @return 0 on success, any other value indicates an error. */ virtual int OnExit(); }; /** Declaration as the wxApp object. */ #if wxCHECK_VERSION(3,0,0) wxDECLARE_APP(Bmpp4App); #else DECLARE_APP(Bmpp4App) #endif /* vim: set ai sw=4 ts=4 : */ %% module #include "wxbmpp.h" #ifndef DK4VERS_H_INCLUDED #include "dk4vers.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4STRD_H_INCLUDED #include "dk4strd.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #ifndef DK4PAPEA_H_INCLUDED #include "dk4papea.h" #endif #ifndef DK4GRCOA_H_INCLUDED #include "dk4grcoa.h" #endif #ifndef DK4STRX_H_INCLUDED #include "dk4strx.h" #endif $!trace-include /** Localized wxChar texts. */ static wxChar const * const wxbmpp_texts[] = { $!string-table macro=wxT # # 0: Menu "File" # File # # 1: Menu item "File/Quit" # Quit # # 2: Tool tip text for menu item "File/Exit" # Exit the application # # 3: Menu "Help" # Help # # 4: Menu item "Help/About" # About # # 5: Tooltip text for menu item "Help/About" # Show version information # # 6: Menu item "Help/Contents" # Contents # # 7: Tooltip text for menu item "Help/Contents" # Open table of contents # # 8: Initial status text # Ready # # 9: Copyright notice. # Copyright (c) # # 10: Dialog box title "About ..." # About # # 11: This program uses the following libraries # This program uses the following libraries: # # 12: See # See: # # 13-14 Make mode # Make Avoid unnecessary conversions # # 15-16 Label and tip for checkbox color # Color Produce colored output # # 17 Label for output type # Output: # # 18-23 Output type choices # PDF object PDF image PDF document EPS image PS image PS document # # 24 Tip for output type choice # Set output file type and intended purpose # # 25-26 Label and tip for image interpolation checkbox # Interpolation Set image interpolation flag # # 27 Label for PS level # PS level: # # 28-30 PS level choices and tip # 2 3 Choose the PS language level # # 31-32 Label and tip for DSC checkbox # DSC Write DSC comments to PS output # # 33-34 Label and tip for LZW compression # LZW Allow LZW compression in PS level 2 output # # 35-36 Label and tip for DCT data checkbox # JPEG DCT data Directly re-use DCT encoded data from JPEG files # # 37-38 Label and tip for paper size choice # Paper size: Specify paper size # # 39-40 Label and tip for rotation checkbox # Rotation Allow image rotation for better page fitting # # 41-42 Label and tip for DCT data interpolation checkbox # DCT interpolation Allow image interpolation for directly re-used DCT data from JPEG files # # 43-47 Choices and tip for finishing choice # Finishing: Single side Duplex Duplex+Tumble Choose single side printing or duplex printing like a book or calendar # # 48-49 Label and tip for analyze bit depth checkbox # Analyze bit depth Attempt to reduce the number of bits per component # # 50-54 Label, tip and choices for resolution handling checkbox # Resolution: How to handle image resolution (use information from file, ignore or specify) from file ignore specify # # 55 Initial resolution value # 72.0 # # 56 Empty line # # # 57-58 Label and tip for analyze colors checkbox # Analyze color use Analyze use of colors, switch output to gray if no colors used # # 59-62 Label and tip for bg color selector and bg enforce checkbox # Background: Choose a background color Enforce background Use specified background color even if the input file provides a background # # 63-64 Label and tip for analyze alpha checkbox # Analyze alpha Analyze alpha channel data # # 65-66 Label and tip for choose directory menu item and button # Choose directory Choose directory containing the images to convert # # 67-69 Label and tip for conversion menu and menu item # Conversion Run Run conversion # # 70 Text for directory label # No directory specified yet! # # 71 Title for directory selection box # Choose directory # # 72 Text for menu extras # Extras # # 73 Label for menu item # Reset options # # 74-75 Message box texts for "are you sure" dialog box # Reset options - are you sure? Do you really want to reset all options to default values? # # 76-88 Color to grayscale method names # Luma BT.601 Luma short Luma BT.709 fast faster average desaturation decomposition (min) decomposition (med) decomposition (max) red green blue # # 89-90 Label and tip for rgb to gray conversion choice # RGB to gray: Choose method for RGB to gray conversions # # 91-92 Texts for summary label # Success, application will exit. Error, application will exit. # # 93-95 Processing stages # Reading image from file. Generating output. Writing output file. # # 96-97 Label and tip for cancel button in progress dialog # Cancel Abort processing # # 98 Title for progress dialog # Conversion progress # # 99 ERROR: Memory # Not enough memory!\n # # 100 ERROR: No files found in directory # No files found in directory!\n # # 101 File processing stage: Finished processing. # Finished. # # 102 Title for error message boxes # Error # # 103 Error message # Internal error (bug): No argv[0] argument found! # # 104 Error message # Internal error (bug): Application group name not found! # # 105 Error message # Illegal characters in language/options string! # # 106 Error message # Failed to parse command line options! # # 107 Error message # Too many paper sizes configured! # # 108 Error message # Illegal character(s) in paper size names! # # 109 Error message # Internal error (bug): Paper size without a name! # # 110 Error message # Failed to obtain paper size information! # # 111 Error message # Paper size not correctly configured! # # 112 Error message # Not enough memory (RAM)!\n # # 113 Error message # :\nERROR: Illegal character(s) in file name!\n # # 114 Error message # :\nERROR: File name too long!\n # # 115 Error message # :\nERROR: Empty directory\n # # 116 Error message # :\nERROR: Not enough memory!\n # # 117 Error message # :\nERROR: Failed to read image from file!\n # # 118 Error message # :\nERROR: Failed to open graphics output!\n # # 119 Error message # :\nERROR: Failed to select frame!\n # # 120 Error message # :\nERROR: Failed to write graphics output to file!\n # # 121 Error message # Aborted by user. # # 122 Tip for menu item # Reset all options to default values $!end }; /** Non-localized wxChar texts. */ static wxChar const * const wxbmpp_nl_wx[] = { $!string-table macro=wxT # # 0: Program name. # wxbmpp # # 1: Program version. # 1.0.0 # # 2: Copyright owner name. # Dirk Krause # # 3: Software vendor name. # DKrause # # 4: Resource name of Windows icon # aaaaa # # 5: UNUSED (previously Windows chm help file name) # # # 6: UNUSED (previously non-Windows htb help file name) # # # 7: Space # # # 8: Newline # \n # # 9 10 11 12 13 14 15: List of libraries used. # DK tools, wxWidgets, libpng, libjpeg, libtiff, zlib. http://sourceforge.net/p/dktools/wiki/Home/ http://www.wxwidgets.org http://www.libpng.org/pub/png/libpng.html http://www.ijg.org http://www.remotesensing.org/libtiff http://www.zlib.net # # 16 17 # Error Not enough memory (RAM)! $!end }; /** Non-localized dkChar texts. */ static dkChar const * const wxbmpp_nl_dk[] = { $!string-table macro=dkT # # 0: Program group name. # dktools # # 1: String table name. # wxbmpp4.str # # 2: CHM help file name # wxbmpp.chm # # 3: HTB help file name # wxbmpp.htb # # 4 Dummy file name for application # dummy.txt $!end }; /** Empty dummy text for help text and license file for application. */ static dkChar const * dummy_text[] = { $!string-table macro=dkT $!end }; static dkChar const versno_dk[] = { DKT_VERSION_DK }; /** Implementation of the wxApp functionality. */ #if wxCHECK_VERSION(3,0,0) wxIMPLEMENT_APP(Bmpp4App); #else IMPLEMENT_APP(Bmpp4App) #endif bool Bmpp4App::OnInit() { Bmpp4Frame *frame = NULL; wxChar const * const *localizedTexts = NULL; wxPNGHandler *phPng = NULL; wxXPMHandler *phXpm = NULL; wxICOHandler *phIco = NULL; wxArchiveFSHandler *phArchiveFS = NULL; bool back = false; $? "+ Bmpp4App::OnInit" /* Initialize members. */ pAh = NULL; pHc = NULL; bRestoreGx = true; bRestoreMake = true; bRestoreLocation = true; bMakeMode = false; bAutorun = false; pPaperSizes = NULL; pasPaperSizes = NULL; pDirname = NULL; szPaperSizes = 0; dk4gra_conf_init(&graconf); /* __CHANGE__ 009: Initialize further members here. */ /* Set up helper object. */ pAh = new Dk4WxApplicationHelper(); if (NULL == pAh) { ShowMemoryErrorMessage(); goto finished; } if (!(pAh->Initialize(argv[0], wxbmpp_nl_wx[3], wxbmpp_nl_dk[0]))) { goto finished; } /* Add image and file system handlers for online help. */ phPng = new wxPNGHandler(); if (NULL != phPng) { wxImage::AddHandler(phPng); } else { ShowMemoryErrorMessage(); goto finished; } phXpm = new wxXPMHandler(); if (NULL != phXpm) { wxImage::AddHandler(phXpm); } else { ShowMemoryErrorMessage(); goto finished; } phIco = new wxICOHandler(); if (NULL != phIco) { wxImage::AddHandler(phIco); } else { ShowMemoryErrorMessage(); goto finished; } phArchiveFS = new wxArchiveFSHandler(); if (NULL != phArchiveFS) { wxFileSystem::AddHandler(phArchiveFS); } else { ShowMemoryErrorMessage(); goto finished; } /* Set up help controller. */ pHc = new Dk4WxHelpController(); if (NULL == pHc) { ShowMemoryErrorMessage(); goto finished; } if (!(pHc->Initialize(pAh, wxbmpp_nl_dk[2], wxbmpp_nl_dk[3]))) { goto finished; } /* Attempt to obtain localized texts in users preferred language. */ localizedTexts = pAh->GetStringTable(wxbmpp_nl_dk[1], wxbmpp_texts); if(!(localizedTexts)) { localizedTexts = wxbmpp_texts; } /* Find list of paper sizes and process options. */ $? ". before new ..." pasPaperSizes = new wxArrayString(); if (NULL == pasPaperSizes) { $? "! pasPaperSizes" ShowMemoryErrorMessage(); goto finished; } $? ". pasPaperSizes" if (!ProcessOptionsAndInitializeComponents(localizedTexts)) { $? "! Process..." goto finished; } $? ". Process..." /* Create and show frame. */ frame = new Bmpp4Frame( Bmpp4Frame_MainWindow, pAh, pHc, localizedTexts, wxbmpp_nl_wx, wxbmpp_nl_dk, &graconf, pasPaperSizes, pDirname, szPaperSizes, bRestoreGx, bRestoreMake, bRestoreLocation, bMakeMode, bAutorun, pPaperSizes ); if(!(frame)) { ShowMemoryErrorMessage(); goto finished; } /* Show frame, restore position and indicate success. */ frame->RestoreSettings(); frame->CorrectGUI(); frame->RestorePosition(); frame->Show(); back = true; /* Release resources if initialization failed. */ finished: if(!(back)) { if (NULL != pPaperSizes) { dk4mem_free(pPaperSizes); pPaperSizes = NULL; } if (NULL != pDirname) { $? ". delete pDirname" dk4mem_free(pDirname); pDirname = NULL; } if (NULL != pasPaperSizes) { $? ". delete pasPaperSizes" delete(pasPaperSizes); pasPaperSizes = NULL; $? ". deleted pasPaperSizes" } if (NULL != pHc) { pHc->Cleanup(); delete(pHc); pHc = NULL; } if (NULL != pAh) { pAh->Cleanup(); delete(pAh); pAh = NULL; } } $? "- Bmpp4App::OnInit %d", (back ? 1 : 0) return back; } int Bmpp4App::OnExit() { int back = 0; $? "+ Bmpp4App::OnExit" /* __CHANGE__ 009: Release resources allocated by further members. */ /* Release resources. */ if (NULL != pPaperSizes) { $? ". delete pPaperSizes" dk4mem_free(pPaperSizes); } if (NULL != pDirname) { $? ". delete pDirname" dk4mem_free(pDirname); $? ". deleted pDirname" } if (NULL != pasPaperSizes) { $? ". delete pasPaperSizes" delete(pasPaperSizes); pasPaperSizes = NULL; $? ". deleted pasPaperSizes" } if (NULL != pHc) { pHc->Cleanup(); delete(pHc); pHc = NULL; } if (NULL != pAh) { pAh->Cleanup(); delete(pAh); pAh = NULL; } /* __CHANGE__ 010: Set exit status code. */ $? "- Bmpp4App::OnExit %d", back return back; } void Bmpp4App::ShowMemoryErrorMessage(void) { const wxChar *s_title = NULL; const wxChar *s_text = NULL; if (NULL != pAh) { s_title = pAh->GetBasicString(6); s_text = pAh->GetBasicString(7); } if (NULL == s_title) { s_title = wxbmpp_nl_wx[16]; } if (NULL == s_text) { s_text = wxbmpp_nl_wx[17]; } wxMessageBox(s_text, s_title, (wxOK | wxCENTRE | wxICON_ERROR)); } bool Bmpp4App::ProcessOptionsAndInitializeComponents( wxChar const * const *localizedTexts ) { dkChar *margv[4]; dk4_app_t *app = NULL; dkChar *argv0 = NULL; dkChar const *pahargv0 = NULL; dkChar const *grname = NULL; bool back = false; $? "+ ProcessOptionsAndInitializeComponents" pahargv0 = pAh->GetDkArgv0(); if (NULL == pahargv0) { $? "! pahargv0" /* ERROR: No argv[0] */ wxMessageBox( localizedTexts[103], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); goto finished; } $? ". pahargv0" argv0 = dk4str_dup(pahargv0, NULL); if (NULL == argv0) { $? "! argv0" /* ERROR: Memory */ ShowMemoryErrorMessage(); goto finished; } $? ". argv0" grname = pAh->GetDkGroupName(); if (NULL == grname) { $? "! grname" /* ERROR: No group name */ wxMessageBox( localizedTexts[104], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); goto finished; } $? ". grname" margv[0] = argv0; margv[1] = NULL; app = dk4app_open_silent( 1, margv, NULL, 0, grname, versno_dk, wxbmpp_nl_dk[4], dummy_text, dummy_text ); if (NULL == app) { $? "! app" /* ERROR: No app */ ShowMemoryErrorMessage(); goto finished; } $? ". app" back = ProcessOptions(app, localizedTexts); finished: if (NULL != app) { dk4app_close(app); } if (NULL != argv0) { dk4mem_free(argv0); } $? "- ProcessOptionsAndInitializeComponents %d", ((back) ? 1 : 0) return back; } #if __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif static const wxCmdLineEntryDesc wxbmpp_cmd_line_desc[] = { { wxCMD_LINE_OPTION, wxT_2("l"), wxT_2("language"), wxT_2("Choose output language"), wxCMD_LINE_VAL_STRING }, { wxCMD_LINE_SWITCH, wxT_2("m"), wxT_2("make"), wxT_2("Run in make mode") }, { wxCMD_LINE_PARAM, NULL, NULL, wxT_2("input file"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_NONE } }; #if __GNUC__ #pragma GCC diagnostic pop #endif bool Bmpp4App::ProcessOptions(dk4_app_t *app, wxChar const * const *localizedTexts) { dkChar cobu[DK4_MAX_PATH]; wxChar buf[256]; wxString sLanguage(wxT("")); dk4_paper_size_collection_t *pscoll = NULL; dk4_paper_size_t const *paps = NULL; wxChar const *ptr = NULL; size_t i; int res = -1; bool back = false; $? "+ ProcessOptions" { wxCmdLineParser parser(wxbmpp_cmd_line_desc, argc, argv); { wxLogNull log; res = parser.Parse(false); } if (0 == res) { back = true; if(parser.Found(wxT("l"), &sLanguage)) { bRestoreGx = false; bRestoreMake = false; bAutorun = true; wxCStrData sLanguageData = sLanguage.c_str(); ptr = (wxChar const *)sLanguageData; if (NULL != ptr) { if (pAh->StringToDk(cobu, DK4_MAX_PATH, ptr, NULL)) { (void)dk4gra_conf_setup( &graconf, cobu, 1, DK4_GRA_CONF_SCOPE_BMPP, app ); } else { /* ERROR: Conversion to dkChar string failed */ wxMessageBox( localizedTexts[105], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); back = false; goto finished; } } else { /* ERROR: No c_str (can not happen) */ back = false; goto finished; } } if(parser.Found(wxT("m"))) { bMakeMode = true; } if(parser.GetParamCount() > 0) { wxString cmdfn = parser.GetParam(0); wxFileName fn(cmdfn); fn.Normalize( wxPATH_NORM_LONG | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE ); #if 0 /* 2018-04-04 Change Whenever wxbmpp is called with -l option the program starts a conversion automatically, now for both directories and single files. */ if (!(fn.FileExists())) { bAutorun = false; } #endif cmdfn = fn.GetFullPath(); wxCStrData fnstrdata = cmdfn.c_str(); ptr = (wxChar const *)fnstrdata; if (NULL != ptr) { pDirname = dk4strx_dup(ptr, NULL); if (NULL != pDirname) { bRestoreLocation = false; } else { /* ERROR: Memory */ ShowMemoryErrorMessage(); back = false; goto finished; } } } else { bAutorun = false; } } else { /* ERROR: In command line options */ wxMessageBox( localizedTexts[106], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); goto finished; } } pscoll = dk4app_get_paper_sizes(app); if (NULL != pscoll) { dk4papersize_coll_reset(pscoll); do { paps = dk4papersize_coll_next(pscoll); if (NULL != paps) { if (NULL != paps->name) { $? ". paper size \"%!ds\"", paps->name if ( pAh->StringToWx( buf, DK4_SIZEOF(buf,wxChar), paps->name, NULL ) ) { if (SIZE_MAX > szPaperSizes) { pasPaperSizes->Add(buf); szPaperSizes += 1; } else { /* ERROR: Too many paper sizes */ wxMessageBox( localizedTexts[107], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); back = false; } } else { /* ERROR: Failed to convert to wx */ wxMessageBox( localizedTexts[108], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); back = false; } } else { /* ERROR: Paper size with no name (bug) */ wxMessageBox( localizedTexts[109], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); } } } while((NULL != paps) && (back)); if ((0 < szPaperSizes) && (back)) { pPaperSizes = dk4mem_new(dk4_paper_size_t,szPaperSizes,NULL); for (i = 0; i < szPaperSizes; i++) { pPaperSizes[i].name = NULL; pPaperSizes[i].name = NULL; pPaperSizes[i].w = 595.0; pPaperSizes[i].h = 842.0; pPaperSizes[i].i = 56.0; pPaperSizes[i].o = 28.0; pPaperSizes[i].b = 14.0; pPaperSizes[i].t = 14.0; } if (NULL != pPaperSizes) { dk4papersize_coll_reset(pscoll); i = 0; do { paps = dk4papersize_coll_next(pscoll); if (NULL != paps) { DK4_MEMCPY(&(pPaperSizes[i]),paps,sizeof(dk4_paper_size_t)); pPaperSizes[i].name = NULL; } i++; } while((NULL != paps) && (i < szPaperSizes)); } else { /* ERROR: Memory */ ShowMemoryErrorMessage(); back = false; } } dk4papersize_coll_close(pscoll); $? ". paper sizes found = %u", (unsigned)szPaperSizes } else { /* ERROR: Failed to obtain paper sizes collection */ wxMessageBox( localizedTexts[110], localizedTexts[102], (wxOK | wxCENTRE | wxICON_ERROR) ); back = false; } finished: $? "- ProcessOptions %d", ((back) ? 1 : 0) return back; } /* vim: set ai sw=4 ts=4 : */