1 /////////////////////////////////////////////////////////////////////////////
2 /*
3   Copyright 2008,2009 Ronald S. Burkey <info@sandroid.org>
4 
5   This file is part of GutenMark.
6 
7   GutenMark is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2 of the License, or
10   (at your option) any later version.
11 
12   GutenMark is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16 
17   You should have received a copy of the GNU General Public License
18   along with GutenMark; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 
21   Filename:	main.cpp
22   Purpose:	This is a simple GUI front-end for GutenMark.
23   Mods:		04/18/2008 RSB	Began.
24   		04/21/2008 RSB	I'd cautiously say, "It's working."
25 		05/09/2008 RSB	On Mac OS X target, altered the name
26 				of the GutenMark application to
27 				correspond to the way I actually
28 				build it, namely GutenMark-macosx.
29 		05/18/2008 RSB	A bunch of the Mac OS X stuff no
30 				longer compiles, for some reason.
31 				But no matter, since I needed to
32 				mod it for the directory structures
33 				needed in "application bundles"
34 				anyway.
35 		05/28/2008 RSB	Fixed C-string to/from wxString
36 				conversions so that it would would
37 				with Unicode-enabled wxWidgets like
38 				on Mac OS X.
39 		05/29/2008 RSB	Added stuff related to GutenSplit.
40 		10/08/2008 RSB	Worked around wxGetHomeDir() in the
41 				__APPLE__ case by using native Mac
42 				(Carbon) API, since wxGetHomeDir()
43 				fails when wxWidgets is compiled by
44 				IMCROSS for some reason, and this
45 				prevents GUItenMark as compiled by
46 				IMCROSS from working on Macs at all.
47 		10/09/2008 RSB	It's really *all* of the wx file
48 				functions, like wxDirExists(),
49 				wxMkdir(), etc., as well.  I've
50 				checked with both unicode and
51 				non-unicode builds of wxWidgets,
52 				and it still doesn't work.
53 				Fortunately, my use of all these
54 				functions is localized to teh
55 				BaseDirectory class, and so were
56 				easy to work around.
57 		02/15/2009 RSB	If found some comments online that
58 				there's something about the wxMac
59 				string functions that aren't thread-
60 				safe, so if there are string-conver-
61 				sions that occur in multiple threads,
62 				eventually the program will crash.
63 				I've therefore changed the BaseDir
64 				variable so that even though it
65 				remains a global variable, its
66 				content strings are initialized by
67 				the main program thread.  This seems
68 				to alleviate the problem.
69 
70   This program is written using wxWidgets, and is intended to be as
71   cross-platform as GutenMark is ... or at least as much as possible.
72   Basically, all it does is to provide a way to do all of the same
73   stuff as GutenMark, but to avoid the command-line.
74 
75   The user interface was designed with wxGlade, and the files
76   GUItenMark.h and GUItenMark.cpp consist entirely of code generated
77   by wxGlade.
78 
79   The event handlers in this file were all originally auto-generated
80   to reside in GUItenMark.cpp.  For some reason that now escapes me,
81   I thought it was better to move them into this separate file ...
82   I guess, to make sure that wxGlade didn't overwrite them later.
83   But it wouldn't have anyhow.
84 */
85 
86 #include "GUItenMark.h"
87 #include <wx/filename.h>
88 #include <wx/dir.h>
89 #ifdef __APPLE__
90 #include <CoreFoundation/CoreFoundation.h>	// For CFxxxxx()
91 #include <CoreServices/CoreServices.h>		// For FSxxxxx()
92 #include <sys/param.h>				// For MAXPATHLEN
93 #endif
94 
95 // I found out somewhat belatedly that if you try to create a
96 // directory that already exists, it will cause the app to silently
97 // die in Mac OS X 10.4.  (I had no problems with it in Linux,
98 // Windows, or Mac OS X 10.5.)
99 #define wxMkdirRon(x) if (!wxDirExists (x)) wxMkdir (x);
100 
101 //#define DEBUG_LOG
102 #ifdef DEBUG_LOG
103 #include <stdio.h>
104 static FILE *LogFile = NULL;
105 static int LogBroken = 0;
106 static void
LOGTHIS(wxString ws)107 LOGTHIS (wxString ws)
108 {
109   static char s[1025];
110   if (LogBroken)
111     return;
112   strcpy (s, ws.char_str ());
113   if (LogFile == NULL)
114     {
115       LogFile = fopen ("GUItenMark.log", "w");
116       if (LogFile == NULL)
117         {
118 	  LogBroken = 1;
119 	  return;
120 	}
121     }
122   fprintf (LogFile, "%s\n", s);
123   fflush (LogFile);
124 }
125 #else
126 #define LOGTHIS(x)
127 #endif
128 
129 ////////////////////////////////////////////////////////////////////////////
130 // Auxiliary functions not in MyFrame or MyApp classes.
131 
132 //-----------------------------------------------------
133 // Define working/configuration directory.
134 
135 #ifdef WIN32
136 #define DIRECTORY_DELIMITER "\\"
137 #else
138 #define DIRECTORY_DELIMITER "/"
139 #endif
140 
141 // At the present writing (02/15/2009), there is a problem in wxMac 2.8.9
142 // in which string-conversion functions are not thread-safe.  The method
143 // BaseDirectory2() is really the constructor for this class, but we
144 // give it a different name so that we can call it explicitly from the
145 // main program thread.  Otherwise, a global definition of a BaseDirectory
146 // would have its constructor called at power-up outside of the main
147 // thread, and the program would crash on the Mac.
148 class BaseDirectory {
149 public:
150   void BaseDirectory2 (void);
151   wxString Name;
152   wxString ExeDirectory;
153   wxString GUIConfigDirectory;
154   wxString GutConfigDirectory;
155   wxString WordlistDirectory;
156   wxString DesktopDirectory;
157 };
158 
159 void
BaseDirectory2(void)160 BaseDirectory::BaseDirectory2 (void)
161 {
162   wxString HomeDirectory;
163 
164   LOGTHIS (wxT ("BaseDirectory: entry"));
165 
166 #ifdef __APPLE__
167 
168   HomeDirectory = wxGetHomeDir ();
169   DesktopDirectory = HomeDirectory + wxT (DIRECTORY_DELIMITER "Desktop");
170 
171   // Find path to GUItenMark application bundle.
172   const char *AppBundle;
173   LOGTHIS (wxT ("BaseDirectory: 1"));
174   AppBundle = CFStringGetCStringPtr (CFURLCopyFileSystemPath (CFBundleCopyBundleURL (CFBundleGetMainBundle()),
175                                                               kCFURLPOSIXPathStyle),
176                                      CFStringGetSystemEncoding());
177   LOGTHIS (wxT ("BaseDirectory: 2"));
178   Name = wxString (AppBundle, wxConvUTF8);
179 
180   Name += wxT ("/Contents");
181 
182   LOGTHIS (wxT ("BaseDirectory: 3"));
183   ExeDirectory = Name + wxT ("/MacOS");
184   GUIConfigDirectory = Name + wxT ("/Resources/GUIConfigs");
185   GutConfigDirectory = Name + wxT ("/Resources");
186   WordlistDirectory = Name + wxT ("/Resources");
187 
188 #else // must not be __APPLE__ after all.
189 
190   HomeDirectory = wxGetHomeDir ();
191   DesktopDirectory = HomeDirectory + wxT (DIRECTORY_DELIMITER "Desktop");
192 
193 #ifdef WIN32
194   Name = wxT ("c:\\Program Files\\GutenMark");
195 #else // Linux
196   Name = HomeDirectory + wxT ("/.GutenMark");
197 #endif
198 
199   LOGTHIS (wxT ("BaseDirectory: 4"));
200   ExeDirectory = Name + wxT (DIRECTORY_DELIMITER "binary");
201   GUIConfigDirectory = Name + wxT (DIRECTORY_DELIMITER "GUIConfigs");
202   GutConfigDirectory = Name + wxT (DIRECTORY_DELIMITER "GutConfigs");
203   WordlistDirectory = Name + wxT (DIRECTORY_DELIMITER "binary");
204 
205   //wxMkdirRon (Name + wxT (DIRECTORY_DELIMITER "Outputs"));
206 
207 #endif // __APPLE__ vs. not __APPLE__
208 
209   LOGTHIS (wxT ("BaseDirectory: 5"));
210   LOGTHIS (Name);
211   wxMkdirRon (Name);
212   LOGTHIS (wxT ("BaseDirectory: 6"));
213   LOGTHIS (GUIConfigDirectory);
214   wxMkdirRon (GUIConfigDirectory);
215   LOGTHIS (wxT ("BaseDirectory: 7"));
216   LOGTHIS (GutConfigDirectory);
217   wxMkdirRon (GutConfigDirectory);
218   LOGTHIS (wxT ("BaseDirectory: 8"));
219   LOGTHIS (ExeDirectory);
220   wxMkdirRon (ExeDirectory);
221   LOGTHIS (wxT ("BaseDirectory: 9"));
222   LOGTHIS (WordlistDirectory);
223   wxMkdirRon (WordlistDirectory);
224 
225   LOGTHIS (wxT ("BaseDirectory: 10"));
226   LOGTHIS (WordlistDirectory);
227   wxSetWorkingDirectory (WordlistDirectory);
228   LOGTHIS (wxT ("BaseDirectory: exit"));
229 }
230 
231 BaseDirectory *BaseDir = new BaseDirectory ();
232 
233 
234 ////////////////////////////////////////////////////////////////////////////
235 // Functions for the MyApp class.
236 
237 class MyApp: public wxApp
238 {
239   public:
240     virtual bool OnInit();
241 };
242 
IMPLEMENT_APP(MyApp)243 IMPLEMENT_APP (MyApp)
244 
245 bool MyApp::OnInit()
246 {
247   BaseDir->BaseDirectory2 ();
248   LOGTHIS (BaseDir->Name);
249   LOGTHIS (BaseDir->GUIConfigDirectory);
250   LOGTHIS (BaseDir->GutConfigDirectory);
251   LOGTHIS (BaseDir->ExeDirectory);
252   LOGTHIS (BaseDir->WordlistDirectory);
253   wxInitAllImageHandlers ();
254   MyFrame *frame = new MyFrame( NULL, -1, wxT ("") );
255   frame->SetTitle (wxT ("GUItenMark build " __DATE__
256   			", (c)2008-2009 by Ron Burkey <info@sandroid.org>, "
257 			"http://www.sandroid.org/GutenMark"));
258   frame->SideEffectsOfLists ();
259   frame->GetConfiguration (wxT ("Default"));
260 
261 #ifdef __APPLE__
262   wxMenu *file_menu = new wxMenu;
263   file_menu->Append(MyFrame::ID_APPLE_QUIT, _T("E&xit\tAlt-X"), _T("Quit this program"));
264   wxMenuBar *menu_bar = new wxMenuBar( wxMB_DOCKABLE );
265   menu_bar->Append(file_menu, _T("&File"));
266   frame->SetMenuBar(menu_bar);
267 #endif // __APPLE__
268 
269   frame->Maximize(TRUE);
270   frame->Show(TRUE);
271   SetTopWindow(frame);
272   return TRUE;
273 }
274 
275 
276 ////////////////////////////////////////////////////////////////////////////
277 // Event handlers for the MyFrame class.
278 
OnClose(wxCloseEvent & event)279 void MyFrame::OnClose (wxCloseEvent & event)
280 {
281   PutConfiguration (wxT ("Default"));
282   Destroy ();
283 }
284 
ClickPopulate(wxCommandEvent & event)285 void MyFrame::ClickPopulate(wxCommandEvent &event)
286 {
287     wxArrayString Filenames;
288     wxDir::GetAllFiles (OutputFolder->GetValue (), &Filenames, wxT (""), wxDIR_FILES);
289     OutputFiles->Append (Filenames);
290     SideEffectsOfLists ();
291 }
292 
ClickOutputFile(wxCommandEvent & event)293 void MyFrame::ClickOutputFile(wxCommandEvent &event)
294 {
295   int i;
296   wxString Name;
297 
298   //event.Skip();
299   i = OutputFiles->GetSelection ();
300   if (i == wxNOT_FOUND)
301     return;
302   Name = OutputFiles->GetString (i);
303   if (Name.Matches (wxT ("*.html")) || Name.Matches (wxT ("*.log")) || Name.Matches (wxT ("*.tex")))
304     wxLaunchDefaultBrowser (wxT ("file://") + Name);
305 }
306 
ClickInputFile(wxCommandEvent & event)307 void MyFrame::ClickInputFile(wxCommandEvent &event)
308 {
309   int i;
310   wxString Name;
311 
312   //event.Skip();
313   i = InputFiles->GetSelection ();
314   if (i == wxNOT_FOUND)
315     return;
316   Name = InputFiles->GetString (i);
317   wxLaunchDefaultBrowser (wxT ("file://") + Name);
318 }
319 
ClickOutputFolderBrowse(wxCommandEvent & event)320 void MyFrame::ClickOutputFolderBrowse(wxCommandEvent &event)
321 {
322     //event.Skip();
323     wxString Dir = wxDirSelector (wxT ("Choose a folder for output"), OutputFolder->GetValue ());
324     if (!Dir.empty ())
325       OutputFolder->SetValue (Dir);
326 }
327 
ClickAddFiles(wxCommandEvent & event)328 void MyFrame::ClickAddFiles(wxCommandEvent &event)
329 {
330     //int i;
331     //wxString Directory;
332     wxArrayString Filenames;
333     //event.Skip();
334     //i = InputFiles->GetCount ();
335     //if (!i)
336     //  Directory = "";
337     //else
338     //  Directory = wxPathOnly (InputFiles->GetString (i - 1));
339     wxFileDialog *Dialog = new wxFileDialog (this, wxT ("Choose etext file(s)"),
340     					     Directory, wxT (""),
341 					     wxT ("Text files (*.txt)|*.txt|All files (*.*)|*.*"),
342 					     wxFD_DEFAULT_STYLE |
343 					     wxFD_FILE_MUST_EXIST |
344 					     wxFD_MULTIPLE |
345 					     wxFD_CHANGE_DIR);
346     if (wxID_OK == Dialog->ShowModal ())
347       {
348 	Dialog->GetPaths (Filenames);
349 	InputFiles->Append (Filenames);
350 	Directory = Dialog->GetDirectory ();
351 	SideEffectsOfLists ();
352       }
353     delete Dialog;
354 }
355 
ClickClearInputFiles(wxCommandEvent & event)356 void MyFrame::ClickClearInputFiles(wxCommandEvent &event)
357 {
358   //event.Skip();
359   InputFiles->Clear ();
360   SideEffectsOfLists ();
361 }
362 
ClickConvertTexts(wxCommandEvent & event)363 void MyFrame::ClickConvertTexts(wxCommandEvent &event)
364 {
365   wxArrayString Filenames;
366   int Count, i, j, Skip = 0;
367 
368   LOGTHIS (wxT ("ClickConvertTexts: start"));
369 
370   //event.Skip();
371   Filenames = InputFiles->GetStrings ();
372   for (i = 0, Count = Filenames.GetCount (); i < Count; i++)
373     {
374       LOGTHIS (wxT ("ClickConvertTexts: loop"));
375 
376       // Name of the output file (from GutenMark).
377       wxString OutputFile, OutputDirSplit;
378       wxFileName *Input = new wxFileName (Filenames[i]);
379       OutputDirSplit = OutputFolder->GetValue () +
380       		       wxT (DIRECTORY_DELIMITER) +
381 		       Input->GetName ();
382       if (LatexOutput->GetValue ())
383         OutputFile = OutputDirSplit + wxT (".tex");
384       else
385         OutputFile = OutputDirSplit + wxT (".html");
386 
387       //-------------------------------------------------------------
388       // First, construct GutenSplit command line.
389 
390       // Program name for GutenSplit.
391       wxString CommandLineSplit = wxT ("\"") + BaseDir->ExeDirectory + wxT (DIRECTORY_DELIMITER "GutenSplit");
392 #if defined (WIN32)
393       CommandLineSplit += wxT (".exe");
394 #endif
395       CommandLineSplit += wxT ("\"");
396 
397       if (LevelOne->GetValue ())
398         CommandLineSplit += wxT (" -1");
399 
400       if (LevelTwo->GetValue ())
401         CommandLineSplit += wxT (" -2");
402 
403       if (LevelThree->GetValue ())
404         CommandLineSplit += wxT (" -3");
405 
406       if (LevelFour->GetValue ())
407         CommandLineSplit += wxT (" -4");
408 
409       if (!SkipFirstHeading->GetValue ())
410         CommandLineSplit += wxT (" --no-skip");
411 
412       if (!TableOfContents->GetValue ())
413         CommandLineSplit += wxT (" --no-toc");
414 
415       // Input file is the output file from GutenMark.
416       CommandLineSplit += wxT (" \"");
417       CommandLineSplit += OutputFile;
418       CommandLineSplit += wxT ("\"");
419 
420       // Output base.
421       CommandLineSplit += wxT (" \"") + Input->GetName () + wxT ("_\"");
422 
423       //-------------------------------------------------------------
424       // Then, construct GutenMark command line.
425 
426       // Program name for GutenMark.
427       wxString CommandLine = wxT ("");
428       CommandLine += wxT ("\"") + BaseDir->ExeDirectory + wxT (DIRECTORY_DELIMITER "GutenMark");
429 #if defined (WIN32)
430       CommandLine += wxT (".exe");
431 #endif
432       CommandLine += wxT ("\"");
433 
434       // --author
435       if (AuthorOverride->IsEnabled () && !AuthorOverride->IsEmpty ())
436         {
437           CommandLine += wxT (" \"--author=");
438 	  CommandLine += AuthorOverride->GetValue ();
439 	  CommandLine += wxT ("\"");
440 	}
441 
442       // --caps-ok
443       if (AllCapsOk->GetValue ())
444         CommandLine += wxT (" --caps-ok");
445 
446       if (!ConfigurationFile->IsEmpty ())
447         {
448           CommandLine += wxT (" \"--config=");
449 	  CommandLine += ConfigurationFile->GetValue ();
450 	  CommandLine += wxT ("\"");
451 	}
452 
453       // --first-capital
454       if (FirstWordAllCapsOk->GetValue ())
455         CommandLine += wxT (" --first-capital");
456 
457       // --first-italics
458       if (FirstWordItalicsOk->GetValue ())
459         CommandLine += wxT (" --first-italics");
460 
461       // --force-symbolic/--force-numeric
462       if (HtmlOutput->GetValue () && HtmlUseSymbolicEntities->GetValue ())
463         CommandLine += wxT (" --force-symbolic");
464       else
465         CommandLine += wxT (" --force-numeric");
466 
467       // --latex
468       if (LatexOutput->GetValue ())
469         CommandLine += wxT (" --latex");
470 
471       // --latex
472       if (LatexOutput->GetValue () && LatexSectionMarkup->GetValue ())
473         CommandLine += wxT (" --latex-sections");
474 
475       // --no-diacritical
476       if (!RestoreDiacrits->GetValue ())
477         CommandLine += wxT (" --no-diacritical");
478 
479       // --no-foreign
480       if (!ItalicizeNonEnglish->GetValue ())
481         CommandLine += wxT (" --no-foreign");
482 
483       // --no-justify
484       if (RaggedRightMargin->GetValue ())
485         CommandLine += wxT (" --no-justify");
486 
487       // --no-mdash
488       if (PreserveStringsOfHyphens->GetValue ())
489         CommandLine += wxT (" --no-mdash");
490 
491       // --no-parskip
492       if (LatexOutput->GetValue () && LatexIndentParagraphs->GetValue ())
493         CommandLine += wxT (" --no-parskip");
494 
495       // --no-prefatory
496       if (HtmlOutput->GetValue () && HtmlAddPrefatoryMarks->GetValue ())
497         CommandLine += wxT (" --no-prefatory");
498 
499       // --no-toc
500       if (LatexOutput->GetValue () && LatexEliminateToc->GetValue ())
501         CommandLine += wxT (" --no-toc");
502 
503       // --page-breaks
504       if (HtmlOutput->GetValue () && HtmlAddPageBreakMarks->GetValue ())
505         CommandLine += wxT (" --page-breaks");
506 
507       // --profile
508       j = Profile->GetSelection ();
509       if (wxNOT_FOUND != j)
510         {
511 	  CommandLine += wxT (" \"--profile=");
512 	  CommandLine += Profile->GetString (j);
513 	  CommandLine += wxT ("\"");
514 	}
515 
516       // --single-space
517       if (SingleSpaceBetweenSentences->GetValue ())
518         CommandLine += wxT (" --single-space");
519 
520       // --title
521       if (TitleOverride->IsEnabled () && !TitleOverride->IsEmpty ())
522         {
523           CommandLine += wxT (" \"--title=");
524 	  CommandLine += TitleOverride->GetValue ();
525 	  CommandLine += wxT ("\"");
526 	}
527 
528       // --yes-header
529       if (RetainProjectGutenbergHeader->GetValue ())
530         CommandLine += wxT (" --yes-header");
531 
532       // --debug
533       if (Debug->GetValue ())
534         CommandLine += wxT (" --debug");
535 
536       // --ron
537       if (RonsOptions->GetValue ())
538         CommandLine += wxT (" --ron");
539 
540       // Input file.
541       CommandLine += wxT (" \"");
542       CommandLine += Filenames[i];
543       CommandLine += wxT ("\"");
544 
545       // Output file.
546       CommandLine += wxT (" \"");
547       CommandLine += OutputFile;
548       CommandLine += wxT ("\"");
549 
550       //wxMessageBox (CommandLine);
551 
552       wxBeginBusyCursor ();
553 
554       //---------------------------------------------------------------
555       // Now convert the text.
556       LOGTHIS (wxT ("ClickConvertTexts: conversion command line"));
557       LOGTHIS (CommandLine);
558       long ConversionCode = wxExecute (CommandLine, wxEXEC_SYNC);
559       LOGTHIS (wxT ("ClickConvertTexts: converted"));
560 
561       //---------------------------------------------------------------
562       // Check results.
563       if (Debug->GetValue ())
564         {
565 	  wxString LogFile;
566           LOGTHIS (wxT ("ClickConvertTexts: moving log"));
567 	  LogFile = Input->GetPath ();
568 	  LogFile += wxT (DIRECTORY_DELIMITER "GutenMark.log");
569 	  OutputFiles->Append (LogFile);
570 	}
571       if (ConversionCode)
572         {
573           LOGTHIS (wxT ("ClickConvertTexts: error code"));
574 	  OutputFile += wxT (" (Conversion error ");
575 	  OutputFile += wxString::Format (wxT ("%ld"), ConversionCode);
576 	  OutputFile += wxT (")");
577 	  OutputFiles->Append (OutputFile);
578 	  Skip++;
579 	}
580       else
581         {
582           LOGTHIS (wxT ("ClickConvertTexts: moving filename"));
583           OutputFiles->Append (OutputFile);
584 
585 	  // If we're suppose to run GutenSplit, then do it now.
586 	  if (!LatexOutput->GetValue () && RunGutenSplit->GetValue ())
587 	    {
588 	      wxMkdirRon (OutputDirSplit);
589 	      if (wxSetWorkingDirectory (OutputDirSplit))
590 		{
591 	          long ConversionCodeSplit = wxExecute (CommandLineSplit, wxEXEC_SYNC);
592 		  if (ConversionCodeSplit)
593 		    OutputDirSplit += wxT (" (Splitting exec error)");
594 		  else
595 		    OutputDirSplit += wxT (DIRECTORY_DELIMITER) + Input->GetName () + wxT ("_000.html");
596                   wxSetWorkingDirectory (BaseDir->WordlistDirectory);
597 		}
598 	      else
599 	        OutputDirSplit += wxT (" (Splitting folder error)");
600 	      OutputFiles->Append (OutputDirSplit);
601 	    }
602 
603           InputFiles->Delete (Skip);
604         }
605 
606       wxEndBusyCursor ();
607 
608       delete Input;
609       LOGTHIS (wxT ("ClickConvertTexts: continue"));
610 
611     }
612 
613   // All done!
614   LOGTHIS (wxT ("ClickConvertTexts: side effects"));
615   SideEffectsOfLists ();
616   LOGTHIS (wxT ("ClickConvertTexts: done!"));
617 
618 }
619 
ClickClearOutputList(wxCommandEvent & event)620 void MyFrame::ClickClearOutputList(wxCommandEvent &event)
621 {
622   //event.Skip();
623   OutputFiles->Clear ();
624   SideEffectsOfLists ();
625 }
626 
ClickHtmlOutput(wxCommandEvent & event)627 void MyFrame::ClickHtmlOutput(wxCommandEvent &event)
628 {
629   //event.Skip();
630   if (HtmlOutput->GetValue ())
631     {
632       // LaTeX options.
633       LatexSectionMarkup->Disable ();
634       LatexIndentParagraphs->Disable ();
635       LatexEliminateToc->Disable ();
636       // HTML options.
637       HtmlUseSymbolicEntities->Enable ();
638       HtmlAddPrefatoryMarks->Enable ();
639       HtmlAddPageBreakMarks->Enable ();
640       RonsOptions->SetValue (FALSE);
641       // GutenSplitOptions.
642       RunGutenSplit->Enable ();
643       LevelOne->Enable (RunGutenSplit->GetValue ());
644       LevelTwo->Enable (RunGutenSplit->GetValue ());
645       LevelThree->Enable (RunGutenSplit->GetValue ());
646       LevelFour->Enable (RunGutenSplit->GetValue ());
647       SkipFirstHeading->Enable (RunGutenSplit->GetValue ());
648       TableOfContents->Enable (RunGutenSplit->GetValue ());
649     }
650 }
651 
ClickLatexOutput(wxCommandEvent & event)652 void MyFrame::ClickLatexOutput(wxCommandEvent &event){
653   //event.Skip();
654   if (LatexOutput->GetValue ())
655     {
656       // LaTeX options.
657       LatexSectionMarkup->Enable ();
658       LatexIndentParagraphs->Enable ();
659       LatexEliminateToc->Enable ();
660       // HTML options
661       HtmlUseSymbolicEntities->Disable ();
662       HtmlAddPrefatoryMarks->Disable ();
663       HtmlAddPageBreakMarks->Disable ();
664       // GutenSplit options
665       RunGutenSplit->Disable ();
666       LevelOne->Disable ();
667       LevelTwo->Disable ();
668       LevelThree->Disable ();
669       LevelFour->Disable ();
670       SkipFirstHeading->Disable ();
671       TableOfContents->Disable ();
672     }
673 }
674 
ClickRon(wxCommandEvent & event)675 void MyFrame::ClickRon (wxCommandEvent &event) {
676   //event.Skip ();
677   LatexOutput->SetValue (TRUE);
678   LatexIndentParagraphs->SetValue (TRUE);
679   ClickLatexOutput (event);
680 }
681 
ClickLatexIndentParagraphs(wxCommandEvent & event)682 void MyFrame::ClickLatexIndentParagraphs (wxCommandEvent &event) {
683   //event.Skip ();
684   if (!LatexIndentParagraphs->GetValue ())
685     RonsOptions->SetValue (FALSE);
686   ClickLatexOutput (event);
687 }
688 
NewConfigurationFiles(wxCommandEvent & event)689 void MyFrame::NewConfigurationFiles(wxCommandEvent &event){
690 #define MAXSTRING 1024
691   FILE *fp;
692   char *s, *ss;
693   //event.Skip();
694 
695   // What we need to do here is to parse the configuration
696   // file to see what profiles are available in it.  The
697   // profiles (in regex terms) match "^\[.*\]$".
698   Profile->Clear ();
699   s = (char *) malloc (MAXSTRING);
700   strcpy (s, ConfigurationFile->GetValue ().char_str ());
701   fp = fopen ((const char *) s, "r");
702   free (s);
703   if (fp != NULL)
704     {
705       s = (char *) malloc (MAXSTRING);
706       while (NULL != fgets (s, MAXSTRING, fp))
707         if (*s == '[')
708 	  {
709 	    for (ss = s + 1; *ss && *ss != ']'; ss++);
710 	    if (*ss == ']')
711 	      {
712 	        *ss = 0;
713 		Profile->Append (wxString (&s[1], wxConvUTF8));
714 	      }
715 	  }
716       fclose (fp);
717       free (s);
718     }
719   Profile->SetSelection (0);
720 #undef MAXSTRING
721 }
722 
ClickConfigurationFileBrowse(wxCommandEvent & event)723 void MyFrame::ClickConfigurationFileBrowse(wxCommandEvent &event){
724     //event.Skip();
725     wxString Path = wxPathOnly ( ConfigurationFile->GetValue ());
726     wxString File = wxFileSelector (wxT ("Choose a GutenMark configuration file"),
727     				    Path, wxT (""), wxT (""),
728 				    wxT ("Configuration files (*.cfg)|*.cfg|All files (*.*)|*.*"));
729     if (!File.empty ())
730       {
731         ConfigurationFile->SetValue (File);
732 	NewConfigurationFiles (event);
733       }
734 }
735 
ClickProfile(wxCommandEvent & event)736 void MyFrame::ClickProfile(wxCommandEvent &event){
737   //event.Skip();
738 }
739 
ClickSaveSettings(wxCommandEvent & event)740 void MyFrame::ClickSaveSettings(wxCommandEvent &event){
741     //event.Skip();
742     wxString Path = BaseDir->GUIConfigDirectory;
743     wxString File = wxFileSelector (wxT ("Save your GUItenMark configuration as"),
744     				    Path, wxT (""), wxT (""), wxT ("*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
745     if (!File.empty ())
746       {
747         wxFileName *Filename = new wxFileName (File);
748         PutConfiguration (Filename->GetName ());
749 	delete Filename;
750       }
751 }
752 
ClickRestoreSettings(wxCommandEvent & event)753 void MyFrame::ClickRestoreSettings(wxCommandEvent &event){
754     //event.Skip();
755     wxString Path = BaseDir->GUIConfigDirectory;
756     wxString File = wxFileSelector (wxT ("Restore your GUItenMark configuration from"),
757     				    Path, wxT (""), wxT (""), wxT ("*"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
758     if (!File.empty ())
759       {
760         wxFileName *Filename = new wxFileName (File);
761         GetConfiguration (Filename->GetName ());
762 	delete Filename;
763       }
764 }
765 
ClickGoodbye(wxCommandEvent & event)766 void MyFrame::ClickGoodbye(wxCommandEvent &event){
767   //event.Skip();
768   Close ();
769 }
770 
ClickDefaultSettings(wxCommandEvent & event)771 void MyFrame::ClickDefaultSettings(wxCommandEvent &event){
772   //event.Skip();
773   GetConfiguration (wxT ("ThisFilenameDoesNotExistSoTheHardCodedDefaultIsUsed"));
774 }
775 
SplitCheck(wxCommandEvent & event)776 void MyFrame::SplitCheck (wxCommandEvent & event)
777 {
778   LevelOne->Enable (RunGutenSplit->GetValue ());
779   LevelTwo->Enable (RunGutenSplit->GetValue ());
780   LevelThree->Enable (RunGutenSplit->GetValue ());
781   LevelFour->Enable (RunGutenSplit->GetValue ());
782   SkipFirstHeading->Enable (RunGutenSplit->GetValue ());
783   TableOfContents->Enable (RunGutenSplit->GetValue ());
784 }
785 
786 ////////////////////////////////////////////////////////////////////////////
787 // Non-event-handler auxiliary functions which I've added to the MyFrame class.
788 
SideEffectsOfLists(void)789 void MyFrame::SideEffectsOfLists (void)
790 {
791   switch (InputFiles->GetCount ())
792     {
793     case 0:
794       ClearInputList->Disable ();
795       ConvertTexts->Disable ();
796       AuthorOverride->Disable ();
797       AuthorLabel->Disable ();
798       TitleOverride->Disable ();
799       TitleLabel->Disable ();
800       break;
801     case 1:
802       ClearInputList->Enable ();
803       ConvertTexts->Enable ();
804       AuthorOverride->Enable ();
805       AuthorLabel->Enable ();
806       TitleOverride->Enable ();
807       TitleLabel->Enable ();
808       break;
809     default:
810       ClearInputList->Enable ();
811       ConvertTexts->Enable ();
812       AuthorOverride->Enable ();
813       AuthorLabel->Enable ();
814       TitleOverride->Disable ();
815       TitleLabel->Disable ();
816       break;
817     }
818   if (OutputFiles->GetCount ())
819     ClearOutputList->Enable ();
820   else
821     ClearOutputList->Disable ();
822 }
823 
824 // Get a saved configuration identified by Name.  (Name is not a filename,
825 // but a base from which a filename is constructed by prefixing a path and
826 // suffixing an extension.)  Returns 0 on success, non-zero on failure.
827 // "Failure" means that that configuration doesn't exist.  In this case, the
828 // configuration is replaced by a fallback configuration of my choosing.
829 // On entry to the program, there is an automatic call with Name=="Default".
GetConfiguration(wxString Name)830 int MyFrame::GetConfiguration (wxString Name)
831 {
832   FILE *fp;
833   int ReturnValue = 1, i;
834   wxCommandEvent DummyEvent;
835   wxString CfgName;
836   char *s;
837 
838   s = (char *) malloc (2048);
839   if (s == NULL)
840     return (ReturnValue);
841 
842   // Configure according to my preferences.
843   OutputFolder->SetValue (BaseDir->DesktopDirectory);
844   AllCapsOk->SetValue (FALSE);
845   RestoreDiacrits->SetValue (TRUE);
846   RaggedRightMargin->SetValue (FALSE);
847   HtmlOutput->SetValue (TRUE);
848   ClickHtmlOutput (DummyEvent);
849   FirstWordAllCapsOk->SetValue (FALSE);
850   ItalicizeNonEnglish->SetValue (TRUE);
851   PreserveStringsOfHyphens->SetValue (FALSE);
852   HtmlUseSymbolicEntities->SetValue (FALSE);
853   LatexSectionMarkup->SetValue (FALSE);
854   FirstWordItalicsOk->SetValue (FALSE);
855   SingleSpaceBetweenSentences->SetValue (FALSE);
856   HtmlAddPrefatoryMarks->SetValue (FALSE);
857   LatexIndentParagraphs->SetValue (TRUE);
858   RetainProjectGutenbergHeader->SetValue (FALSE);
859   HtmlAddPageBreakMarks->SetValue (FALSE);
860   LatexEliminateToc->SetValue (FALSE);
861   wxString ConfigFilename = BaseDir->GutConfigDirectory + wxT (DIRECTORY_DELIMITER "GutenMark.cfg");
862   ConfigurationFile->SetValue (ConfigFilename);
863   RunGutenSplit->SetValue (FALSE);
864   SplitCheck (DummyEvent);
865   LevelOne->SetValue (TRUE);
866   LevelTwo->SetValue (FALSE);
867   LevelThree->SetValue (FALSE);
868   LevelFour->SetValue (FALSE);
869   SkipFirstHeading->SetValue (TRUE);
870   TableOfContents->SetValue (TRUE);
871 
872   NewConfigurationFiles (DummyEvent);
873   // Note that NewConfigurationFiles automatically sets Profile.  However,
874   // I don't necessarily like the default selection it makes.
875   i = Profile->FindString (wxT ("english"));
876   if (i != wxNOT_FOUND)
877     Profile->SetSelection (i);
878   Directory = BaseDir->DesktopDirectory;
879   Debug->SetValue (FALSE);
880   RonsOptions->SetValue (FALSE);
881 
882   // Fetch the named configuration.
883   CfgName = BaseDir->GUIConfigDirectory + wxT (DIRECTORY_DELIMITER) + Name;
884 
885   strcpy (s, CfgName.char_str ());
886   fp = fopen ((const char *) s, "r");
887   if (fp != NULL)
888     {
889       int i;
890 
891       if (1 == fscanf (fp, "OutputFolder=%[^\n]\n", s))
892         OutputFolder->SetValue (wxString (s, wxConvUTF8));
893       else
894         goto Done;
895       if (1 == fscanf (fp, "AllCapsOk=%d\n", &i))
896         AllCapsOk->SetValue (i);
897       else
898         goto Done;
899       if (1 == fscanf (fp, "RestoreDiacrits=%d\n", &i))
900         RestoreDiacrits->SetValue (i);
901       else
902         goto Done;
903       if (1 == fscanf (fp, "RaggedRightMargin=%d\n", &i))
904         RaggedRightMargin->SetValue (i);
905       else
906         goto Done;
907       if (1 == fscanf (fp, "HtmlOutput=%d\n", &i))
908         {
909 	  if (i)
910 	    {
911 	      HtmlOutput->SetValue (TRUE);
912 	      ClickHtmlOutput (DummyEvent);
913 	    }
914 	  else
915 	    {
916 	      LatexOutput->SetValue (TRUE);
917 	      ClickLatexOutput (DummyEvent);
918 	    }
919 	}
920       else
921         goto Done;
922       if (1 == fscanf (fp, "FirstWordAllCapsOk=%d\n", &i))
923         FirstWordAllCapsOk->SetValue (i);
924       else
925         goto Done;
926       if (1 == fscanf (fp, "ItalicizeNonEnglish=%d\n", &i))
927         ItalicizeNonEnglish->SetValue (i);
928       else
929         goto Done;
930       if (1 == fscanf (fp, "PreserveStringsOfHyphens=%d\n", &i))
931         PreserveStringsOfHyphens->SetValue (i);
932       else
933         goto Done;
934       if (1 == fscanf (fp, "HtmlUseSymbolicEntities=%d\n", &i))
935         HtmlUseSymbolicEntities->SetValue (i);
936       else
937         goto Done;
938       if (1 == fscanf (fp, "LatexSectionMarkup=%d\n", &i))
939         LatexSectionMarkup->SetValue (i);
940       else
941         goto Done;
942       if (1 == fscanf (fp, "FirstWordItalicsOk=%d\n", &i))
943         FirstWordItalicsOk->SetValue (i);
944       else
945         goto Done;
946       if (1 == fscanf (fp, "SingleSpaceBetweenSentences=%d\n", &i))
947         SingleSpaceBetweenSentences->SetValue (i);
948       else
949         goto Done;
950       if (1 == fscanf (fp, "HtmlAddPrefatoryMarks=%d\n", &i))
951         HtmlAddPrefatoryMarks->SetValue (i);
952       else
953         goto Done;
954       if (1 == fscanf (fp, "LatexIndentParagraphs=%d\n", &i))
955         LatexIndentParagraphs->SetValue (i);
956       else
957         goto Done;
958       if (1 == fscanf (fp, "RetainProjectGutenbergHeader=%d\n", &i))
959         RetainProjectGutenbergHeader->SetValue (i);
960       else
961         goto Done;
962       if (1 == fscanf (fp, "HtmlAddPageBreakMarks=%d\n", &i))
963         HtmlAddPageBreakMarks->SetValue (i);
964       else
965         goto Done;
966       if (1 == fscanf (fp, "LatexEliminateToc=%d\n", &i))
967         LatexEliminateToc->SetValue (i);
968       else
969         goto Done;
970       if (1 == fscanf (fp, "ConfigurationFile=%[^\n]\n", s))
971         ConfigurationFile->SetValue (wxString (s, wxConvUTF8));
972       else
973         goto Done;
974       NewConfigurationFiles (DummyEvent);
975       if (1 == fscanf (fp, "Profile=%d\n", &i))
976         Profile->SetSelection (i);
977       else
978         goto Done;
979       if (1 == fscanf (fp, "InputDirectory=%[^\n]\n", s))
980         Directory = wxString (s, wxConvUTF8);
981       else
982         goto Done;
983       if (1 == fscanf (fp, "Debug=%d\n", &i))
984         Debug->SetValue (i);
985       else
986         goto Done;
987       if (1 == fscanf (fp, "RonsOptions=%d\n", &i))
988         RonsOptions->SetValue (i);
989       else
990         goto Done;
991       if (1 == fscanf (fp, "RunGutenSplit=%d\n", &i))
992         {
993           RunGutenSplit->SetValue (i);
994 	  SplitCheck (DummyEvent);
995 	}
996       else
997         goto Done;
998       if (1 == fscanf (fp, "LevelOne=%d\n", &i))
999         LevelOne->SetValue (i);
1000       else
1001         goto Done;
1002       if (1 == fscanf (fp, "LevelTwo=%d\n", &i))
1003         LevelTwo->SetValue (i);
1004       else
1005         goto Done;
1006       if (1 == fscanf (fp, "LevelThree=%d\n", &i))
1007         LevelThree->SetValue (i);
1008       else
1009         goto Done;
1010       if (1 == fscanf (fp, "LevelFour=%d\n", &i))
1011         LevelFour->SetValue (i);
1012       else
1013         goto Done;
1014       if (1 == fscanf (fp, "SkipFirstHeading=%d\n", &i))
1015         SkipFirstHeading->SetValue (i);
1016       else
1017         goto Done;
1018       if (1 == fscanf (fp, "TableOfContents=%d\n", &i))
1019         TableOfContents->SetValue (i);
1020       else
1021         goto Done;
1022       fclose (fp);
1023     }
1024 
1025   ReturnValue = 0;
1026 Done:
1027   free (s);
1028   return (ReturnValue);
1029 }
1030 
1031 // Write a saved configuration identified by Name.  (Name is not a filename,
1032 // but a base from which a filename is constructed by prefixing a path and
1033 // suffixing an extension.)  Returns 0 on success, non-zero on failure.
1034 // On exit from the program, there is an automatic call with Name=="Default".
PutConfiguration(wxString Name)1035 int MyFrame::PutConfiguration (wxString Name)
1036 {
1037   FILE *fp;
1038   int ReturnValue = 0;
1039   wxString CfgName;
1040   char *s;
1041 
1042   CfgName = BaseDir->GUIConfigDirectory + wxT (DIRECTORY_DELIMITER) + Name;
1043   s = (char *) malloc (1025);
1044   strcpy (s, CfgName.char_str ());
1045   fp = fopen ((const char *)s, "w");
1046   if (fp != NULL)
1047     {
1048       strcpy (s, OutputFolder->GetValue ().char_str ());
1049       fprintf (fp, "OutputFolder=%s\n", (const char *) s);
1050       fprintf (fp, "AllCapsOk=%d\n", AllCapsOk->GetValue ());
1051       fprintf (fp, "RestoreDiacrits=%d\n", RestoreDiacrits->GetValue ());
1052       fprintf (fp, "RaggedRightMargin=%d\n", RaggedRightMargin->GetValue ());
1053       fprintf (fp, "HtmlOutput=%d\n", HtmlOutput->GetValue ());
1054       fprintf (fp, "FirstWordAllCapsOk=%d\n", FirstWordAllCapsOk->GetValue ());
1055       fprintf (fp, "ItalicizeNonEnglish=%d\n", ItalicizeNonEnglish->GetValue ());
1056       fprintf (fp, "PreserveStringsOfHyphens=%d\n", PreserveStringsOfHyphens->GetValue ());
1057       fprintf (fp, "HtmlUseSymbolicEntities=%d\n", HtmlUseSymbolicEntities->GetValue ());
1058       fprintf (fp, "LatexSectionMarkup=%d\n", LatexSectionMarkup->GetValue ());
1059       fprintf (fp, "FirstWordItalicsOk=%d\n", FirstWordItalicsOk->GetValue ());
1060       fprintf (fp, "SingleSpaceBetweenSentences=%d\n", SingleSpaceBetweenSentences->GetValue ());
1061       fprintf (fp, "HtmlAddPrefatoryMarks=%d\n", HtmlAddPrefatoryMarks->GetValue ());
1062       fprintf (fp, "LatexIndentParagraphs=%d\n", LatexIndentParagraphs->GetValue ());
1063       fprintf (fp, "RetainProjectGutenbergHeader=%d\n", RetainProjectGutenbergHeader->GetValue ());
1064       fprintf (fp, "HtmlAddPageBreakMarks=%d\n", HtmlAddPageBreakMarks->GetValue ());
1065       fprintf (fp, "LatexEliminateToc=%d\n", LatexEliminateToc->GetValue ());
1066       strcpy (s, ConfigurationFile->GetValue ().char_str ());
1067       fprintf (fp, "ConfigurationFile=%s\n", (const char *) s);
1068       fprintf (fp, "Profile=%d\n", Profile->GetSelection ());
1069       strcpy (s, Directory.char_str ());
1070       fprintf (fp, "InputDirectory=%s\n", (const char *) s);
1071       fprintf (fp, "Debug=%d\n", Debug->GetValue ());
1072       fprintf (fp, "RonsOptions=%d\n", RonsOptions->GetValue ());
1073       fprintf (fp, "RunGutenSplit=%d\n", RunGutenSplit->GetValue ());
1074       fprintf (fp, "LevelOne=%d\n", LevelOne->GetValue ());
1075       fprintf (fp, "LevelTwo=%d\n", LevelTwo->GetValue ());
1076       fprintf (fp, "LevelThree=%d\n", LevelThree->GetValue ());
1077       fprintf (fp, "LevelFour=%d\n", LevelFour->GetValue ());
1078       fprintf (fp, "SkipFirstHeading=%d\n", SkipFirstHeading->GetValue ());
1079       fprintf (fp, "TableOfContents=%d\n", TableOfContents->GetValue ());
1080       fclose (fp);
1081     }
1082 
1083   free (s);
1084   return (ReturnValue);
1085 }
1086 
1087