Back
1 // KERNEL
2 // * allow " or ' as escape chars, define able one for each (character/string)
3 // * parse single/multi line comment strings: exception handling
4 // * make " defineable as symbol
5 // * think about "CharsWithinString" -> identify identifier without this option!!
6 // ... or make word list matching with whole string
7
8 // Future:
9 // * Option: generate output using style sheets (css)
10 // * Option: add line anchors
11
12
13 //------------------------------------------------------------------------------
14 // Module: FMain.cpp //
15 // //
16 // Main program of Lore's Source to HTML Converter //
17 // //
18 // Copyright (c) 2000-2004 by Lars Haendel //
19 // Home: http://www.newty.de //
20 // //
21 // This program is free software and can be used under the terms of the //
22 // GNU licence. See header-file for further information and disclaimer. //
23 // //
24 //------------------------------------------------------------------------------
25
26
27
28 #include <vcl.h>
29 #pragma hdrstop
30
31 #pragma package(smart_init)
32 #pragma resource "*.dfm"
33
34
35 //----------------------------------------------------------------------------------------------------------------------
36 #include <FileCtrl.hpp> // due to: MinimizeName
37 #include <stdio> // sprintf
38 #include <process> // _beginthread
39 #include <iostream> // ifstream ...
40
41 #include "FMain.h"
42 #include "ThrConvert.h" // thread class for converting
43 #include "Conv2HTML.h" // TConv2HTML
44 #include "ErrText.h" // TErrText
45 #include "defines.h" // defines like using namspace etc.
46
47
48 //----------------------------------------------------------------------------------------------------------------------
49 // program's registry keys, filenames ...
50 #define SZ_REGISTRY_KEY "Source2HTML" // program's registry keys
51 #define SZ_ICON_FILE "Source2HTML.ico"
52 #define SZ_INITIALIZED "Initialized"
53 #define SZ_PROJECT_DIR "Default project directory"
54 #define SZ_SOURCE_DIR "Default source directory"
55 #define SZ_OUTPUT_DIR "Default output directory"
56 #define SZ_INCLUDE_DIR "Default include directory"
57 #define SZ_HELP_FILE "Source2HTML.hlp" // name of help file
58 #define INI_FILENAME "Source2HTML.ini" // name of ini file
59 #define STYLE_FILENAME "Styles.ini" // name of style file
60 #define LANGUAGE_FILENAME1 "Languages.ini" // name of language definition file
61 #define LANGUAGE_FILENAME2 "Languages.log" // backup
62 #define SZ_OVERVIEW_FILE "Overview.html" // name of generated overview file
63 #define PROJECT_EXTENSION "lsc" // project file extension
64 #define SZ_DEF_STYLE_NAME "User Defined" // default filename when saving style
65 #define SZ_SAVE_WARNING "Not all styles were loaded. Saving overwrites style file. \
66 Some styles may be lost!! Save style file?"
67
68
69 //----------------------------------------------------------------------------------------------------------------------
70 // file filters
71 #define FILE_FILTER_HTML "HTML files (*.html)|*.html|Any file (*.*)|*.*"
72
73
74 //----------------------------------------------------------------------------------------------------------------------
75 // Misc.
76 #define MAX_MESSAGES_IN_LISTVIEW 150 // max. number messages shown in list view
77
78
79 //----------------------------------------------------------------------------------------------------------------------
80 // globals
81 static char szCmdLine[STS];
82 char* GetCmdLine() { return szCmdLine; } // command line
83
84
85 //----------------------------------------------------------------------------------------------------------------------
86 // Utility function: Interpret character as hex and convert it to int
87 int Hex2Int(const char& c)
88 {
89 if(IsDigit(c))
90 return (int) c-48; // number 0..9
91
92 if(c>96)
93 return (int) c-87; // lower case letter a..f
94 else
95 return (int) c-55; // capital letter A..F
96 }
97
98
99 //----------------------------------------------------------------------------------------------------------------------
100 // Utility function: Convert color string to TColor
101 inline TColor StringToTColor(const char*const& szColor)
102 {
103 return TColor(RGB(Hex2Int(szColor[1])*16+Hex2Int(szColor[2]), Hex2Int(szColor[3])*16+Hex2Int(szColor[4])
104 , Hex2Int(szColor[5])*16+Hex2Int(szColor[6])));
105 }
106
107
108
109 TFMain *FMain;
110 //----------------------------------------------------------------------------------------------------------------------
111 // constructor
112 __fastcall TFMain::TFMain(TComponent* Owner) : TForm(Owner)
113 {
114 // a) compose and set window caption
115 Caption = szCmplPrgName = AnsiString(SZ_PRGNAME) + " " + AnsiString(SZ_VERSION);
116
117 // b) set style, registry and language to NULL Note: Ini is done in OnShow()
118 style = NULL;
119 registry = NULL;
120 lang = NULL;
121
122 // c) store directory of the executable, clear project filename and set help filename
123 szDir = IncludeTrailingBackslash(ExtractFileDir(Application->ExeName));
124 szProjectFile = ""; // clear
125 Application->HelpFile = szDir + SZ_HELP_FILE;
126
127 // d) set flags
128 f_Converting = f_ManipCtrls = false;
129 f_Saved = true;
130
131 /* rest of initialization is done in OnShow() */
132 }
133
134
135 //----------------------------------------------------------------------------------------------------------------------
136 // destructor
137 __fastcall TFMain::~TFMain()
138 {
139 delete registry; // registry
140 };
141
142
143 //----------------------------------------------------------------------------------------------------------------------
144 // Called when user tries to close the main form: If conversion process is running, ask user before closing.
145 void __fastcall TFMain::OnCloseQuery(TObject*, bool &CanClose)
146 {
147 // a) ask user if program is busy
148 if(f_Converting)
149 if(f_Stop)
150 {
151 if(Application->MessageBox("Enforce \
152 termination ??", "Process should terminate but doesn't do so!", MB_YESNO | MB_ICONQUESTION)== ID_NO)
153 CanClose = false;
154 }
155 else
156 if(Application->MessageBox("Terminate it anyway ??", "Process still running!", MB_YESNO | MB_ICONQUESTION)== ID_YES)
157 {
158 CanClose = false;
159 f_Stop = true;
160 }
161
162 // b) ask user if project is unsaved and there is at least one file specified
163 if(!f_Saved && project.nFiles()>0)
164 if(Application->MessageBox("Project not saved!! Save it now ??", "Question", MB_YESNO | MB_ICONQUESTION)==ID_YES)
165 TbSaveProjectClick(this);
166
167
168 // c) write default directories to registry
169 try
170 {
171 registry->OpenKey(AnsiString("\\Software\\") + SZ_REGISTRY_KEY, true); // open key
172 registry->WriteString(SZ_PROJECT_DIR, szProjectDir);
173 registry->WriteString(SZ_SOURCE_DIR, szSourceDir);
174 registry->WriteString(SZ_OUTPUT_DIR, szOutputDir);
175 registry->WriteString(SZ_INCLUDE_DIR, szIncludeDir);
176 registry->CloseKey(); // close key
177 }
178 catch(ERegistryException& err) // exception handling
179
180 {
181 // Note: Should not happen cause access to subkeys of HKEY_CURRENT_USER should be given
182 Application->MessageBox("Should not happen for root key 'HKEY_CURRENT_USER'!!", "Error accessing registry !!"
183 , MB_OK | MB_ICONWARNING);
184 }
185 }
186
187
188 //----------------------------------------------------------------------------------------------------------------------
189 // Save style file using SaveStyles() when closing ...
190 void __fastcall TFMain::OnClose(TObject*, TCloseAction &Action) { SaveStyles(); }
191
192
193 //----------------------------------------------------------------------------------------------------------------------
194 // exit application
195 void __fastcall TFMain::MnExitClick(TObject*)
196 {
197 bool f_CanClose = true;
198 OnCloseQuery(this, f_CanClose); // ask user if application is busy
199 if(f_CanClose)
200 Application->Terminate();
201 }
202
203
204 //----------------------------------------------------------------------------------------------------------------------
205 // Load styles from file, set the language sample texts, enable drag#&drop ...
206 void __fastcall TFMain::OnShow(TObject*)
207 {
208 //-------------------------------------------------------------------------------------------------------------------
209 // 1. create registry object and register project file extension if program is started first time
210 registry = new TRegistry;
211
212 try
213 {
214 registry->OpenKey(AnsiString("\\Software\\") + SZ_REGISTRY_KEY, true); // open key
215 if(registry->ReadString(SZ_INITIALIZED).IsEmpty()) // if data value 'Initialized is empty'
216 {
217 registry->CloseKey(); // close key
218 int res = RegisterExtension(); // register extension
219 registry->RootKey = HKEY_CURRENT_USER; // change root key back
220 registry->OpenKey(AnsiString("\\Software\\") + SZ_REGISTRY_KEY, true); // open previous key again
221
222 // set 'Initialized' ...
223 if(res==ID_NO) // ... user decided NOT to register project file extension to me
224 registry->WriteString(SZ_INITIALIZED, "Extension NOT registered!");
225
226 if(res==ID_YES) // ... project file extension was registered
227 registry->WriteString(SZ_INITIALIZED, "Extension registered!");
228
229 if(res==-1) // ... error accessing registry
230 registry->WriteString(SZ_INITIALIZED, "Error accessing registry!");
231 }
232
233 // f) read default directories for projects, source files and output
234 szProjectDir = registry->ReadString(SZ_PROJECT_DIR);
235 szSourceDir = registry->ReadString(SZ_SOURCE_DIR);
236 szOutputDir = registry->ReadString(SZ_OUTPUT_DIR);
237 szIncludeDir = registry->ReadString(SZ_INCLUDE_DIR);
238 registry->CloseKey(); // close key
239 }
240 catch(ERegistryException& err) // exception handling
241 {
242 // Note: Should not happen cause access to subkeys of HKEY_CURRENT_USER should be given
243 AddMessage("Error accessing registry. Should not happen for root key 'HKEY_CURRENT_USER'!!");
244 }
245
246
247 //-------------------------------------------------------------------------------------------------------------------
248 // 2. load ini file
249
250 // a) try to load ini file and display message if an error occurs
251 try
252 {
253 // open file for output and check success
254 ifstream file((szDir + INI_FILENAME).c_str(), ios::in);
255 if(!file)
256 throw TErrText("Unable to open ini file: ", (szDir + INI_FILENAME).c_str());
257
258 defaults.Load(file); // load ini file
259 }
260 catch(TErrText err) // exception handling
261 {
262 // display error message
263 AddMessage(AnsiString("Error loading ini file! " ) + err.szErrText + " Using defaults!");
264
265 // reset to factory defaults
266 defaults.RestoreFactoryDefaults();
267
268 // try to create new ini file using SaveDefaults()
269 SaveDefaults();
270 }
271
272
273 //-------------------------------------------------------------------------------------------------------------------
274 // 3. load language definition file
275
276 // a) try to load language definition file and display message if an error occurs
277 try
278 {
279 // open file for output and check success
280 ifstream file((szDir + LANGUAGE_FILENAME1).c_str(), ios::in);
281 if(!file)
282 throw TErrText("Unable to open language definition file: ", (szDir + INI_FILENAME).c_str());
283
284 langs.Load(file); // load language definition file
285 }
286 catch(TErrText err) // exception handling
287 {
288 if(langs.Size()>0) // display error in message list if at least one language definition was loaded ...
289 {
290 AddMessage(AnsiString("Error loading language definition file!"));
291 AddMessage(err.szErrText);
292 AddMessage("");
293 }
294
295 // ... else terminate program
296 else
297 {
298 Application->MessageBox(err.szErrText, "Fatal error loading language definitions! Program will terminate!"
299 , MB_OK | MB_ICONERROR);
300 Application->Terminate(); // terminate application
301 }
302 }
303
304 try
305 {
306 // open output file
307 ofstream file((szDir + LANGUAGE_FILENAME2).c_str(), ios::out);
308 if(!file)
309 throw TErrText("Unable to open log file for language definitions: ", (szDir + INI_FILENAME).c_str());
310
311 langs.Save(file);
312 }
313 catch(TErrText err)
314 {
315 // display error message
316 AddMessage(AnsiString("Error writing log of language definition file! ") + err.szErrText);
317 }
318
319 // initialize names in language drop down list
320 for(int i=0;i<langs.Size();i++)
321 CbLanguage->Items->Add(langs.Get(i)->Name());
322
323
324
325 //-------------------------------------------------------------------------------------------------------------------
326 // 4. load styles
327 f_StyleLoadError = false;
328
329 // a) try to load styles from style file and display message if an error occurs
330 try
331 {
332 styles.Load((szDir + STYLE_FILENAME).c_str()); // load style file
333 }
334 catch(TErrText err)
335 {
336 AddMessage(AnsiString("Error loading style file !! ") + err.szErrText);
337 f_StyleLoadError = true; // set flag: a warning will be displayed when saving style file
338 }
339
340 // b) transfer the names of each style to the list box
341 for(int i=0;i<styles.nStyles();i++)
342 LbStyles->Items->Add(styles.GetStyle(i)->szName);
343
344 // c) select style: if there are styles in the list, take the first one. Otherwise create temporary style object
345 InitializeStyle();
346
347
348
349 //-------------------------------------------------------------------------------------------------------------------
350 // 5. enable drag&drop and misc. settings
351 DragAcceptFiles(Handle, true); // now the window receives WM_DROPFILES messages
352
353 PageControl->ActivePage = TsConvert; // set active tab sheet
354 wrapper.hwnd = Handle;
355
356
357 //-------------------------------------------------------------------------------------------------------------------
358 // 6. open project if filename is passed in command line, else initialize to new project
359 char szCmdLine[STS];
360 strcpy(szCmdLine, GetCmdLine()); // copy command line
361 if(szCmdLine[0]!='\0') // if not empty ...
362 {
363 // get first whitespace terminated string removing enclosing '"'
364 char* szString = szCmdLine; // ini
365 if(szCmdLine[0]=='"')
366 szString = &(szCmdLine[1]); // skip the '"' if necessary
367
368 int i=0; // find terminating whitespace or '"'
369 while(!isspace(szString[i]) && szString[i]!='"')
370 i++;
371 szString[i]='\0'; // terminate string
372
373 OpenProject(ExpandFileName(szString).c_str()); // ... open project expanding relative filenames if necessary
374 }
375 else
376 MnNewProjectClick(this); // initialize new project
377 }
378
379
380 //----------------------------------------------------------------------------------------------------------------------
381 // register project file extension
382 int TFMain::RegisterExtension()
383 {
384 try
385 {
386 // a) change root key and generate extension string ('.lsc')
387 registry->RootKey = HKEY_CLASSES_ROOT; // change root key
388 AnsiString szTmp = AnsiString(".") + PROJECT_EXTENSION; // extension string
389
390
391 // b) ask user if extension is already registered to another program
392 if(registry->KeyExists(szTmp)) // if extension key already exists
393 {
394 // read class registered to extension now
395 registry->OpenKey(szTmp, false); // open key
396 AnsiString szOtherApp = registry->ReadString(""); // read class asigned to extension
397 registry->CloseKey(); // close key again
398
399 // if ...
400 if(szOtherApp != SZ_REGISTRY_KEY)
401 {
402 // read command line registered to class
403 registry->OpenKey(AnsiString("\\") + szOtherApp + "\\shell\\open\\command", true); // open key
404 AnsiString szCmdLine = registry->ReadString(""); // read
405 registry->CloseKey(); // close key
406
407 // compose message text and ask user
408 AnsiString szMsgText = "Project file extension '" + szTmp + "' already registered to '" + szOtherApp + "'"
409 + " (" + szCmdLine.SubString(1, szCmdLine.LastDelimiter(" ")-1) + ").\n" + "Re-assign extension to me ??"
410 + " If you choose 'Cancel' you'll be prompted again next time.";
411 int res = Application->MessageBox(szMsgText.c_str(), "Project file extension alread registered !!"
412 , MB_YESNOCANCEL | MB_ICONQUESTION);
413 if(res!=ID_YES)
414 return res; // user canceled
415 }
416 }
417
418 // c) write extensions string (assigning class 'Source2HTML' to extension '.lsc')
419 registry->OpenKey(szTmp, true); // open key
420 registry->WriteString("", SZ_REGISTRY_KEY); //
421 registry->CloseKey(); // close key
422
423 // d) write shell command (assigning executable to class 'Source2HTML')
424 registry->OpenKey(AnsiString("\\") + SZ_REGISTRY_KEY + "\\shell\\open\\command", true);// open key
425 registry->WriteString("", Application->ExeName + " %1"); // set command line
426 registry->CloseKey(); // close key
427
428 // e) set default icon that is displayed in explorer together with '.lsc' files
429 registry->OpenKey(AnsiString("\\") + SZ_REGISTRY_KEY + "\\DefaultIcon", true); // open key
430 registry->WriteString("", szDir + SZ_ICON_FILE); // file's icon
431 registry->CloseKey(); // close key
432
433 return ID_YES; // all ok
434 }
435 catch(ERegistryException& err)
436 {
437 Application->MessageBox("Project file extension was not registered!! You may need administrator\nrights to\
438 access root key 'HKEY_CLASSES_ROOT'!!", "Error accessing registry !!", MB_OK | MB_ICONWARNING);
439 return -1;
440 }
441 }
442
443
444 //----------------------------------------------------------------------------------------------------------------------
445 // response to size changes: re-write file selection list view
446 // Response to 'F1'_ open help using MnOpenHelpClick()
447 void __fastcall TFMain::CmOpenHelp(TWMKey &Msg, bool &Handled)
448 {
449 if(Msg.CharCode==VK_F1)
450 MnOpenHelpClick(this);
451 }
452
453
454 //----------------------------------------------------------------------------------------------------------------------
455 // Show about dialog note: dialog deletes itself when closed
456 void __fastcall TFMain::MnAboutClick(TObject*)
457 {
458 TFAbout* about = new TFAbout(this, szCmplPrgName, szDir); // create dialog
459 about->ShowModal(); // show dialog (modal)
460 }
461
462
463 //----------------------------------------------------------------------------------------------------------------------
464 // open help file
465 void __fastcall TFMain::MnOpenHelpClick(TObject*)
466 {
467 Application->HelpCommand(HELP_CONTENTS, 0);
468 }
469
470
471 //----------------------------------------------------------------------------------------------------------------------
472 // Disallow changing of tab sheet if program is converting
473 void __fastcall TFMain::PageControlChanging(TObject*, bool &AllowChange)
474 {
475 AllowChange = !f_Converting;
476 }
477
478
479 //----------------------------------------------------------------------------------------------------------------------
480 // Enable controls and set focus if the active tab sheets changes
481 void __fastcall TFMain::PageControlChange(TObject*)
482 {
483 // a) Move language drop down list to correct position
484 PositionLanguageDropDownList();
485
486 // b) move language drop down list to the selected tab sheet
487 GbLanguage->Parent = PageControl->ActivePage;
488 }
489
490 //----------------------------------------------------------------------------------------------------------------------
491 void __fastcall TFMain::PageControlResize(TObject *Sender)
492 {
493 // adjust file selection list view
494 RefreshFileSelectionListView();
495
496 // move language drop down list to correct position
497 PositionLanguageDropDownList();
498 }
499
500
501 //----------------------------------------------------------------------------------------------------------------------
502 // Move language drop down list to correct position
503 void TFMain::PositionLanguageDropDownList()
504 {
505 // a) if it's the "Highlighting" tab sheet ...
506 if(PageControl->ActivePage == TsHighlighting)
507 {
508 // position language drop down list
509 GbLanguage->Top = GbCurrentStyle->Top + GbCurrentStyle->Height + 10;
510 GbLanguage->Left = GbStyleSpeedSettings->Left + GbStyleSpeedSettings->Width + 10;
511 GbLanguage->Visible = true; // show it
512 }
513
514 // b) if it's the "Options" tab sheet ...
515 if(PageControl->ActivePage == TsOptions)
516 GbLanguage->Visible = false; // hide it
517
518 // c) if it's the "Convert" tab sheet ...
519 if(PageControl->ActivePage == TsConvert)
520 {
521 BtAddFile->SetFocus(); // ... focus on "Add File" button
522 EnableConvertCtrls(); // enable/disable controls
523
524 // position language drop down list
525 GbLanguage->Top = GbFileSelection->Top + GbFileSelection->Height + 2;
526 GbLanguage->Left = 5;
527 GbLanguage->Visible = true; // show it
528 }
529 }
530
531
532 //-------------------------------------------------------------------------------------------------------------------
533 // Project management
534 //
535
536 //----------------------------------------------------------------------------------------------------------------------
537 // initialize controls on tab sheet 'Options'
538 void TFMain::EnableOptionsCtrls()
539 {
540 // enable/disable dependant controls in groupbox 'Misc'
541 CbAddLineAnchors->Enabled = project.f_AddLineNumbers;
542
543 // enable/disable dependant controls in groupbox 'Back Links'
544 RbBackLink1->Enabled = project.f_AddBackLink;
545 RbBackLink2->Enabled = project.f_AddBackLink;
546 BtBackLink->Enabled = project.f_AddBackLink && project.f_UserDefinedBackLink;
547 LaBackLinkText->Enabled = project.f_AddBackLink && project.f_UserDefinedBackLink;
548
549 // enable/disable dependant controls in groupbox 'Expert Settings'
550 UdEndlNo->Enabled = project.f_TagClosingOnEndl;
551 LaEndlNo->Enabled = project.f_TagClosingOnEndl;
552 LaHint->Visible = project.f_AddLineNumbers && project.f_TagClosingOnEndl && project.nEndl!=1;
553
554 // enable/disable dependant controls in groupbox 'Overview File'
555 BtSetOverviewFileName->Enabled = project.f_GenerateOverviewFile;
556 LaOverviewFileName->Enabled = project.f_GenerateOverviewFile;
557 }
558
559
560 //----------------------------------------------------------------------------------------------------------------------
561 // set GUI according to project settings note: Calls OptionsToGUI()
562 void TFMain::ProjectToGUI()
563 {
564 f_ManipCtrls = true;
565
566 //-------------------------------------------------------------------------------------------------------------------
567 // tab sheet 'Options'
568
569
570 //-------------------------------------------------------------------------------------------------------------------
571 // tab sheet 'Convert'
572
573 // group box 'File Selection'
574 CbShowPath->Checked = project.f_ShowPath;
575 CbOverwriteExistingFiles->Checked = project.f_OverwriteExistingFiles;
576 CbEnforceOutputDir->Checked = project.f_EnforceOutputDir;
577 LaOutputDir->Caption = project.szOutputDir;
578
579 // source and destination filenames
580 while(project.nFiles()-LvFiles->Items->Count) // if there are more filenames in project than in list view
581 (LvFiles->Items->Add())->SubItems->Add(""); // add item and subitem to list view
582
583 RefreshFileSelectionListView();
584
585
586 //-------------------------------------------------------------------------------------------------------------------
587 // tab sheet 'Highlighting'
588 // set style
589 bool f_StyleNotFound = false;
590 if(project.szStyle[0]!='\0') // if style name is not empty
591 {
592 int id = styles.GetStyleId(project.szStyle); // try to find style in list
593 if(id>=0)
594 { // if found ...
595 LbStyles->ItemIndex = id; // set style id ...
596 CmStyleChange(this); // ... and change style
597 }
598 else
599 {
600 // display warning message if style wasn't found
601 Application->MessageBox((AnsiString("Style '") + project.szStyle + "' not found! Using defaults!").c_str()
602 , "Error loading project file !!", MB_OK | MB_ICONWARNING);
603
604 strcpy(project.szStyle, style->szName); // ... else set style name in project
605 f_StyleNotFound = true;
606 }
607 }
608
609
610 //-------------------------------------------------------------------------------------------------------------------
611 // enable/disable controls
612 OptionsToGUI();
613 EnableOptionsCtrls();
614 EnableConvertCtrls();
615
616 ProjectSaved(!f_StyleNotFound); // save buttons Note: function is only called if project is loaded or new empty
617 // one has been created.
618
619 f_ManipCtrls = false;
620 }
621
622
623 //----------------------------------------------------------------------------------------------------------------------
624 // set GUI according to options settings (TOptions part of TProject)
625 void TFMain::OptionsToGUI()
626 {
627 //-------------------------------------------------------------------------------------------------------------------
628 // tab sheet 'Options'
629
630
631 // groupbox 'Expert Settings'
632 CbTabClosingOnEndl->Checked = project.f_TagClosingOnEndl;
633 CbTags->Checked = project.f_HtmlAndBodyTags;
634 LaEndlNo->Caption = AnsiString(project.nEndl);
635 UdEndlNo->Position = project.nEndl;
636
637
638 // section 'Misc': tab stop positions, indent and language
639 LaTab ->Caption = AnsiString(project.tabPos);
640 LaIndent->Caption = AnsiString(project.indent);
641 UdIndent->Position = project.indent;
642 UdTab ->Position = project.tabPos;
643 CbAddBackLink->Checked = project.f_AddBackLink;
644 CbAddTopLinks->Checked = project.f_AddTopLinks;
645 CbAddLineNumbers->Checked = project.f_AddLineNumbers;
646 CbAddLineAnchors->Checked = project.f_AddLineAnchors;
647
648 if(!project.f_UserDefinedBackLink)
649 RbBackLink1->Checked=true;
650 else
651 RbBackLink2->Checked=true;
652 LaBackLinkText->Caption = project.szBackLinkText;
653
654
655 // groupbox 'Generated Overview File'
656 CbGenerateOverviewFile ->Checked = project.f_GenerateOverviewFile;
657 LaOverviewFileName->Caption = MinimizeName(project.szOverviewFileName, LaOverviewFileName->Canvas, LaOverviewFileName->Width*0.9);
658
659
660
661 //-------------------------------------------------------------------------------------------------------------------
662 // enable/disable controls and language
663 EnableOptionsCtrls();
664
665 // language and corresponding sample texts
666 int id = langs.GetId(project.szLanguage); // try to find langauge
667 if(id<0) // if language wasn't found ...
668 {
669 // ... display warning message
670 AddMessage((AnsiString("Language '") + project.szLanguage + "' not found! Using defaults!").c_str());
671 if(id<0) // if still no match is found ...
672 id=0; // ... use first language as default
673
674 ProjectSaved(false); // project is not saved anymore
675 }
676 lang = langs.Get(id); // get pointer to language
677 CbLanguage->ItemIndex = id; // select language in drop down list
678 }
679
680
681 //----------------------------------------------------------------------------------------------------------------------
682 void TFMain::ProjectSaved(const bool& _f_Saved)
683 {
684 f_Saved = _f_Saved;
685 TbSaveProject->Enabled = !f_Saved;
686 MnSaveProject->Enabled = !f_Saved;
687 }
688
689
690 //----------------------------------------------------------------------------------------------------------------------
691 // response to menu item 'New Project'
692 void __fastcall TFMain::MnNewProjectClick(TObject*)
693 {
694 // a) ask user if project is unsaved
695 if(!f_Saved && project.nFiles()>0)
696 if(Application->MessageBox("Current project settings are not saved! Continue ??", "Question", MB_YESNO | MB_ICONQUESTION)==ID_NO)
697 return;
698
699
700 // a) clear
701 szProjectFile = ""; // clear project filename
702 Caption = AnsiString(szCmplPrgName); // reset window caption
703 project.RestoreDefaults(defaults); // restore defaults for current project's options
704 CmClearList(this); // clear file lists (in list view, the ones in project arfe already cleared)
705
706 // b)
707 ProjectToGUI(); // transfer changes to GUI
708
709 // c) enable/disable controls
710 EnableOptionsCtrls();
711 EnableConvertCtrls();
712 }
713
714 //----------------------------------------------------------------------------------------------------------------------
715 // save project as ...
716 void __fastcall TFMain::MnSaveProjectAsClick(TObject*)
717 {
718 szProjectFile = ""; // clear project filename
719 Caption = AnsiString(szCmplPrgName); // reset window caption
720 TbSaveProjectClick(this); // save project
721 }
722
723
724 //----------------------------------------------------------------------------------------------------------------------
725 // Save project
726 void __fastcall TFMain::TbSaveProjectClick(TObject*)
727 {
728 // a) ask for filename if project filename is empty
729 if(szProjectFile.IsEmpty())
730 {
731 // set dialog captions and options
732 SaveDialog->Title = "Save project as ...";
733 SaveDialog->Options << ofPathMustExist << ofOverwritePrompt << ofNoReadOnlyReturn;
734 SaveDialog->Filter = "Project file (*." + AnsiString(PROJECT_EXTENSION) + ")|*."
735 + AnsiString(PROJECT_EXTENSION);
736 SaveDialog->DefaultExt = PROJECT_EXTENSION; // set default extension
737
738 SaveDialog->FileName = ""; // clear as ini
739 if(!szProjectFile.IsEmpty()) // if not empty ...
740 SaveDialog->FileName = szProjectFile; // ... initialize filename
741 else
742 if(!szProjectDir.IsEmpty()) // else, again if not empty, ...
743 SaveDialog->InitialDir = szProjectDir; // ... set directory last time used with 'Save Project' dialog
744
745
746 // execute open dialog and return if dialog closed with cancel
747 if(!SaveDialog->Execute())
748 return;
749
750 // store project filename and directory and display in windows caption
751 szProjectFile = SaveDialog->FileName;
752 szProjectDir = ExtractFileDir(szProjectFile);
753 Caption = AnsiString(szCmplPrgName) + " " + szProjectFile;
754 }
755
756
757 // b) save project
758 try
759 {
760 // try to open file and check success
761 ofstream file(szProjectFile.c_str(), ios::out);
762 if(!file)
763 throw TErrText("Unable to open project file: ", szProjectFile.c_str());
764
765 project.Save(file); // save project
766
767 // display warning if style is temporary, i.e. style name in project is empty
768 if(project.szStyle[0]=='\0')
769 Application->MessageBox("Temporary style wasn't saved. Please save style first.", "Problem saving project file"
770 , MB_OK | MB_ICONWARNING);
771
772 ProjectSaved(true); // disable save buttons
773 }
774 catch(TErrText err)
775 {
776 // display error message
777 Application->MessageBox(err.szErrText, "Error saving project file!!", MB_OK | MB_ICONERROR);
778 }
779 }
780
781
782 //----------------------------------------------------------------------------------------------------------------------
783 // ask user for project filename and it using OpenProject()
784 void __fastcall TFMain::TbOpenProjectClick(TObject*)
785 {
786 // a) ask user if project is unsaved
787 if(!f_Saved && project.nFiles()>0)
788 if(Application->MessageBox("Current project settings are not saved! Continue ??", "Question", MB_YESNO | MB_ICONQUESTION)==ID_NO)
789 return;
790
791 f_Saved = true; // hack to prevent user questioning in MnNewProjectClick()
792 MnNewProjectClick(this); // clear project
793
794
795 // set dialog captions and options
796 OpenDialog->Title = "Choose Project File ...";
797 OpenDialog->Options << ofFileMustExist << ofPathMustExist;
798 OpenDialog->Filter = "Project file (*." + AnsiString(PROJECT_EXTENSION) + ")|*."
799 + AnsiString(PROJECT_EXTENSION);
800 OpenDialog->FileName = ""; // clear as ini
801 if(!szProjectFile.IsEmpty()) // if not empty ...
802 OpenDialog->FileName = szProjectFile; // ... initialize filename
803 else
804 if(!szProjectDir.IsEmpty()) // else, again if not empty, ...
805 OpenDialog->InitialDir = szProjectDir; // ... set directory last time used with 'Open Project' dialog
806
807
808
809 // execute open dialog and return if dialog closed with cancel
810 if(!OpenDialog->Execute())
811 return;
812
813 // open project
814 OpenProject(OpenDialog->FileName.c_str());
815 }
816
817
818 //----------------------------------------------------------------------------------------------------------------------
819 // open project
820 void TFMain::OpenProject(const char*const& szFileName)
821 {
822 // load project file with exception handling
823 try
824 {
825 // open file for output and check success
826 ifstream file(szFileName, ios::in);
827 if(!file)
828 throw TErrText("Unable to open project file: ", szFileName);
829
830 project.Load(file);
831
832 szProjectFile = szFileName; // store project filename ...
833 szProjectDir = ExtractFileDir(szProjectFile); // ... and directory
834 Caption = AnsiString(szCmplPrgName) + " " + szProjectFile; // display project filename in window caption
835 ProjectToGUI(); // transfer changes to GUI
836 PageControl->ActivePage = TsConvert; // set active tab sheet
837 }
838 catch(TErrText err)
839 {
840 Application->MessageBox(err.szErrText, "Error loading project file!", MB_OK | MB_ICONERROR);
841 MnNewProjectClick(this); // clear project again
842 }
843 }
844
845
846 //----------------------------------------------------------------------------------------------------------------------
847 // user has selected a new langauge
848 void __fastcall TFMain::CbLanguageChange(TObject *Sender)
849 {
850 lang = langs.Get(CbLanguage->ItemIndex); // get pointer to language
851 ProjectSaved(false); // project is not saved anymore
852 strcpy(project.szLanguage, lang->Name()); // set new language in project
853 }
854
855
856 //-------------------------------------------------------------------------------------------------------------------
857 // (default) options management like restore default etc.
858 //
859
860 //----------------------------------------------------------------------------------------------------------------------
861 // set settings to factory defaults
862 void __fastcall TFMain::BtRestoreFactoryDefaultsClick(TObject*)
863 {
864 defaults.RestoreFactoryDefaults(); // restore factory defaults for default options ...
865
866 // ... and copy them to current project's options
867 // note: call base class version as only the options part and not the project part should be set to defaults
868 project.TOptions::RestoreDefaults(defaults);
869
870 OptionsToGUI(); // transfer changes to GUI
871 SaveDefaults(); // save defaults
872
873 ProjectSaved(false); // enable save buttons
874 }
875
876
877 //----------------------------------------------------------------------------------------------------------------------
878 // initialize settings with defaults from ini file
879 void __fastcall TFMain::BtRestoreDefaultsClick(TObject*)
880 {
881 // restore defaults for current project's options
882 // note: call base class version as only the options part and not the project part should be set to defaults
883 project.TOptions::RestoreDefaults(defaults);
884
885 OptionsToGUI(); // transfer changes to GUI
886 ProjectSaved(false); // enable save buttons
887 }
888
889
890 //----------------------------------------------------------------------------------------------------------------------
891 // save current settings as defaults to ini file
892 void __fastcall TFMain::BtSaveDefaultsClick(TObject*)
893 {
894 defaults.RestoreDefaults(project); // copy current settings to default settings ...
895 SaveDefaults(); // ... and save them
896 }
897
898
899 //----------------------------------------------------------------------------------------------------------------------
900 // Utility: Save default settings
901 void TFMain::SaveDefaults()
902 {
903 // save default settings
904 try
905 {
906 // try to open ini file and check success
907 ofstream file((szDir + INI_FILENAME).c_str(), ios::out);
908 if(!file)
909 throw TErrText("Unable to open ini file: ", (szDir + INI_FILENAME).c_str());
910
911 defaults.Save(file);
912 }
913 catch(TErrText err)
914 {
915 Application->MessageBox(err.szErrText, "Error creating ini file! ", MB_OK | MB_ICONWARNING);
916 }
917 }
918
919
920
921
922 //-------------------------------------------------------------------------------------------------------------------
923 // Response to controls on tab sheet 'Options'
924 //
925
926 //----------------------------------------------------------------------------------------------------------------------
927 // response to check box 'Generate Overview File'
928 void __fastcall TFMain::CbGenerateOverviewFileClick(TObject*)
929 {
930 project.f_GenerateOverviewFile = CbGenerateOverviewFile->Checked;
931 EnableOptionsCtrls();
932 ProjectSaved(false); // enable save buttons
933 }
934
935
936 //----------------------------------------------------------------------------------------------------------------------
937 // Respond to changes of the tab stop positions
938 void __fastcall TFMain::CmTab(TObject*, TUDBtnType Button)
939 {
940 project.tabPos = UdTab->Position; // copy new value ...
941 LaTab->Caption = AnsiString(project.tabPos); // ... and display it
942 ProjectSaved(false); // enable save buttons
943 }
944
945 //----------------------------------------------------------------------------------------------------------------------
946 // Respond to changes of the indent
947 void __fastcall TFMain::CmIndent(TObject*, TUDBtnType Button)
948 {
949 project.indent = UdIndent->Position; // copy new value ...
950 LaIndent->Caption = AnsiString(project.indent); // ... and display it
951 ProjectSaved(false); // enable save buttons
952 }
953
954 //----------------------------------------------------------------------------------------------------------------------
955 // Respond to changes of the "nEndl" setting
956 void __fastcall TFMain::CmEndlNo(TObject*, TUDBtnType Button)
957 {
958 project.nEndl = UdEndlNo->Position; // copy new value ...
959 LaEndlNo->Caption = AnsiString(project.nEndl); // ... and display it
960 EnableOptionsCtrls(); // enable/disable hint
961 ProjectSaved(false); // enable save buttons
962 }
963
964 //----------------------------------------------------------------------------------------------------------------------
965 // Respond to changes of the expert mode enable/disable check box
966 void __fastcall TFMain::CmTabClosingOnEndl(TObject*)
967 {
968 project.f_TagClosingOnEndl = CbTabClosingOnEndl->Checked; // set in project
969
970 // enable/disable the text/updown-control and hint
971 EnableOptionsCtrls();
972
973 // enable save buttons
974 ProjectSaved(false);
975 }
976
977 //----------------------------------------------------------------------------------------------------------------------
978 // Repond to changes of the remaining options chek boxes
979 void __fastcall TFMain::CmTags (TObject*){ project.f_HtmlAndBodyTags = CbTags->Checked; ProjectSaved(false);}
980 void __fastcall TFMain::CbAddBackLinkClick (TObject*){ project.f_AddBackLink = CbAddBackLink->Checked; EnableOptionsCtrls(); ProjectSaved(false);}
981 void __fastcall TFMain::CbAddTopLinksClick (TObject*){ project.f_AddTopLinks = CbAddTopLinks->Checked; ProjectSaved(false);}
982 void __fastcall TFMain::CbAddLineNumbersClick(TObject*){ project.f_AddLineNumbers = CbAddLineNumbers->Checked; EnableOptionsCtrls(); ProjectSaved(false);}
983 void __fastcall TFMain::RbBackLink1Click(TObject*){ project.f_UserDefinedBackLink = RbBackLink2->Checked; EnableOptionsCtrls(); ProjectSaved(false);}
984 void __fastcall TFMain::RbBackLink2Click(TObject *Sender){ project.f_UserDefinedBackLink = RbBackLink2->Checked; EnableOptionsCtrls(); ProjectSaved(false);}
985 void __fastcall TFMain::CbAddLineAnchorsClick(TObject *Sender){ project.f_AddLineAnchors = CbAddLineAnchors->Checked; ProjectSaved(false);}
986
987 //-------------------------------------------------------------------------------------------------------------------
988 // Functions to show current style in GUI (e.g. preview)
989 //
990
991 //----------------------------------------------------------------------------------------------------------------------
992 // Utility function: Open choose color dialog and write back the result
993 void TFMain::SetColor(char*const& szColor)
994 {
995 // a) convert color string to TColor
996 TColor color = StringToTColor(szColor);
997
998 // b)
999 ColorDialog->Color = color; // set actual color as default for the color-dialog
1000 ColorDialog->Execute(); // execute the dialog
1001
1002 // c) write back the results
1003 unsigned char* c = (unsigned char*) &(ColorDialog->Color);
1004 sprintf(szColor, "#%02x%02x%02x", (unsigned int) c[0], (unsigned int) c[1], (unsigned int) c[2]);
1005
1006 // d) update preview sample text fields
1007 StyleToPreview();
1008 }
1009
1010
1011 //----------------------------------------------------------------------------------------------------------------------
1012 // set checkboxes according to current style
1013 void TFMain::StyleToCheckboxes()
1014 {
1015 // a) set check boxes for bold styles
1016 CbBold1->Checked = style->f_Bold[TItemStyle::Comment];
1017 CbBold2->Checked = style->f_Bold[TItemStyle::Keyword];
1018 CbBold4->Checked = style->f_Bold[TItemStyle::Symbol];
1019 CbBold5->Checked = style->f_Bold[TItemStyle::String];
1020 CbBold6->Checked = style->f_Bold[TItemStyle::Number];
1021 CbBold7->Checked = style->f_Bold[TItemStyle::Character];
1022 CbBold8->Checked = style->f_Bold[TItemStyle::Preproc];
1023 CbBold9->Checked = style->f_Bold[TItemStyle::Custom1];
1024 CbBoldA->Checked = style->f_Bold[TItemStyle::Custom2];
1025 CbBoldB->Checked = style->f_Bold[TItemStyle::Custom3];
1026 CbBoldC->Checked = style->f_Bold[TItemStyle::Custom4];
1027
1028 // b) set check boxes for italic styles
1029 CbItalic1->Checked = style->f_Italic[TItemStyle::Comment];
1030 CbItalic2->Checked = style->f_Italic[TItemStyle::Keyword];
1031 CbItalic4->Checked = style->f_Italic[TItemStyle::Symbol];
1032 CbItalic5->Checked = style->f_Italic[TItemStyle::String];
1033 CbItalic6->Checked = style->f_Italic[TItemStyle::Number];
1034 CbItalic7->Checked = style->f_Italic[TItemStyle::Character];
1035 CbItalic8->Checked = style->f_Italic[TItemStyle::Preproc];
1036 CbItalic9->Checked = style->f_Italic[TItemStyle::Custom1];
1037 CbItalicA->Checked = style->f_Italic[TItemStyle::Custom2];
1038 CbItalicB->Checked = style->f_Italic[TItemStyle::Custom3];
1039 CbItalicC->Checked = style->f_Italic[TItemStyle::Custom4];
1040 }
1041
1042
1043 //----------------------------------------------------------------------------------------------------------------------
1044 // Utility function for StyleToPreview(): Sets bold and italic style of a TLabel
1045 void SetStyle(TLabel* label, const bool f_Bold, const bool f_Italic)
1046 {
1047 TFontStyles font = label->Font->Style;
1048
1049 if(f_Bold) font << fsBold;
1050 else font >> fsBold;
1051
1052 if(f_Italic) font << fsItalic;
1053 else font >> fsItalic;
1054
1055 label->Font->Style = font;
1056 }
1057
1058
1059 //----------------------------------------------------------------------------------------------------------------------
1060 // Actualize preview sample text fields according to currently active style
1061 void TFMain::StyleToPreview()
1062 {
1063 // a) set sample text font color
1064 LaSample1->Font->Color = StringToTColor(style->szColor[TItemStyle::Comment]);
1065 LaSample2->Font->Color = StringToTColor(style->szColor[TItemStyle::Keyword]);
1066 LaSample3->Font->Color = StringToTColor(style->szColor[TItemStyle::Identifier]);
1067 LaSample4->Font->Color = StringToTColor(style->szColor[TItemStyle::Symbol]);
1068 LaSample5->Font->Color = StringToTColor(style->szColor[TItemStyle::String]);
1069 LaSample6->Font->Color = StringToTColor(style->szColor[TItemStyle::Number]);
1070 LaSample7->Font->Color = StringToTColor(style->szColor[TItemStyle::Character]);
1071 LaSample8->Font->Color = StringToTColor(style->szColor[TItemStyle::Preproc]);
1072 LaSample9->Font->Color = StringToTColor(style->szColor[TItemStyle::Custom1]);
1073 LaSampleA->Font->Color = StringToTColor(style->szColor[TItemStyle::Custom2]);
1074 LaSampleB->Font->Color = StringToTColor(style->szColor[TItemStyle::Custom3]);
1075 LaSampleC->Font->Color = StringToTColor(style->szColor[TItemStyle::Custom4]);
1076
1077
1078 // b) set sample text (and panel) background color
1079 LaSample1->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1080 LaSample2->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1081 LaSample3->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1082 LaSample4->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1083 LaSample5->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1084 LaSample6->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1085 LaSample7->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1086 LaSample8->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1087 LaSample9->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1088 LaSampleA->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1089 LaSampleB->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1090 LaSampleC->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1091 PaPreview->Color = StringToTColor(style->szColor[TItemStyle::Bkgnd]);
1092
1093 // c) set sample text bold and/or italic styles
1094 SetStyle(LaSample1, style->f_Bold[TItemStyle::Comment], style->f_Italic[TItemStyle::Comment]);
1095 SetStyle(LaSample2, style->f_Bold[TItemStyle::Keyword], style->f_Italic[TItemStyle::Keyword]);
1096 SetStyle(LaSample3, style->f_Bold[TItemStyle::Identifier], style->f_Italic[TItemStyle::Identifier]);
1097 SetStyle(LaSample4, style->f_Bold[TItemStyle::Symbol], style->f_Italic[TItemStyle::Symbol]);
1098 SetStyle(LaSample5, style->f_Bold[TItemStyle::String], style->f_Italic[TItemStyle::String]);
1099 SetStyle(LaSample6, style->f_Bold[TItemStyle::Number], style->f_Italic[TItemStyle::Number]);
1100 SetStyle(LaSample7, style->f_Bold[TItemStyle::Character], style->f_Italic[TItemStyle::Character]);
1101 SetStyle(LaSample8, style->f_Bold[TItemStyle::Preproc], style->f_Italic[TItemStyle::Preproc]);
1102 SetStyle(LaSample9, style->f_Bold[TItemStyle::Custom1], style->f_Italic[TItemStyle::Custom1]);
1103 SetStyle(LaSampleA, style->f_Bold[TItemStyle::Custom2], style->f_Italic[TItemStyle::Custom2]);
1104 SetStyle(LaSampleB, style->f_Bold[TItemStyle::Custom3], style->f_Italic[TItemStyle::Custom3]);
1105 SetStyle(LaSampleC, style->f_Bold[TItemStyle::Custom4], style->f_Italic[TItemStyle::Custom4]);
1106
1107 // d)
1108 BtDeleteStyle->Hint = "Delete current style '" + (AnsiString) style->szName +"'";
1109 }
1110
1111
1112 //----------------------------------------------------------------------------------------------------------------------
1113 // Respond to clicks of the "Choose Color" buttons
1114 void __fastcall TFMain::BtColor0Click(TObject*) { SetColor(style->szColor[TItemStyle::Bkgnd]); }
1115 void __fastcall TFMain::BtColor1Click(TObject*) { SetColor(style->szColor[TItemStyle::Comment]); }
1116 void __fastcall TFMain::BtColor2Click(TObject*) { SetColor(style->szColor[TItemStyle::Keyword]); }
1117 void __fastcall TFMain::BtColor3Click(TObject*) { SetColor(style->szColor[TItemStyle::Identifier]); }
1118 void __fastcall TFMain::BtColor4Click(TObject*) { SetColor(style->szColor[TItemStyle::Symbol]); }
1119 void __fastcall TFMain::BtColor5Click(TObject*) { SetColor(style->szColor[TItemStyle::String]); }
1120 void __fastcall TFMain::BtColor6Click(TObject*) { SetColor(style->szColor[TItemStyle::Number]); }
1121 void __fastcall TFMain::BtColor7Click(TObject*) { SetColor(style->szColor[TItemStyle::Character]); }
1122 void __fastcall TFMain::BtColor8Click(TObject*) { SetColor(style->szColor[TItemStyle::Preproc]); }
1123 void __fastcall TFMain::BtColor9Click(TObject*) { SetColor(style->szColor[TItemStyle::Custom1]); }
1124 void __fastcall TFMain::BtColorAClick(TObject*) { SetColor(style->szColor[TItemStyle::Custom2]); }
1125 void __fastcall TFMain::BtColorBClick(TObject*) { SetColor(style->szColor[TItemStyle::Custom3]); }
1126 void __fastcall TFMain::BtColorCClick(TObject*) { SetColor(style->szColor[TItemStyle::Custom4]); }
1127
1128
1129 //----------------------------------------------------------------------------------------------------------------------
1130 // Respond to clicks of the "Bold" check boxes
1131 void __fastcall TFMain::CbBold1Click(TObject*) { style->f_Bold[TItemStyle::Comment] = (CbBold1->Checked); StyleToPreview(); }
1132 void __fastcall TFMain::CbBold2Click(TObject*) { style->f_Bold[TItemStyle::Keyword] = (CbBold2->Checked); StyleToPreview(); }
1133 void __fastcall TFMain::CbBold4Click(TObject*) { style->f_Bold[TItemStyle::Symbol] = (CbBold4->Checked); StyleToPreview(); }
1134 void __fastcall TFMain::CbBold5Click(TObject*) { style->f_Bold[TItemStyle::String] = (CbBold5->Checked); StyleToPreview(); }
1135 void __fastcall TFMain::CbBold6Click(TObject*) { style->f_Bold[TItemStyle::Number] = (CbBold6->Checked); StyleToPreview(); }
1136 void __fastcall TFMain::CbBold7Click(TObject*) { style->f_Bold[TItemStyle::Character] = (CbBold7->Checked); StyleToPreview(); }
1137 void __fastcall TFMain::CbBold8Click(TObject*) { style->f_Bold[TItemStyle::Preproc] = (CbBold8->Checked); StyleToPreview(); }
1138 void __fastcall TFMain::CbBold9Click(TObject*) { style->f_Bold[TItemStyle::Custom1] = (CbBold9->Checked); StyleToPreview(); }
1139 void __fastcall TFMain::CbBoldAClick(TObject*) { style->f_Bold[TItemStyle::Custom2] = (CbBoldA->Checked); StyleToPreview(); }
1140 void __fastcall TFMain::CbBoldBClick(TObject*) { style->f_Bold[TItemStyle::Custom3] = (CbBoldB->Checked); StyleToPreview(); }
1141 void __fastcall TFMain::CbBoldCClick(TObject*) { style->f_Bold[TItemStyle::Custom4] = (CbBoldC->Checked); StyleToPreview(); }
1142
1143
1144 //----------------------------------------------------------------------------------------------------------------------
1145 // Respond to clicks of the "Italic" check boxes
1146 void __fastcall TFMain::CbItalic1Click(TObject*) { style->f_Italic[TItemStyle::Comment] = (CbItalic1->Checked); StyleToPreview(); }
1147 void __fastcall TFMain::CbItalic2Click(TObject*) { style->f_Italic[TItemStyle::Keyword] = (CbItalic2->Checked); StyleToPreview(); }
1148 void __fastcall TFMain::CbItalic4Click(TObject*) { style->f_Italic[TItemStyle::Symbol] = (CbItalic4->Checked); StyleToPreview(); }
1149 void __fastcall TFMain::CbItalic5Click(TObject*) { style->f_Italic[TItemStyle::String] = (CbItalic5->Checked); StyleToPreview(); }
1150 void __fastcall TFMain::CbItalic6Click(TObject*) { style->f_Italic[TItemStyle::Number] = (CbItalic6->Checked); StyleToPreview(); }
1151 void __fastcall TFMain::CbItalic7Click(TObject*) { style->f_Italic[TItemStyle::Character] = (CbItalic7->Checked); StyleToPreview(); }
1152 void __fastcall TFMain::CbItalic8Click(TObject*) { style->f_Italic[TItemStyle::Preproc] = (CbItalic8->Checked); StyleToPreview(); }
1153 void __fastcall TFMain::CbItalic9Click(TObject*) { style->f_Italic[TItemStyle::Custom1] = (CbItalic9->Checked); StyleToPreview(); }
1154 void __fastcall TFMain::CbItalicAClick(TObject*) { style->f_Italic[TItemStyle::Custom2] = (CbItalicA->Checked); StyleToPreview(); }
1155 void __fastcall TFMain::CbItalicBClick(TObject*) { style->f_Italic[TItemStyle::Custom3] = (CbItalicB->Checked); StyleToPreview(); }
1156 void __fastcall TFMain::CbItalicCClick(TObject*) { style->f_Italic[TItemStyle::Custom4] = (CbItalicC->Checked); StyleToPreview(); }
1157
1158
1159
1160 //-------------------------------------------------------------------------------------------------------------------
1161 // Functions for style management like load, save, delete, insert ...
1162 //
1163
1164 //----------------------------------------------------------------------------------------------------------------------
1165 // Insert new style in style list, ask user for its name and select it as active style
1166 // Note: Style file is saved on exit, not here
1167 void __fastcall TFMain::CmSaveStyle(TObject*)
1168 {
1169 //-------------------------------------------------------------------------------------------------------------------
1170 // 1. ask the user for the style's name
1171 AnsiString szTmpName = SZ_DEF_STYLE_NAME;
1172 if(!InputQuery("Insert Style", "Enter a name for the new style:", szTmpName)) // ask and return if user cancels
1173 return;
1174
1175 // return with warning message if entered string is empty
1176 if(szTmpName.IsEmpty())
1177 {
1178 Application->MessageBox("The style name must not be empty!", "Style saving aborted !!", MB_OK | MB_ICONWARNING);
1179 return;
1180 }
1181
1182
1183 //-------------------------------------------------------------------------------------------------------------------
1184 // 2. insert new style in style list
1185 style = &styles.InsertStyle(style); // insert new style (copied from actual one) and set it as active one
1186
1187
1188
1189 //-------------------------------------------------------------------------------------------------------------------
1190 // 3. exchange '=', ':', '\n', '\t' and '_' from the style's name. All except the last are regarded to be
1191 // delimiters in the style file and thus they're exchanged. the '_' is exchanged cause a space is encoded
1192 // with it when the file is written to disk.
1193 strcpy(style->szName, szTmpName.c_str()); // copy name
1194 int i=0;
1195 bool f_Modified = false;
1196 while(style->szName[i]!='\0')
1197 {
1198 if(style->szName[i]==':' || style->szName[i]=='=' || style->szName[i]=='_'
1199 || style->szName[i]=='\n' || style->szName[i]=='\t' ) // exchange with space
1200 {
1201 style->szName[i]=' ';
1202 f_Modified=true; // set flag: name was modified
1203 }
1204
1205 i++;
1206 }
1207
1208 // make a message if name was modified
1209 if(f_Modified)
1210 Application->MessageBox("The whitespaces and the characters '=', '_' and ':' were mapped to space!"
1211 , "Style name was modified !!", MB_OK | MB_ICONINFORMATION);
1212
1213 strcpy(project.szStyle, style->szName); // set style name in project
1214 ProjectSaved(false); // enable save buttons
1215
1216
1217
1218
1219 //-------------------------------------------------------------------------------------------------------------------
1220 // 4. insert style name in list box, select it and actualize preview
1221 LbStyles->Items->Insert(0, style->szName);
1222 LbStyles->ItemIndex=0;
1223
1224 StyleToPreview();
1225 }
1226
1227
1228 //----------------------------------------------------------------------------------------------------------------------
1229 // User has selected a style from the list box. Set it as active style.
1230 void __fastcall TFMain::CmStyleChange(TObject*)
1231 {
1232 // set the selected style as current one and actualize sample texts and controls
1233 style = styles.GetStyle(LbStyles->ItemIndex);
1234
1235 StyleToPreview(); // update preview sample text fields
1236 StyleToCheckboxes(); // set checkboxes according to current style
1237
1238 strcpy(project.szStyle, style->szName); // set style name in project
1239 ProjectSaved(false); // enable save buttons
1240 }
1241
1242
1243 //----------------------------------------------------------------------------------------------------------------------
1244 // Set active style. Take first style, if there are style objects in the style list. Otherwise create new tmporary
1245 // style object.
1246 void TFMain::InitializeStyle()
1247 {
1248 // a) style list is empty: insert new style in style list
1249 if(styles.nStyles()==0)
1250 {
1251 style = &styles.InsertStyle();
1252 strcpy(style->szName, SZ_DEF_STYLE_NAME); // set its name (remove?)
1253 project.szStyle[0]='\0'; // set empty style name in project
1254 LbStyles->Items->Insert(0, SZ_DEF_STYLE_NAME); // insert item in list box
1255 }
1256
1257 // b) there are style objects in the style list: select the first one
1258 else
1259 style = styles.GetStyle(0); // get the first style from the list
1260
1261
1262 strcpy(project.szStyle, style->szName); // set style name in project
1263
1264 LbStyles->ItemIndex = 0;
1265 StyleToCheckboxes(); // set checkboxes according to current style
1266 StyleToPreview(); // update preview sample text fields
1267 }
1268
1269
1270 //----------------------------------------------------------------------------------------------------------------------
1271 // Button 'Delete Style' pressed: Delete current style
1272 void __fastcall TFMain::CmDeleteStyle(TObject*)
1273 {
1274 // ask user, if he really wants to delete the currently selected style
1275 char szText[256];
1276 sprintf(szText, "Delete style '%s'??", styles.GetStyle(LbStyles->ItemIndex)->szName);
1277 if(Application->MessageBox(szText, "Style Editing", MB_YESNO | MB_ICONQUESTION) == IDNO)
1278 return;
1279
1280
1281 styles.DeleteStyle(LbStyles->ItemIndex); // delete from style list
1282 LbStyles->Items->Delete(LbStyles->ItemIndex); // delete from list box
1283 InitializeStyle(); // get another style
1284 SaveStyles(); // save using the wrapper
1285
1286 strcpy(project.szStyle, style->szName); // set new style name in project
1287 ProjectSaved(false); // enable save buttons
1288
1289 }
1290
1291
1292 //----------------------------------------------------------------------------------------------------------------------
1293 // Utility: Save styles to file. Display error message if saving fails.
1294 void TFMain::SaveStyles()
1295 {
1296 try
1297 {
1298 // if flag is set: ask if style list shall be saved or not
1299 if(f_StyleLoadError)
1300 if(Application->MessageBox(SZ_SAVE_WARNING, "Warning !!", MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2)==IDNO)
1301 return;
1302
1303 // save style list moving active style to first
1304 styles.Save((szDir + STYLE_FILENAME).c_str(), LbStyles->ItemIndex);
1305 }
1306 catch(TErrText err)
1307 {
1308 MessageBox(Handle, err.szErrText, "Error saving style file !!", MB_OK | MB_ICONWARNING);
1309 }
1310 }
1311
1312
1313
1314 //-------------------------------------------------------------------------------------------------------------------
1315 // Functions to manage overview file generation and to open it in browser
1316 //
1317
1318
1319 //----------------------------------------------------------------------------------------------------------------------
1320 // generate overview filename and store it in wrapper.szFileName
1321 void TFMain::IniOverviewFileName()
1322 {
1323 // generate filename using directory of first file in file list as base directory
1324 AnsiString szBaseFile = project.GetDestinationFileName(0);
1325 AnsiString szBaseDir = IncludeTrailingBackslash(ExtractFileDir(szBaseFile));
1326
1327 // store filename of overview file
1328 strcpy(wrapper.szFileName, (szBaseDir + project.szOverviewFileName).c_str());
1329 }
1330
1331
1332 //----------------------------------------------------------------------------------------------------------------------
1333 // return relative filename
1334 const char* TFMain::MakeRelativeLink(const char*const& szBaseFile, const char*const& szFileName)
1335 {
1336 // a) write link considering relative paths
1337 char szTmpPath[STS];
1338 strcpy(szTmpPath, Sysutils::ExtractRelativePath(szBaseFile, szFileName).c_str());
1339
1340 // b) exchange backslash by '/'
1341 int i = 0;
1342 while(szTmpPath[i]!='\0')
1343 {
1344 if(szTmpPath[i]=='\\')
1345 szTmpPath[i]='/';
1346 i++;
1347 }
1348
1349
1350 // c) prepend protocol 'file://' if link contains drive
1351 static char szRelPath[STS];
1352 if(!ExtractFileDir(szTmpPath).IsEmpty())
1353 sprintf(szRelPath, "file://%s", szTmpPath);
1354 else
1355 strcpy(szRelPath, szTmpPath);
1356
1357
1358 // c) return
1359 return szRelPath;
1360 }
1361
1362
1363 //----------------------------------------------------------------------------------------------------------------------
1364 // Generate overview file
1365 void TFMain::GenerateOverviewFile()
1366 {
1367 //-------------------------------------------------------------------------------------------------------------------
1368 // 1. pre-play
1369
1370
1371
1372 // if not disabled: check if overview file alread exists
1373 if(!project.f_OverwriteExistingFiles)
1374 {
1375 ifstream file(wrapper.szFileName, ios::in); // try to open for reading(!)
1376 if(file)
1377 if(Application->MessageBox(wrapper.szFileName, // ask user if file already exists
1378 "File already exists! Overwrite it ??", MB_YESNO | MB_ICONWARNING)==IDNO)
1379 return;
1380 }
1381
1382 // GUI update
1383 AddMessage("Generated overview file " + (AnsiString) wrapper.szFileName);
1384 BtViewInBrowser->Enabled = true; // enable button
1385
1386
1387 // open file
1388 ofstream file(wrapper.szFileName, ios::out);
1389
1390
1391 //-------------------------------------------------------------------------------------------------------------------
1392 // 2. write header
1393 file << "<html>" << endl << "<head>" << endl;
1394 file << " <title>Overview: Files</title>" << endl;
1395 file << " <meta name=\"generator\" content=\"" << SZ_HTML_PRGNAME << " - http://" << SZ_HTML_PRGLINK << "\">" << endl;
1396 file << "</head>" << endl << endl;
1397 file << "<body text=\"#000000\" bgcolor=\"#ffffff\" vlink=\"#660066\" alink=\"#3300cc\" link=\"#3300cc\">";
1398 file << endl << endl << "<basefont face=\"Arial\">" << endl << endl;
1399 file << "<h1>Overview</h1>" << endl << endl;
1400 if(project.f_UserDefinedBackLink)
1401 file << "<p><font color=\"#FF0000\">User defined back link text. Back link may be broken.</font></p>" << endl << endl;
1402 file << "<table cellpadding=\"3\">" << endl;
1403
1404
1405 //-------------------------------------------------------------------------------------------------------------------
1406 // 3. write table with names/links for each file in filelist
1407 for(int i=0;i<project.nFiles();i++)
1408 {
1409 // a) write link considering relative paths - Note: backslash is exchanged by '/'
1410 file << "<tr><td><a href=\"" << MakeRelativeLink(wrapper.szFileName, project.GetDestinationFileName(i)) << "\">";
1411
1412
1413 // b) write filename
1414 file << "<font size=\"+1\" face=\"arial\"> " << (Sysutils::ExtractFileName(project.GetSourceFileName(i))).c_str();
1415 file << " </font></a>" << "</td></tr>" << endl;
1416 }
1417 file << "</table>" << endl << endl;
1418
1419
1420 //-------------------------------------------------------------------------------------------------------------------
1421 // 4. write statistics and link to program's homepage
1422 file << "<p>Converted by <a href=\"http://www.newty.de/lsc/index.html\" target=_parent>";
1423 file << "<i>" << SZ_HTML_PRGNAME << "</i></a>";
1424
1425
1426 file << "<br>Converted a total of " << (toDo/1024) << "kb in ";
1427 file << (endTime-startTime)/CLK_TCK << " seconds</p>" << endl << endl;
1428
1429
1430 file << "</body></html>";
1431 }
1432
1433
1434 //----------------------------------------------------------------------------------------------------------------------
1435 // Function executes the shell command in an additional thread - see below
1436 void ViewHtmlFile(void* _tmp)
1437 {
1438 TFMain::THandleWrap* tmp = (TFMain::THandleWrap*) _tmp;
1439 ShellExecute(tmp->hwnd, "open", tmp->szFileName, 0, 0, SW_NORMAL);
1440 }
1441
1442
1443 //----------------------------------------------------------------------------------------------------------------------
1444 // Function to open the last converted file in the browser. Called via a thread function which executes
1445 // the necessary shell command. Done this way cause some browsers need a long time to open ... ;-)
1446 void __fastcall TFMain::CmViewInBrowser(TObject*)
1447 {
1448 // check if the file still exists and if not ...
1449 ifstream test(wrapper.szFileName);
1450 if(!test)
1451 {
1452 // ... disable button
1453 BtViewInBrowser->Enabled = false;
1454
1455 // inform user
1456 MessageBox(Handle, wrapper.szFileName, "Ups, the file seems to be history ...", MB_OK | MB_ICONWARNING);
1457 }
1458 else
1459 _beginthread(ViewHtmlFile, 4096, (void*) &wrapper); // else: everythings ok -> start browser
1460 }
1461
1462
1463
1464
1465 //-------------------------------------------------------------------------------------------------------
1466 // Functions for management of the source and target filename lists/list view
1467 //
1468
1469 //----------------------------------------------------------------------------------------------------------------------
1470 // Respond to drag&drop message. Query dropped files and add them to the lists/list view.
1471 void __fastcall TFMain::EvDragDrop(TMessage& msg)
1472 {
1473 // get number of dropped files
1474 int n = DragQueryFile((HANDLE) msg.WParam, 0xFFFFFFFF, NULL, 0);
1475 if(n==0)
1476 return;
1477
1478
1479 // succesively query filenames and add them to project file lists using AddName2Lists()
1480 for(int i=0;i<n;i++)
1481 {
1482 char szFileName[MAXPATH];
1483 DragQueryFile((HANDLE) msg.WParam, i, szFileName, sizeof(szFileName)); // query filename
1484
1485 // if extension of first filename matches project file extension
1486 if(i==0)
1487 {
1488 if(ExtractFileExt(szFileName) == AnsiString(".") + PROJECT_EXTENSION)
1489 {
1490 MnNewProjectClick(this); // clear project
1491 OpenProject(szFileName); // ... open project
1492 return; // ... and return
1493 }
1494 }
1495 // else ...
1496 AddName2Lists(szFileName); // add filename to file lists and list view
1497 }
1498
1499 RefreshFileSelectionListView(); // refresh list view
1500 PageControl->ActivePage = TsConvert; // change tab to 'Convert'
1501 ProjectSaved(false); // enable save buttons
1502 }
1503
1504
1505 //----------------------------------------------------------------------------------------------------------------------
1506 // Open dialog and let the user add a file to the file list
1507 void __fastcall TFMain::CmAddFile(TObject*)
1508 {
1509 // a) select language specific file filter
1510 OpenDialog->Filter = AnsiString(lang->Name()) + " (" + lang->Extensions() + ")|" + lang->Extensions() +
1511 "|Any file (*.*)|*.*";
1512
1513
1514 // b) set dialog captions and options
1515 OpenDialog->Title = "Choose Source File(s) ...";
1516 OpenDialog->Options << ofFileMustExist << ofPathMustExist << ofAllowMultiSelect;
1517 OpenDialog->FileName = ""; // clear as ini
1518 if(!szSourceDir.IsEmpty()) // if not empty ...
1519 OpenDialog->InitialDir = szSourceDir; // ... set directory last time used with 'AddFile' dialog
1520
1521
1522 // c) execute open dialog and return if dialog closed with cancel
1523 if(!OpenDialog->Execute()) return;
1524
1525
1526 // d) add name(s) to file lists and list view
1527 for(int i=0;i<OpenDialog->Files->Count;i++)
1528 AddName2Lists(OpenDialog->Files->Strings[i]);
1529
1530 // e) refresh list view and save buttons
1531 RefreshFileSelectionListView();
1532 ProjectSaved(false);
1533 szSourceDir = ExtractFileDir(OpenDialog->Files->Strings[0]); // save source directory
1534 }
1535
1536
1537 //----------------------------------------------------------------------------------------------------------------------
1538 // Utility function: Adds message to the list box and ensures visibility
1539 void TFMain::AddMessage(const AnsiString& szMessage)
1540 {
1541 if(LbMessages->Items->Count > MAX_MESSAGES_IN_LISTVIEW) // eventually delete oldest message
1542 LbMessages->Items->Delete(0);
1543
1544 LbMessages->Items->Add(szMessage);
1545 LbMessages->TopIndex = LbMessages->Items->Count-1; // ensure visibility of the new message
1546 }
1547
1548
1549 //----------------------------------------------------------------------------------------------------------------------
1550 // refresh file selection list view
1551 void TFMain::RefreshFileSelectionListView()
1552 {
1553 // for all items
1554 for(int i=0;i<LvFiles->Items->Count;i++) // note: check box states are queried in ModifyFileName()
1555 {
1556 LvFiles->Items->Item[i]->Caption = ModifyFileName(project.GetSourceFileName(i)); // source
1557 LvFiles->Items->Item[i]->SubItems->Strings[0] = ModifyFileName(project.GetDestinationFileName(i), true); // target
1558 }
1559 }
1560
1561
1562 //----------------------------------------------------------------------------------------------------------------------
1563 // If it's not already in the lists: Add filename to project filelist
1564 void TFMain::AddName2Lists(const AnsiString& szName)
1565 {
1566 // a) check for dupes
1567 for(int i=0;i<project.nFiles();i++)
1568 if(strcmp(project.GetSourceFileName(i), szName.c_str())==0)
1569 {
1570 AddMessage("File already in list! Refused to add: " + szName);
1571 return;
1572 }
1573
1574
1575 // b) add source and destination filename to project
1576 project.AddFileNames(szName.c_str(), (szName + ".html").c_str());
1577
1578
1579 // c) add item and subitem to list view
1580 (LvFiles->Items->Add())->SubItems->Add("");
1581
1582
1583 // d) enable buttons
1584 EnableConvertCtrls();
1585 }
1586
1587
1588 //----------------------------------------------------------------------------------------------------------------------
1589 // Utility function: Return filename with or without path
1590 // Note: filename is already with exchanged path (f_EnforceOutputDir==true)
1591 AnsiString TFMain::ModifyFileName(AnsiString szFileName, const bool& f_Destination/*=false*/)
1592 {
1593 if(CbShowPath->Checked)
1594 return MinimizeName(szFileName, LvFiles->Canvas, LvFiles->Columns->Items[0]->Width*0.9);
1595 else
1596 {
1597 int endPath = szFileName.LastDelimiter("\\");
1598 return szFileName.SubString(endPath+1, szFileName.Length()-endPath);
1599 }
1600 }
1601
1602
1603 //----------------------------------------------------------------------------------------------------------------------
1604 void __fastcall TFMain::LvFilesResize(TObject*)
1605 {
1606 LvFiles->Columns->Items[0]->Width = LvFiles->ClientWidth/2;
1607 LvFiles->Columns->Items[1]->Width = LvFiles->ClientWidth/2;
1608 }
1609
1610
1611 //----------------------------------------------------------------------------------------------------------------------
1612 // Redirect insert and delete keys
1613 void __fastcall TFMain::LvOnKeyDown(TObject*, WORD &Key, TShiftState Shift)
1614 {
1615 if(Key==VK_DELETE) CmDelete(this);
1616 if(Key==VK_INSERT) CmAddFile(this);
1617 }
1618
1619
1620 //----------------------------------------------------------------------------------------------------------------------
1621 // User clicked check box "Show Path". Update list view
1622 void __fastcall TFMain::CmPath(TObject*)
1623 {
1624 if(f_ManipCtrls) // return if executed due to state change by program
1625 return;
1626
1627 project.f_ShowPath = CbShowPath->Checked; // set new state in project
1628 RefreshFileSelectionListView(); // refresh list view
1629 ProjectSaved(false); // enable save buttons
1630 }
1631
1632
1633 //----------------------------------------------------------------------------------------------------------------------
1634 //
1635 void __fastcall TFMain::CbEnforceOutputDirClick(TObject*)
1636 {
1637 if(f_ManipCtrls) // return if executed due to state change by program
1638 return;
1639
1640 project.f_EnforceOutputDir = CbEnforceOutputDir->Checked; // set in project
1641 EnableConvertCtrls(); // enable/disable controls
1642 RefreshFileSelectionListView(); // refresh list view
1643 ProjectSaved(false); // enable save buttons
1644 }
1645
1646
1647 //----------------------------------------------------------------------------------------------------------------------
1648 // open directory selection dialog
1649 void __fastcall TFMain::BtSetOutputDirClick(TObject*)
1650 {
1651 // a) initialize default directory where dialog starts
1652 AnsiString szDir; // directory
1653 if(project.szOutputDir[0]!='\0') // if not empty ...
1654 szDir = project.szOutputDir; // ... initialize directory from project
1655 else
1656 if(!szOutputDir.IsEmpty()) // else, again if not empty, ...
1657 szDir = szOutputDir; // ... set directory last time used with select directory dialog
1658
1659 // b) set dialog's options
1660 TSelectDirOpts opt;
1661 opt << sdAllowCreate << sdPerformCreate << sdPrompt;
1662
1663
1664 // c) execute select directory dialog
1665 if(SelectDirectory(szDir, opt, 0))
1666 {
1667 // if closed with OK button
1668
1669 // display chosen directory an set it in project
1670 LaOutputDir->Caption = MinimizeName(IncludeTrailingBackslash(szDir), LaOutputDir->Canvas, LaOutputDir->Width);
1671 strcpy(project.szOutputDir, IncludeTrailingBackslash(szDir).c_str());
1672
1673 // refresh list view and enable save buttons
1674 RefreshFileSelectionListView();
1675 ProjectSaved(false);
1676 szOutputDir = szDir;
1677 }
1678 }
1679
1680
1681 //----------------------------------------------------------------------------------------------------------------------
1682 // User clicked check box "Overwrite existing files"
1683 void __fastcall TFMain::CbOverwriteExistingFilesClick(TObject*)
1684 {
1685 if(f_ManipCtrls) // return if executed due to state change by program
1686 return;
1687
1688 project.f_OverwriteExistingFiles = CbOverwriteExistingFiles->Checked; // set new state in project
1689 ProjectSaved(false); // enable save buttons
1690 }
1691
1692
1693 //----------------------------------------------------------------------------------------------------------------------
1694 // User clicked in list view: enable/disable "Delete"/"Rename" buttons
1695 void __fastcall TFMain::CmListView(TObject*)
1696 {
1697 EnableConvertCtrls();
1698 }
1699
1700
1701 //----------------------------------------------------------------------------------------------------------------------
1702 // Remove selected file from lists/list view
1703 void __fastcall TFMain::CmDelete(TObject*)
1704 {
1705 // a) get selected file and it's index, return if none is selected
1706 TListItem* item = LvFiles->Selected;
1707
1708 if(!item)
1709 return;
1710
1711 const int index = LvFiles->Items->IndexOf(item);
1712
1713
1714 // b) delete from filelists/list view
1715 project.DeleteFileName(index);
1716 LvFiles->Items->Delete(index);
1717
1718
1719 // if there are still list elements
1720 LvFiles->Selected = LvFiles->Items->Item[min(index, LvFiles->Items->Count-1)];
1721 ActiveControl = LvFiles; // set focus back
1722
1723
1724 // c) enable/disable controls and enable save buttons
1725 EnableConvertCtrls();
1726 ProjectSaved(false);
1727 }
1728
1729
1730 //----------------------------------------------------------------------------------------------------------------------
1731 // Rename selected (target-)filename
1732 void __fastcall TFMain::CmRename(TObject*)
1733 {
1734 // a) disable buttons
1735 EnableConvertCtrls();
1736
1737
1738 // b) get selected file and it's index, return if none is selected
1739 TListItem* item = LvFiles->Selected;
1740
1741 if(!item)
1742 return;
1743
1744 const int index = LvFiles->Items->IndexOf(item);
1745
1746
1747 // c) set dialogs captions and options
1748 SaveDialog->Title = "Enter Target Filename ...";
1749 SaveDialog->Filter = "HTML files (*.html;*.htm)|*.html;*.htm|Any file (*.*)|*.*";
1750 SaveDialog->DefaultExt = "html"; // default extension - added if none specified
1751
1752 SaveDialog->Options << ofNoReadOnlyReturn;
1753 SaveDialog->FileName = project.GetDestinationFileName(index);
1754
1755
1756 // d) execute dialog and return if dialog closed with cancel
1757 if(!SaveDialog->Execute())
1758 return;
1759
1760
1761 // e) check for dupes
1762 for(int i=0;i<project.nFiles();i++)
1763 if(strcmp(project.GetDestinationFileName(i), SaveDialog->FileName.c_str())==0)
1764 {
1765 MessageBox(Handle, SaveDialog->FileName.c_str(), "Target filename already in list! Refused to rename!"
1766 , MB_ICONWARNING | MB_OK);
1767 return;
1768 }
1769
1770
1771 // f) write back modified target filename and enable save buttons
1772 project.SetDestinationFileName(SaveDialog->FileName.c_str(), index); // file list
1773 item->SubItems->Strings[0] = ModifyFileName(SaveDialog->FileName, true); // list view
1774 ProjectSaved(false);
1775 }
1776
1777
1778 //----------------------------------------------------------------------------------------------------------------------
1779 void __fastcall TFMain::DisableDeleteAndRename(TObject*)
1780 {
1781 // disable buttons
1782 BtDelete->Enabled = false;
1783 BtRename->Enabled = false;
1784 }
1785
1786
1787 //----------------------------------------------------------------------------------------------------------------------
1788 // Clear file lists/list view
1789 void __fastcall TFMain::CmClearList(TObject*)
1790 {
1791 project.ClearFileNames(); // clear file lists
1792 LvFiles->Items->Clear(); // clear list view
1793
1794 EnableConvertCtrls(); // enable/disable controls
1795 ProjectSaved(false); // enable save buttons
1796 }
1797
1798
1799 //----------------------------------------------------------------------------------------------------------------------
1800 // enable/disable controls on tab sheet convert
1801 void TFMain::EnableConvertCtrls()
1802 {
1803 // buttons
1804 BtDelete->Enabled = (LvFiles->Selected) && (ActiveControl==LvFiles);
1805 BtRename->Enabled = (LvFiles->Selected) && (ActiveControl==LvFiles);
1806 BtClear->Enabled = (project.nFiles()!=0);
1807 BtStart->Enabled = (project.nFiles()!=0);
1808
1809 // output directory controls
1810 BtSetOutputDir->Enabled = CbEnforceOutputDir->Checked;
1811 LaOutputDir->Enabled = CbEnforceOutputDir->Checked;
1812 }
1813
1814
1815
1816 //-------------------------------------------------------------------------------------------------------
1817 // Functions to start/do the converting process
1818 //
1819
1820 //----------------------------------------------------------------------------------------------------------------------
1821 // Start converting using additional thread
1822 void __fastcall TFMain::CmStart(TObject*)
1823 {
1824 // a) disable buttons and drag&drop
1825 GbFileSelection->Enabled = false;
1826 CbLanguage->Enabled = false;
1827 BtClear ->Enabled = false;
1828 BtDelete ->Enabled = false;
1829 BtRename ->Enabled = false;
1830 BtAddFile ->Enabled = false;
1831 CbShowPath->Enabled = false;
1832 DragAcceptFiles(Handle, false); // disable drag&drop
1833
1834
1835 // b) if not disabled: check if target files already exist
1836 if(!project.f_OverwriteExistingFiles)
1837 {
1838 char* szText = new char[STS+MAXPATH*project.nFiles()]; // this should be enough :-)
1839 szText[0] = '\0'; // terminate
1840
1841 // check each file
1842 for(int i=0;i<project.nFiles();i++)
1843 {
1844 const char* szName = project.GetDestinationFileName(i);
1845
1846 // try to open for reading(!)
1847 ifstream file(szName, ios::in);
1848
1849 if(file)
1850 {
1851 strcat(szText, szName);
1852 strcat(szText, "\n");
1853 }
1854 }
1855
1856 // ask user if some files already exist
1857 if(szText[0]!='\0')
1858 if(Application->MessageBox(szText, "The following file(s) already exist! Overwrite them?",
1859 MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2)==ID_NO)
1860 {
1861 delete[] szText;
1862 Finish(false); // adjust/reset controls (buttons, timers) again etc.
1863 return;
1864 }
1865
1866 delete[] szText;
1867 }
1868
1869
1870 // c) move message window etc. 80 pixel up to make progress bars visible
1871 BtViewInBrowser->Top -= 80;
1872 BtStart ->Top -= 80;
1873 BtCancel ->Top -= 80;
1874 GbMessages ->Top -= 80;
1875 GbLanguage ->Top -= 80;
1876 GbFileSelection->Height -= 80; // resize file selection group box
1877 LvFiles ->Height += 75; // after group box size change: correct list view
1878
1879
1880
1881 // d) reset gauges and make progress bars and cancel button visible
1882 ProgressBar1->Position = 0;
1883 ProgressBar2->Position = 0;
1884 GbProgress->Visible = true;
1885 BtStart ->Visible = false;
1886 BtCancel ->Visible = true;
1887
1888
1889 // e) set flag, reset progress counter and start timer for display actualization
1890 f_Converting = true;
1891 f_Stop = false;
1892 Timer->Enabled = true;
1893
1894 toDo = 1; // to prevent "divison by zero" errors
1895 done = 0;
1896 startTime = clock(); // get time
1897
1898 IniOverviewFileName(); // initialize filename of overview file
1899
1900
1901 // f) start thread which does all the work in its member-function Execute - note: deletes itself
1902 new ThreadFunc(false, this);
1903 }
1904
1905
1906 //----------------------------------------------------------------------------------------------------------------------
1907 // Actualize progress bars
1908 void __fastcall TFMain::OnTimer(TObject*)
1909 {
1910 // hint: altering screen components is expensive. thus check!
1911 int tmp = progress*inv5Percent;
1912 if(tmp>gaugePos)
1913 {
1914 gaugePos = tmp;
1915 ProgressBar1->Position = tmp * 5;
1916 ProgressBar2->Position = 100 * (progress+done) / toDo;
1917 }
1918 }
1919
1920
1921 //----------------------------------------------------------------------------------------------------------------------
1922 // Function is called when the conversion thread finishes
1923 void TFMain::Finish(const bool& f_AllOk/*=true*/)
1924 {
1925 // conversion progress was not aborted before(!) conversion thread was started
1926 if(f_AllOk)
1927 {
1928 // stop timer
1929 endTime = clock(); // get time
1930 Timer->Enabled = false; // stop
1931
1932 // write overview of generated files note: must be executed before CmClearList() and after ini of endTime (?)
1933 GenerateOverviewFile();
1934
1935 // move message window etc. 80 pixel down again
1936 BtViewInBrowser->Top += 80;
1937 BtStart ->Top += 80;
1938 BtCancel ->Top += 80;
1939 GbMessages ->Top += 80;
1940 GbLanguage ->Top += 80;
1941 GbFileSelection->Height += 80; // resize file selection group box
1942 LvFiles ->Height -= 75; // after group box size change: move list view
1943
1944
1945 // exchange 'Cancel' and 'Start' button again
1946 BtStart ->Visible = true;
1947 BtCancel->Visible = false;
1948 f_Converting = false; // reset flag
1949
1950 AddMessage("Finished!"); // add message
1951 }
1952 else
1953 AddMessage("Aborted!");
1954
1955
1956 // enable/disable controls
1957 GbProgress->Visible = false; // hide groupbox with progress bars
1958 GbFileSelection->Enabled = true; // enable file selection group box
1959 BtAddFile ->Enabled = true; // buttons
1960 CbShowPath->Enabled = true; // check boxes
1961 CbLanguage->Enabled = true; // language radio buttons
1962 DragAcceptFiles(Handle, true); // enable drag&drop again
1963
1964 EnableConvertCtrls();
1965
1966 // set focus etc.
1967 BtAddFile->SetFocus();
1968 AddMessage(""); // add empty line
1969 }
1970
1971
1972 //----------------------------------------------------------------------------------------------------------------------
1973 // User clicks "Cancel" button: set stop flag
1974 void __fastcall TFMain::CmCancel(TObject*) { f_Stop = true; }
1975
1976
1977
1978
1979 //----------------------------------------------------------------------------------------------------------------------
1980 // Response to 'Set Name' button in group box 'Overview File'
1981 void __fastcall TFMain::BtSetOverviewFileNameClick(TObject *Sender)
1982 {
1983 // ask the user for the overview file name
1984 AnsiString szFileName = project.szOverviewFileName;
1985 if(!InputQuery("Overview File", "Enter File Name ...", szFileName)) // ask and return if user cancels
1986 return;
1987
1988 // return with warning message if entered string is empty
1989 if(szFileName.IsEmpty())
1990 {
1991 Application->MessageBox("The file name must not be empty!", "Overview file", MB_OK | MB_ICONWARNING);
1992 return;
1993 }
1994
1995
1996 // display file name
1997 szFileName = ChangeFileExt(szFileName, ".html"); // ensure correct extension
1998 strcpy(project.szOverviewFileName, szFileName.c_str()); // set filename in project
1999 LaOverviewFileName->Caption = project.szOverviewFileName;
2000 ProjectSaved(false);
2001 }
2002
2003
2004 //-------------------------------------------------------------------------------------------------------------------
2005 // Response to 'Set Link Text' button in group box 'Back Links'
2006 void __fastcall TFMain::BtBackLinkClick(TObject *Sender)
2007 {
2008 // 1. ask the user for the back link text
2009 AnsiString szText = project.szBackLinkText;
2010 if(!InputQuery("Back Links", "Enter Text ...", szText)) // ask and return if user cancels
2011 return;
2012
2013 // return with warning message if entered string is empty
2014 if(szText.IsEmpty())
2015 {
2016 Application->MessageBox("The text must not be empty!", "Back Links", MB_OK | MB_ICONWARNING);
2017 return;
2018 }
2019
2020 // display file name
2021 strcpy(project.szBackLinkText, szText.c_str()); // set text in project
2022 LaBackLinkText->Caption = project.szBackLinkText;
2023 ProjectSaved(false);
2024 }
Top |