unit Core;

interface

uses
  Classes, SysUtils, FileUtil, Controls, ActnList, Forms, Dialogs, ExtCtrls,
  LastOpenedList, ApplicationInfo, PersistentForm, ScaleDPI, Common,
  Translator, DataFile, VCard, Menus, RegistryEx, Theme, FormMain,
  Registry, VCardFile, FormKeyShortcuts, LazFileUtils;

type

  { TCore }

  TCore = class(TDataModule)
    AAbout: TAction;
    AKeyShortcuts: TAction;
    AFullScreen: TAction;
    AFileImport: TAction;
    AFileExport: TAction;
    ANormalize: TAction;
    ARemoveExactDuplicates: TAction;
    AFileCompare: TAction;
    AViewSource: TAction;
    ATest: TAction;
    AFind: TAction;
    AFileSplit: TAction;
    AGenerate: TAction;
    AFindDuplicate: TAction;
    AFileCombine: TAction;
    ASettings: TAction;
    AFileOpenRecent: TAction;
    AHomePage: TAction;
    AFileClose: TAction;
    AFileSaveAs: TAction;
    AFileSave: TAction;
    AFileOpen: TAction;
    AFileNew: TAction;
    AExit: TAction;
    ActionList1: TActionList;
    ApplicationInfo1: TApplicationInfo;
    SelectDirectoryDialog1: TSelectDirectoryDialog;
    Translator: TTranslator;
    ImageList1: TImageList;
    LastOpenedList1: TLastOpenedList;
    OpenDialog1: TOpenDialog;
    PersistentForm1: TPersistentForm;
    SaveDialog1: TSaveDialog;
    ScaleDPI1: TScaleDPI;
    ThemeManager1: TThemeManager;
    procedure AAboutExecute(Sender: TObject);
    procedure AExitExecute(Sender: TObject);
    procedure AFileCombineExecute(Sender: TObject);
    procedure AFileCompareExecute(Sender: TObject);
    procedure AFileExportExecute(Sender: TObject);
    procedure AFileImportExecute(Sender: TObject);
    procedure AFileNewExecute(Sender: TObject);
    procedure AFileOpenExecute(Sender: TObject);
    procedure AFileOpenRecentExecute(Sender: TObject);
    procedure AFileSaveExecute(Sender: TObject);
    procedure AFileSaveAsExecute(Sender: TObject);
    procedure AFileCloseExecute(Sender: TObject);
    procedure AFileSplitExecute(Sender: TObject);
    procedure AFindDuplicateExecute(Sender: TObject);
    procedure AFindExecute(Sender: TObject);
    procedure AFullScreenExecute(Sender: TObject);
    procedure AGenerateExecute(Sender: TObject);
    procedure AHomePageExecute(Sender: TObject);
    procedure AKeyShortcutsExecute(Sender: TObject);
    procedure ANormalizeExecute(Sender: TObject);
    procedure ARemoveExactDuplicatesExecute(Sender: TObject);
    procedure ASettingsExecute(Sender: TObject);
    procedure ATestExecute(Sender: TObject);
    procedure AViewSourceExecute(Sender: TObject);
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure LastOpenedList1Change(Sender: TObject);
    procedure TranslatorTranslate(Sender: TObject);
  private
    FOnDataFileChange: TNotifyEvent;
    FOnLastOpenedListChange: TNotifyEvent;
    InitializeStarted: Boolean;
    InitializeFinished: Boolean;
    LoadErrors: string;
    ProfileImage: TImage;
    LastSplitDir: string;
    ProfilePhotoFileName: string;
    RecentFileRegistryContext: TRegistryContext;
    FormMain: TFormMain;
    FormKeyShortcuts: TFormKeyShortcuts;
    procedure FileModified(Sender: TObject);
    function FindFirstNonOption: string;
    function GetAppShareDir(Dir: string): string;
    procedure LoadConfig;
    procedure SaveConfig;
    procedure DoError(Text: string; Line: Integer);
    procedure AddItemToLastOpenedList(FileName: string);
    procedure DoDataFileChange;
    function GetDefaultCompareTool: string;
  public
    DefaultDataFileClass: TDataFileClass;
    DataFile: TDataFile;
    FileClosed: Boolean;
    ReopenLastFileOnStart: Boolean;
    LastContactTabIndex: Integer;
    LastContactFileName: string;
    LastPhotoFileName: string;
    LastQrCodeFileName: string;
    LastPropertyValueFileName: string;
    MapUrl: string;
    GenerateCount: Integer;
    ToolbarVisible: Boolean;
    DefaultVcardVersion: string;
    DefaultPhoneCountryCode: string;
    DefaultInternationalCallPrefix: string;
    CompareTool: string;
    procedure UpdateFile;
    function GetProfileImage: TImage;
    function GetTempDir: string;
    procedure FileNew;
    procedure FileOpen(FileName: string);
    procedure FileClose;
    procedure Initialize;
    procedure UpdateInterface;
    property OnDataFileChange: TNotifyEvent read FOnDataFileChange
      write FOnDataFileChange;
    property OnLastOpenedListChange: TNotifyEvent read FOnLastOpenedListChange
      write FOnLastOpenedListChange;
  end;

var
  Core: TCore;


implementation

{$R *.lfm}

uses
  FormSettings, FormFindDuplicity, FormCompare, TestCase, FormNormalize,
  FormGenerate, FormError, FormFind, FormSource, TestCases, FormExport, FormEx,
  FormAbout, FormTests, FormImport;

resourcestring
  SAppExit = 'Application exit';
  SAppExitQuery = 'File was modified. Do you want to save it before exit?';
  SFileSplit = 'Contacts split';
  SFileSplitFinishedOpenDirectory = 'Total %d contact files saved. Do you want to open the directory %s?';
  SFileNotFound = 'File ''%s'' not found.';
  SCombinedContacts = 'Combined %d contact files.';
  SLine = 'Line %d: %s';
  SRemovedDuplicates = 'Removed %d duplicates.';

{ TCore }

procedure TCore.AExitExecute(Sender: TObject);
begin
  FormMain.Close;
  Application.Terminate;
end;

procedure TCore.AFileCombineExecute(Sender: TObject);
var
  TempFile: TDataFile;
  I: Integer;
  LoadedFiles: Integer;
begin
  TempFile := DefaultDataFileClass.Create(nil);
  try
    OpenDialog1.Filter := TempFile.GetFileFilter;
  finally
    TempFile.Free;
  end;
  OpenDialog1.DefaultExt := '';
  if Assigned(DataFile) then begin
    OpenDialog1.InitialDir := ExtractFileDir(DataFile.FileName);
    OpenDialog1.FileName := ExtractFileName(DataFile.FileName);
  end;
  OpenDialog1.Options := OpenDialog1.Options + [ofAllowMultiSelect];
  if OpenDialog1.Execute then begin
    LoadedFiles := 0;
    for I := 0 to OpenDialog1.Files.Count - 1 do begin
      if FileExists(OpenDialog1.Files[I]) then begin
        TempFile := TVCardFile.Create(nil);
        try
          TempFile.LoadFromFile(OpenDialog1.Files[I]);
          TVCardFile(DataFile).VCard.Contacts.AddContacts(TVCardFile(TempFile).VCard.Contacts);
          Inc(LoadedFiles);
        finally
          TempFile.Free;
        end;
      end;
    end;
    if LoadedFiles > 0 then TVCardFile(DataFile).Modified := True;
    ShowMessage(Format(SCombinedContacts, [LoadedFiles]));
    UpdateFile;
  end;
end;

procedure TCore.AFileCompareExecute(Sender: TObject);
var
  FormCompare: TFormCompare;
begin
  FormCompare := TFormCompare.Create(nil);
  try
    FormCompare.ShowModal;
  finally
    FreeAndNil(FormCompare);
  end;
end;

procedure TCore.AFileExportExecute(Sender: TObject);
var
  FormExport: TFormExport;
begin
  FormExport := TFormExport.Create(nil);
  try
    FormExport.ShowModal;
  finally
    FormExport.Free;
  end;
end;

procedure TCore.AFileImportExecute(Sender: TObject);
var
  FormImport: TFormImport;
begin
  FormImport := TFormImport.Create(nil);
  try
    if FormImport.ShowModal = mrOK then begin
      TVCardFile(DataFile).Modified := True;
      UpdateFile;
    end;
  finally
    FormImport.Free;
  end;
end;

procedure TCore.AAboutExecute(Sender: TObject);
var
  FormAbout: TFormAbout;
begin
  FormAbout := TFormAbout.Create(nil);
  FormAbout.ApplicationInfo := ApplicationInfo1;
  FormAbout.ShowModal;
  FreeAndNil(FormAbout);
end;

procedure TCore.AFileCloseExecute(Sender: TObject);
begin
  FileClose;
  UpdateFile;
end;

procedure TCore.AFileSplitExecute(Sender: TObject);
var
  I: Integer;
  C: Integer;
  FileName: string;
  ModalResult: TModalResult;
begin
  C := 0;
  SelectDirectoryDialog1.FileName := LastSplitDir;
  if SelectDirectoryDialog1.Execute then begin
    LastSplitDir := SelectDirectoryDialog1.FileName;
    with TVCardFile(DataFile).VCard.Contacts do
    for I := 0 to Count - 1 do begin
      if Items[I].Fields[cfFullName] <> '' then begin
        FileName := SelectDirectoryDialog1.FileName + DirectorySeparator +
          Items[I].FullNameToFileName + VCardFileExt;
        Items[I].SaveToFile(FileName);
        Inc(C);
      end;
    end;
    ModalResult := MessageDlg(SFileSplit,
      Format(SFileSplitFinishedOpenDirectory, [C,
      SelectDirectoryDialog1.FileName]), mtConfirmation, [mbYes, mbNo], 0);
    if ModalResult = mrYes then begin
      {$IFDEF WINDOWS}
      ExecuteProgram('explorer.exe', ['"' + SelectDirectoryDialog1.FileName + '"'], []);
      {$ENDIF}
      {$IFDEF UNIX}
      ExecuteProgram('/usr/bin/xdg-open', [SelectDirectoryDialog1.FileName], []);
      {$ENDIF}
    end;
  end;
end;

procedure TCore.AFindDuplicateExecute(Sender: TObject);
begin
  with TFormFindDuplicity.Create(nil) do
  try
    Contacts := TVCardFile(DataFile).VCard.Contacts;
    ShowModal;
    DoDataFileChange;
  finally
    Free;
  end;
end;

procedure TCore.AFindExecute(Sender: TObject);
begin
  with TFormFind.Create(nil) do
  try
    Contacts := TVCardFile(DataFile).VCard.Contacts;
    ShowModal;
    DoDataFileChange;
  finally
    Free;
  end;
end;

procedure TCore.AFullScreenExecute(Sender: TObject);
begin
  FormMain.ToggleFullScreen;
end;

procedure TCore.AGenerateExecute(Sender: TObject);
begin
  with TFormGenerate.Create(nil) do
  try
    Contacts := TVCardFile(DataFile).VCard.Contacts;
    if ShowModal = mrOk then begin
      DataFile.Modified := True;
      DoDataFileChange;
    end;
  finally
    Free;
  end;
end;

procedure TCore.AHomePageExecute(Sender: TObject);
begin
  OpenWebPage(ApplicationInfo1.HomePage);
end;

procedure TCore.AKeyShortcutsExecute(Sender: TObject);
begin
  if not Assigned(FormKeyShortcuts) then
    FormKeyShortcuts := TFormKeyShortcuts.Create(nil);
  FormKeyShortcuts.Images := ImageList1;
  FormKeyShortcuts.MainForm := FormMain;
  FormKeyShortcuts.SourceComponents.Clear;
  FormKeyShortcuts.SourceComponents.Add(Self);
  FormKeyShortcuts.Show;
end;

procedure TCore.ANormalizeExecute(Sender: TObject);
var
  FormNormalize: TFormNormalize;
begin
  FormNormalize := TFormNormalize.Create(nil);
  try
    FormNormalize.ShowModal;
  finally
    FreeAndNil(FormNormalize);
  end;
end;

procedure TCore.ARemoveExactDuplicatesExecute(Sender: TObject);
var
  RemovedCount: Integer;
begin
  RemovedCount := TVCardFile(DataFile).VCard.Contacts.RemoveExactDuplicates;
  ShowMessage(Format(SRemovedDuplicates, [RemovedCount]));
  if RemovedCount > 0 then begin
    DataFile.Modified := True;
    UpdateFile;
  end;
end;

procedure TCore.ASettingsExecute(Sender: TObject);
begin
  with TFormSettings.Create(nil) do
  try
    LoadData;
    if ShowModal = mrOK then begin
      SaveData;
      FormMain.SettingsChanged;
    end;
  finally
    Free;
  end;
end;

procedure TCore.ATestExecute(Sender: TObject);
begin
  with TFormTests.Create(nil) do
  try
    TestCases := InitTestCases;
    try
      ShowModal;
    finally
      TestCases.Free;
    end;
  finally
    Free;
  end;
end;

procedure TCore.AViewSourceExecute(Sender: TObject);
begin
  with TFormSource.Create(nil) do
  try
    Source := TVCardFile(DataFile).VCard.AsString;
    if ShowModal = mrOk then begin
      TVCardFile(DataFile).VCard.AsString := Source;
      UpdateFile;
    end;
  finally
    Free;
  end;
end;

procedure TCore.AFileNewExecute(Sender: TObject);
begin
  FileNew;
  UpdateFile;
end;

procedure TCore.AFileOpenExecute(Sender: TObject);
var
  TempFile: TDataFile;
begin
  TempFile := DefaultDataFileClass.Create(nil);
  try
    OpenDialog1.Filter := TempFile.GetFileFilter;
  finally
    TempFile.Free;
  end;
  OpenDialog1.DefaultExt := '';
  if Assigned(DataFile) then begin
    OpenDialog1.InitialDir := ExtractFileDir(DataFile.FileName);
    OpenDialog1.FileName := ExtractFileName(DataFile.FileName);
  end;
  OpenDialog1.Options := OpenDialog1.Options - [ofAllowMultiSelect];
  if OpenDialog1.Execute then begin
    FileOpen(OpenDialog1.FileName);
    UpdateFile;
  end;
end;

procedure TCore.AFileOpenRecentExecute(Sender: TObject);
begin
  FileOpen(TMenuItem(Sender).Caption);
  UpdateFile;
end;

procedure TCore.AFileSaveAsExecute(Sender: TObject);
begin
  SaveDialog1.DefaultExt := DataFile.GetFileExt;
  SaveDialog1.Filter := DataFile.GetFileFilter;
  SaveDialog1.InitialDir := ExtractFileDir(DataFile.FileName);
  SaveDialog1.FileName := ExtractFileName(DataFile.FileName);
  if SaveDialog1.Execute then begin
    DataFile.SaveToFile(SaveDialog1.FileName);
    AddItemToLastOpenedList(SaveDialog1.FileName);
    UpdateFile;
  end;
end;

procedure TCore.AFileSaveExecute(Sender: TObject);
begin
  if FileExists(DataFile.FileName) then begin
    DataFile.SaveToFile(DataFile.FileName);
    AddItemToLastOpenedList(DataFile.FileName);
    UpdateFile;
  end else AFileSaveAs.Execute;
end;

function TCore.GetAppShareDir(Dir: string): string;
{$IFDEF UNIX}
var
  NewDir: string;
{$ENDIF}
begin
  Result := ExtractFileDir(Application.ExeName) + DirectorySeparator + Dir;
  {$IFDEF UNIX}
  // If installed in Linux system then try to use different installation directory
  if not DirectoryExists(Result) then begin
    NewDir := ExtractFileDir(Application.ExeName) + DirectorySeparator + '..' +
      DirectorySeparator + 'share' + DirectorySeparator +
      ExtractFileNameOnly(Application.ExeName) + DirectorySeparator + Dir;
    if DirectoryExists(NewDir) then Result := NewDir;
  end;
  {$ENDIF}
end;

procedure TCore.DataModuleCreate(Sender: TObject);
begin
  ProfilePhotoFileName := GetAppShareDir('Images') + DirectorySeparator + 'Profile.png';
  Translator.POFilesFolder := GetAppShareDir('Languages');

  DataFile := nil;
  DefaultDataFileClass := TVCardFile;
  FileClosed := True;
  RecentFileRegistryContext := TRegistryContext.Create(ApplicationInfo1.RegistryRoot,
    ApplicationInfo1.RegistryKey + '\RecentFiles');
  LoadConfig;

  TFormEx.ScaleDPI := ScaleDPI1;
  TFormEx.Translator := Translator;
  TFormEx.ThemeManager := ThemeManager1;
  TFormEx.PersistentForm := PersistentForm1;

  Application.CreateForm(TFormMain, FormMain);
  FormMain.Show;
end;

procedure TCore.DataModuleDestroy(Sender: TObject);
begin
  FileClose;
  SaveConfig;
  if Assigned(ProfileImage) then
    FreeAndNil(ProfileImage);
  if Assigned(FormKeyShortcuts) then
    FreeAndNil(FormKeyShortcuts);
end;

procedure TCore.LastOpenedList1Change(Sender: TObject);
begin
  if Assigned(FOnLastOpenedListChange) then
    FOnLastOpenedListChange(Self);
end;

procedure TCore.TranslatorTranslate(Sender: TObject);
begin
  TestCase.Translate;
end;

procedure TCore.FileModified(Sender: TObject);
begin
  UpdateFile;
end;

procedure TCore.FileOpen(FileName: string);
var
  FormError: TFormError;
begin
  if FileExists(FileName) then begin
    FileClose;
    if FileClosed then begin
      FileNew;
      LoadErrors := '';
      DataFile.LoadFromFile(FileName);
      AddItemToLastOpenedList(FileName);
      if LoadErrors <> '' then begin
        FormError := TFormError.Create(nil);
        FormError.MemoErrors.Text := LoadErrors;
        FormError.ShowModal;
        FreeAndNil(FormError);
      end;
    end;
  end else ShowMessage(Format(SFileNotFound, [FileName]));
end;

procedure TCore.FileClose;
var
  ModalResult: TModalResult;
  DoClose: Boolean;
begin
  DoClose := False;
  if Assigned(DataFile) then begin
    if DataFile.Modified then begin
       ModalResult := MessageDlg(SAppExit, SAppExitQuery,
       mtConfirmation, [mbYes, mbNo, mbCancel], 0);
      if ModalResult = mrYes then begin
        AFileSave.Execute;
        DoClose := True;
      end
      else if ModalResult = mrNo then begin
        DoClose := True;
      end else FileClosed := False;
    end else DoClose := True;
  end else DoClose := True;
  if DoClose then begin
    if Assigned(DataFile) then FreeAndNil(DataFile);
    FileClosed := True;
    UpdateFile;
  end;
end;

procedure TCore.FileNew;
begin
  FileClose;
  if FileClosed then begin
    DataFile := DefaultDataFileClass.Create(nil);
    DataFile.OnModify := FileModified;
    TVCardFile(DataFile).VCard.OnError := DoError;
  end;
end;

procedure TCore.UpdateFile;
begin
  UpdateInterface;
  DoDataFileChange;
end;

procedure TCore.LoadConfig;
begin
  PersistentForm1.RegistryContext := ApplicationInfo1.GetRegistryContext;
  LastOpenedList1.LoadFromRegistry(RecentFileRegistryContext);

  with TRegistryEx.Create do
  try
    CurrentContext := ApplicationInfo1.GetRegistryContext;
    if ValueExists('LanguageCode') then
      Translator.Language := Translator.Languages.SearchByCode(ReadStringWithDefault('LanguageCode', ''))
      else Translator.Language := Translator.Languages.SearchByCode('');
    if ValueExists('Theme') then
      ThemeManager1.Theme := ThemeManager1.Themes.FindByName(ReadStringWithDefault('Theme', 'System'))
      else ThemeManager1.Theme := ThemeManager1.Themes.FindByName('System');
    ReopenLastFileOnStart := ReadBoolWithDefault('ReopenLastFileOnStart', True);
    LastContactTabIndex := ReadIntegerWithDefault('LastContactTabIndex', 0);
    LastContactFileName := ReadStringWithDefault('LastContactFileName', '');
    LastSplitDir := ReadStringWithDefault('LastSplitDir', '');
    LastPropertyValueFileName := ReadStringWithDefault('LastPropertyValueFileName', '');
    GenerateCount := ReadIntegerWithDefault('GenerateCount', 1);
    DefaultVcardVersion := ReadStringWithDefault('DefaultVcardVersion', '2.1');
    MapUrl := ReadStringWithDefault('MapUrl', 'https://www.openstreetmap.org/search?query=');
    LastPhotoFileName := ReadStringWithDefault('LastPhotoFileName', '');
    LastQrCodeFileName := ReadStringWithDefault('LastQrCodeFileName', '');
    CompareTool := ReadStringWithDefault('CompareTool', GetDefaultCompareTool);
    DefaultPhoneCountryCode := ReadStringWithDefault('DefaultPhoneCountryPrefix', DefaultPhoneCountryCode);
    DefaultInternationalCallPrefix := ReadStringWithDefault('DefaultInternationalCallPrefix', DefaultInternationalCallPrefix);
  finally
    Free;
  end;
end;

procedure TCore.SaveConfig;
begin
  with TRegistryEx.Create do
  try
    CurrentContext := ApplicationInfo1.GetRegistryContext;
    if Assigned(Translator.Language) and (Translator.Language.Code <> '') then
      WriteString('LanguageCode', Translator.Language.Code)
      else DeleteValue('LanguageCode');
    if Assigned(ThemeManager1.Theme) and (ThemeManager1.Theme.Name <> '') then
      WriteString('Theme', ThemeManager1.Theme.Name)
      else DeleteValue('Theme');
    WriteBool('ReopenLastFileOnStart', ReopenLastFileOnStart);
    WriteInteger('LastContactTabIndex', LastContactTabIndex);
    WriteString('LastContactFileName', LastContactFileName);
    WriteString('LastSplitDir', LastSplitDir);
    WriteString('LastPropertyValueFileName', LastPropertyValueFileName);
    WriteInteger('GenerateCount', GenerateCount);
    WriteString('DefaultVcardVersion', DefaultVcardVersion);
    WriteString('MapUrl', MapUrl);
    WriteString('LastPhotoFileName', LastPhotoFileName);
    WriteString('LastQrCodeFileName', LastQrCodeFileName);
    WriteString('CompareTool', CompareTool);
    WriteString('DefaultPhoneCountryPrefix', DefaultPhoneCountryCode);
    WriteString('DefaultInternationalCallPrefix', DefaultInternationalCallPrefix);
  finally
    Free;
  end;
end;

procedure TCore.DoError(Text: string; Line: Integer);
begin
  LoadErrors := LoadErrors + Format(SLine, [Line, Text]) + LineEnding;
end;

procedure TCore.AddItemToLastOpenedList(FileName: string);
begin
  with LastOpenedList1 do begin
    LoadFromRegistry(RecentFileRegistryContext);
    AddItem(FileName);
    SaveToRegistry(RecentFileRegistryContext);
  end;
end;

procedure TCore.DoDataFileChange;
begin
  if Assigned(FOnDataFileChange) then
    FOnDataFileChange(Self);
end;

function TCore.GetDefaultCompareTool: string;
const
  KDiff3 = '/usr/bin/kdiff3';
  Kompare = '/usr/bin/kompare';
  Meld = '/usr/bin/meld';
  Diffuse = '/usr/bin/diffuse';
  BeyondCompareLin = '/usr/bin/bcompare';
  BeyondCompareWin3 = 'c:\Program Files\Beyond Compare 3\BCompare.exe';
  BeyondCompareWin4 = 'c:\Program Files\Beyond Compare 4\BCompare.exe';
  BeyondCompareWin5 = 'c:\Program Files\Beyond Compare 5\BCompare.exe';
begin
  if FileExists(KDiff3) then Result := KDiff3
  else if FileExists(Meld) then Result := Meld
  else if FileExists(Kompare) then Result := Kompare
  else if FileExists(Diffuse) then Result := Diffuse
  else if FileExists(BeyondCompareLin) then Result := BeyondCompareLin
  else if FileExists(BeyondCompareWin5) then Result := BeyondCompareWin5
  else if FileExists(BeyondCompareWin4) then Result := BeyondCompareWin4
  else if FileExists(BeyondCompareWin3) then Result := BeyondCompareWin3
  else Result := '';
end;

function TCore.GetProfileImage: TImage;
begin
  if not Assigned(ProfileImage) then begin
    ProfileImage := TImage.Create(nil);
    if FileExists(ProfilePhotoFileName) then
      ProfileImage.Picture.LoadFromFile(ProfilePhotoFileName);
  end;
  Result := ProfileImage;
end;

function TCore.GetTempDir: string;
begin
  Result := SysUtils.GetTempDir + Application.Title;
end;

procedure TCore.UpdateInterface;
begin
  AFileSave.Enabled := Assigned(DataFile) and DataFile.Modified;
  AFileSaveAs.Enabled := Assigned(DataFile);
  AFileClose.Enabled := Assigned(DataFile);
  AFileSplit.Enabled := Assigned(DataFile);
  AFileCombine.Enabled := Assigned(DataFile);
  AFileCompare.Enabled := Assigned(DataFile);
  AFind.Enabled := Assigned(DataFile);
  AFindDuplicate.Enabled := Assigned(DataFile);
  AGenerate.Enabled := Assigned(DataFile);
  {$IFOPT D+}
  ATest.Enabled := True;
  {$ENDIF}
  {$IFOPT D-}
  ATest.Enabled := False;
  {$ENDIF}
  ATest.Visible := ATest.Enabled;
  AFileCompare.Visible := AFileCompare.Enabled;
end;

procedure TCore.Initialize;
var
  FileNameOption: string;
begin
  if not InitializeStarted then begin
    InitializeStarted := True;

    FileNameOption := FindFirstNonOption;
    if FileNameOption <> '' then begin
      // Open file specified as command line parameter
      AFileNew.Execute;
      DataFile.LoadFromFile(FileNameOption);
      AddItemToLastOpenedList(FileNameOption);
    end else
    if ReopenLastFileOnStart and (LastOpenedList1.Items.Count > 0) and FileExists(LastOpenedList1.Items[0]) then begin
      // Open last opened file
      AFileNew.Execute;
      DataFile.LoadFromFile(LastOpenedList1.Items[0])
    end else AFileNew.Execute;

    UpdateFile;
    InitializeFinished := True;
  end;
end;

function TCore.FindFirstNonOption: string;
var
  S: string;
  I: Integer;
begin
  Result := '';
  for I := 1 to Application.ParamCount do begin
    S := Application.Params[I];
    if S[1] = Application.OptionChar then Continue;
    Result := S;
    Break;
  end;
end;

end.

