unit frmEditorUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,maplistload,langload, StdCtrls, shellapi,common,Registry,
  ExtCtrls, Menus, Grids, ValEdit, colors, ComCtrls, ImgList, ShlObj,ActiveX,
  frmWizardUnit;

type
  TfrmEditor = class(TForm)
    pmnuEdit: TPopupMenu;
    mnuEditAdd: TMenuItem;
    mnuEditDelete: TMenuItem;
    pmnuFile: TPopupMenu;
    mnuFileNew: TMenuItem;
    mnuFileOpen: TMenuItem;
    mnuFileSaveProject: TMenuItem;
    mnuFileSaveMapPack: TMenuItem;
    mnuFileExit: TMenuItem;
    pmnuHeaderEdit: TPopupMenu;
    mnuHeaderEditAdd: TMenuItem;
    mnuHeaderEditDelete: TMenuItem;
    pmnuFilesEdit: TPopupMenu;
    mnuFilesEditAdd: TMenuItem;
    mnuFilesEditDelete: TMenuItem;
    pmnuPropertiesEdit: TPopupMenu;
    mnuPropertiesEditAdd: TMenuItem;
    mnuPropertiesEditDelete: TMenuItem;
    pmnuResourcesEdit: TPopupMenu;
    mnuResourcesEditAdd: TMenuItem;
    mnuResourcesEditDelete: TMenuItem;
    imlFiles: TImageList;
    dlgResources: TOpenDialog;
    mnuResourcesEditAddDir: TMenuItem;
    pnlCompile: TPanel;
    lblCompile: TLabel;
    lstCompile: TMemo;
    pmnuCompile: TPopupMenu;
    mnuCompileSaveToFile: TMenuItem;
    mnuCompileClear: TMenuItem;
    splMidRight: TSplitter;
    splLeftMid: TSplitter;
    pnlRight: TPanel;
    splResourcesPreview: TSplitter;
    pnlPreview: TPanel;
    lblPreview: TLabel;
    lblNoPreview: TLabel;
    sbPreview: TScrollBox;
    imgPreview: TImage;
    txtPreview: TMemo;
    pnlResources: TPanel;
    lblResources: TLabel;
    pnlResourcesMenu: TPanel;
    mnuResourcesEdit: TLabel;
    lstResources: TListView;
    pnlMid: TPanel;
    splPropertiesFiles: TSplitter;
    pnlProperties: TPanel;
    lblProperties: TLabel;
    pnlPropertiesMenu: TPanel;
    mnuPropertiesEdit: TLabel;
    lstProperties: TValueListEditor;
    pnlFiles: TPanel;
    lblFiles: TLabel;
    lstFiles: TTreeView;
    pnlFilesMenu: TPanel;
    mnuFilesEdit: TLabel;
    pnlLeft: TPanel;
    splMapsHeader: TSplitter;
    pnlMaps: TPanel;
    lblMaps: TLabel;
    lstMaps: TListBox;
    pnlMapsMenu: TPanel;
    mnuFile: TLabel;
    mnuEdit: TLabel;
    pnlHeader: TPanel;
    lblHeader: TLabel;
    lstHeader: TValueListEditor;
    pnlHeaderMenu: TPanel;
    mnuHeaderEdit: TLabel;
    dlgCompile: TSaveDialog;
    mnuFileShowConsole: TMenuItem;
    mnuResourcesEditAddSubDirs: TMenuItem;
    mnuResourcesEditClear: TMenuItem;
    mnuFilesEditCreateFolder: TMenuItem;
    imlResources: TImageList;
    cmbProperties: TComboBox;
    cmbHeader: TComboBox;
    cmbPropertiesTga: TComboBox;
    mnuPropertiesEditTexturesDir: TMenuItem;
    lstScripts: TListBox;
    cmdScripts: TButton;
    mnuHeaderEditAddInfo: TMenuItem;
    dlgSaveMapPack: TSaveDialog;
    mnuFilePackProperties: TMenuItem;
    mnuResourcesEditRename: TMenuItem;
    dlgSaveProject: TSaveDialog;
    dlgOpenProject: TOpenDialog;
    mnuFileHelp: TMenuItem;

    procedure Compile(quiet:boolean);
    procedure SetColors();
    function  NewFile():Boolean;
    function  SaveFile():Boolean;
    function  OpenFile():Boolean;

    procedure ChangeTexturesDir(Dir:string);
    
    procedure AddNewResource(FileName:string);
    procedure AddFolder(Folder:String;SubFolders:Boolean);

    function SelectDirectory(const Caption: string; const Root: WideString; out Directory: string): Boolean;

    function TgaSize(bufer:Pointer): TPoint;
    function DrawTgaOnImage(FileName:string;Image: TImage;ScrollBox:TScrollBox; XGrid: Boolean): Boolean;
    function LoadTgaToMemory(FileName:string):Pointer;
    function ViewTga(bufer: Pointer; b:TBitmap; XGrid: Boolean): Boolean;

    function NodeFileExists(where:TTreeNode;what:string):TTreeNode;
    function NodeDirExists(where:TTreeNode;what:string):TTreeNode;

    function AddRootElement(treetext,name:string):TTreeNode;
    function AddDirElement(where:TTreeNode;treetext:string):TTreeNode;
    function AddFileElement(where:TTreeNode;treetext,filename:string;filetype:integer):TTreeNode;

    procedure PropertiesMenuChangeEnabled(en:Boolean);
    procedure ResourcesMenuChangeEnabled(en:Boolean);
    procedure FilesMenuChangeEnabled(en:Boolean);
    procedure HeaderMenuChangeEnabled(en:Boolean);
    procedure MapMenuChangeEnabled(en:Boolean);
    procedure pnlPropertiesChangeEnabled(en:Boolean);
    procedure pnlHeaderChangeEnabled(en:Boolean);
    procedure pnlFilesChangeEnabled(en:Boolean);
    procedure pnlResourcesChangeEnabled(en:Boolean);
    procedure PanelsChangeEnabled(en:Boolean);

    procedure FormCreate(Sender: TObject);

    procedure mnuMouseLeave(Sender: TObject);
    procedure mnuMouseEnter(Sender: TObject);
    procedure mnuMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);

    procedure pnlMapsResize(Sender: TObject);
    procedure pnlHeaderResize(Sender: TObject);
    procedure pnlTopResize(Sender: TObject);
    procedure pnlFilesResize(Sender: TObject);
    procedure pnlResourcesResize(Sender: TObject);
    procedure pnlPreviewResize(Sender: TObject);
    procedure pnlPropertiesResize(Sender: TObject);
    procedure FormResize(Sender: TObject);

    procedure mnuMainClick(Sender: TObject);
    procedure mnuHeaderClick(Sender: TObject);
    procedure mnuPropertiesClick(Sender: TObject);
    procedure mnuFilesClick(Sender: TObject);
    procedure mnuResourcesClick(Sender: TObject);
    procedure mnuFileNewClick(Sender: TObject);
    procedure lstHeaderSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure lstPropertiesSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure mnuEditAddClick(Sender: TObject);
    procedure lstMapsClick(Sender: TObject);
    procedure mnuPropertiesEditAddClick(Sender: TObject);
    procedure mnuEditDeleteClick(Sender: TObject);
    procedure mnuHeaderEditAddClick(Sender: TObject);
    procedure mnuHeaderEditAddInfoClick(Sender: TObject);
    procedure mnuFileExitClick(Sender: TObject);
    procedure mnuPropertiesEditDeleteClick(Sender: TObject);
    procedure lstPropertiesClick(Sender: TObject);
    procedure lstHeaderClick(Sender: TObject);
    procedure mnuHeaderEditDeleteClick(Sender: TObject);
    procedure mnuResourcesEditAddClick(Sender: TObject);
    procedure lstPropertiesStringsChange(Sender: TObject);
    procedure lstHeaderStringsChange(Sender: TObject);
    procedure mnuResourcesEditAddDirClick(Sender: TObject);
    procedure mnuFileSaveMapPackClick(Sender: TObject);
    procedure mnuCompileClearClick(Sender: TObject);
    procedure lstCompileExit(Sender: TObject);
    procedure pnlCompileResize(Sender: TObject);
    procedure mnuCompileSaveToFileClick(Sender: TObject);
    procedure mnuFileShowConsoleClick(Sender: TObject);
    procedure mnuResourcesEditAddSubDirsClick(Sender: TObject);
    procedure mnuResourcesEditDeleteClick(Sender: TObject);
    procedure mnuResourcesEditClearClick(Sender: TObject);
    procedure lstFilesClick(Sender: TObject);
    procedure mnuFilesEditAddClick(Sender: TObject);
    procedure lstResourcesSelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
    procedure lstFilesDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure lstResourcesStartDrag(Sender: TObject;
      var DragObject: TDragObject);
    procedure lstFilesDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure mnuFilesEditCreateFolderClick(Sender: TObject);
    procedure cmbPropertiesSelect(Sender: TObject);
    procedure mnuPropertiesEditTexturesDirClick(Sender: TObject);
    procedure cmbPropertiesTgaDrawItem(Control: TWinControl;
      Index: Integer; Rect: TRect; State: TOwnerDrawState);
    procedure FormDestroy(Sender: TObject);
    procedure lstPropertiesStringsChanging(Sender: TObject);
    procedure mnuFilesEditDeleteClick(Sender: TObject);
    procedure cmdScriptsClick(Sender: TObject);
    procedure lstScriptsExit(Sender: TObject);
    procedure lstScriptsClick(Sender: TObject);
    procedure lstFilesChange(Sender: TObject; Node: TTreeNode);
    procedure lstHeaderMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure lstPropertiesMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure mnuFilePackPropertiesClick(Sender: TObject);
    procedure cmbHeaderSelect(Sender: TObject);
    procedure mnuResourcesEditRenameClick(Sender: TObject);
    procedure mnuFileSaveProjectClick(Sender: TObject);
    procedure lstHeaderStringsChanging(Sender: TObject);
    procedure mnuFileOpenClick(Sender: TObject);
    procedure mnuFileHelpClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMapInfo = class(TObject)
  private
  public
    Keys:TStrings;
    Types:array of integer;
    constructor Create(Keys:Tstrings);
  end;

  THeaderKeyInfo = class(TObject)
  private
  public
    keytype:integer;
    constructor Create(keytype:integer);
  end;
var
  frmEditor: TfrmEditor;  
implementation

uses StrUtils, Types, Math;

{$R *.dfm}

type
PTreeNodeInfo = ^TTreeNodeInfo;
TTreeNodeInfo = record
  filename: string;
  exists: integer;
end;

var
  SelectedMap,SelectedProperty,SelectedHeaderProperty,SelectedResource,
  SelectedFileType,LastRow,LastHeaderRow:Integer;
  ProjectFile:string;
  NodeFiles,NodeMaps,NodeHMaps,NodeIcons,NodeTextures,NodeLua,NodeMpl:TTreeNode;
  Bufs:array[1..5,1..64] of Pointer;
  
//Конструкторы
constructor TMapInfo.Create(Keys:Tstrings);
begin
  self.Keys:=Keys;
  SetLength(self.Types,Keys.Count);
end;

constructor THeaderKeyInfo.Create(keytype:integer);
begin
  self.keytype:=keytype;
end;

//Загрузка данных реестра, загрузка языка, текста надписей, цветов, выравнивание.
procedure TfrmEditor.FormCreate(Sender: TObject);
var
  reg,regLauncher:TRegistry;
begin
  {$IF (DebugMode=1)}
  AllocConsole;
  {$IFEND}
  reg := TRegistry.Create;
  reg.RootKey:=HKEY_LOCAL_MACHINE;
  reg.OpenKey(regKey,true);

  regLauncher := TRegistry.Create;
  regLauncher.RootKey:=HKEY_LOCAL_MACHINE;
  regLauncher.OpenKey(LauncherRegKey,true);

  AppDir:=reg.ReadString('AppDir');
  if length(AppDir)>0 then
    if not (RightStr(AppDir,1)='\') then
      AppDir:=AppDir+'\';
  if not DirectoryExists(AppDir) then
    AppDir:=ExtractFileDir(Application.ExeName)+'\';

  LauncherDir:=regLauncher.ReadString('AppDir');
  if length(LauncherDir)>0 then
    if not (RightStr(LauncherDir,1)='\') then
      LauncherDir:=LauncherDir+'\';
  if not DirectoryExists(LauncherDir) then
    LauncherDir:='';

  WormsDir:=regLauncher.ReadString('WormsDir');
  if length(WormsDir)>0 then
    if not (RightStr(WormsDir,1)='\') then
      WormsDir:=WormsDir+'\';
  if not DirectoryExists(WormsDir) then
    WormsDir:='';

  TexturesDir:=reg.ReadString('TexturesDir');
  LastDir:=reg.ReadString('LastDir');

  Caption:=Translate('[frmEditor.Caption]');

  ProjectFile:='';

  lblMaps.Caption:= Translate('[lblMaps.Caption]');
  lblProperties.Caption:=Translate('[lblProperties.Caption]');
  lblHeader.Caption:=Translate('[lblHeader.Caption]');
  lblFiles.Caption:=Translate('[lblFiles.Caption]');
  lblResources.Caption:=Translate('[lblResources.Caption]');
  lblPreview.Caption:=Translate('[lblPreview.Caption]');
  lblNoPreview.Caption:=Translate('[lblNoPreview.Caption]');
  lblCompile.Caption:=Translate('[lblCompile.Caption]');

  mnuFile.Caption:= ' '+Translate('[mnuFile.Caption]');
  mnuEdit.Caption:= ' '+Translate('[mnuEdit.Caption]');
  mnuHeaderEdit.Caption:= ' '+Translate('[mnuHeaderEdit.Caption]');
  mnuPropertiesEdit.Caption:= ' '+Translate('[mnuPropertiesEdit.Caption]');
  mnuResourcesEdit.Caption:= ' '+Translate('[mnuResourcesEdit.Caption]');
  mnuFilesEdit.Caption:= ' '+Translate('[mnuFilesEdit.Caption]');

  mnuFileNew.Caption:= Translate('[mnuFile.New.Caption]');
  mnuFileOpen.Caption:= Translate('[mnuFile.Open.Caption]');
  mnuFileSaveProject.Caption:= Translate('[mnuFile.SaveProject.Caption]');
  mnuFileSaveMapPack.Caption:= Translate('[mnuFile.SaveMapPack.Caption]');
  mnuFilePackProperties.Caption:= Translate('[mnuFile.PackProperties.Caption]');
  mnuFileShowConsole.Caption:= Translate('[mnuFile.ShowConsole.Caption]');
  mnuFileHelp.Caption:= Translate('[mnuFile.Help.Caption]');
  mnuFileExit.Caption:= Translate('[mnuFile.Exit.Caption]');

  mnuEditAdd.Caption:= Translate('[mnuEdit.Add.Caption]');
  mnuEditDelete.Caption:= Translate('[mnuEdit.Delete.Caption]');

  mnuHeaderEditAdd.Caption:= Translate('[mnuHeaderEdit.Add.Caption]');
  mnuHeaderEditAddInfo.Caption:= Translate('[mnuHeaderEdit.AddInfo.Caption]');
  mnuHeaderEditDelete.Caption:= Translate('[mnuHeaderEdit.Delete.Caption]');

  mnuFilesEditAdd.Caption:= Translate('[mnuFilesEdit.Add.Caption]');    
  mnuFilesEditCreateFolder.Caption:= Translate('[mnuFilesEdit.CreateFolder.Caption]');
  mnuFilesEditDelete.Caption:= Translate('[mnuFilesEdit.Delete.Caption]');

  mnuPropertiesEditAdd.Caption:= Translate('[mnuPropertiesEdit.Add.Caption]');
  mnuPropertiesEditDelete.Caption:= Translate('[mnuPropertiesEdit.Delete.Caption]');  
  mnuPropertiesEditTexturesDir.Caption:= Translate('[mnuPropertiesEdit.TexturesDir.Caption]');

  mnuResourcesEditAdd.Caption:= Translate('[mnuResourcesEdit.Add.Caption]');
  mnuResourcesEditAddDir.Caption:= Translate('[mnuResourcesEdit.AddDir.Caption]');
  mnuResourcesEditAddSubDirs.Caption:= Translate('[mnuResourcesEdit.AddSubDirs.Caption]');
  mnuResourcesEditRename.Caption:= Translate('[mnuResourcesEdit.Rename.Caption]');
  mnuResourcesEditDelete.Caption:= Translate('[mnuResourcesEdit.Delete.Caption]');
  mnuResourcesEditClear.Caption:= Translate('[mnuResourcesEdit.Clear.Caption]');

  mnuCompileSaveToFile.Caption:= Translate('[mnuCompile.SaveToFile.Caption]');
  mnuCompileClear.Caption:= Translate('[mnuCompile.Clear.Caption]');

  lstProperties.TitleCaptions[0]:=Translate('[TValueListEditor.Key.Name]');
  lstProperties.TitleCaptions[1]:=Translate('[TValueListEditor.Value.Name]'); 
  lstHeader.TitleCaptions[0]:=Translate('[TValueListEditor.Key.Name]');
  lstHeader.TitleCaptions[1]:=Translate('[TValueListEditor.Value.Name]');
  lstResources.Columns.Items[0].Caption:=Translate('[lstResources.Column1.Name]');
  lstResources.Columns.Items[1].Caption:=Translate('[lstResources.Column2.Name]');

  if Translate('[mnuFile.Help.Visible]')='1' then
    mnuFileHelp.Visible:=true
  else
    mnuFileHelp.Visible:=false;

  mnuFile.Top:=0;
  mnuEdit.Top:=0;
  mnuHeaderEdit.Top:=0;
  mnuFilesEdit.Top:=0;
  mnuPropertiesEdit.Top:=0;
  mnuResourcesEdit.Top:=0;

  mnuFile.Left:=0;
  mnuHeaderEdit.Left:=0;
  mnuFilesEdit.Left:=0;
  mnuPropertiesEdit.Left:=0;
  mnuResourcesEdit.Left:=0;

  mnuFile.AutoSize:=False;
  mnuEdit.AutoSize:=False;
  mnuHeaderEdit.AutoSize:=False;
  mnuFilesEdit.AutoSize:=False;
  mnuPropertiesEdit.AutoSize:=False;
  mnuResourcesEdit.AutoSize:=False;

  mnuFile.Height:=pnlMapsMenu.Height;
  mnuEdit.Height:=pnlMapsMenu.Height;
  mnuHeaderEdit.Height:=pnlHeaderMenu.Height;
  mnuFilesEdit.Height:=pnlFilesMenu.Height;
  mnuPropertiesEdit.Height:=pnlPropertiesMenu.Height;
  mnuResourcesEdit.Height:=pnlResourcesMenu.Height;

  mnuHeaderEdit.Height:=pnlHeaderMenu.Height;
  mnuFile.Width:=mnuFile.Width +10;
  mnuEdit.Width:=mnuEdit.Width +10;
  mnuHeaderEdit.Width:=mnuHeaderEdit.Width +10;
  mnuFilesEdit.Width:=mnuFilesEdit.Width +10;
  mnuPropertiesEdit.Width:=mnuPropertiesEdit.Width +10;
  mnuResourcesEdit.Width:=mnuResourcesEdit.Width +10;

  mnuEdit.Left:=mnuFile.Width;

  SetColors;

  ChangeTexturesDir(TexturesDir); 
  NewFile;
end;

//Установка цветов
procedure TfrmEditor.SetColors();
begin
  lblMaps.Color:=ucBackground;
  lblHeader.Color:=ucBackground;
  lblProperties.Color:=ucBackground;
  lblFiles.Color:=ucBackground;
  lblPreview.Color:=ucBackground;
  lblResources.Color:=ucBackground;
  lblNoPreview.Color:=ucBackground;
  lblCompile.Color:=ucBackground;

  pnlLeft.Color:=ucBackground;
  pnlRight.Color:=ucBackground;
  pnlMaps.Color:=ucBackground;
  pnlHeader.Color:=ucBackground;
  pnlProperties.Color:=ucBackground;
  pnlMid.Color:=ucBackground;
  pnlFiles.Color:=ucBackground;
  pnlResources.Color:=ucBackground;
  pnlPreview.Color:=ucBackground;
  pnlCompile.Color:=ucBackground;

  lstHeader.FixedColor:=ucBackground;
  lstProperties.FixedColor:=ucBackground;

  splLeftMid.Color:=ucBackground;
  splMidRight.Color:=ucBackground;
  splMapsHeader.Color:=ucBackground;
  splPropertiesFiles.Color:=ucBackground;
  splResourcesPreview.Color:=ucBackground;

  pnlMapsMenu.Color:=ucMenubar;
  pnlHeaderMenu.Color:=ucMenubar;
  pnlPropertiesMenu.Color:=ucMenubar;
  pnlFilesMenu.Color:=ucMenubar;
  pnlResourcesMenu.Color:=ucMenubar;

  mnuFile.Color:=ucMenubar;
  mnuEdit.Color:=ucMenubar;
  mnuHeaderEdit.Color:=ucMenubar;
  mnuFilesEdit.Color:=ucMenubar;
  mnuPropertiesEdit.Color:=ucMenubar;
  mnuResourcesEdit.Color:=ucMenubar;

  mnuFile.Font.Color:=ucWindowText;
  mnuEdit.Font.Color:=ucWindowText;
  mnuHeaderEdit.Font.Color:=ucWindowText;
  mnuFilesEdit.Font.Color:=ucWindowText;
  mnuPropertiesEdit.Font.Color:=ucWindowText;
  mnuResourcesEdit.Font.Color:=ucWindowText;

  lblMaps.Font.Color:=ucWindowText;
  lblHeader.Font.Color:=ucWindowText;
  lblProperties.Font.Color:=ucWindowText;
  lblFiles.Font.Color:=ucWindowText;
  lblPreview.Font.Color:=ucWindowText;
  lblResources.Font.Color:=ucWindowText;
  lblNoPreview.Font.Color:=ucWindowText;
  lblCompile.Font.Color:=ucWindowText;

  lstMaps.Font.Color:=ucWindowText;
  lstHeader.Font.Color:=ucWindowText;
  lstFiles.Font.Color:=ucWindowText;
  lstProperties.Font.Color:=ucWindowText;
  lstResources.Font.Color:=ucWindowText;
  lstCompile.Font.Color:=ucWindowText;

  txtPreview.Font.Color:=ucWindowText;

  cmbProperties.Font.Color:=ucWindowText;
  cmbHeader.Font.Color:=ucWindowText;

  lstMaps.Color:=ucWindow;
  lstHeader.Color:=ucWindow;
  lstProperties.Color:=ucWindow;
  lstFiles.Color:=ucWindow;
  lstResources.Color:=ucWindow;
  lstCompile.Color:=ucWindow;

  txtPreview.Color:=ucWindow;

  cmbProperties.Color:=ucWindow;
  cmbHeader.Color:=ucWindow;
end;


//Сборка установочного файла
procedure TfrmEditor.Compile(quiet:boolean);
var
  sa:SECURITY_ATTRIBUTES;
  hr,hw,readed:Cardinal;
  pi:TProcessInformation;
  si:TStartupInfo;
  buf:char;
  s:string;
  ExitCode: DWORD;
  CmdLine,Directory:PChar;
begin
  if quiet then                                    //Задаём параметры
    CmdLine := PChar(AppDir+'iscc\iscc.exe /q setup.iss')
  else
    CmdLine := PChar(AppDir+'iscc\iscc.exe setup.iss') ;
  Directory := PChar(AppDir+'iscc\') ;
                                                   //Чистим память
  FillChar(sa, SizeOf(sa), 0);
  FillChar(pi, SizeOf(pi), 0);
  FillChar(si, SizeOf(si), 0);

  sa.nLength := SizeOf(sa);
  sa.bInheritHandle:=true;

	CreatePipe(hr,hw,@sa,0);                        //Пайп

  si.cb:=sizeof(TStartupInfo);
  si.wShowWindow:=0;                              //Не показываем окошко
  si.dwFlags:=STARTF_USESTDHANDLES;
  si.hStdOutput:=hw;                              //Вывод запускаемого приложения на пайп

	if CreateProcess(nil,CmdLine,nil,nil,true,DETACHED_PROCESS,nil,Directory,si,pi) then
  begin
    PanelsChangeEnabled(false);
    lstCompile.Lines.Add(Translate('[message.Compile.Start]'));
    CloseHandle(hw);
    s:='';
    repeat
      Application.ProcessMessages;
        ReadFile(hr,buf,1,readed,nil);
      if readed>0 then
        s:=s+char(buf);
      if pos(char(13)+char(10),s)>0 then
      begin
        lstCompile.Lines.Add(LeftStr(s,length(s)-2));  //Пишем строку
        s:='';
      end;
      GetExitCodeProcess(pi.hProcess, ExitCode);
    until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
    if length(s)>0 then
      lstCompile.Lines.Add(s);
    if ExitCode=0 then               //Проверка кода выхода
      lstCompile.Lines.Add(Translate('[message.Compile.Success]'))
    else
      lstCompile.Lines.Add(Translate('[message.Compile.Error]'));
    PanelsChangeEnabled(true);
  end
  else
  begin
    CloseHandle(hw);               //Не вышло запустить компилятор
    lstCompile.Lines.Add(Translate('[message.Compile.Fail]'));
  end;
end;

//Прорисовка эффектов меню
procedure TfrmEditor.mnuMouseLeave(Sender: TObject);
begin
  (Sender as TLabel).Color:=ucMenubar;
end;

procedure TfrmEditor.mnuMouseEnter(Sender: TObject);
begin
  (Sender as TLabel).Color:=ucMenuhighlight;
end;

procedure TfrmEditor.mnuMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  (Sender as TLabel).Color:=ucMenuhighlight;
end;


//Обработка вызовов меню
procedure TfrmEditor.mnuMainClick(Sender: TObject);
var
  mi:TMapInfo;
begin
  if SelectedMap>=0 then
    if SelectedMap<lstMaps.Items.count then
    begin
      mi:=lstMaps.Items.Objects[SelectedMap]as TMapInfo;
      mi.Keys:=TStringList.Create;
      mi.Keys.AddStrings(lstProperties.Strings);
    end;
  lstCompileExit(lstCompile);
  if lstMaps.Enabled and lstMaps.Enabled then
    lstMaps.SetFocus;
  (Sender as TLabel).PopupMenu.Popup(
    frmEditor.Left + pnlLeft.left + pnlMaps.left + pnlMapsMenu.left + (Sender as TLabel).left + (frmEditor.Width-frmEditor.ClientWidth)  div 2,
    frmEditor.Top  + pnlLeft.Top  + pnlMaps.Top + pnlMapsMenu.Top  + pnlMapsMenu.Height   + (frmEditor.Height-frmEditor.ClientHeight)-(frmEditor.Width-frmEditor.ClientWidth)div 2);
  (Sender as TLabel).Color:=ucMenubar;
end;

procedure TfrmEditor.mnuHeaderClick(Sender: TObject);
begin
  lstCompileExit(lstCompile);
  if lstHeader.Enabled and lstHeader.Enabled then
    lstHeader.SetFocus;
  (Sender as TLabel).PopupMenu.Popup(
    frmEditor.Left + pnlLeft.left  + pnlHeader.left     + pnlHeaderMenu.left     + (Sender as TLabel).left + (frmEditor.Width-frmEditor.ClientWidth)  div 2,
    frmEditor.Top  + pnlLeft.Top   + pnlHeader.Top      + pnlHeaderMenu.Top      + pnlHeaderMenu.Height   + (frmEditor.Height-frmEditor.ClientHeight)-(frmEditor.Width-frmEditor.ClientWidth)div 2);
  (Sender as TLabel).Color:=ucMenubar;
end;

procedure TfrmEditor.mnuPropertiesClick(Sender: TObject);
begin
  lstCompileExit(lstCompile);
  if lstProperties.Enabled and lstProperties.Enabled then
    lstProperties.SetFocus;
  (Sender as TLabel).PopupMenu.Popup(
    frmEditor.Left + pnlMid.left   + pnlProperties.left + pnlPropertiesMenu.left + (Sender as TLabel).left    + (frmEditor.Width-frmEditor.ClientWidth)  div 2,
    frmEditor.Top  + pnlMid.Top    + pnlProperties.Top  + pnlPropertiesMenu.Top  + pnlPropertiesMenu.Height   + (frmEditor.Height-frmEditor.ClientHeight)-(frmEditor.Width-frmEditor.ClientWidth)div 2);
  (Sender as TLabel).Color:=ucMenubar;
end;

procedure TfrmEditor.mnuFilesClick(Sender: TObject);
begin
  lstCompileExit(lstCompile);
  if lstFiles.Enabled and lstFiles.Enabled then
    lstFiles.SetFocus;
  (Sender as TLabel).PopupMenu.Popup(
    frmEditor.Left + pnlMid.left   + pnlFiles.left      + pnlFilesMenu.left      + (Sender as TLabel).left    + (frmEditor.Width-frmEditor.ClientWidth)  div 2,
    frmEditor.Top  + pnlMid.Top    + pnlFiles.Top       + pnlFilesMenu.Top       + pnlFilesMenu.Height        + (frmEditor.Height-frmEditor.ClientHeight)-(frmEditor.Width-frmEditor.ClientWidth)div 2);
  (Sender as TLabel).Color:=ucMenubar;
end;

procedure TfrmEditor.mnuResourcesClick(Sender: TObject);
begin
  lstCompileExit(lstCompile);
  if lstResources.Enabled and lstResources.Enabled then
    lstResources.SetFocus;
  (Sender as TLabel).PopupMenu.Popup(
    frmEditor.Left + pnlRight.left + pnlResources.left  + pnlResourcesMenu.left  + (Sender as TLabel).left    + (frmEditor.Width-frmEditor.ClientWidth)  div 2,
    frmEditor.Top  + pnlRight.Top  + pnlResources.Top   + pnlResourcesMenu.Top   + pnlResourcesMenu.Height    + (frmEditor.Height-frmEditor.ClientHeight)-(frmEditor.Width-frmEditor.ClientWidth)div 2);
  (Sender as TLabel).Color:=ucMenubar;
end;


//Изменение размеров панелей
procedure TfrmEditor.pnlMapsResize(Sender: TObject);
begin
  pnlMapsMenu.Width:=pnlMaps.Width-16;
  lstMaps.Width:=pnlMaps.Width-16;
  lstMaps.Height:=pnlMaps.Height-48;
end;

procedure TfrmEditor.pnlHeaderResize(Sender: TObject);
begin
  pnlHeaderMenu.Width:=pnlHeader.Width-16;
  lstHeader.Width:=pnlHeader.Width-16;
  lstHeader.Height:=pnlHeader.Height-48;
  if (SelectedHeaderProperty>-1) and (lstProperties.RowCount>0) then
  begin
    cmbHeader.Left:=lstHeader.Left+lstHeader.ColWidths[0]+lstHeader.GridLineWidth;
    cmbHeader.Width:=lstHeader.ColWidths[1];
  end;
end;

procedure TfrmEditor.pnlTopResize(Sender: TObject);
begin
  pnlFilesResize(pnlFiles);
  pnlPropertiesResize(pnlFiles);
end;

procedure TfrmEditor.pnlResourcesResize(Sender: TObject);
begin
  pnlResourcesMenu.Width:=pnlResources.Width-16;
  lstResources.Width:=pnlResources.Width-16;
  lstResources.Height:=pnlResources.Height-48;
end;

procedure TfrmEditor.pnlPreviewResize(Sender: TObject);
begin
  sbPreview.Width:=pnlPreview.Width-16;
  sbPreview.Height:=pnlPreview.Height-31;
  txtPreview.Width:=pnlPreview.Width-16;
  txtPreview.Height:=pnlPreview.Height-31;
  imgPreview.Left := (sbPreview.Width - imgPreview.Width) div 2;
  imgPreview.Top := (sbPreview.Height - imgPreview.Height) div 2;
  if imgPreview.Left < 0 then
    imgPreview.Left := 0;
  if imgPreview.Top < 0 then
    imgPreview.Top := 0;
end;

procedure TfrmEditor.pnlPropertiesResize(Sender: TObject);
begin
  pnlPropertiesMenu.Width:=pnlProperties.Width-16;
  lstProperties.Width:=pnlProperties.Width-16;
  lstProperties.Height:=pnlProperties.Height-48;
  if (SelectedProperty>-1) and (lstProperties.RowCount>0) then
  begin
    cmbProperties.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    cmbProperties.Width:=lstProperties.ColWidths[1];
    cmbPropertiesTga.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    cmbPropertiesTga.Width:=lstProperties.ColWidths[1];
    lstScripts.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    lstScripts.Width:=lstProperties.ColWidths[1];
  end;
end;

procedure TfrmEditor.pnlFilesResize(Sender: TObject);
begin
  pnlFilesMenu.Width:=pnlFiles.Width-16;
  lstFiles.Width:=pnlFiles.Width-16;
  lstFiles.Height:=pnlFiles.Height-48;
end;

procedure TfrmEditor.pnlCompileResize(Sender: TObject);
begin
  lstCompile.Width:=pnlCompile.Width-16;
  lstCompile.Height:=pnlCompile.Height-32;
end;

procedure TfrmEditor.FormResize(Sender: TObject);
begin
  pnlCompile.Width:=frmEditor.ClientWidth;
  pnlCompile.Top:=frmEditor.ClientHeight-pnlCompile.Height;
  pnlFilesResize(pnlFiles);
end;

//Изменяем состояние всех элементов управления
procedure TfrmEditor.MapMenuChangeEnabled(en:Boolean);
begin
  mnuFile.Enabled:=en;
  mnuEdit.Enabled:=en;
  mnuEditAdd.Enabled:=en;
  mnuEditDelete.Enabled:=en;
  mnuFileNew.Enabled:=en;
  mnuFileOpen.Enabled:=en;
  mnuFileSaveProject.Enabled:=en;
  mnuFileSaveMapPack.Enabled:=en;    
  mnuFilePackProperties.Enabled:=en;
  mnuFileExit.Enabled:=en;
end;

procedure TfrmEditor.HeaderMenuChangeEnabled(en:Boolean);
begin
  mnuHeaderEdit.Enabled:=en;
  mnuHeaderEditAdd.Enabled:=en; 
  mnuHeaderEditAddInfo.Enabled:=en;
  mnuHeaderEditDelete.Enabled:=en;
end;

procedure TfrmEditor.FilesMenuChangeEnabled(en:Boolean);
begin
  mnuFilesEditAdd.Enabled:=en;      
  mnuFilesEditCreateFolder.Enabled:=en;
  mnuFilesEditDelete.Enabled:=en;
  mnuFilesEdit.Enabled:=en;
end;

procedure TfrmEditor.ResourcesMenuChangeEnabled(en:Boolean);
begin
  mnuResourcesEditAdd.Enabled:=en;
  mnuResourcesEditAddDir.Enabled:=en;
  mnuResourcesEditAddSubDirs.Enabled:=en; 
  mnuResourcesEditRename.Enabled:=en;
  mnuResourcesEditDelete.Enabled:=en;
  mnuResourcesEditClear.Enabled:=en;
  mnuResourcesEdit.Enabled:=en;
end;

procedure TfrmEditor.PropertiesMenuChangeEnabled(en:Boolean);
begin
  mnuPropertiesEditAdd.Enabled:=en;
  mnuPropertiesEditDelete.Enabled:=en;
  mnuPropertiesEditAdd.Enabled:=en;
end;

procedure TfrmEditor.pnlPropertiesChangeEnabled(en:Boolean);
begin
  lstProperties.Enabled:=en;
  PropertiesMenuChangeEnabled(en);
end;

procedure TfrmEditor.pnlHeaderChangeEnabled(en:Boolean);
begin
  lstHeader.Enabled:=en;
  HeaderMenuChangeEnabled(en);
end;

procedure TfrmEditor.pnlFilesChangeEnabled(en:Boolean);
begin
  lstFiles.Enabled:=en;
  FilesMenuChangeEnabled(en);
end;

procedure TfrmEditor.pnlResourcesChangeEnabled(en:Boolean);
begin
  lstResources.Enabled:=en;
  ResourcesMenuChangeEnabled(en);
end;

procedure TfrmEditor.PanelsChangeEnabled(en:Boolean);
begin
  pnlRight.Enabled:=en;
  pnlMid.Enabled:=en;
  pnlLeft.Enabled:=en;
end;

//Создаём новый документ
procedure TfrmEditor.mnuFileNewClick(Sender: TObject);
begin
  NewFile;
end;

//Сохранить
procedure TfrmEditor.mnuFileSaveProjectClick(Sender: TObject);
begin
  SaveFile;
end;

//Открыть
procedure TfrmEditor.mnuFileOpenClick(Sender: TObject);
begin
  OpenFile;
end;

//Сохраняем документ
function  TfrmEditor.SaveFile():Boolean;
var
  f: TextFile;
  i,j:integer;
  pti:PTreeNodeInfo;
  tn:TTreeNode;
  mi:TMapInfo;

  procedure WriteList(sl:TStrings);
  var
    i:integer;
  begin
    Writeln(F,sl.Count-1);      //Количество элементов
    for i:=0 to sl.Count-1 do   //Элементы
      Writeln(F,sl.Strings[i]);
  end;

begin
  dlgSaveProject.Title:=Translate('[dlgSaveProject.Title]');
  dlgSaveProject.Filter:=Translate('[dlgSaveProject.Filter]');
  dlgSaveProject.FilterIndex:=Integer(Translate('[dlgSaveProject.FilterIndex]'));
  if dlgSaveProject.Execute then
  begin
    ProjectFile:=dlgSaveProject.Files.Strings[0];
    try
      AssignFile(F, ProjectFile);
      Rewrite(F);
      Writeln(F,PackName);
      Writeln(F,PackAuthor);
      Writeln(F,PackWebSite);
      Writeln(F,PackVersion);
      Writeln(F,BoolToStr(WizardShown));
      WriteList(Languages);          //Языки
      WriteList(lstHeader.Strings);   //Ключи заголовка
      for i:=0 to lstHeader.Strings.Count do
        Writeln(F,(lstHeader.Strings.objects[i] as THeaderKeyInfo).keytype);
      Writeln(F,lstFiles.Items.Count-1);      //Количество файлов в дереве
      for i:=0 to lstFiles.Items.Count-1 do   //Элементы дерева
      begin
        tn:=lstFiles.Items[i];
        Writeln(F,tn.Text);
        pti:=tn.Data;
        if tn.Parent=nil then
          Writeln(F,-1)
        else
          Writeln(F,tn.Parent.AbsoluteIndex);
        Writeln(F,pti^.filename);
        Writeln(F,pti^.exists);
        Writeln(F,tn.ImageIndex);
      end;
      Writeln(F,lstMaps.Items.Count-1);      //Количество карт
      for i:=0 to lstMaps.Items.Count-1 do   //Карты
      begin
        Writeln(F,lstMaps.Items.Strings[i]);
        mi:=(lstMaps.Items.Objects[i] as TMapInfo);
        WriteList(mi.Keys);              //Ключи
        for j:=0 to mi.Keys.Count-1 do   //Типы ключей
        begin
          Writeln(F,mi.Types[j]);
        end;
      end;
    finally
      CloseFile(f);
    end;
  end;
end;

//Открываем документ
function TfrmEditor.OpenFile():Boolean;
var
  f: TextFile;
  i,j,c,k,p,d:integer;
  s,fn:string;
  pti:PTreeNodeInfo;
  tn:TTreeNode;
  mi:TMapInfo;
  sl:TStringList;
  tnodes:TTreeNodes;
  hki:THeaderKeyInfo;

  function ReadList():TStringList;
  var
    i:integer;
  begin
    result:=TStringList.Create;
    Readln(F,c);       //Количество элементов
    for i:=0 to c do   //Элементы
    begin
      Readln(F,s);
      result.Add(s);
    end;
  end;

begin
  dlgOpenProject.Title:=Translate('[dlgOpenProject.Title]');
  dlgOpenProject.Filter:=Translate('[dlgOpenProject.Filter]');
  dlgOpenProject.FilterIndex:=Integer(Translate('[dlgOpenProject.FilterIndex]'));
  if dlgOpenProject.Execute then
  begin
    ProjectFile:=dlgOpenProject.Files.Strings[0];
    try
      AssignFile(F, ProjectFile);
      Reset(F);
      try
        Readln(F,PackName);
        Readln(F,PackAuthor);
        Readln(F,PackWebSite);
        Readln(F,PackVersion);
        Readln(F,s);
        WizardShown:=StrToBool(s);

        Languages:=ReadList;
        lstHeader.Strings:=ReadList;
        for i:=0 to lstHeader.Strings.Count do
        begin                    
          Readln(F,c);
          hki:=THeaderKeyInfo.create(c);
          lstHeader.Strings.Objects[i]:=hki;
        end;

        tnodes:=TTreeNodes.Create(lstFiles);
        lstFiles.Items:=tnodes;
        NodeFiles:= AddRootElement(Translate('[lstFiles.RootNames.Files]'),'{files}');
        NodeMaps:= AddRootElement(Translate('[lstFiles.RootNames.Maps]'),'{maps}');
        NodeHMaps:= AddRootElement(Translate('[lstFiles.RootNames.HeightMaps]'),'{hmaps}');
        NodeIcons:= AddRootElement(Translate('[lstFiles.RootNames.LevelIcons]'),'{icons}');
        NodeTextures:= AddRootElement(Translate('[lstFiles.RootNames.TextureFiles]'),'{textures}');
        NodeLua:= AddRootElement(Translate('[lstFiles.RootNames.Scripts]'),'{scripts}');


        Readln(F,c);         //Количество файлов в дереве
        for i:=0 to c do     //Элементы дерева
        begin
          Readln(F,s);
          Readln(F,k);
          Readln(F,fn);
          Readln(F,p);
          Readln(F,d);
          if k<>-1 then
            if d=11 then
              NodeMpl:=AddFileElement(lstFiles.Items[k],s,fn,d-4)
            else
              if d=2 then
                AddDirElement(lstFiles.Items[k],s)
              else
                AddFileElement(lstFiles.Items[k],s,fn,d-4);
        end;
        Readln(F,c);                        //Количество карт
        lstMaps.Items:=TStringList.Create;
        for i:=0 to c do                    //Карты
        begin
          Readln(F,fn);
          mi:=TMapInfo.Create(ReadList);
          for j:=0 to mi.Keys.Count-1 do   //Ключи и их типы
          begin
            Readln(F,mi.Types[j]);
          end;
          lstMaps.Items.AddObject(fn,mi);
        end;
      except
        NewFile;
        raise Exception.Create('Reraise file error');
      end;
    finally
      CloseFile(f);
    end;
  end;
end;

//Создаём документ
function TfrmEditor.NewFile():Boolean;
var
  s:TStrings;
  tnodes:TTreeNodes;
  hki:THeaderKeyInfo;

begin
  //!!!!!!!!!!ВСТАВИТЬ УСЛОВИЕ СОХРАНЕНИЯ ПРОЕКТА!
                                 //Очистка старой информации

  SelectedMap:=-1;
  SelectedProperty:=-1;
  SelectedHeaderProperty:=-1;
  SelectedFileType:=-1;
  SelectedResource:=-1;
  LastRow:=-1;

  lstMaps.Clear;
  lstResources.Clear;
  lstFiles.Items.Clear;

  PackName:='New map pack';
  PackAuthor:='';
  PackWebSite:='http://w4tweaks.ucoz.ru/';
  PackVersion:='1.0';

  WizardShown:=false;

  Languages:=TStringList.Create;

  s:=TStringList.Create;         //Свойства нового списка карт
  hki:=THeaderKeyInfo.Create(0);
  s.AddObject('[english]=New map pack',hki);
  hki:=THeaderKeyInfo.Create(1);
  s.AddObject('[htmlenglish]=',hki);
  lstHeader.Strings:=s;

  if ProjectFile='' then
    Caption:=StringReplace(Translate('[frmEditor.ProjectCaption]'),'/p',lstHeader.Values['[english]'],[rfReplaceAll])
  else
    Caption:=StringReplace(StringReplace(Translate('[frmEditor.ProjectCaption]'),'/p',lstHeader.Values['[english]'],[rfReplaceAll]),'/f',ProjectFile,[rfReplaceAll]);

  lstProperties.Strings:=TStringList.Create;

  tnodes:=TTreeNodes.Create(lstFiles);
  lstFiles.Items:=tnodes;

  NodeFiles:= AddRootElement(Translate('[lstFiles.RootNames.Files]'),'{files}');
  NodeMaps:= AddRootElement(Translate('[lstFiles.RootNames.Maps]'),'{maps}');
  NodeHMaps:= AddRootElement(Translate('[lstFiles.RootNames.HeightMaps]'),'{hmaps}');
  NodeIcons:= AddRootElement(Translate('[lstFiles.RootNames.LevelIcons]'),'{icons}');
  NodeTextures:= AddRootElement(Translate('[lstFiles.RootNames.TextureFiles]'),'{textures}');
  NodeLua:= AddRootElement(Translate('[lstFiles.RootNames.Scripts]'),'{scripts}');

  NodeMpl:=AddFileElement(NodeFiles,'New map pack.mpl','(mappack)',7);

  MapMenuChangeEnabled(true);
  pnlHeaderChangeEnabled(true);
  pnlFilesChangeEnabled(true);
  pnlResourcesChangeEnabled(true);
  pnlPropertiesChangeEnabled(false);

  mnuHeaderEditDelete.Enabled:=False;
  mnuFilesEditDelete.Enabled:=False;
  mnuEditDelete.Enabled:=False;
  mnuResourcesEditDelete.Enabled:=False;
  result:=true;
end;

//Определяем, есть ли файл или папка в этой ветке
//Если есть, то возвращаем ненулевую ссылку на него

function TfrmEditor.NodeFileExists(where:TTreeNode;what:string):TTreeNode;
var
  i:integer;
  s:string;
  t:TTreeNode;
begin
  s:=LowerCase(what);
  for i:=0 to where.Count-1 do
  begin
    t:=where.Item[i];
    if t.ImageIndex>3 then
      if lowercase(t.Text)=s then
      begin
        result:=t;
        exit;
      end;
  end;
  result:=nil;
end;

function TfrmEditor.NodeDirExists(where:TTreeNode;what:string):TTreeNode;
var
  i:integer;
  s:string;
  t:TTreeNode;
begin
  s:=LowerCase(what);
  for i:=0 to where.Count-1 do
  begin
    t:=where.Item[i];
    if t.ImageIndex=2 then
      if lowercase(t.Text)=s then
      begin
        result:=t;
        exit;
      end;
  end;
  result:=nil;
end;

//Добавление элементов в список файлов
function TfrmEditor.AddRootElement(treetext,name:string):TTreeNode;
var           
  TreeNodeInfo: PTreeNodeInfo;
  tnode:TTreeNode;
begin
  tnode:=TTreeNode.Create(lstFiles.Items);
  tnode.ImageIndex:=0;
  tnode.SelectedIndex:=1;
  New(TreeNodeInfo);
  TreeNodeInfo^.filename := name+'\';
  TreeNodeInfo^.exists := 0;

  lstFiles.Items.AddNode(tnode,nil,treetext,TreeNodeInfo,naAdd);
  result:=tnode;
end;

function TfrmEditor.AddDirElement(where:TTreeNode;treetext:string):TTreeNode;
var
  TreeNodeInfo,parentni: PTreeNodeInfo;
  tnode:TTreeNode;
begin
  tnode:=TTreeNode.Create(lstFiles.Items);
  tnode.ImageIndex:=2;
  tnode.SelectedIndex:=3;
  New(TreeNodeInfo);
  parentni:=where.Data;
  TreeNodeInfo^.filename := parentni^.filename+treetext+'\';
  TreeNodeInfo^.exists := 1;

  lstFiles.Items.AddNode(tnode,where,treetext,TreeNodeInfo,naAddChild);
  result:=tnode;
end;

function TfrmEditor.AddFileElement(where:TTreeNode;treetext,filename:string;filetype:integer):TTreeNode;
var
  TreeNodeInfo: PTreeNodeInfo;
  tnode:TTreeNode;
begin
  tnode:=TTreeNode.Create(lstFiles.Items);
  tnode.ImageIndex:=filetype+4;
  tnode.SelectedIndex:=filetype+4;
  New(TreeNodeInfo);
  TreeNodeInfo^.filename := filename;
  if FileExists(filename) then
    TreeNodeInfo^.exists := 2
  else
    TreeNodeInfo^.exists := -1;
  lstFiles.Items.AddNode(tnode,where,treetext,TreeNodeInfo,naAddChild);
  result:=tnode;
end;

//Блокировка изменения основных ключей
procedure TfrmEditor.lstHeaderSelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
  if ARow>2 then
  begin
    CanSelect:=true;
    mnuHeaderEditDelete.Enabled:=true;
  end
  else
  begin
    if ACol>0 then
      CanSelect:=true
    else
      CanSelect:=false;
    mnuHeaderEditDelete.Enabled:=false;
  end;
end;

procedure TfrmEditor.lstPropertiesSelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
  if ARow>7 then
  begin
    CanSelect:=true;
    mnuPropertiesEditDelete.Enabled:=true;
  end
  else
  begin
    if ACol>0 then
      CanSelect:=true
    else
      CanSelect:=false;
    mnuPropertiesEditDelete.Enabled:=false;
  end;
end;

//Создание новой карты
procedure TfrmEditor.mnuEditAddClick(Sender: TObject);
var
  s:TStringList;
  mi:TMapInfo;
begin
  s:=TStringList.Create;
  s.Add('[text]=New map');
  s.Add('[image]=nolevel.tga');
  s.Add('[scripts]=stdvs,wormpot');
  s.Add('[map]=');
  s.Add('[textures]=ThemeBuilding\ThemeBuilding.txt');
  s.Add('[texture1]=C01');
  s.Add('[texture2]=C03');
  mi:=TMapInfo.Create(s);
  mi.Types[0]:=0;
  mi.Types[1]:=1;
  mi.Types[2]:=2;
  mi.Types[3]:=3;
  mi.Types[4]:=4;
  mi.Types[5]:=5;
  mi.Types[6]:=5;
  lstMaps.ItemIndex:=lstMaps.Items.AddObject('New map',mi);
  lstMapsClick(lstMaps);
  if lstMaps.Count>88 then
    mnuEditAdd.Enabled:=false;
end;

//Выбор другой карты.
//Обновляем список свойств карты.
//Сохраняем прошлые значения свойств.
procedure TfrmEditor.lstMapsClick(Sender: TObject);
var
  mi:TMapInfo;
begin
  if SelectedMap>=0 then
    if SelectedMap<lstMaps.Items.count then
    begin
      mi:=lstMaps.Items.Objects[SelectedMap]as TMapInfo;
      mi.Keys:=TStringList.Create;
      mi.Keys.AddStrings(lstProperties.Strings);
    end;
  if lstMaps.ItemIndex>-1 then
  begin
    mi:=lstMaps.Items.Objects[lstMaps.ItemIndex] as TMapInfo;
    SelectedMap:=lstMaps.ItemIndex;
    lstProperties.Strings:=mi.Keys;
    pnlPropertiesChangeEnabled(true);
    SelectedProperty:=-1;
    mnuPropertiesEditDelete.Enabled:=False;
  end;
  if SelectedMap>=0 then
    mnuEditDelete.Enabled:=true
  else
    mnuEditDelete.Enabled:=false;
  if cmbProperties.Visible then
    cmbProperties.ItemIndex:=cmbProperties.Items.IndexOf(lstProperties.Cells[1,LastRow]);
  if cmbPropertiesTga.Visible then
    cmbPropertiesTga.ItemIndex:=cmbPropertiesTga.Items.IndexOf(lstProperties.Cells[1,LastRow]);
end;

//Создать ключ в списке свойств карты
procedure TfrmEditor.mnuPropertiesEditAddClick(Sender: TObject);
var
  s:string;
  r,l:integer;
  mi:TMapInfo;
begin
  s:=InputBox(Translate('[message.NewKey.Caption]'),Translate('[message.NewKey.Promt]'),Translate('[message.NewKey.Default]') );
  if lstProperties.FindRow(s,r) then
    ShowMessage(StringReplace( Translate('[message.NewKey.Exist]'),'/k',s,[rfReplaceAll]))
  else
  begin
    SelectedProperty:=lstProperties.Strings.Add(s+'=');
    if SelectedMap>-1 then
    begin
      mi:=(lstMaps.Items.Objects[SelectedMap] as TMapInfo);
      l:=length(mi.Types);
      SetLength(mi.Types,l+1);
      mi.Types[l]:=0;
    end;
    lstProperties.Row:=SelectedProperty+1;
    if SelectedProperty>=2 then
      mnuPropertiesEditDelete.Enabled:=true
    else
      mnuPropertiesEditDelete.Enabled:=false;
  end;
end;

//Создать ключ в списке свойств пака карт
procedure TfrmEditor.mnuHeaderEditAddClick(Sender: TObject);
var
  s:string;
  r:integer;
  hki:THeaderKeyInfo;
begin
  s:=Translate('[message.NewHeaderKey.Default]');
  if InputQuery(Translate('[message.NewHeaderKey.Caption]'),Translate('[message.NewHeaderKey.Promt]'), s) then
  begin
    if s='' then
      exit;
    if lstHeader.FindRow(s,r) then
      ShowMessage(StringReplace( Translate('[message.NewHeaderKey.Exist]'),'/k',s,[rfReplaceAll]))
    else
    begin
      hki:=THeaderKeyInfo.Create(0);
      SelectedHeaderProperty:=lstHeader.Strings.AddObject(s+'=',hki);  
      lstHeader.Row:=SelectedHeaderProperty+1;
      if SelectedHeaderProperty>=2 then
        mnuHeaderEditDelete.Enabled:=true
      else
        mnuHeaderEditDelete.Enabled:=false;
    end;
  end;
end;

//Создать ключ-ссылку на файл страницы в списке свойств пака карт
procedure TfrmEditor.mnuHeaderEditAddInfoClick(Sender: TObject);
var
  s:string;
  r:integer;
  hki:THeaderKeyInfo;
begin
  s:=Translate('[message.NewHeaderLinkKey.Default]');
  if InputQuery(Translate('[message.NewHeaderLinkKey.Caption]'),Translate('[message.NewHeaderLinkKey.Promt]'), s) then
  begin
    if s='' then
      exit;
    if lstHeader.FindRow(s,r) then
      ShowMessage(StringReplace( Translate('[message.NewHeaderLinkKey.Exist]'),'/k',s,[rfReplaceAll]))
    else
    begin
      hki:=THeaderKeyInfo.Create(1);
      SelectedHeaderProperty:=lstHeader.Strings.AddObject(s+'=',hki);
      lstHeader.Row:=SelectedHeaderProperty+1;
      if SelectedHeaderProperty>=2 then
        mnuHeaderEditDelete.Enabled:=true
      else
        mnuHeaderEditDelete.Enabled:=false;
    end;
  end;
end;

//Удалить карту
procedure TfrmEditor.mnuEditDeleteClick(Sender: TObject);
begin
  if SelectedMap>=0 then
    if SelectedMap<lstMaps.Items.count then
    begin
      pnlPropertiesChangeEnabled(false);
      lstProperties.Strings.Clear;
      lstMaps.Items.Delete(SelectedMap);
      SelectedMap:=-1;
      pnlPropertiesChangeEnabled(false); 
      mnuEditAdd.Enabled:=true;
    end;
end;

//Выход
procedure TfrmEditor.mnuFileExitClick(Sender: TObject);
begin
  //ВСТАВИТЬ УСЛОВИЕ СОХРАНЕНИЯ ПРОЕКТА!
  halt;
end;

//Удаляем ключ из свойств карты
procedure TfrmEditor.mnuPropertiesEditDeleteClick(Sender: TObject);
begin
  if SelectedProperty>=7 then
    if SelectedProperty<lstProperties.Strings.count then
    begin
      lstProperties.Strings.Delete(SelectedProperty);
      SelectedProperty:=SelectedProperty-1;
      if lastrow>lstProperties.RowCount then
        lastrow:=lstProperties.RowCount;
      lstPropertiesClick(lstProperties);
      if SelectedProperty>=7 then
        mnuPropertiesEditDelete.Enabled:=true
      else
        mnuPropertiesEditDelete.Enabled:=false;
    end;
end;

//Выбор строчки в списке свойств карты  и показ соответсвующего списка значений
procedure TfrmEditor.lstPropertiesClick(Sender: TObject);
var
  mi:TMapInfo;
  alignableBox:TComboBox;

  //Заполняем список значениями из списка файлов
  procedure FillList(tr:TTreeNode;Items:TStrings;IncludeExtentions:Boolean);
  var
    s:string;    
    child:TTreeNode;
  begin
    if not tr.HasChildren then exit;
    child:=tr.getFirstChild;
    while child<>nil do
    begin
      if IncludeExtentions then
        Items.Add(child.Text)
      else
      begin
        s:=ExtractFileName(child.Text);
        Items.Add(LeftStr(s,length(s)-length(ExtractFileExt(s))));
      end;
      child:=tr.GetNextChild(child);
    end;
  end;

begin
  SelectedProperty:=lstProperties.Row-1;
  if LastRow>0 then
    lstProperties.RowHeights[LastRow]:=lstProperties.DefaultRowHeight;
  if SelectedMap>-1 then
  begin
    mi:=(lstMaps.Items.Objects[SelectedMap] as TMapInfo);
    if SelectedProperty>-1 then
    begin
      cmbProperties.Visible:=false;
      cmbPropertiesTga.Visible:=false;
      lstScripts.Visible:=false;
      cmdScripts.Visible:=false;
      if (mi.Types[SelectedProperty]=0) or (lstProperties.Col=0) then
      begin
        lstProperties.RowHeights[lstProperties.Row]:=lstProperties.DefaultRowHeight;
      end
      else
        if mi.Types[SelectedProperty]=2 then
        begin
          lstScripts.Items.Clear;
          lstScripts.Items.Add('stdvs.lua');        
          lstScripts.Items.Add('wormpot.lua');
          FillList(NodeLua,lstScripts.Items,false);
          lstProperties.RowHeights[lstProperties.Row]:=cmdScripts.Height;
          cmdScripts.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.ColWidths[1]-cmdScripts.Width+lstProperties.GridLineWidth+2;
          cmdScripts.Top:=lstProperties.Top+(lstProperties.DefaultRowHeight+lstProperties.GridLineWidth)*lstProperties.Row+1;
          lstScripts.Top:=cmdScripts.Top+cmdScripts.Height;
          lstScripts.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
          lstScripts.Width:=lstProperties.ColWidths[1];
          LastRow:=lstProperties.Row;
          cmdScripts.Visible:=true;
        end
        else
        begin
          if mi.Types[SelectedProperty]=5 then
            alignableBox:=cmbPropertiesTga
          else
            alignableBox:=cmbProperties;
          case mi.Types[SelectedProperty] of
            3:
            begin
              cmbProperties.Items.Clear;
              FillList(NodeMaps,cmbProperties.Items,false);
            end;
            1:
            begin
              cmbProperties.Items.Clear;
              cmbProperties.Items.Add('nolevel.tga');
              FillList(NodeIcons,cmbProperties.Items,true);
            end;
            4:
            begin
              cmbProperties.Items.Clear;
              cmbProperties.Items.Add('ThemeArabian\ThemeArabian.txt');
              cmbProperties.Items.Add('ThemeBuilding\ThemeBuilding.txt');
              cmbProperties.Items.Add('ThemeCamelot\ThemeCamelot.txt');
              cmbProperties.Items.Add('ThemePrehistoric\ThemePrehistoric.txt');
              cmbProperties.Items.Add('ThemeWildwest\ThemeWildwest.txt');
              FillList(NodeTextures,cmbProperties.Items,true);
            end;
          end;
          alignableBox.Top:=lstProperties.Top+(lstProperties.DefaultRowHeight+lstProperties.GridLineWidth)*lstProperties.Row;
          alignableBox.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
          alignableBox.Width:=lstProperties.ColWidths[1];
          lstProperties.RowHeights[lstProperties.Row]:=alignableBox.Height-2;
          alignableBox.Text:=lstProperties.Cells[1,lstProperties.Row];
          alignableBox.ItemIndex:=alignableBox.Items.IndexOf(lstProperties.Cells[1,lstProperties.Row]);
          alignableBox.Visible:=true;
          LastRow:=lstProperties.Row;
        end;
      end;
    end;
end;

//Удаляем ключ из свойств пака
procedure TfrmEditor.mnuHeaderEditDeleteClick(Sender: TObject);
begin
  if SelectedHeaderProperty>=2 then
    if SelectedHeaderProperty<lstHeader.Strings.count then
    begin
      lstHeader.Strings.Delete(SelectedHeaderProperty);
      SelectedHeaderProperty:=SelectedHeaderProperty-1;  
      if lastrow>lstProperties.RowCount then
        lastrow:=lstProperties.RowCount;
      lstHeaderClick(lstHeader); 
      if SelectedHeaderProperty>=2 then
        mnuHeaderEditDelete.Enabled:=true
      else
        mnuHeaderEditDelete.Enabled:=false;
    end;
end;

//Выбор строчки в списке свойств пака
procedure TfrmEditor.lstHeaderClick(Sender: TObject);
var
  hki:THeaderKeyInfo;

  procedure FillList(tr:TTreeNode;path:string);
  var
    s:string;
    child:TTreeNode;
  begin
    child:=tr.getFirstChild;
    while child<>nil do
    begin
      if child.ImageIndex<>2 then
        cmbHeader.Items.Add(path+child.Text);
      FillList(child,path+child.Text+'\');
      child:=tr.GetNextChild(child);
    end;
  end;

begin
  SelectedHeaderProperty:=lstHeader.Row-1;
  if LastHeaderRow>-1 then
    lstHeader.RowHeights[LastHeaderRow]:=lstHeader.DefaultRowHeight;
  if SelectedHeaderProperty>-1 then
  begin
    hki:=(lstHeader.Strings.Objects[SelectedHeaderProperty] as THeaderKeyInfo);
    cmbHeader.Visible:=false;
    if hki <> nil then
    begin
      if hki.keytype=1 then
      begin
        cmbHeader.Items.Clear;
        FillList(NodeFiles,'');
        cmbHeader.Top:=lstHeader.Top+(lstHeader.DefaultRowHeight+lstHeader.GridLineWidth)*lstHeader.Row;
        cmbHeader.Left:=lstHeader.Left+lstHeader.ColWidths[0]+lstHeader.GridLineWidth;
        cmbHeader.Width:=lstHeader.ColWidths[1];
        lstHeader.RowHeights[lstHeader.Row]:=cmbHeader.Height-2;
        cmbHeader.Text:=lstHeader.Cells[1,lstHeader.Row];
        cmbHeader.ItemIndex:=cmbHeader.Items.IndexOf(lstHeader.Cells[1,lstHeader.row]);
        cmbHeader.Visible:=true;
        LastHeaderRow:=lstHeader.Row;
      end;
    end;
  end;
end;

//Добавление ресурсов
procedure TfrmEditor.mnuResourcesEditAddClick(Sender: TObject);
var
  i:integer;
  fls:TStrings;
begin
  dlgResources.Title:=Translate('[dlgResources.Title]');
  dlgResources.Filter:=Translate('[dlgResources.Filter]');
  dlgResources.FilterIndex:=Integer(Translate('[dlgResources.FilterIndex]'));
  if dlgResources.InitialDir='' then
    dlgResources.InitialDir:=WormsDir;
  fls:=dlgResources.Files;
  if dlgResources.Execute then
    for i:=0 to fls.Count-1 do
      AddNewResource(fls.Strings[i]);

end;

//Добавление ресурса, если он ещё не добавлен
procedure TfrmEditor.AddNewResource(FileName:string);
label
  l;   
var
  li:TListItem;
  it:TListItems;
  i:integer;
begin                    
  it:=lstResources.Items;
  for i:= 0 to it.Count-1 do
    if it.Item[i].SubItems.Strings[1]=FileName then
      goto l;
  li:=it.Add;
  li.Caption:=ExtractFileName(FileName);
  li.SubItems.Add(ExtractFileDir(FileName) );
  li.SubItems.Add(FileName);
  l:
end;

//Обновление имени карты в списке
procedure TfrmEditor.lstPropertiesStringsChange(Sender: TObject);
var
  r:integer;
begin
  if SelectedMap>=0 then
    if lstProperties.FindRow('[text]',r) then
      lstMaps.Items.Strings[SelectedMap]:=lstProperties.Values['[text]'];
end;

//Обновление заголовка окна при изменении имени пака
procedure TfrmEditor.lstHeaderStringsChange(Sender: TObject);
var
  r:integer;
begin
  if lstHeader.FindRow('[english]',r) then
  begin
    if NodeMpl<>nil then
      NodeMpl.Text:=lstHeader.Values['[english]']+'.mpl';
    if ProjectFile='' then
      Caption:=StringReplace(Translate('[frmEditor.ProjectCaption]'),'/p',lstHeader.Values['[english]'],[rfReplaceAll])
    else
      Caption:=StringReplace(StringReplace(Translate('[frmEditor.ProjectCaption]'),'/p',lstHeader.Values['[english]'],[rfReplaceAll]),'/f',ProjectFile,[rfReplaceAll]);
  end;
end;

//Оконная процедура для выбора папки
function ProcFolder(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): Integer; stdcall;
var
  TempPath: array[0..MAX_PATH] of Char;
begin
  Result := 0;
  if uMsg = BFFM_SELCHANGED then
  begin
    SHGetPathFromIDList(PItemIDList(lParam), TempPath);
    SendMessage(hwnd, BFFM_ENABLEOK, 0, 1) // Кнопку OK доступна
  end;        
  if uMsg = BFFM_INITIALIZED then
  begin
    SendMessage(hwnd, BFFM_SETSELECTION, 1, Longint(PChar(LastDir)))
  end;
end;

//Окно выбора папки
function TfrmEditor.SelectDirectory(const Caption: string; const Root: WideString; out Directory: string): Boolean;
var
  BrowseInfo: TBrowseInfo;
  Buffer: PChar;
  RootItemIDList, ItemIDList: PItemIDList;
  ShellMalloc: IMalloc;
  IDesktopFolder: IShellFolder;
  Eaten, Flags: Longword;
begin
  Directory:='';
  Result := false;
  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
    Buffer := ShellMalloc.Alloc(MAX_PATH);
    try
      RootItemIDList := nil;
      if Root <> '' then
      begin
        SHGetDesktopFolder(IDesktopFolder);
        IDesktopFolder.ParseDisplayName(0, nil,
          POleStr(Root), Eaten, RootItemIDList, Flags);
      end;
      with BrowseInfo do
      begin
        hwndOwner := 0;
        pidlRoot := RootItemIDList;
        pszDisplayName := Buffer;
        lpszTitle := PChar(Caption);
        ulFlags := BIF_RETURNONLYFSDIRS;
        lpfn := @ProcFolder;
      end;

      try
        ItemIDList := ShBrowseForFolder(BrowseInfo);
      finally
      end;
      Result := ItemIDList <> nil;
      if Result then
      begin
        ShGetPathFromIDList(ItemIDList, Buffer);
        ShellMalloc.Free(ItemIDList);
        Directory := Buffer;
      end;
    finally
      ShellMalloc.Free(Buffer);
    end;
  end;
end;

//Добавление папки в список ресурсов
procedure TfrmEditor.AddFolder(Folder:String;SubFolders:Boolean);
var
  SearchRec: TSearchRec;
  s:string;
  c:integer;
begin
  if length(Folder)>0 then
  begin
    if RightStr(Folder,1)<>'\' then
      Folder:=Folder+'\';
    if FindFirst(Folder+'*', faAnyFile, SearchRec)=0 then
    begin
      c:=1;
      s:=Folder+SearchRec.Name;
      if FileExists(s) then
        AddNewResource(s);
      if SubFolders then
        if DirectoryExists(s) then
          if rightstr(s,2)<>'\.' then
            AddFolder(s,true);
      while FindNext(SearchRec)=0 do
      begin
        c:=c+1;
        if c mod 10=0 then
        begin
           Application.ProcessMessages;
           c:=0;
        end;
        s:=Folder+SearchRec.Name;
        if FileExists(s) then
          AddNewResource(s);
        if SubFolders then
          if DirectoryExists(s) then  
            if rightstr(s,3)<>'\..' then
              AddFolder(s,true);
      end;
      FindClose(SearchRec);
    end
    else
      FindClose(SearchRec);
  end;
end;

//Добавить папку в список ресурсов
procedure TfrmEditor.mnuResourcesEditAddDirClick(Sender: TObject);
var
  Dir:string;
begin
  if SelectDirectory(Translate('[dlgResourcesDir.Title]'),'',Dir ) then
  begin
    if DirectoryExists(dir) then
    begin
      if RightStr(Dir,1)<>'\' then
        Dir:=Dir+'\';
      LastDir:=Dir;
      PanelsChangeEnabled(false);
      AddFolder(dir,false);
      PanelsChangeEnabled(true);
    end;
  end;
end;
    
//Добавить папку и все её подпапки в список ресурсов
procedure TfrmEditor.mnuResourcesEditAddSubDirsClick(Sender: TObject);
var
  Dir:string;
begin
  if SelectDirectory(Translate('[dlgResourcesDir.Title]'),'',Dir ) then
  begin
    if DirectoryExists(dir) then
    begin    
      if RightStr(Dir,1)<>'\' then
        Dir:=Dir+'\';
      LastDir:=Dir;
      PanelsChangeEnabled(false);
      AddFolder(dir,true);
      PanelsChangeEnabled(true);
    end;
  end;
end;

//Генерируем скрипт для W4MapPackLauncher, iss-скрипт установки и компилируем его
procedure TfrmEditor.mnuFileSaveMapPackClick(Sender: TObject);
var
  s,ob,cb:TStringList;
  TreeNodeInfo:PTreeNodeInfo;
  f:string;
  i:integer;
  fs:TFileStream;

  procedure MakeDirs(tr:TTreeNode;path:string);
  var
    child:TTreeNode;
  begin
    child:=tr.getFirstChild;
    while child<>nil do
    begin
      if child.ImageIndex=2 then
        s.Add('          CreateSubDir('''+child.text+'\'','''+ path +''');');;
      MakeDirs(child,path+child.Text+'\');
      child:=tr.GetNextChild(child);
    end;
  end;

  procedure CopyToWorms(tr:TTreeNode;path:string);
  var
    child:TTreeNode;
  begin
    child:=tr.getFirstChild;
    while child<>nil do
    begin
      s.Add('          CopyToWorms('''+inttostr(child.AbsoluteIndex)+'.tmp'','''+ path +''','''+child.Text +''');');;
      child:=tr.GetNextChild(child);
    end;
  end;

  procedure CopyToLauncher(tr:TTreeNode;path:string);
  var
    child:TTreeNode;
  begin
    child:=tr.getFirstChild;
    while child<>nil do
    begin
      if child.ImageIndex<>2 then
        s.Add('          CopyToMaplists('''+inttostr(child.AbsoluteIndex)+'.tmp'','''+ path +''','''+child.Text +''');');;
      CopyToLauncher(child,path+child.Text+'\');
      child:=tr.GetNextChild(child);
    end;
  end;

begin
  //!!!!!!!!!!!!!Вставить сохранение проекта!!!!!
  if not WizardShown then
    if not ShowWizard then
      exit;
  dlgSaveMapPack.Title:=Translate('[dlgSaveMapPack.Title]');
  dlgSaveMapPack.Filter:=Translate('[dlgSaveMapPack.Filter]');
  dlgSaveMapPack.FilterIndex:=Integer(Translate('[dlgSaveMapPack.FilterIndex]'));
  if dlgSaveMapPack.Execute then
  begin

    f:=dlgSaveMapPack.Files.Strings[0];
    //Генерация списка карт (*.mpl файла)
    fs:=TFileStream.Create(AppDir+ 'iscc/maplists/'+lstHeader.Values['[english]']+'.mpl',fmCreate);
    lstHeader.Strings.SaveToStream(fs);
    ob:=TStringList.Create;
    cb:=TStringList.Create;
    ob.Add('{');
    cb.Add('}');
    for i:=0 to lstMaps.Count-1 do
    begin
      ob.SaveToStream(fs);
      (lstMaps.items.objects[i] as TMapInfo).Keys.SaveToStream(fs);
      cb.SaveToStream(fs);
    end;
    fs.Destroy;

    //Генерация скрипта установки
    s:=TStringList.create;
    with s do
    begin
      Add('[Setup]');
      Add('AppName='+PackName);
      Add('AppVerName='+PackName+' '+ PackVersion);
      Add('AppPublisher='+PackAuthor);
      Add('AppPublisherURL='+PackWebSite);
      Add('AppSupportURL='+PackWebSite);
      Add('AppUpdatesURL='+PackWebSite);
      Add('DisableDirPage=yes');
      Add('DisableProgramGroupPage=yes');
      Add('DefaultDirName={pf}\W4MapPackLauncher\installed\'+PackName);
      Add('DefaultGroupName=W4MapPackLauncher\Maplists\'+PackName);
      Add('OutputDir='+ExtractFileDir(f));
      f:=ExtractFileName(f);
      Add('OutputBaseFilename='+LeftStr(f,length(f)-length(ExtractFileExt(f))));
      Add('SetupIconFile='+AppDir+'iscc\setup.ico');
      Add('Compression=lzma');
      Add('SolidCompression=yes');
      Add('');
      Add('[Languages]');
      for i:=0 to Languages.Count-1 do
        Add('Name: "'+Languages.Strings[i]+'"; MessagesFile: "compiler:Languages\'+Languages.Strings[i]+'.isl"');
      Add('Name: "english"; MessagesFile: "compiler:Default.isl"');
              
      Add('');
      Add('[CustomMessages]');
      Add('CopyingFiles = Copying files to Worms 4 Mayhem directory');
      Add('CopyingFilesLong = All needed files will be copyed to Worms 4 Mayhem directory and to W4MapPackLauncher.');
      Add('Backup = Select files to copy and backup');
      Add('BackupLong = If you have some changed files, you should select to replace these files with standart files. You can also backup them');
      Add('WormsNotFound = Worms 4 Mayhem not found');
      Add('LauncherNotFound = W4MapPackLauncher not found. Visit http://w4tweaks.ucoz.ru/index/0-6');
      Add('Progress = Copying file');
      if Languages.IndexOf('russian')> 0 then
      begin
        Add('russian.CopyingFiles = Копирование файлов в папку Worms 4 Mayhem');
        Add('russian.CopyingFilesLong = Все нужные файлы будут скопированы в папку Worms 4 Mayhem и в W4MapPackLauncher.');
        Add('russian.Backup = Выберите файлы, которые необходима заменить и сохранить');
        Add('russian.BackupLong = Если некотрые файлы были изменены, то вам следует заменить их стандартными для поддержки нормальной онлайн игры. Также вы можете сохранить старые файлы.');
        Add('russian.WormsNotFound = Не найдена игра Worms 4 Mayhem');
        Add('russian.LauncherNotFound = Не найдено приложение W4MapPackLauncher. Посетите сайт http://w4tweaks.ucoz.ru/, чтобы узнать больше');
        Add('russian.Progress = Копируется файл');
      end;

      Add('');
      Add('[Icons]');
      Add('Name: "{group}\{cm:ProgramOnTheWeb,'+ PackName +'}"; Filename: "'+PackWebSite+'"');
      Add('Name: "{group}\{cm:UninstallProgram,'+ PackName +'}"; Filename: "{uninstallexe}"');

      Add('');
      Add('[Files]');
      for i:=0 to lstFiles.Items.Count-1 do
      begin
        TreeNodeInfo:=lstFiles.Items[i].Data;
        if TreeNodeInfo^.exists=2 then
          Add('Source: "'+TreeNodeInfo^.filename +'"; DestName:"' + IntToStr(i) + '.tmp"; Flags: dontcopy')              //Обычный файл
        else
          if TreeNodeInfo^.exists=-1 then
            Add('Source: "'+AppDir+ 'iscc\maplists\' +lstFiles.Items[i].Text +'"; DestName:"' + IntToStr(i) + '.tmp"; Flags: dontcopy');   //Список карт
      end;

      Add('');
      Add('[UninstallDelete]');
      for i:=0 to lstFiles.Items.Count-1 do
      begin
        TreeNodeInfo:=lstFiles.Items[i].Data;
        if TreeNodeInfo^.exists=-1 then
          Add('Type: filesandordirs; Name: "{code:getLauncherDir}\maplists\' +lstFiles.Items[i].Text +'"');
      end;

      Add('');
      Add('[Code]');
      Add('var');
      Add('  CountToCopy:integer;');
      Add('  LauncherDir,WormsDir: String;');
      Add('  CopyingFiles: TOutputProgressWizardPage;');
      Add('  FilesCopyed:integer;');
                 
      Add('');
      Add('procedure InitializeWizard();');
      Add('begin');
      Add('  CopyingFiles:=CreateOutputProgressPage(ExpandConstant(''{cm:CopyingFiles}''), ExpandConstant(''{cm:CopyingFilesLong}''));');
      Add('end;');
           
      Add('');
      Add('function InitializeUninstall(): Boolean;');
      Add('begin');
      Add('  RegQueryStringValue(HKEY_LOCAL_MACHINE, ''Software\Gerich\W4MapPackLauncher'',''AppDir'', LauncherDir);');
      Add('  RegQueryStringValue(HKEY_LOCAL_MACHINE, ''Software\Gerich\W4MapPackLauncher'', ''WormsDir'', WormsDir);');
      Add('  result:=true;');
      Add('end;');

      Add('');
      Add('function getLauncherDir(Param: String): String;');
      Add('begin');
      Add('  result:=LauncherDir;');
      Add('end;');


      Add('');
      Add('procedure CopyToWorms(FileToExtract:string;Where:string;realname:string);');
      Add('var');
      Add('  Dest:string;');
      Add('begin');
      Add('  CopyingFiles.SetText(ExpandConstant(''{cm:Progress}''),FileToExtract);');
      Add('  Dest:=WormsDir+Where+realname;');
      Add('  ExtractTemporaryFile(FileToExtract);');
      Add('  if FileExists(Dest) then');
      Add('  begin');
      Add('    if not DirExists(WormsDir+Where+''backup\'') then');
      Add('      CreateDir(WormsDir+Where+''backup\'');');
      Add('    FileCopy(Dest,WormsDir+Where+''backup\''+FileToExtract,true);');
      Add('  end;');
      Add('  FileCopy(ExpandConstant(''{tmp}\'')+FileToExtract,Dest,false);');
      Add('  FilesCopyed:=FilesCopyed+1;');
      Add('  CopyingFiles.SetProgress(FilesCopyed,CountToCopy);');
      Add('end;');

      Add('');
      Add('procedure CopyToMaplists(FileToExtract:string;Where:string;realname:string);');
      Add('var');
      Add('  Dest:string;');
      Add('begin');
      Add('  CopyingFiles.SetText(ExpandConstant(''{cm:Progress}''),FileToExtract);');
      Add('  Dest:=LauncherDir+''maplists\''+Where+realname;');
      Add('  ExtractTemporaryFile(FileToExtract);');
      Add('  if FileExists(Dest) then');
      Add('  begin');
      Add('    if not DirExists(LauncherDir+''maplists\''+Where+''backup\'') then');
      Add('      CreateDir(LauncherDir+''maplists\''+Where+''backup\'');');
      Add('    FileCopy(Dest,LauncherDir+''maplists\''+Where+''backup\''+realname,true);');
      Add('  end;');
      Add('  FileCopy(ExpandConstant(''{tmp}\'')+FileToExtract,Dest,false);');
      Add('  FilesCopyed:=FilesCopyed+1;');
      Add('  CopyingFiles.SetProgress(FilesCopyed,CountToCopy);');
      Add('end;');

      Add('');
      Add('procedure CreateSubDir(dir:string;Where:string);');
      Add('begin');
      Add('  if DirExists(LauncherDir+''maplists\''+Where) then');
      Add('    CreateDir(LauncherDir+''maplists\''+Where+dir);');
      Add('end;');

      Add('');
      Add('function NextButtonClick(CurPageID: Integer): Boolean;');
      Add('begin');
      Add('  Result:=True;');
      Add('  case CurPageID of');
      Add('    wpReady:');
      Add('    begin');
      Add('      if RegQueryStringValue(HKEY_LOCAL_MACHINE, ''Software\Gerich\W4MapPackLauncher'',''AppDir'', LauncherDir) then');
      Add('      begin');
      Add('        if RegQueryStringValue(HKEY_LOCAL_MACHINE, ''Software\Gerich\W4MapPackLauncher'', ''WormsDir'', WormsDir) then');
      Add('        begin');
      Add('          if not DirExists(LauncherDir+''maplists\'') then');
      Add('            CreateDir(LauncherDir+''maplists\'')');
      Add('        end');
      Add('        else');
      Add('        begin');
      Add('          MsgBox(ExpandConstant(''{cm:WormsNotFound}''), mbInformation, MB_OK);');
      Add('          Result := False;');
      Add('          exit;');
      Add('        end;');
      Add('      end');
      Add('      else');
      Add('      begin');
      Add('        MsgBox(ExpandConstant(''{cm:LauncherNotFound}''), mbInformation, MB_OK);');
      Add('        Result := False;');
      Add('        exit;');
      Add('      end;');
      Add('      try');
      Add('        begin');
      Add('          FilesCopyed:=0;');

      Add('          CountToCopy:='+ inttostr(lstFiles.Items.Count-6) +';');

      Add('          CopyingFiles.Show;');
      MakeDirs(NodeFiles,'');
      CopyToLauncher(NodeFiles,'');
      CopyToWorms(NodeMaps,'data\maps\');
      CopyToWorms(NodeHMaps,'data\maps\');
      CopyToWorms(NodeTextures,'data\maps\');
      CopyToWorms(NodeLua,'data\scripts\');
      CopyToWorms(NodeIcons,'data\frontend\levels\');
      Add('        end;');
      Add('      finally');
      Add('        CopyingFiles.Hide;');
      Add('      end;');
      Add('    end;');
      Add('  end;');
      Add('end;');
    end;
    s.SaveToFile(AppDir+'iscc\setup.iss');
    //Начинаем компиляцию
    pnlCompile.Visible:=true;
    lstCompile.SetFocus;
    Compile(false);
  end;
end;

//Очистка консоли
procedure TfrmEditor.mnuCompileClearClick(Sender: TObject);
begin
  lstCompile.Clear;
end;

//Скрытие консоли
procedure TfrmEditor.lstCompileExit(Sender: TObject);
begin
  pnlCompile.Visible:=false;
end;

//Сохранение окна консоли в файл
procedure TfrmEditor.mnuCompileSaveToFileClick(Sender: TObject);
begin
  dlgCompile.Title:=Translate('[dlgCompile.Title]');
  dlgCompile.Filter:=Translate('[dlgCompile.Filter]');
  dlgCompile.FilterIndex:=Integer(Translate('[dlgCompile.FilterIndex]'));
  dlgCompile.DefaultExt:=Translate('[dlgCompile.DefaultExt]');
  if dlgCompile.Execute then
    lstCompile.Lines.SaveToFile(dlgCompile.Files.Strings[0]);
end;

//Показать консоль
procedure TfrmEditor.mnuFileShowConsoleClick(Sender: TObject);
begin
  pnlCompile.Visible:=true;
  lstCompile.SetFocus;
end;



//Типы для цветов
type
  TRGBA = record
    b, g, r, a: Byte;
  end;
  ARGBA  = array [0..1] of TRGBA;
  PARGBA = ^ARGBA;

  TRGB = record
    b, g, r: Byte;
  end;
  ARGB  = array [0..1] of TRGB;
  PARGB = ^ARGB;

//Вывод изображения на рисунок
function TfrmEditor.DrawTgaOnImage(FileName:string;Image: TImage;ScrollBox:TScrollBox; XGrid: Boolean): Boolean;
var
  b:TBitMap;
begin
  DeleteObject(Image.Picture.Bitmap.Handle);
  Image.Picture.Bitmap.Create;

  b := Image.Picture.Bitmap;
  b.canvas.Brush.Style := bsSolid;
  b.canvas.Brush.Color := clBlack;
  result:=true;
  try
    ViewTga(LoadTgaToMemory(FileName),b,true);
  except
    result:=false;
  end;
  Image.Left := (ScrollBox.Width - b.Width) div 2;
  Image.Top := (ScrollBox.Height - b.Height) div 2;
  if Image.Left < 0 then
    Image.Left := 0;
  if Image.Top < 0 then
    Image.Top := 0;
end;

//Размеры изображения в буфере
function TfrmEditor.TgaSize(bufer:Pointer): TPoint;
var
  buf:Pointer;
  TGAformat: Boolean;


  function TestByte(_p: Pointer): Boolean;
  begin
    if Byte(_p^) > 127 then
    begin
      Result := true;
    end
    else
      Result := false;
  end;

begin
  buf:=bufer;
  if buf=nil then
  begin
    Result.X := 0;
    Result.y := 0;
    exit;
  end;

  if TestByte(Pointer(Longword(Buf) + 3)) then
    Buf := Pointer(Longword(Buf) + 4)
  else
    Buf := Pointer(Longword(Buf) + 3);

  Result.X := Word(Pointer(Longword(Buf) + 1)^);
  if Result.X = 0 then
    TGAformat := true;
  if TGAformat then
    Result.X := Word(Pointer(Longword(Buf) + 9)^);
  if Result.X > 512 then
  begin
    Result.X:=0;
    Result.Y:=0;
    exit;
  end;
  Result.Y := Word(Pointer(Longword(Buf) + 3)^);
  if TGAformat then
    Result.Y := Word(Pointer(Longword(Buf) + 11)^);
  if Result.Y > 512 then
    Result.Y:=0;
end;

//Загрузка tga изображения в память
function TfrmEditor.LoadTgaToMemory(FileName:string):Pointer;
var
  iFileHandle,iFileLength:integer;
begin
  if FileExists(FileName) then
  begin
    iFileHandle := FileOpen(FileName, fmOpenRead);
    if iFileHandle > 0 then
    begin
      iFileLength := FileSeek(iFileHandle, 0, 2);
      FileSeek(iFileHandle, 0, 0);
      result := AllocMem(iFileLength + 1);
      FileRead(iFileHandle, result^, iFileLength);
      FileClose(iFileHandle);
    end;
  end
end;

//Прорисовка tga изображения
function TfrmEditor.ViewTga(bufer: Pointer; b:TBitmap; XGrid: Boolean): Boolean;
label
  f24;
var
  w, h, i, j: Integer;
  p0, p1: PARGBA;
  p2, p4: PARGB;
  Grid, tbte,tmp: Byte;
  Bgrid, Tgrid, TGAformat: Boolean;
  alfa, beta: Real;
  offsetbyte, typeimage: Integer;
  VBuf,buf: Pointer;

  function TestByte(_p: Pointer): Boolean;
  begin
    if Byte(_p^) > 127 then
    begin
      Result := true;
    end
    else
      Result := false;
  end;
begin     
  buf:=bufer;
  if buf=nil then
  begin
    result:=false;
    exit;
  end;
  if TestByte(Pointer(Longword(Buf) + 3)) then
    Buf := Pointer(Longword(Buf) + 4)
  else
    Buf := Pointer(Longword(Buf) + 3);
  TGAformat := false;

  w := Word(Pointer(Longword(Buf) + 1)^);
  if w = 0 then
    TGAformat := true;
  if TGAformat then
    w := Word(Pointer(Longword(Buf) + 9)^);
  if w > 512 then
  begin
    Result := false;
    Exit;
  end;
  b.Width := w;
  h := Word(Pointer(Longword(Buf) + 3)^);
  if TGAformat then
    h := Word(Pointer(Longword(Buf) + 11)^);
  if h > 512 then
  begin
    Result := false;
    Exit;
  end;
  b.Height := h;
  typeimage := Byte(Pointer(Longword(Buf) + 5)^);
  if TGAformat then
    typeimage := 0;
  if typeimage < 10 then
    offsetbyte := 16 + typeimage * 8
  else
  begin
    Result := false;
    Exit;
  end;
  if TestByte(Pointer(Longword(Buf) + offsetbyte)) then
    offsetbyte := offsetbyte + 2
  else 
    offsetbyte := offsetbyte + 1;
  if TGAformat then
    offsetbyte := 15;
  tbte := Byte(Pointer(Longword(Buf) + 7)^);
  if TGAformat and (Byte(Pointer(Longword(Buf) + 13)^) = 32) then 
    tbte := 2;
  if (tbte = 2) or (tbte = 4) then
  begin
    b.PixelFormat := pf32bit;
    VBuf          := Pointer(Longword(Buf) + offsetbyte);
    Bgrid         := false;
    for j := 0 to h - 1 do
    begin
      if (j mod 8 = 0) then 
        Bgrid := not Bgrid;
      Tgrid := Bgrid;
      p0 := b.scanline[h - 1 - j];
      p1 := Pointer(Longword(VBuf) + j * w * 4);
      for i := 0 to w - 1 do
      begin
        p0[i] := p1[i];
        if XGrid then
        begin
          alfa := (p1[i].a / 256);
          beta := 1 - alfa;
          if (i mod 8 = 0) then
            Bgrid := not Bgrid;
          if Bgrid then 
            grid := 192 
          else 
            grid := 255;
          p0[i].b := Round(p1[i].r * alfa + Grid * beta);
          p0[i].g := Round(p1[i].g * alfa + Grid * beta);
          p0[i].r := Round(p1[i].b * alfa + Grid * beta);
          if TGAformat then
          begin
            tmp:=p0[i].b;
            p0[i].b := p0[i].r;
            p0[i].r := tmp;
          end;
        end
        else if not TGAformat then
        begin
          p0[i].b := p1[i].r;
          p0[i].r := p1[i].b;
        end;
      end;
      Bgrid := Tgrid;
    end;
  end
  else

  begin
    b.PixelFormat := pf24bit;
    VBuf          := Pointer(Longword(Buf) + offsetbyte);
    for j := 0 to h - 1 do
    begin
      Pointer(p2) := Pointer(b.scanline[h - 1 - j]);
      p4 := Pointer(Longword(VBuf) + j * w * 3);
      for i := 0 to w - 1 do
      begin
        p2[i] := p4[i];
        if not TGAformat then
        begin
          p2[i].r := p4[i].r;
          p2[i].g := p4[i].b;
        end;
      end;
    end;
  end;

  Result := true;
end;

//Удаляем файл(ы) из ресурсов
procedure TfrmEditor.mnuResourcesEditDeleteClick(Sender: TObject);
var
  it:TListItems;
  i:integer;
begin
  it:=lstResources.Items;
  for i:=it.Count-1 downto 0 do
    if it.Item[i].Selected then
      it.Delete(i);
end;

//Очистить список ресурсов
procedure TfrmEditor.mnuResourcesEditClearClick(Sender: TObject);
begin
  lstResources.Items.Clear;
end;

//Определение типа элемента в списке файлов
procedure TfrmEditor.lstFilesClick(Sender: TObject);
var
  tn:TTreeNode;
begin
  tn:=lstFiles.Selected;
  if tn=nil then
    SelectedFileType:=-1
  else
    if tn.Parent=nil then
    begin
      SelectedFileType:=tn.Index; //Корневые элементы
      mnuFilesEditDelete.Enabled:=False;
    end
    else
      if tn.ImageIndex=2 then
      begin
        SelectedFileType:=0;                    //Папка
        mnuFilesEditDelete.Enabled:=true;
      end
      else
      begin
        SelectedFileType:=tn.ImageIndex+2;      //Файл
        if SelectedFileType=13 then
          mnuFilesEditDelete.Enabled:=false     //*.mpl файл
        else
          mnuFilesEditDelete.Enabled:=true;
      end;
  if (SelectedFileType=0) or (SelectedFileType=4) then
    mnuFilesEditCreateFolder.Enabled:=true
  else
    mnuFilesEditCreateFolder.Enabled:=false;
  if Sender = nil then
    exit;                //Если нажатие сделано "ручками", а не вызванно программно

  if (SelectedFileType=9) and not (tn =nil) then      //Предпросмотр
  begin
    txtPreview.Visible:=false;
    lblNoPreview.Visible:=false;
    sbPreview.Visible:=true;
    if not DrawTgaOnImage(PTreeNodeInfo(tn.Data)^.filename,imgPreview,sbPreview,true) then
    begin
      txtPreview.Visible:=false;
      sbPreview.Visible:=false;
      lblNoPreview.Visible:=true;
    end;
  end
  else
    if (SelectedFileType>9) and (SelectedFileType<13) and not (tn =nil) then
    begin
      sbPreview.Visible:=false;
      lblNoPreview.Visible:=false;
      txtPreview.Visible:=true;
      try
        txtPreview.Lines.LoadFromFile(PTreeNodeInfo(tn.Data)^.filename);
      except
        txtPreview.Visible:=false;
        sbPreview.Visible:=false;
        lblNoPreview.Visible:=true;
      end;
    end
    else
      begin
        txtPreview.Visible:=false;
        sbPreview.Visible:=false;
        lblNoPreview.Visible:=true;
      end;

end;


//Добавление выбранных ресурсов в список устанавливаемых файлов
procedure TfrmEditor.mnuFilesEditAddClick(Sender: TObject);
var
  it:TListItems;
  li:TListItem;
  tn:TTreeNode;
  i:integer;
  ext:string;
  replacemode:integer;

  function AddWithPromt(where:TTreeNode;treetext,filename:string;filetype:integer):boolean;
  var
    t:TTreeNode;

    procedure Replace();   
    begin
      txtPreview.Visible:=false;
      sbPreview.Visible:=false;
      lblNoPreview.Visible:=true;
      t.Delete;
      AddFileElement(where,treetext,filename,filetype);
    end;

  begin
    result:=true;
    t:=NodeFileExists(where,treetext);
    if t=nil then
      AddFileElement(where,treetext,filename,filetype)
    else
    begin
      if replacemode=mrYesToAll then
        Replace
      else
        if replacemode<>mrNoToAll then
        case MessageDlg(StringReplace(Translate('[message.ReplaceFile.Caption]'),'/f',treetext,[rfReplaceAll]),mtInformation,[mbYes, mbNo, mbYesToAll, mbNoToAll],0) of
          mrYes:
            Replace;
          mrYesToAll:
          begin
            Replace;
            replacemode:=mrYesToAll;
          end;
          mrNoToAll:
            replacemode:=mrNoToAll;
        end;
    end;
  end;

begin
  replacemode:=mrYes;
  tn:=lstFiles.Selected;
  if tn<>nil then
  begin        
    it:=lstResources.Items;
    if SelectedFileType = 0 then
    begin
      for i:=0 to it.Count-1 do
      begin
        li:=it.Item[i];
        if li.Selected then
        begin
          ext:=ExtractFileExt(li.SubItems[1]);
          if (ext='.htm') or (ext='.html') then
            AddWithPromt(tn,li.Caption,li.SubItems[1] ,6)
          else
            if (ext<>'.mpl') then
              AddWithPromt(tn,li.Caption,li.SubItems[1] ,0);
        end;
      end;
    end
    else
    begin
      if SelectedFileType=1 then
        ext:='.xan';
      if SelectedFileType=2 then
        ext:='.hmp';
      if SelectedFileType=3 then
        ext:='.tga';
      if SelectedFileType=4 then
        ext:='.txt';
      if SelectedFileType=5 then
        ext:='.lua';
      for i:=0 to it.Count-1 do
      begin
        li:=it.Item[i];
        if li.Selected then
          if ExtractFileExt(li.SubItems[1])=ext then
            if SelectedFileType=5 then
            begin
              if (lowercase(li.Caption)<>'stdvs.lua') and (lowercase(li.Caption)<>'stdlib.lua') and (lowercase(li.Caption)<>'wormpot.lua') then
                AddWithPromt(tn,li.Caption,li.SubItems[1],SelectedFileType);
            end
            else
              AddWithPromt(tn,li.Caption,li.SubItems[1],SelectedFileType);
      end;
    end;
  end;
  lstHeaderClick(lstHeader);
  lstPropertiesClick(lstProperties);
end;

//Выделение файлов
procedure TfrmEditor.lstResourcesSelectItem(Sender: TObject;
  Item: TListItem; Selected: Boolean);
begin
  mnuResourcesEditDelete.Enabled:=(lstResources.SelCount>0);
  mnuResourcesEditRename.Enabled:=(lstResources.SelCount>0);
end;

//Перетаскиваем ресурсы в список файлов
procedure TfrmEditor.lstFilesDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var
  li:TTreeNode;
begin
  li:=lstFiles.GetNodeAt(X,Y);
  lstFiles.Selected:=li;
  if not (li=nil) then
  begin
    lstFilesClick(nil);
    if SelectedFileType<6 then
      Accept:=true
    else
      Accept:=false;
    if not li.Expanded then
      li.Expand(false);
  end;
end;

procedure TfrmEditor.lstResourcesStartDrag(Sender: TObject;
  var DragObject: TDragObject);
begin
  if lstResources.SelCount >1 then
    lstResources.DragCursor:=crMultiDrag
  else
    lstResources.DragCursor:=crDrag;
end;

procedure TfrmEditor.lstFilesDragDrop(Sender, Source: TObject; X,
  Y: Integer);
begin
  mnuFilesEditAddClick(mnuFilesEditAdd);
end;

//Создаём папку в списке файлов
procedure TfrmEditor.mnuFilesEditCreateFolderClick(Sender: TObject);
label
  l;
var
  s:string;
  i:integer;
  li:TTreeNode;
begin
  li:=lstFiles.Selected;
  if li=nil then
    goto l;
  s:=InputBox(Translate('[message.NewFolder.Caption]'),Translate('[message.NewFolder.Promt]'),Translate('[message.NewFolder.Default]'));
  for i:=0 to li.Count-1 do
    if LowerCase(li.Item[i].Text)=LowerCase(s) then
    begin
      ShowMessage(StringReplace( Translate('[message.NewFolder.Exist]'),'/f',s,[rfReplaceAll]));
      goto l;
    end;
  AddDirElement(li,s);
  l:
end;

//Выбрано новое значение для ключа
procedure TfrmEditor.cmbPropertiesSelect(Sender: TObject);
begin
  if (Sender as TComboBox).ItemIndex >-1 then
    lstProperties.Cells[1,LastRow]:= (Sender as TComboBox).Items.Strings[(Sender as TComboBox).ItemIndex];
end;


//Загрузка изображений для выбора текстур
procedure TfrmEditor.ChangeTexturesDir(Dir:string);
var
  s,f,num:string;
  FileBases,Letters:array[1..5] of string;
  i,j:integer;


  function FileEnding(n:integer):String;
  begin
    if n>9 then
      result:=IntToStr(n)
    else
      result:='0'+IntToStr(n);
  end;

begin
  FileBases[1]:='ThemeArabian\';
  FileBases[2]:='ThemeBuilding\';
  FileBases[3]:='ThemeCamelot\';
  FileBases[4]:='ThemePrehistoric\';
  FileBases[5]:='ThemeWildwest\';
  Letters[1]:='A';
  Letters[2]:='B';
  Letters[3]:='C';
  Letters[4]:='P';
  Letters[5]:='W';
  cmbPropertiesTga.Clear;
  for i:=1 to 5 do
  begin
    s:=TexturesDir+FileBases[i]+Letters[i];
    for j:=1 to 64 do
    begin
      num:=FileEnding(j);
      f:=s+num+'.tga';
      if FileExists(f) then
        Bufs[i,j]:=LoadTgaToMemory(f)
      else
        Bufs[i,j]:=nil;
      cmbPropertiesTga.Items.Add(Letters[i]+num);
    end;
  end;
end;

//Выбор новой папки текстур
procedure TfrmEditor.mnuPropertiesEditTexturesDirClick(Sender: TObject);
var
  Dir:string;
begin
  Dir:=TexturesDir;
  if SelectDirectory(Translate('[dlgTexturesDir.Title]'),'',Dir ) then
  begin
    if DirectoryExists(Dir) then
    begin
      if RightStr(Dir,1)<>'\' then
        Dir:=Dir+'\';
      ChangeTexturesDir(Dir);
      TexturesDir:=Dir;
    end;
  end;
end;

//Перерисовка
procedure TfrmEditor.cmbPropertiesTgaDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  b:TBitmap;
  r:TRect;
  c:TCanvas;
begin
  b:=TBitmap.Create();
  r.Left:=0;
  r.Top:=0;

  c:=(Control as TComboBox).Canvas;
  c.FillRect(Rect);
  if index=-1 then
    c.TextOut(Rect.Left + 258, Rect.Top+33, (Control as TComboBox).Items[Index])
  else
  begin

    if ViewTga(bufs[(Index div 64)+1,(Index mod 64)+1],b,true) then
	   	c.StretchDraw(Bounds(Rect.Left + 1, Rect.Top+1,64, 64),b)
    else
      c.TextOut(Rect.Left + 66, Rect.Top+33, (Control as TComboBox).Items[Index]);
	  c.TextOut(Rect.Left + 66, Rect.Top+33, (Control as TComboBox).Items[Index]);
    {$IF (DebugMode=1)}
    writeln('Drawing ' + inttostr(index));
    {$IFEND}
  end;
end;


//Запись данных в реестр
procedure TfrmEditor.FormDestroy(Sender: TObject);
var
  reg:TRegistry;
begin
  reg := TRegistry.Create;
  reg.RootKey:=HKEY_LOCAL_MACHINE;
  reg.OpenKey(regKey,true);

  reg.WriteString('AppDir',AppDir);
  reg.WriteString('TexturesDir',TexturesDir);
  reg.WriteString('LastDir',LastDir);
end;

//Блокировка изменения поля, если оно-типа ComboBox
procedure TfrmEditor.lstPropertiesStringsChanging(Sender: TObject);
var
  mi:TMapInfo;
begin
  if SelectedMap>-1 then
  begin
    mi:=(lstMaps.Items.Objects[SelectedMap] as TMapInfo);
    if SelectedProperty>-1 then
    begin
      if (mi.Types[SelectedProperty]>0) and (lstProperties.Col=1) then
      begin
        if mi.Types[SelectedProperty]=5 then
        begin
          if cmbPropertiesTga.Visible and cmbPropertiesTga.Enabled then
            cmbPropertiesTga.SetFocus;
        end
        else
          if mi.Types[SelectedProperty]=2 then
          begin
            if lstScripts.visible and lstScripts.Enabled then
              lstScripts.SetFocus;
          end
          else
            if cmbProperties.visible and cmbProperties.Enabled then
              cmbProperties.SetFocus;
      end;
    end;
  end;
end;

//Удаляем файл
procedure TfrmEditor.mnuFilesEditDeleteClick(Sender: TObject);
begin
  if lstFiles.Selected<>nil then
  begin
    lstFiles.Selected.Delete;
    lstFilesClick(lstFiles);
  end;
end;

//Показать или скрыть список скриптов в свойствах
procedure TfrmEditor.cmdScriptsClick(Sender: TObject);
begin
  lstScripts.Visible:=not lstScripts.Visible;
  if lstScripts.Visible then
    lstScripts.SetFocus
  else
    lstProperties.SetFocus;
end;

//Скрыть список скриптов
procedure TfrmEditor.lstScriptsExit(Sender: TObject);
begin
  lstScripts.Visible:=false;
  if lstProperties.Enabled and lstProperties.Visible then
    lstProperties.SetFocus;
end;

//Добавить к скриптам этоу запись
procedure TfrmEditor.lstScriptsClick(Sender: TObject);
begin
  if (Sender as TListBox).ItemIndex >-1 then
    if SelectedProperty=2 then
      if lstProperties.Cells[1,LastRow]<>'' then
        lstProperties.Cells[1,LastRow]:=lstProperties.Cells[1,LastRow] + ',' + (Sender as TListBox).Items.Strings[(Sender as TListBox).ItemIndex]
      else
        lstProperties.Cells[1,LastRow]:=(Sender as TListBox).Items.Strings[(Sender as TListBox).ItemIndex];
  lstScripts.Visible:=false;
  lstProperties.SetFocus;
end;

//Обработка стрелок
procedure TfrmEditor.lstFilesChange(Sender: TObject; Node: TTreeNode);
begin
  lstFilesClick(lstFiles);
end;

//Изменяем размеры комбобоксов
procedure TfrmEditor.lstHeaderMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if (SelectedHeaderProperty>-1) and (lstProperties.RowCount>0) then
  begin
    cmbHeader.Left:=lstHeader.Left+lstHeader.ColWidths[0]+lstHeader.GridLineWidth;
    cmbHeader.Width:=lstHeader.ColWidths[1];
  end;
end;

procedure TfrmEditor.lstPropertiesMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if (SelectedProperty>-1) and (lstProperties.RowCount>0) then
  begin
    cmbProperties.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    cmbProperties.Width:=lstProperties.ColWidths[1];
    cmbPropertiesTga.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    cmbPropertiesTga.Width:=lstProperties.ColWidths[1];
    lstScripts.Left:=lstProperties.Left+lstProperties.ColWidths[0]+lstProperties.GridLineWidth;
    lstScripts.Width:=lstProperties.ColWidths[1];
  end;
end;

//Показать окно визарда
procedure TfrmEditor.mnuFilePackPropertiesClick(Sender: TObject);
begin
   ShowWizard;
end;
                     
//Выбрано новое значение для ключа
procedure TfrmEditor.cmbHeaderSelect(Sender: TObject);
begin
  if (Sender as TComboBox).ItemIndex >-1 then
    lstHeader.Cells[1,LastHeaderRow]:= (Sender as TComboBox).Items.Strings[(Sender as TComboBox).ItemIndex];
end;

//Переименовать файл
procedure TfrmEditor.mnuResourcesEditRenameClick(Sender: TObject);
var
  s,ext:string;
begin                              
  if lstResources.Selected=nil then
    exit;
  s:=lstResources.Selected.Caption;
  ext:=ExtractFileExt(s);
  s:=LeftStr(s,length(s)-length(ExtractFileExt(s)));
  if InputQuery(Translate('[message.Rename.Caption]'),Translate('[message.Rename.Promt]'), s) then
  begin
    lstResources.Selected.Caption:=s+ext;
  end;
end;

//Блокировка изменения поля
procedure TfrmEditor.lstHeaderStringsChanging(Sender: TObject);
begin
  if cmbHeader.Visible and cmbHeader.Enabled then
    cmbHeader.SetFocus;
end;

//Показать справку
procedure TfrmEditor.mnuFileHelpClick(Sender: TObject);
begin
  if ShellExecute(0, nil, 'W4MapPackEditor.chm', nil, nil, 1) = ERROR_FILE_NOT_FOUND then
    MessageBox(Handle, PAnsiChar(Translate('[message.HelpError.Promt]')), PAnsiChar(Translate('[message.HelpError.Caption]')), MB_OK);
end;

end.




