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