//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "main.h"
#include <stdio.h>
#include "uclwin.h"
#include "finf.h"
#include <registry.hpp>
#include <shellapi.h>
#include "about.h"
#include "wf.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "VmxAlphaImage"
#pragma resource "*.dfm"
TMainForm *MainForm;
extern FeedbackProc *StdFeedback;
//---------------------------------------------------------------------------

AnsiString __fastcall GetNewTempDir (void)
{
  GUID a;
  CoInitialize (NULL);
  CoCreateGuid (&a);
  CoUninitialize ();
  return ("C:\\TEMP\\VMXSTOREUCL.TMP."+GUIDToString(a)+"\\");
}

typedef void __fastcall TCallbackProc (int Progress);

void __fastcall HexToFile (AnsiString FI, AnsiString FO)
{
  TFileStream *fi = new TFileStream (FI,fmOpenRead);
  TFileStream *fo = new TFileStream (FO,fmOpenWrite|fmCreate);
  fo->Position=0;
  BYTE b;
  AnsiString H;
  char c[2];
  while (fi->Position!=fi->Size)
  {
    fi->Read(&c[0],1);
    fi->Read(&c[1],1);
    H = AnsiString (c[0]) + AnsiString (c[1]);
    b = StrToInt ("0x"+H);
    fo->Write(&b,1);
  }
  delete fi;
  delete fo;
}

void __fastcall ignore (AnsiString FI, AnsiString FO)
{
  FILE *fp = fopen (FI.c_str(),"r");
  FILE *f2 = fopen (FO.c_str(),"w");
  char c;
  while (!feof(fp))
  {
    c = fgetc (fp);
    if (feof(fp))
      break;
    if (c != '\n' && c != '\r' && c != '\0')
      fputc (c, f2);
  }
  fclose (fp);
  fclose (f2);
}

__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormShow(TObject *Sender)
{
  VEMemo->Lines->SaveToFile(ExtractFilePath(ParamStr(0))+"ven.tmp");
  ignore (ExtractFilePath(ParamStr(0))+"ven.tmp",ExtractFilePath(ParamStr(0))+"veh.tmp");
  remove ((ExtractFilePath(ParamStr(0))+"ven.tmp").c_str());
  HexToFile (ExtractFilePath(ParamStr(0))+"veh.tmp",ExtractFilePath(ParamStr(0))+"ve.tmp");
  remove ((ExtractFilePath(ParamStr(0))+"veh.tmp").c_str());
  VmxAlphaImage1->Picture->LoadFromFile(ExtractFilePath(ParamStr(0))+"ve.tmp");
  remove ((ExtractFilePath(ParamStr(0))+"ve.tmp").c_str());
  if (ParamStr(1)!="")
    Open (ParamStr(1));
  TRegistry *Reg = new TRegistry;
  Reg->RootKey=HKEY_CLASSES_ROOT;
  if (!Reg->KeyExists (".vsu"))
  {
    if (Application->MessageBox("Связать файлы *.vsu (VMX Store UCL) с программой VMX Store UCL?","Подтверждение",MB_YESNO|MB_ICONQUESTION)==IDYES)
    {
      Reg->OpenKey (".vsu",true);
      Reg->WriteString("","vsu_file");
      Reg->CloseKey();
      Reg->OpenKey("vsu_file",true);
      Reg->WriteString("","Архив VSU");
      Reg->OpenKey("DefaultIcon",true);
      Reg->WriteString("",ParamStr(0)+",1");
      Reg->CloseKey();
      Reg->OpenKey("vsu_file\\shell\\open\\command",true);
      Reg->WriteString("","\""+ParamStr(0)+"\" \"%1\"");
      Reg->CloseKey();
    }
  }
  delete Reg;
}
//---------------------------------------------------------------------------

// VMX STORE ROUTINES

/***************************************************************************/
/*  Используется сигнатура 'VSU' и улучшенный вариант VMX Store (2.1.01)   */
/*     с поддержкой структурированного хранилища (по "папкам")             */
/*                                                                         */
/*  Функции:                                                               */
/*   CreateStore           VSUGetContent     VSUAddFiles                   */
/*   StoreExtractFiles     VSUExtractFiles   VSUDeleteFiles                */
/*   StoreAddFiles         VSUCreateFile                                   */
/*   StoreRemoveFiles      VSUFileInfo                                     */
/*                                                                         */
/***************************************************************************/

__int64 __fastcall GetFileSize (AnsiString File)
{
  TFileStream *fs = new TFileStream (File, fmOpenRead);
  __int64 a = fs->Size;
  delete fs;
  return a;
}

AnsiString StreamString (TFileStream *fs)
{
  char c;
  fs->Read(&c,1);
  AnsiString A;
  while (c!='\n'&&c!='\r'&&c!='\0'&&fs->Position!=fs->Size)
  {
    A+=c;
    fs->Read(&c,1);
  }
  return A;
}

void __fastcall CreateStore (AnsiString File, TStrings *Files, TCallbackProc *Proc)
{
  TFileStream *fs = new TFileStream (File,fmCreate|fmOpenRead);
  fs->Position=0;
  TFileStream *f2;
  char *sign = new char [4];
  sign = "VSU";
  sign[3] = '\0';
  fs->Write(sign,3);
  int N = Files -> Count;
  fs->Write(&N,4);
  __int64 sall = 0, sc = 0;
  __int64 *sizes = new __int64 [N];
  for (int i = 0; i < Files -> Count; i++)
  {
    f2 = new TFileStream (Files->Strings[i],fmOpenRead);
    __int64 ii = f2 -> Size;
    fs->Write(&ii,8);
    delete f2;
    sall+=ii;
    sizes[i]=ii;
  }
  for (int i = 0; i < Files -> Count; i++)
  {
    AnsiString str = ExtractFileName(Files->Strings[i])+'\n';
    fs->Write(str.c_str(),str.Length());
  }
  // writing directory structure
  // т.е её не наблюдается (всё в корне)
  for (int i = 0; i < Files -> Count; i++)
  {
    AnsiString str = "\\\n";
    fs->Write(str.c_str(),2);
  }
  // end
  for (int i = 0; i < Files -> Count; i++)
  {
    f2 = new TFileStream (Files->Strings[i],fmOpenRead);
    fs->CopyFrom(f2,f2->Size);
    delete f2;
    sc+=sizes[i];
    if (Proc!=NULL)
      Proc(100*sc/sall);
  }
  delete fs;
  delete [] sign;
  delete [] sizes;
}

void __fastcall StoreExtractFiles (AnsiString Store, TStrings *Files, AnsiString Dir, TCallbackProc *Proc, bool KeepDirStruct = false)
{
  if (!DirectoryExists (Dir))
    CreateDirectory (Dir.c_str(),NULL);
  TFileStream *fs = new TFileStream (Store, fmOpenRead);
  char *sign = new char [4];
  fs->Read(sign,3);
  if (sign[0]!='V'||sign[1]!='S'||sign[2]!='U')
  {
    Application->MessageBoxA("Это не файл VMX Store","Ошибка",MB_OK|MB_ICONERROR);
    delete fs;
    return;
  }
  int N;
  fs->Read(&N,4);
  __int64 *sizes = new __int64 [N];
  __int64 sall = 0, sc = 0;
  for (int i = 0; i < N; i++)
  {
    fs->Read(&sizes[i],8);
    sall+=sizes[i];
  }
  AnsiString *names = new AnsiString [N];
  for (int i = 0; i < N; i++)
    names[i] = StreamString(fs);
  // dir struct
  AnsiString *dirs = new AnsiString [N];
  for (int i = 0; i < N; i++)
  {
    dirs[i] = StreamString(fs);
    if (dirs[i]=="\\")
      dirs[i]="";
    else dirs[i]=dirs[i].SubString(2,dirs[i].Length()-1);
  }
  // end reading
  if (KeepDirStruct)
  {
    for (int i = 0; i < N; i++)
    {
      if (dirs[i]!="")
        CreateDirectory ((Dir+dirs[i]).c_str(),NULL);
    }
  }
  TFileStream *f2;
  for (int i = 0; i < N; i++)
  {
    if (Files->IndexOf(names[i])>-1)
    {
      f2=new TFileStream (Dir+(KeepDirStruct?dirs[i]:AnsiString(""))+names[i],fmCreate|fmOpenWrite);
      f2->Position=0;
      f2->CopyFrom(fs,sizes[i]);
      delete f2;
    }
    else
      fs->Seek (sizes[i],soCurrent);
    sc+=sizes[i];
    if (Proc!=NULL)
      Proc (100*sc/sall);
  }
  delete [] sizes;
  delete fs;
  delete [] names;
  delete [] dirs;
}

void __fastcall StoreAddFiles (AnsiString File, AnsiString ToDir, TStrings *AddFiles, TCallbackProc *Proc)
{
  AnsiString TempDir = GetNewTempDir ();
  CreateDirectory (TempDir.c_str(),NULL);
  TFileStream *fs = new TFileStream (File, fmOpenRead);
  char *sign = new char [4];
  fs->Read(sign,3);
  if (sign[0]!='V'||sign[1]!='S'||sign[2]!='U')
  {
    Application->MessageBoxA("Это не файл VMX Store","Ошибка",MB_OK|MB_ICONERROR);
    delete fs;
    return;
  }
  int N;
  fs->Read(&N,4);
  __int64 *sizes = new __int64 [N];
  __int64 sall = 0, sc = 0;
  for (int i = 0; i < N; i++)
  {
    fs->Read(&sizes[i],8);
    sall+=sizes[i];
  }
  AnsiString *names = new AnsiString [N];
  for (int i = 0; i < N; i++)
    names [i] = StreamString(fs);
  // dir struct
  AnsiString *dirs = new AnsiString [N];
  for (int i = 0; i < N; i++)
    dirs[i] = StreamString(fs);
  // end reading
  TFileStream *f2;
  for (int i = 0; i < N; i++)
  {
    f2=new TFileStream (TempDir+names[i],fmCreate|fmOpenWrite);
    f2->Position=0;
    f2->CopyFrom(fs,sizes[i]);
    delete f2;
    sc+=sizes[i];
    if (Proc!=NULL)
      Proc(100*sc/sall);
  }
  delete [] sizes;
  delete fs;
  TStrings *NewFiles = new TStringList;
  for (int i = 0; i < N; i++)
    NewFiles->Add (TempDir+names[i]);
  NewFiles->AddStrings(AddFiles);
  fs = new TFileStream (File,fmCreate|fmOpenWrite);
  fs->Position=0;
  sign = new char [4];
  sign = "VSU";
  sign[3] = '\0';
  fs->Write(sign,3);
  int N2 = NewFiles->Count;
  fs->Write(&N2,4);
  __int64 tmp;
  sall = 0;
  sc = 0;
  for (int i = 0; i < N2; i++)
  {
    f2=new TFileStream (NewFiles->Strings[i],fmOpenRead);
    tmp = f2->Size;
    fs->Write(&tmp,8);
    delete f2;
    sall+=tmp;
  }
  AnsiString s;
  for (int i = 0; i < N2; i++)
  {
    s = ExtractFileName(NewFiles->Strings[i])+'\n';
    fs->Write(s.c_str(),s.Length());
  }
  // writing dir struct
  for (int i = 0; i < N2; i++)
  {
    if (i < N)
      s = dirs[i]+'\n';
    else s = ToDir+'\n';
    fs->Write(s.c_str(),s.Length());
  }
  // end
  for (int i = 0; i < N2; i++)
  {
    f2=new TFileStream (NewFiles->Strings[i],fmOpenRead);
    tmp=f2->Size;
    fs->CopyFrom(f2,f2->Size);
    delete f2;
    sc+=tmp;
    if (Proc!=NULL)
      Proc(100*sc/sall);
  }
  delete fs;
  for (int i = 0; i < N; i++)
    remove ((TempDir+names[i]).c_str());
  RemoveDirectory (TempDir.c_str());
  delete NewFiles;
  delete [] names;
  delete [] dirs;
}

void __fastcall StoreRemoveFiles (AnsiString File, TStrings* RemFiles, TCallbackProc *Proc)
{
  AnsiString TempDir = GetNewTempDir ();
  CreateDirectory (TempDir.c_str(),NULL);
  TFileStream *fs = new TFileStream (File, fmOpenRead);
  char *sign = new char [4];
  fs->Read(sign,3);
  if (sign[0]!='V'||sign[1]!='S'||sign[2]!='U')
  {
    Application->MessageBoxA("Это не файл VMX Store","Ошибка",MB_OK|MB_ICONERROR);
    delete fs;
    return;
  }
  int N;
  fs->Read(&N,4);
  __int64 *sizes = new __int64 [N];
  __int64 sall = 0, sc = 0;
  for (int i = 0; i < N; i++)
  {
    fs->Read(&sizes[i],8);
    sall+=sizes[i];
  }
  AnsiString *names = new AnsiString [N];
  for (int i = 0; i < N; i++)
    names[i]=StreamString(fs);
  // dir struct
  AnsiString *dirs = new AnsiString [N];
  for (int i = 0; i < N; i++)
    dirs[i] = StreamString(fs);
  // end reading
  TFileStream *f2;
  for (int i = 0; i < N; i++)
  {
    f2=new TFileStream (TempDir+names[i],fmCreate|fmOpenWrite);
    f2->Position=0;
    f2->CopyFrom(fs,sizes[i]);
    delete f2;
    sc+=sizes[i];
    if (Proc!=NULL)
      Proc(100*sc/sall);
  }
  delete [] sizes;
  delete fs;
  TStrings *NewFiles = new TStringList;
  TStrings *NewDirs = new TStringList;
  for (int i = 0; i < N; i++)
    if (RemFiles->IndexOf(names[i])==-1)
    {
      NewFiles->Add (TempDir+names[i]);
      NewDirs->Add (dirs[i]);
    }
  fs = new TFileStream (File,fmCreate|fmOpenWrite);
  fs->Position=0;
  sign = new char [4];
  sign = "VSU";
  sign[3] = '\0';
  fs->Write(sign,3);
  int N2 = NewFiles->Count;
  fs->Write(&N2,4);
  __int64 tmp;
  sall = 0;
  sc = 0;
  for (int i = 0; i < N2; i++)
  {
    f2=new TFileStream (NewFiles->Strings[i],fmOpenRead);
    tmp = f2->Size;
    fs->Write(&tmp,8);
    delete f2;
    sall+=tmp;
  }
  AnsiString s;
  for (int i = 0; i < N2; i++)
  {
    s = ExtractFileName(NewFiles->Strings[i])+'\n';
    fs->Write(s.c_str(),s.Length());
  }
  // writing directory structure
  for (int i = 0; i < N2; i++)
  {
    s = NewDirs->Strings[i]+'\n';
    fs->Write(s.c_str(),s.Length());
  }
  // end
  for (int i = 0; i < N2; i++)
  {
    f2=new TFileStream (NewFiles->Strings[i],fmOpenRead);
    tmp=f2->Size;
    fs->CopyFrom(f2,f2->Size);
    delete f2;
    sc+=tmp;
    if (Proc!=NULL)
      Proc(100*sc/sall);
  }
  delete fs;
  for (int i = 0; i < N; i++)
    remove ((TempDir+names[i]).c_str());
  RemoveDirectory (TempDir.c_str());
  delete NewFiles;
  delete [] names;
  delete [] dirs;
  delete NewDirs;
}

// Files is the pointer to the TStringList object
bool __fastcall VSUGetContent (AnsiString File, TStrings *Files, TStrings *Dirs)
{
  TFileStream *fs = new TFileStream (File,fmOpenRead);
  char *sign = new char [4];
  fs->Read(sign,3);
  if (sign[0]!='V'||sign[1]!='S'||sign[2]!='U')
  {
    Application->MessageBoxA("Это не файл VMX Store UCL","Ошибка",MB_OK|MB_ICONERROR);
    delete fs;
    return false;
  }
  int N;
  fs->Read(&N,4);
  __int64 tmp;
  for (int i = 0; i < N; i++)
    fs->Read(&tmp,8);
  for (int i = 0; i < N; i++)
    Files->Add(StreamString(fs));
  for (int i = 0; i < N; i++)
    Dirs->Add(StreamString(fs));
  delete [] sign;
  delete fs;
  return true;
}

void __fastcall VSUExtractFiles (AnsiString File, TStrings *Files, AnsiString Dir, TCallbackProc *Proc, bool KeepDirStruct = false)
{
  TStrings *fs = new TStringList, *ds = new TStringList;
  VSUGetContent (File, fs, ds);
  TStrings *xs = new TStringList;
  for (int i = 0; i < Files->Count; i++)
    if (fs->IndexOf(Files->Strings [i])>-1)
      xs->Add(ds->Strings[fs->IndexOf(Files->Strings [i])]);
  for (int i = 0; i < xs->Count; i++)
  {
    if (xs->Strings[i]=="\\")
      xs->Strings[i]="";
    else xs->Strings[i]=xs->Strings[i].SubString(2,xs->Strings[i].Length()-1);
  }
  StoreExtractFiles (File, Files, Dir, Proc, false);
  for (int i = 0; i < Files->Count; i++)
    rename ((Dir+Files->Strings[i]).c_str(),(Dir+Files->Strings[i]+".tmp").c_str());
  if (KeepDirStruct)
  {
    for (int i = 0; i < xs->Count; i++)
      if (xs->Strings[i]!="")
        CreateDirectory ((Dir+xs->Strings[i]).c_str(),NULL);
  }
  for (int i = 0; i < Files->Count; i++)
    UclDecompressFile (Dir+Files->Strings[i]+".tmp",Dir+(KeepDirStruct?xs->Strings[i]:AnsiString(""))+Files->Strings[i]);
  for (int i = 0; i < Files->Count; i++)
    remove ((Dir+Files->Strings[i]+".tmp").c_str());
  delete fs;
  delete ds;
  delete xs;
}

__int64 cfs = 0;

void __fastcall VSUCreateFile (AnsiString File, TStrings *Files, FeedbackProc *Proc1, TCallbackProc *Proc2)
{
  AnsiString TempDir = GetNewTempDir ();
  CreateDirectory (TempDir.c_str(),NULL);
  StdFeedback = Proc1;
  for (int i = 0; i < Files->Count; i++)
  {
    TFileStream *fs = new TFileStream (Files->Strings[i],fmOpenRead);
    cfs = fs->Size;
    delete fs;
    UclCompressFile (Files->Strings[i],TempDir+ExtractFileName(Files->Strings[i]),0x2b,10);
  }
  TStrings *mFiles = new TStringList;
  for (int i = 0; i < Files->Count; i++)
    mFiles->Add(TempDir+ExtractFileName(Files->Strings[i]));
  CreateStore (File, mFiles, Proc2);
  for (int i = 0; i < Files->Count; i++)
    remove ((TempDir+ExtractFileName(Files->Strings[i])).c_str());
  RemoveDirectory (TempDir.c_str());
  delete mFiles;
}

void __fastcall VSUFileInfo (AnsiString Store, AnsiString File, long& Size, long &CSize)
{
  AnsiString TD = GetNewTempDir ();
  CreateDirectory (TD.c_str(),NULL);
  TStrings *Files = new TStringList;
  Files->Add(File);
  StoreExtractFiles (Store, Files, TD, NULL);
  UclFileInfo (TD+File,Size,CSize);
  delete Files;
  remove ((TD+File).c_str());
  RemoveDirectory (TD.c_str());
}

void __fastcall VSUAddFiles (AnsiString Store, AnsiString ToDir, TStrings *Files, FeedbackProc *Proc1, TCallbackProc *Proc2)
{
  AnsiString TD = GetNewTempDir ();
  CreateDirectory (TD.c_str(),NULL);
  TStrings *IFiles = new TStringList;
  StdFeedback = Proc1;
  for (int i = 0; i < Files->Count; i++)
  {
    TFileStream *fs = new TFileStream (Files->Strings[i],fmOpenRead);
    cfs = fs->Size;
    delete fs;
    UclCompressFile (Files->Strings[i],TD+ExtractFileName(Files->Strings[i]),0x2b,10);
    IFiles->Add(TD+ExtractFileName(Files->Strings[i]));
  }
  StoreAddFiles (Store, ToDir, IFiles, Proc2);
  for (int i = 0; i < IFiles->Count; i++)
    remove (IFiles->Strings[i].c_str());
  RemoveDirectory (TD.c_str());
  delete IFiles;
}

void __fastcall VSUDeleteFiles (AnsiString Store, TStrings *Files, TCallbackProc *Proc2)
{
  StoreRemoveFiles (Store, Files, Proc2);
}

void __fastcall mFeed (long bytes)
{
  MainForm->ProgressBar1->Position=100*bytes/cfs;
  Application->ProcessMessages();
}

void __fastcall mf2 (int pos)
{
  MainForm->ProgressBar1->Position=pos;
  Application->ProcessMessages();
}

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
  if (AddDialog->Execute()&&SaveDialog1->Execute())
  {
    VSUCreateFile (SaveDialog1->FileName,AddDialog->Files,&mFeed,&mf2);
    Open (SaveDialog1->FileName);
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::Open (AnsiString File)
{
  ListBox1->Items->Clear();
  ListBox2->Items->Clear();
  if (VSUGetContent (File, ListBox1->Items, ListBox2->Items))
  {
    OpenedFile->Caption=File;
    if (N16->Checked)
      SpeedButton1Click(NULL);
  }
}
void __fastcall TMainForm::N3Click(TObject *Sender)
{
  if (OpenDialog1->Execute())
    Open(OpenDialog1->FileName);
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::N12Click(TObject *Sender)
{
  long s, cs;
  if (ListBox1->ItemIndex!=-1&&OpenedFile->Caption!="")
  {
    VSUFileInfo (OpenedFile->Caption, ListBox1->Items->Strings[ListBox1->ItemIndex],s,cs);
    FileInfo->FileName->Caption = ListBox1->Items->Strings[ListBox1->ItemIndex];
    FileInfo->SizeL->Caption=IntToStr(cs);
    FileInfo->CSizeL->Caption=IntToStr(s);
    TRegistry *Reg = new TRegistry;
    Reg->RootKey = HKEY_CLASSES_ROOT;
    if (ExtractFileExt(ListBox1->Items->Strings[ListBox1->ItemIndex]).LowerCase()==".exe")
    {
      HICON I = ExtractIcon(HInstance, ListBox1->Items->Strings[ListBox1->ItemIndex].c_str(), 0);
      if (I!=NULL)
        FileInfo->VmxAlphaImage1->Visible=false;
      else FileInfo->VmxAlphaImage1->Visible=true; 
      FileInfo->FileIcon->Picture->Icon->Handle=I;
    }
    else
    {
      if (Reg->KeyExists(ExtractFileExt(ListBox1->Items->Strings[ListBox1->ItemIndex])))
      {
        Reg->OpenKey (ExtractFileExt(ListBox1->Items->Strings[ListBox1->ItemIndex]),false);
        AnsiString X = Reg->ReadString ("");
        Reg->CloseKey();
        FileInfo->FileIcon->Visible=true;
        FileInfo->VmxAlphaImage1->Visible=false;
        if (!Reg->OpenKey (X+"\\DefaultIcon",false))
          FileInfo->FileIcon->Visible=false;
        else
        {
          AnsiString I = Reg->ReadString("");
          AnsiString I1, I2;
          int n = I.LastDelimiter(",");
          if (n >= 0)
          {
            I2 = I.SubString(n+1,I.Length()-n);
            I1 = I.SubString(1,n-1);
          }
          else I1 = I;
          if (I1[1]=='\"')
            I1 = I1.SubString(2,I1.Length()-1);
          if (I1[I1.Length()]=='\"')
            I1 = I1.SubString(1,I1.Length()-1);
          if (I1[2]!=':')
          {
            if (I1[1]=='%')
            {
              AnsiString Var;
              I1 = I1.SubString(2,I1.Length()-1);
              for (;I1.Length()>1&&I1[1]!='%';)
              {
                Var+=I1[1];
                I1 = I1.SubString(2,I1.Length()-1);
              }
              I1 = I1.SubString(2,I1.Length()-1);
              if (Var=="SystemRoot")
                I1 = GetWinDir()+I1.SubString(2,I1.Length()-1);
            }
            else
            {
              if (FileExists (GetWinDir()+I1))
                I1 = GetWinDir()+I1;
              else if (FileExists (GetWinSysDir()+I1))
                I1 = GetWinSysDir()+I1;
              else
              {
                FileInfo->FileIcon->Visible=false;
                FileInfo->VmxAlphaImage1->Visible=true;
                delete Reg;
                return;
              }
            }
          }
          if (ExtractFileExt (I1)==".ico")
            FileInfo->FileIcon->Picture->LoadFromFile(I1);
          else if (ExtractFileExt (I1)==".exe"||ExtractFileExt (I1)==".dll")
          {
            HICON I = ExtractIcon(HInstance, I1.c_str(), StrToInt(I2));
            FileInfo->FileIcon->Picture->Icon->Handle=I;
          }
        }
      }
      else
      {
        FileInfo->FileIcon->Visible=false;
        FileInfo->VmxAlphaImage1->Visible=true;
      }
    }
    delete Reg;
    FileInfo->ShowModal();
  }
}
//---------------------------------------------------------------------------

AnsiString __fastcall TMainForm::GetWinDir (void)
{
  char *windir = new char [MAX_PATH];
  GetWindowsDirectory (windir, MAX_PATH);
  AnsiString WinDir = windir;
  for (int i = 0; i < WinDir.Length(); i++)
    if (i == WinDir.Length()-1 || i == WinDir.Length()-2)
      if (windir [i] == '\\')
      {
        windir [i] = '\0';
        break;
      }
  WinDir = windir;
  return (WinDir+"\\");
}

AnsiString __fastcall TMainForm::GetWinSysDir (void)
{
  char *windir = new char [MAX_PATH];
  GetSystemDirectory (windir, MAX_PATH);
  AnsiString WinDir = windir;
  for (int i = 0; i < WinDir.Length(); i++)
    if (i == WinDir.Length()-1 || i == WinDir.Length()-2)
      if (windir [i] == '\\')
      {
        windir [i] = '\0';
        break;
      }
  WinDir = windir;
  return (WinDir+"\\");
}

void __fastcall TMainForm::N5Click(TObject *Sender)
{
  if (OpenedFile->Caption!=""&&AddDialog->Execute())
  {
    VSUAddFiles (OpenedFile->Caption,Edit1->Text,AddDialog->Files,&mFeed,&mf2);
    Open (OpenedFile->Caption);
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::N11Click(TObject *Sender)
{
  AboutBox->ShowModal ();        
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::N9Click(TObject *Sender)
{
  Close ();        
}
//---------------------------------------------------------------------------

AnsiString __fastcall mSelectDirectory (void)
{
  BROWSEINFO bi;
  LPITEMIDLIST pidlBrowse;
  char* lpBuffer = new char [MAX_PATH];
  bi.hwndOwner = MainForm->Handle;
  bi.pidlRoot = NULL;
  bi.pszDisplayName = lpBuffer;
  bi.lpszTitle = "Выбор папки";
  bi.ulFlags = 0;
  bi.lpfn = NULL;
  bi.lParam = 0;
  pidlBrowse = SHBrowseForFolder(&bi);
  SHGetPathFromIDList(pidlBrowse, lpBuffer);
  AnsiString R = lpBuffer;
  return (R!=""?R+"\\":R);
}

void __fastcall TMainForm::N7Click(TObject *Sender)
{
  if (ListBox1->SelCount>0&&OpenedFile->Caption!="")
  {
    AnsiString D = mSelectDirectory ();
    if (D!="")
    {
      TStrings *Files = new TStringList;
      for (int i = 0; i < ListBox1->Items->Count; i++)
        if (ListBox1->Selected[i])
          Files->Add(ListBox1->Items->Strings[i]);
      VSUExtractFiles (OpenedFile->Caption,Files,D,mf2,N15->Checked);
      delete Files;
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::N6Click(TObject *Sender)
{
  if (OpenedFile->Caption!=""&&ListBox1->SelCount>0)
  {
    TStrings *Files = new TStringList;
    for (int i = 0; i < ListBox1->Items->Count; i++)
      if (ListBox1->Selected[i])
        Files->Add(ListBox1->Items->Strings[i]);
    VSUDeleteFiles (OpenedFile->Caption, Files, mf2);
    delete Files;
    Open (OpenedFile->Caption);
  }
}
//---------------------------------------------------------------------------

void __fastcall TMainForm::N14Click(TObject *Sender)
{
  OpenedFile->Caption="";
  ListBox1->Items->Clear();
  ListBox2->Items->Clear();
}
//---------------------------------------------------------------------------


void __fastcall TMainForm::SpeedButton1Click(TObject *Sender)
{
  if (OpenedFile->Caption!="")
  {
    WaitForm->Show();
    Application->ProcessMessages();
    __int64 sall = 0;
    long a, b;
    for (int i = 0; i < ListBox1->Items->Count; i++)
    {
      VSUFileInfo (OpenedFile->Caption, ListBox1->Items->Strings[i], a, b);
      sall+=b;
    }
    __int64 sca = GetFileSize (OpenedFile->Caption);
    WaitForm->Close();
    perc = 100*((float)sca)/((float)sall);
    PercPB->Invalidate();
  }
}
//---------------------------------------------------------------------------

#define PBC PercPB->Canvas
#define PBW PercPB->Width
#define PBH PercPB->Height

void __fastcall TMainForm::PercPBPaint(TObject *Sender)
{
  PBC->Brush->Style=bsSolid;
  PBC->Brush->Color=0x00FFAA55;
  PBC->Pen->Color=0x000055AA;
  PBC->Font->Color=0x000055AA;
  PBC->Font->Size=8;
  PBC->Font->Name="MS Sans Serif";
  PBC->Font->Style=TFontStyles();
  PBC->Rectangle(0,0,PBW,PBH);
  PBC->Brush->Color=0x0000E0F2;
  PBC->FillRect (TRect(1,(PBH-1)*(1.0-perc/100.0),PBW-1,PBH-1));
  PBC->Brush->Style=bsClear;
  AnsiString P = FloatToStr(perc);
  if (P.LastDelimiter(".,")==2&&P.Length()>4)
    P.SetLength(4);
  else if (P.LastDelimiter(".,")==3&&P.Length()>5)
    P.SetLength(5);
  P+="%";
  PBC->TextOutA(PBW/2-PBC->TextWidth(P)/2,PBH/2-PBC->TextHeight(P)/2,P);
}
//---------------------------------------------------------------------------

