unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, WinProcs, Graphics, Controls, Forms, Dialogs,
  DIB, StdCtrls, ExtCtrls, ComCtrls, ToolWin, Menus, Clipbrd,
  Buttons, ImgList, DXDraws, CheckLst, Spin, ExtDlgs, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP, IniFiles, Registry, ShlObj, ShellApi, GraphicUtils, WindowsUtils,
  DelphiXUtils, DXClass, Jpeg;

type
  TMain = class(TForm)
    ItemPanel: TPanel;
    Splitter2: TSplitter;
    PicturePanel: TPanel;
    MainControlBar: TControlBar;
    MainToolBar: TToolBar;
    IconImageList: TImageList;
    OpenButton: TToolButton;
    SaveButton: TToolButton;
    OpenDialog: TOpenDialog;
    SaveDialog: TSaveDialog;
    StatusBar: TStatusBar;
    ImageBar: TToolBar;
    ImageDel: TToolButton;
    ImageDown: TToolButton;
    ImageUp: TToolButton;
    AddBMP: TToolButton;
    sep1: TToolButton;
    sep7: TToolButton;
    Info: TToolButton;
    sep8: TToolButton;
    OpenPictureDialog: TOpenPictureDialog;
    New: TToolButton;
    sep2: TToolButton;
    ToolButton2: TToolButton;
    ExitApp: TToolButton;
    ImageListBox: TListBox;
    AddBitmapClip: TToolButton;
    ToolButton3: TToolButton;
    CopyToClip: TToolButton;
    ColorDialog: TColorDialog;
    PopupMenu1: TPopupMenu;
    Normal: TMenuItem;
    Center: TMenuItem;
    Fit: TMenuItem;
    DWidth: TMenuItem;
    DHeight: TMenuItem;
    Stretch: TMenuItem;
    Panel2: TPanel;
    PropBar: TToolBar;
    SysMem: TToolButton;
    sep5: TToolButton;
    Trans: TToolButton;
    ColorPanel: TPanel;
    GetTrans: TToolButton;
    sep4: TToolButton;
    FitImage: TToolButton;
    ToolButton1: TToolButton;
    Name: TEdit;
    UpdateName: TToolButton;
    Unique: TToolButton;
    Panel1: TPanel;
    PatBar: TToolBar;
    PatLabel: TPanel;
    PatWidthEdit: TSpinEdit;
    PatHeightEdit: TSpinEdit;
    ShowPat: TToolButton;
    Update: TToolButton;
    ToolButton6: TToolButton;
    PopupMenu2: TPopupMenu;
    Delete1: TMenuItem;
    N2: TMenuItem;
    Selectall1: TMenuItem;
    PopupMenu3: TPopupMenu;
    Exportbyname1: TMenuItem;
    Exportbyindex1: TMenuItem;
    Promptforfilename1: TMenuItem;
    ShowSkip: TToolButton;
    SkipBar: TToolBar;
    SkipLabel: TPanel;
    SkipWidthEdit: TSpinEdit;
    SkipHeightEdit: TSpinEdit;
    SavePictureDialog: TSavePictureDialog;
    AppendButton: TToolButton;
    DXImageList: TDXImageList;
    Http: TIdHTTP;
    N1: TMenuItem;
    Showitemindex: TMenuItem;
    UniqueBar: TToolBar;
    NameLabel: TPanel;
    Separator: TEdit;
    MakeNames: TToolButton;
    DXTimer1: TDXTimer;
    ToolBarAnimation: TToolBar;
    Play: TToolButton;
    FramePosition: TTrackBar;
    Speed: TSpinEdit;
    Panel3: TPanel;
    LabelPos: TPanel;
    Panel4: TPanel;
    FromFrame: TSpinEdit;
    Panel5: TPanel;
    ToFrame: TSpinEdit;
    DummyDXDraw: TDXDraw;
    Animation: TToolButton;
    ToolButton5: TToolButton;
    N200: TMenuItem;
    N300: TMenuItem;
    ScrollBox1: TScrollBox;
    N500: TMenuItem;
    N50: TMenuItem;
    N25: TMenuItem;
    Help: TToolButton;
    Showpatternindex: TMenuItem;
    Showpatterncrosses: TMenuItem;
    PanelPatternCount: TPanel;
    UpdatePreview: TToolButton;
    ToolButton4: TToolButton;
    Fitbigger: TMenuItem;
    Image: TImage;
    procedure OpenButtonClick(Sender: TObject);
    procedure ImageListBoxClick(Sender: TObject);
    procedure AddBMPClick(Sender: TObject);
    procedure SysMemClick(Sender: TObject);
    procedure TransClick(Sender: TObject);
    procedure SaveButtonClick(Sender: TObject);
    procedure NewClick(Sender: TObject);
    procedure UpdateNameClick(Sender: TObject);
    procedure GetTransClick(Sender: TObject);
    procedure ImageDownClick(Sender: TObject);
    procedure ImageDelClick(Sender: TObject);
    procedure ImageUpClick(Sender: TObject);
    procedure PatWidthEditChange(Sender: TObject);
    procedure PatHeightEditChange(Sender: TObject);
    procedure SkipWidthEditChange(Sender: TObject);
    procedure SkipHeightEditChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure InfoClick(Sender: TObject);
    procedure ExitAppClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ColorPanelClick(Sender: TObject);
    procedure DisplayImageClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure ShowPatClick(Sender: TObject);
    procedure CopyToClipClick(Sender: TObject);
    procedure ImageListBoxMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Promptforfilename1Click(Sender: TObject);
    procedure ShowSkipClick(Sender: TObject);
    procedure AddBitmapClipClick(Sender: TObject);
    procedure UniqueClick(Sender: TObject);
    procedure Exportbyindex1Click(Sender: TObject);
    procedure Exportbyname1Click(Sender: TObject);
    procedure AppendButtonClick(Sender: TObject);
    procedure UpdateClick(Sender: TObject);
    procedure ImageListBoxDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure ImageListBoxKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ShowitemindexClick(Sender: TObject);
    procedure Selectall1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure MakeNamesClick(Sender: TObject);
    procedure PlayClick(Sender: TObject);
    procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
    procedure FramePositionChange(Sender: TObject);
    procedure FromFrameChange(Sender: TObject);
    procedure ToFrameChange(Sender: TObject);
    procedure SpeedChange(Sender: TObject);
    procedure AnimationClick(Sender: TObject);
    procedure ScrollBox1MouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure HelpClick(Sender: TObject);
    procedure ShowpatternindexClick(Sender: TObject);
    procedure ShowpatterncrossesClick(Sender: TObject);
    procedure Image2MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure UpdatePreviewClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
 private
    Modified: Boolean;
    ShiftDown: Boolean;
    function OpenErrorDlg(s: String): TModalResult;
    function SaveErrorDlg(s: String; Confirmation: Boolean): TModalResult;
    procedure PaintImage;
    procedure UpdateImageListBox;
    procedure DrawPattern(ImageNo, PatternNo: Integer);
//    procedure CMDialogKey(var Msg: TCMDialogKey); message CM_DIALOGKEY;
//    procedure CMMouseWheel(var Msg: TCMMouseWheel); message CM_MOUSEWHEEL;
  public
    { Public declarations }
  end;

const
  README = 'Readme.txt';
  CrLf = #10#13;
  LocalUpdateFile = 'dxdevs.ini';
  UpdateUrl = 'http://www.wummy-online.de/files/' + LocalUpdateFile;
  AppTitle = 'DxgEdit 1.0';
  PatternCountText = 'PatternCount: %d';
  StatusBarText1 = 'Index: %d - Count: %d';
  FileText = 'File: ';

var
  Main: TMain;
  FontSize: Integer = 8;
  CrossSize: Integer = 5;
  ListBoxIconSpacer: Integer = 0;
  ListBoxTextSpacer: Integer = 4;
  Pos: Integer = 0;

implementation

{$R *.DFM}

procedure TMain.OpenButtonClick(Sender: TObject);
begin
  if OpenDialog.Execute then
  begin
    DXImageList.Items.Clear;
    try
      DXImageList.Items.LoadFromFile(OpenDialog.Filename);
    except
      OpenErrorDlg(OpenDialog.Filename);
      Exit;
    end;
    UpdateImageListBox;
    PaintImage;
    Caption := AppTitle + ' - ' + ExtractFileName(OpenDialog.Filename);
    Application.Title := Caption;
    StatusBar.Panels[1].Text := FileText + OpenDialog.Filename;
    Modified := false;
    if DXImageList.Items.Count > 0 then ImageListBox.Selected[0] := true;
    ImageListBoxClick(nil);
  end;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

procedure TMain.ImageListBoxClick(Sender: TObject);
var i,p: integer;
    Item: TPictureCollectionItem;
begin
  if ImageListBox.Itemindex = - 1 then exit;
  i := ImageListBox.Itemindex;
  Item := DXImageList.Items[i];
  ColorPanel.Color := Item.TransparentColor;
  SysMem.Down := Item.SystemMemory;
  Trans.Down := Item.Transparent;
  Name.Text := Item.Name;
  SkipWidthEdit.Value := Item.SkipWidth;
  SkipHeightEdit.Value := Item.SkipHeight;
  PatWidthEdit.Value := Item.PatternWidth;
  PatHeightEdit.Value := Item.PatternHeight;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
  try
    ToFrame.MaxValue := Item.PatternCount - 1;
    ToFrame.Value := Item.PatternCount - 1;
  except
    ToFrame.MaxValue := 0;
    ToFrame.Value := 0;
  end;
  FramePosition.Min := FromFrame.Value;
  FramePosition.Max := ToFrame.Value;
  FramePosition.Position := FramePosition.Min;
  try
    p := Item.PatternCount;
  except
    p := 0;
  end;
  PanelPatternCount.Caption := Format(PatternCountText, [p]);
  PaintImage;
end;

procedure TMain.AddBMPClick(Sender: TObject);
var i, j: integer;
    s: String;
    AlreadyExists: TStringList;
begin
  if OpenPictureDialog.Execute then begin
    AlreadyExists := TStringList.Create;
    for j := 0 to OpenPictureDialog.Files.Count - 1 do begin
      i := DXImageList.Items.Add.Index;
      try
        DXImageList.Items[i].Picture.LoadFromFile(OpenPictureDialog.Files[j]);
      except;
        OpenErrorDlg(OpenPictureDialog.Files[j]);
        Exit;
      end;

      s := ExtractFileName(ChangeFileExt(OpenPictureDialog.Files[j], EmptyStr));
      try
        if Assigned(DXImageList.Items.Find(s)) then AlreadyExists.AddObject(IntToStr(i), DXImageList.Items[i]);
      except end;
      DXImageList.Items[i].Name := s;
      DXImageList.Items[i].SystemMemory := SysMem.Down;
      DXImageList.Items[i].Transparent := Trans.Down;
      DXImageList.Items[i].TransparentColor := ColorPanel.Color;
      DXImageList.Items[i].Restore;
    end;
    if AlreadyExists.Count > 0 then
      if MessageDlgEng(Format('%d name(s) already exists. Automatically rename them to [Name]' + Separator.Text + '[Index]?', [AlreadyExists.Count]),
        mtInformation, [mbYes, mbNo], 0) = mrYes then
          for i := 0 to AlreadyExists.Count - 1 do
            TPictureCollectionItem(AlreadyExists.Objects[i]).Name := TPictureCollectionItem(AlreadyExists.Objects[i]).Name + Separator.Text + AlreadyExists[i];
    UpdateImageListBox;
    AlreadyExists.Free;
  end;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

procedure TMain.SysMemClick(Sender: TObject);
var i: integer;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items[i].SystemMemory := SysMem.Down;
    DXImageList.Items[i].Restore;
  end;
  Modified := true;
end;

procedure TMain.TransClick(Sender: TObject);
var i: integer;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items[i].Transparent := Trans.Down;
    DXImageList.Items[i].Restore;
    Modified := true;
  end;
end;

procedure TMain.SaveButtonClick(Sender: TObject);
begin
  if SaveDialog.Execute then
  begin
    try
      DXImageList.Items.SaveToFile(SaveDialog.Filename);
    except
      SaveErrorDlg(SaveDialog.Filename, false);
      Exit;
    end;
    Caption := AppTitle + ' - ' + ExtractFileName(SaveDialog.Filename); 
    Application.Title := Caption;
    StatusBar.Panels[1].Text := FileText + SaveDialog.Filename;
    Modified := false;
  end;
end;

procedure TMain.NewClick(Sender: TObject);
begin
  if Modified and (DXImageList.Items.Count > 0) then
    if MessageDlgEng('File modified. Do you really want to loose changes?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then Exit;
  ImageListBox.Items.Clear;
  DXImageList.Items.Clear;
  Image.Canvas.Brush.Color := clBtnFace;
  Image.Canvas.FillRect(Image.ClientRect);
  Caption := AppTitle;
  Application.Title := Caption;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
  StatusBar.Panels[1].Text := FileText;
  Modified := false;
end;

procedure TMain.UpdateNameClick(Sender: TObject);
var i: integer;
begin
  if (ImageListBox.Itemindex = -1) or (ImageListBox.Count = 0) then exit;
  i := ImageListBox.itemindex;
  DXImageList.Items[i].Name := Name.Text;
  DXImageList.Items[i].Restore;
  ImageListBox.Items[i] := Name.Text;
  Modified := true;
end;

procedure TMain.GetTransClick(Sender: TObject);
begin
  if ImageListBox.Count = 0 then begin
    GetTrans.Down := false;
    exit;
  end;
  if GetTrans.Down then begin
    Image.Cursor := crCross
  end
    else Image.Cursor := crDefault;
end;

procedure TMain.ImageDownClick(Sender: TObject);
var i: Integer;
begin
  if (ImageListBox.ItemIndex = -1) or (ImageListBox.Count = 0) or
     (ImageListBox.ItemIndex = ImageListBox.Count - 1) then Exit;
  i := ImageListBox.ItemIndex;
  ImageListBox.Items.Exchange(i, i + 1);
  PictureCollectionMoveItem(DXImageList.Items, i, i + 1);
  ImageListBox.Selected[i + 1] := true;
  ImageListBox.ItemIndex := i + 1;
  ImageListBox.Refresh;
  Modified := true;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

procedure TMain.ImageUpClick(Sender: TObject);
var i: Integer;
begin
  if (ImageListBox.ItemIndex = -1) or (ImageListBox.Count = 0) or
     (ImageListBox.ItemIndex = 0) then Exit;
  i := ImageListBox.ItemIndex;
  ImageListBox.Items.Exchange(i, i - 1);
  PictureCollectionMoveItem(DXImageList.Items, i, i - 1);
  ImageListBox.Selected[i - 1] := true;
  ImageListBox.ItemIndex := i - 1;
  ImageListBox.Refresh;
  Modified := true;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

procedure TMain.ImageDelClick(Sender: TObject);
var i: Integer;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items.Delete(i);
    ImageListBox.Items.Delete(i);
    PaintImage;
  end;
  Modified := true;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

procedure TMain.PatWidthEditChange(Sender: TObject);
var i,p: integer;
    Item: TPictureCollectionItem;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    Item := DXImageList.Items[i];
    Item.PatternWidth := PatWidthEdit.Value;
    Item.Restore;
    try
      p := Item.PatternCount;
    except
      p := 0;
    end;
    PanelPatternCount.Caption := Format(PatternCountText, [p]);
    Modified := true;
  end;
end;

procedure TMain.PatHeightEditChange(Sender: TObject);
var i,p: integer;
    Item: TPictureCollectionItem;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    Item := DXImageList.Items[i];
    Item.PatternHeight := PatHeightEdit.Value;
    Item.Restore;
    try
      p := Item.PatternCount
    except
      p := 0;
    end;
    PanelPatternCount.Caption := Format(PatternCountText, [p]);
    Modified := true;
  end;
end;

procedure TMain.SkipWidthEditChange(Sender: TObject);
var i: integer;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items[i].SkipWidth := SkipWidthEdit.Value;
    DXImageList.Items[i].Restore;
    Modified := true;
  end;
end;

procedure TMain.SkipHeightEditChange(Sender: TObject);
var i: integer;
begin
  if ImageListBox.Count = 0 then exit;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items[i].SkipHeight := SkipHeightEdit.Value;
    DXImageList.Items[i].Restore;
    Modified := true;
  end;
end;

procedure TMain.FormCreate(Sender: TObject);
var Reg: TRegistry;
    i: Integer;
begin
  DoubleBuffered := true;
  Caption := AppTitle;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
  StatusBar.Panels[1].Text := FileText;

  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CURRENT_USER;

  Left := (Screen.Height - Height) DIV 2;
  Top := (Screen.Width - Width) DIV 2;

  try
    if Reg.OpenKeyReadOnly('\Software\DxgEdit') then begin
      ShowItemIndex.Checked := Reg.ReadBool('ShowItemIndex');
      ToolBarAnimation.Visible := Reg.ReadBool('ShowAnimationBar');
      Animation.Down := ToolBarAnimation.Visible;
      UniqueBar.Visible := Reg.ReadBool('ShowUniqueNamesBar');
      Unique.Down := UniqueBar.Visible;
      PatBar.Visible := Reg.ReadBool('ShowPatternBar');
      ShowPat.Down := PatBar.Visible;
      SkipBar.Visible := Reg.ReadBool('ShowSkipBar');
      ShowSkip.Down := SkipBar.Visible;
      i := Reg.ReadInteger('Display');
      PopupMenu1.Items[i].Checked := true;
      PopupMenu1.Items[11].Checked := Reg.ReadBool('Center');
      Separator.Text := Reg.ReadString('Separator');
      Speed.Value := Reg.ReadInteger('Interval');
      ShowPatternIndex.Checked := Reg.ReadBool('ShowPatternIndex');
      ShowPatternCrosses.Checked := Reg.ReadBool('ShowPatternCrosses');
      CrossSize := Reg.ReadInteger('CrossSize');
      FontSize := Reg.ReadInteger('FontSize');
      Left := Reg.ReadInteger('Left');
      Top := Reg.ReadInteger('Top');
      Width  := Reg.ReadInteger('Width');
      Height := Reg.ReadInteger('Height');
      WindowState := TWindowState(Reg.ReadInteger('WindowState'));
    end;
  except
  end;

  Reg.Free;

  Image.Canvas.Brush.Color := clBtnFace;
  Image.Canvas.FillRect(Image.ClientRect);

  Modified := false;
end;

procedure TMain.Image2MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var i: integer;
begin
  if ImageListBox.Count = 0 then exit;
  GetTrans.Down := false;
  Image.Cursor := crDefault;
  for i := DXImageList.Items.Count - 1 downto 0 do begin
    if not ImageListBox.Selected[i] then Continue;
    DXImageList.Items[i].TransparentColor := ColorPanel.Color;
    DXImageList.Items[i].Restore;
    ImageListBox.Refresh;
  end;
  Modified := true;
end;

procedure TMain.InfoClick(Sender: TObject);
var Form: TForm;

  procedure SetHomepageButton (Form: TForm);
  var i: Integer;
  begin
    for i := 0 to Form.ControlCount - 1 do
      if Form.Components[i] is TButton then
         if (Form.Components[i] as TButton).Name = 'Cancel' then
           with Form.Components[i] as TButton do begin
             Caption := '&Homepage';
           end;
  end;
begin
  Form := CreateMessageDialog('DxgEdit (DelphiX Image Library Editor) Version ' + GetFileVersion(Application.ExeName) + CrLf + CrLf +
             'Copyright (C) Dominik Schindler (http://www.wummy-online.de)' + CrLf +
             'Based on Turbo''s DxgEdit (http://turbo.gamedev.net)' + CrLf + CrLf +
             'To get the latest version you can use the auto update function or' + CrLf + 'the homepage button below.', mtInformation, [mbOK, mbCancel]);
  Form.BorderIcons := [];
  SetHomepageButton (Form);
  if Form.ShowModal = mrCancel then
    ShellExecute(0, 'OPEN', 'http://www.wummy-online.de', nil, nil, SW_NORMAL);
  Form.Free;
end;

procedure TMain.ExitAppClick(Sender: TObject);
begin
  Close;
end;

procedure TMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Modified and (DXImageList.Items.Count > 0) then
    if MessageDlgEng('File probably modified. Do you really want to quit?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then Action := caNone;
end;

procedure TMain.ColorPanelClick(Sender: TObject);
var i: Integer;
begin
  if ColorDialog.Execute then begin
    ColorPanel.Color := ColorDialog.Color;
    for i := DXImageList.Items.Count - 1 downto 0 do begin
      if not ImageListBox.Selected[i] then Continue;
      DXImageList.Items[i].TransparentColor := ColorPanel.Color;
      DXImageList.Items[i].Restore;
      ImageListBox.Refresh;
    end;
  end;
  Modified := true;
end;

procedure TMain.PaintImage;
var i,p: Integer;
    Graphic: TGraphic;
    Rec: TRect;
    x, y: Integer;
    dx, dy: Single;
    Item: TPictureCollectionItem;

begin
  Image.Canvas.FillRect(Image.ClientRect);

  if (ImageListBox.ItemIndex = -1) or (ImageListBox.Count = 0) then exit;
  i := ImageListBox.ItemIndex;

  Item := DXImageList.Items[i];
  Graphic := Item.Picture.Graphic;

  ScrollBox1.AutoScroll := false;

  Image.Left := ScrollBox1.ClientRect.Left;
  Image.Top := ScrollBox1.ClientRect.Top;
  Image.Width := ScrollBox1.ClientRect.Right;
  Image.Height := ScrollBox1.ClientRect.Bottom;
  Image.Picture.Bitmap.Width := Image.Width;
  Image.Picture.Bitmap.Height := Image.Height;

  Image.Canvas.Lock;
  Image.Canvas.Brush.Color := clBtnFace;
  Image.Canvas.FillRect(Image.ClientRect);

  Rec := Rect(0, 0, Graphic.Width, Graphic.Height);

//  if Normal.Checked then begin
    // Nothing special to do...
//  end;

  dx := 1;
  dy := 1;

  if DWidth.Checked then begin
    Rec := Image.ClientRect;
    Rec.Bottom := Graphic.Height;
    try
      dx := Rec.Right / Graphic.Width;
    except
      dx := 1;
    end;
  end;

  if DHeight.Checked then begin
    Rec := Image.ClientRect;
    Rec.Right := Graphic.Width;
    try
      dy := Rec.Bottom / Graphic.Height;
    except
      dy := 1;
    end;
  end;

  if Fit.Checked then begin
    ScalePic(Graphic.Width, Graphic.Height, Image.Width, Image.Height, Rec.Right, Rec.Bottom);
    try
      dx := Rec.Right / Graphic.Width;
      dy := Rec.Bottom / Graphic.Height;
    except
      dx := 1;
      dy := 1;
    end;
  end;

  if Fitbigger.Checked then
    if (Scrollbox1.ClientWidth < Graphic.Width) or (ScrollBox1.ClientHeight < Graphic.Height) then begin
      ScalePic(Graphic.Width, Graphic.Height, Image.Width, Image.Height, Rec.Right, Rec.Bottom);
      try
        dx := Rec.Right / Graphic.Width;
        dy := Rec.Bottom / Graphic.Height;
      except
        dx := 1;
        dy := 1;
      end;
    end;

  if Stretch.Checked then begin
    Rec := Image.ClientRect;
    try
      dx := Rec.Right / Graphic.Width;
      dy := Rec.Bottom / Graphic.Height;
    except
      dx := 1;
      dy := 1;
    end;
  end;

  if N200.Checked then begin
    dx := 2;
    dy := 2;
    Rec.Right := Round(Graphic.Width * dx);
    Rec.Bottom := Round(Graphic.Height * dy);
  end;

  if N300.Checked then begin
    dx := 3;
    dy := 3;
    Rec.Right := Round(Graphic.Width * dx);
    Rec.Bottom := Round(Graphic.Height * dy);
  end;

  if N500.Checked then begin
    dx := 5;
    dy := 5;
    Rec.Right := Round(Graphic.Width * dx);
    Rec.Bottom := Round(Graphic.Height * dy);
  end;

  if N50.Checked then begin
    dx := 1 / 2;
    dy := 1 / 2;
    Rec.Right := Round(Graphic.Width * dx);
    Rec.Bottom := Round(Graphic.Height * dy);
  end;

  if N25.Checked then begin
    dx := 1 / 4;
    dy := 1 / 4;
    Rec.Right := Round(Graphic.Width * dx);
    Rec.Bottom := Round(Graphic.Height * dy);
  end;

  if (Center.Checked) and not Stretch.Checked then begin
    Rec.Left := (Image.Width - Rec.Right) DIV 2;
    Rec.Top := (Image.Height - Rec.Bottom) DIV 2;
    if Rec.Left < 0 then Rec.Left := 0;
    If Rec.Top < 0 then Rec.Top := 0;
    Rec.Right := Rec.Left + Rec.Right;
    Rec.Bottom := Rec.Top + Rec.Bottom;
  end else
    Rec := Rect(0, 0, Rec.Right, Rec.Bottom);

  Image.Width := Rec.Right;
  Image.Height := Rec.Bottom;
  Image.Picture.Bitmap.Width := Image.Width;
  Image.Picture.Bitmap.Height := Image.Height;
  //Image.Canvas.BrushCopy(Rec, Pic.Bitmap, Item.Picture.Bitmap.Canvas.ClipRect, clBtnFace);
  Image.Canvas.StretchDraw(Rec, Graphic);

  try
    p := Item.PatternCount;
  except
    p := 0;
  end;
  
  if (p > 0) and (ShowPatternIndex.Checked or ShowPatternCrosses.Checked) then
   // if {not N25.Checked and} not N50.Checked then
      if (Item.PatternWidth > 0) or (Item.PatternHeight > 0) then
        for i := 0 to p-1 do begin
          x := Rec.Left + Round(Item.PatternRects[i].Left * dx);
          y := Rec.Top + Round(Item.PatternRects[i].Top * dy);
          if ShowPatternCrosses.Checked then begin
            Image.Canvas.MoveTo(x, y);
            Image.Canvas.LineTo(x + CrossSize, y);
            Image.Canvas.MoveTo(x, y);
            Image.Canvas.LineTo(x - CrossSize, y);
            Image.Canvas.MoveTo(x, y);
            Image.Canvas.LineTo(x, y + CrossSize);
            Image.Canvas.MoveTo(x, y);
            Image.Canvas.LineTo(x, y - CrossSize);
          end;
          Image.Canvas.Font.Style := [];
          Image.Canvas.Font.Size := FontSize;
          if ShowPatternIndex.Checked then Image.Canvas.TextOut(x + 1, y + 1, IntToStr(i));
        end;

  if (Image.Width > ScrollBox1.ClientWidth) or
     (Image.Height > ScrollBox1.ClientHeight) then
     ScrollBox1.AutoScroll := true
  else
     ScrollBox1.AutoScroll := false;

  Image.Canvas.Unlock;
end;

procedure TMain.DisplayImageClick(Sender: TObject);
begin
  TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.FormResize(Sender: TObject);
begin
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.ShowPatClick(Sender: TObject);
begin
  PatBar.Visible := ShowPat.Down;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.CopyToClipClick(Sender: TObject);
var i: Integer;
    Temp: TImage;
begin
  if (ImageListBox.ItemIndex = - 1) or (ImageListBox.Count = 0) then Exit;
  i := ImageListBox.ItemIndex;
  Temp := TImage.Create(Self);
  Temp.Picture.Bitmap.Width := DXImageList.Items[i].Picture.Width;
  Temp.Picture.Bitmap.Height := DXImageList.Items[i].Picture.Height;
  with Temp.Canvas do begin
    FillRect(Temp.ClientRect);
    Draw(0, 0, DXImageList.Items[i].Picture.Graphic);
  end;
  with Clipboard do begin
    Open;
    Assign(Temp.Picture.Bitmap);
    AsText := ImageListBox.Items[ImageListBox.ItemIndex];
    Close;
  end;
  Temp.Free;
end;

procedure TMain.ImageListBoxMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var p: TPoint;
begin
  if Button = mbRight then begin
    if (ImageListBox.ItemIndex = -1) or (ImageListBox.Count = 0) then Exit;
    p.x := x;
    p.y := y;
    p := ImageListBox.ClientToScreen(p);
    PopupMenu2.Popup(p.x, p.y);
  end;
end;

procedure TMain.Promptforfilename1Click(Sender: TObject);
var i: Integer;
begin
  if ImageListBox.Count = 0 then Exit;

  for i := 0 to ImageListBox.Count - 1 do
    if ImageListBox.SelCount > 0 then begin
      if ImageListBox.Selected[i] then
        with SavePictureDialog do begin
          FileName := DXImageList.Items[i].Name + '.bmp';
          if Execute then
            try
              DXImageList.Items[i].Picture.SaveToFile(Filename)
            except
              if SaveErrorDlg(SaveDialog.Filename, true) = mrNo then Break;
            end
          else Break;
        end;
      end
    else
      with SavePictureDialog do begin
        FileName := DXImageList.Items[i].Name + '.bmp';
        if Execute then
          try
            DXImageList.Items[i].Picture.SaveToFile(Filename);
          except
            if SaveErrorDlg(Filename, true) = mrNo then Break
          end
        else Break;
    end;
end;

procedure TMain.ShowSkipClick(Sender: TObject);
begin
  SkipBar.Visible := ShowSkip.Down;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.AddBitmapClipClick(Sender: TObject);
var i: Integer;
    s: String;
begin
  with Clipboard do begin
    if HasFormat(CF_BITMAP) then begin
      i := DXImageList.Items.Add.Index;
      DXImageList.Items[i].Picture.Assign(Clipboard);
      s := Clipboard.AsText;
      if Length(s) = 0 then DXImageList.Items[i].Name := Separator.Text + IntToStr(i) else DXImageList.Items[i].Name := s;
      s := s + Separator.Text + IntToStr(i);
      DXImageList.Items[i].Transparent := Trans.Down;
      DXImageList.Items[i].TransparentColor := ColorPanel.Color;
      DXImageList.Items[i].Restore;
      ImageListBox.Items.AddObject(s, DXImageList.Items[i]);
    end else
      MessageDlgEng('No compatible image format found in clipboard.', mtInformation, [mbOk], 0);
  end;
  Modified := true;
end;

procedure TMain.UniqueClick(Sender: TObject);
begin
  UniqueBar.Visible := Unique.Down;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.UpdateImageListBox;
var i: Integer;
begin
  ImageListBox.Items.Clear;
  ImageListBox.Items.BeginUpdate;
  for i := 0 to DXImageList.Items.Count - 1 do
    ImageListBox.Items.AddObject(DXImageList.items[i].Name, DXImageList.Items[i]);
  ImageListBox.Items.EndUpdate;
  Modified := true;
end;

procedure TMain.Exportbyindex1Click(Sender: TObject);
var i: Integer;
    f, s: String;
begin
  if ImageListBox.Count = 0 then Exit;

  f := GetFolder(CSIDL_DESKTOP, EmptyStr, BIF_NEWDIALOGSTYLE or BIF_RETURNONLYFSDIRS);
  if f = EmptyStr then Exit;

  for i := 0 to ImageListBox.Count - 1 do begin
    if ImageListBox.SelCount > 0 then begin
      if ImageListBox.Selected[i] then begin
        s := IntToStr(i) + '.bmp';
        try
          DXImageList.Items[i].Picture.SaveToFile(IncludeTrailingPathDelimiter(f) + s)
        except
          if SaveErrorDlg(s, true) = mrNo then Break;
        end;
      end;
    end else begin
      s := IntToStr(i) + '.bmp';
      try
        DXImageList.Items[i].Picture.SaveToFile(IncludeTrailingPathDelimiter(f) + s)
      except
        if SaveErrorDlg(s, true) = mrNo then Break
      end
    end;
  end;
end;

procedure TMain.Exportbyname1Click(Sender: TObject);
var i: Integer;
    f, s: String;
begin
  if ImageListBox.Count = 0 then Exit;

  f := GetFolder(CSIDL_DESKTOP, EmptyStr, BIF_NEWDIALOGSTYLE or BIF_RETURNONLYFSDIRS);
  if f = EmptyStr then Exit;

  for i := 0 to ImageListBox.Count - 1 do begin
    if ImageListBox.SelCount > 0 then begin
      if ImageListBox.Selected[i] then begin
        s := DXImageList.Items[i].Name + '.bmp';
        try
          DXImageList.Items[i].Picture.SaveToFile(IncludeTrailingPathDelimiter(f) + s)
        except
          if SaveErrorDlg(s, true) = mrNo then Break;
        end;
      end;
    end else begin
      s := DXImageList.Items[i].Name + '.bmp';
      try
        DXImageList.Items[i].Picture.SaveToFile(IncludeTrailingPathDelimiter(f) + s)
      except
        if SaveErrorDlg(s, true) = mrNo then Break;
      end
    end;
  end;
end;

procedure TMain.AppendButtonClick(Sender: TObject);
var i, j: Integer;
    Temp: TDXImageList;
    AlreadyExists: TStringList;
begin
  if ImageListBox.Count = 0 then begin
    OpenButtonClick(Self);
    Exit;
  end;

  if not OpenDialog.Execute then Exit;

  Temp := TDXImageList.Create(Self);
  try
    Temp.Items.LoadFromFile(OpenDialog.FileName);
  except
    OpenErrorDlg(OpenDialog.Filename);
    Exit;
  end;

  AlreadyExists := TStringList.Create;

  for j := 0 to Temp.Items.Count - 1 do begin
    i := DXImageList.Items.Add.Index;
    try
      if Assigned(DXImageList.Items.Find(Temp.Items[j].Name)) then AlreadyExists.AddObject(IntToStr(i), DXImageList.Items[i]);
    except end;
    DXImageList.Items[i].Assign(Temp.Items[j]); 
    DXImageList.Items[i].Picture.Assign(Temp.Items[j].Picture);
    DXImageList.Items[i].Name := Temp.Items[j].Name;
    DXImageList.Items[i].PatternWidth := Temp.Items[j].PatternWidth;
    DXImageList.Items[i].PatternHeight := Temp.Items[j].PatternHeight;
    DXImageList.Items[i].SkipWidth := Temp.Items[j].SkipWidth;
    DXImageList.Items[i].SkipHeight := Temp.Items[j].SkipHeight;
    DXImageList.Items[i].SystemMemory := Temp.Items[j].SystemMemory;
    DXImageList.Items[i].Transparent := Temp.Items[j].Transparent;
    DXImageList.Items[i].TransparentColor := Temp.Items[j].TransparentColor;
    DXImageList.Items[i].Restore;
  end;

  if AlreadyExists.Count > 0 then
    if MessageDlgEng(Format('%d name(s) already exist(s). Automatically rename them to [Name]' + Separator.Text + '[Index]?', [AlreadyExists.Count]),
      mtInformation, [mbYes, mbNo], 0) = mrYes then
        for i := 0 to AlreadyExists.Count - 1 do begin
          TPictureCollectionItem(AlreadyExists.Objects[i]).Name := TPictureCollectionItem(AlreadyExists.Objects[i]).Name + Separator.Text + AlreadyExists[i];
          TPictureCollectionItem(AlreadyExists.Objects[i]).Restore;
        end;

  UpdateImageListBox;
  AlreadyExists.Free;
  Temp.Free;
  StatusBar.Panels[0].Text := Format(StatusBarText1, [ImageListBox.ItemIndex, DXImageLIst.Items.Count]);
end;

function TMain.OpenErrorDlg(s: String): TModalResult;
begin
  Result := MessageDlgEng(Format('Unable to open file "%s"!', [s]), mtInformation, [mbOk], 0);
end;

function TMain.SaveErrorDlg(s: String; Confirmation: Boolean): TModalResult;
begin
  result := mrNone;
  case Confirmation of
    false: Result := MessageDlgEng(Format('Unable to save "%s"!', [s]), mtInformation, [mbOk], 0);
    true: Result := MessageDlgEng(Format('Unable to save "%s"!' + CrLf + 'Do you want to continue?', [s]), mtConfirmation, [mbYes, mbNo], 0);
  end;
end;

procedure TMain.UpdateClick(Sender: TObject);
var s: TFileStream;
    Ini: TIniFile;
    OldVer, NewVer, Pathname, Filename, Information: String;
begin
  s := TFileStream.Create(IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + LocalUpdateFile, fmCreate);
  try
    Http.Get(UpdateUrl, s);
  except
    MessageDlgEng('Could not start internet update. Make sure that you are connected' + CrLf +
               'to the internet. If you use a proxy server please go to the homepage' + CrLf +
               'and download it from there. If problem persists try again later or' + CrLF +
               'contact the author.', mtInformation, [mbOk], 0);
    s.Free;
    Exit;
  end;
  s.Free;
  Ini := TIniFile.Create(IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + LocalUpdateFile);
  OldVer := GetFileVersion(Application.ExeName);
  NewVer := Ini.ReadString('DxgEdit', 'Version', EmptyStr);
  if NewerVersion(OldVer, NewVer) then begin
    if MessageDlgEng('Newer version found. Download now?', mtConfirmation, [mbYes, mbNo], 0) = mrNo then Exit
  end else begin
    MessageDlgEng('No update available!', mtInformation, [mbOk], 0);
    Exit;
  end;
  Pathname := IncludeTrailingPathDelimiter(Ini.ReadString('DxgEdit', 'UpdatePath', 'htp://www.wummy-online.de'));
  Filename := Ini.ReadString('DxgEdit', 'UpdateFile', 'dxgedit.exe');
  ShellExecute(0, nil, PChar(Pathname + Filename), nil, nil, SW_HIDE);
  Information := Ini.ReadString('DxgEdit', 'Information', EmptyStr);
  if Length(Information) > 0 then MessageDlgEng(Information, mtInformation, [mbOk], 0);
  Ini.Free;
end;

procedure TMain.ImageListBoxDrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
var
  Can: TCanvas;
  Graphic: TGraphic;
  Picture: TPicture;
  Item: TPictureCollectionItem;
  NewRect: TRect;
begin
  Can := (Control as TListBox).Canvas;
//  Graphic := nil;
  Item := DXImageList.Items[Index];
  if not Assigned(Item) then Exit;
  Picture := Item.Picture;
  Graphic := Item.Picture.Graphic;
  with Can do begin
    Lock;
    FillRect(Rect);
    //ScalePic(Graphic.Width, Graphic.Height, ImageListBox.ItemHeight, ImageListBox.ItemHeight, Rect.Right, Rect.Bottom);
    ScalePic(Picture.Width, Picture.Height, ImageListBox.ItemHeight, ImageListBox.ItemHeight, Rect.Right, Rect.Bottom);
    NewRect.Left := Rect.Left + (ImageListBox.ItemHeight - Rect.Right) DIV 2;
    NewRect.Top := Rect.Top + (ImageListBox.ItemHeight - Rect.Bottom) DIV 2;
    NewRect.Right := NewRect.Left + Rect.Right - ListBoxIconSpacer;
    NewRect.Bottom := NewRect.Top + Rect.Bottom - ListBoxIconSpacer;
    StretchDraw(NewRect, Picture.Graphic);
    //Font.Size := 8;
    Font.Style  := [fsBold];
    if ShowItemIndex.Checked then TextOut(Rect.Left, Rect.Top, IntToStr(Index));
    Rect.Left := Rect.Left + ImageListBox.ItemHeight + ListBoxTextSpacer;
    Font.Style := [fsBold];
    TextOut(Rect.Left, Rect.Top, (Control as TListBox).Items[Index]);
    Font.Style := [];
    TextOut(Rect.Left, Rect.Top + 16, 'W: ' + IntToStr(Graphic.Width) +
      ' - H: ' + IntToStr(Graphic.Height) + ' - Key: ' + ColorToString(DXImageList.Items[Index].TransparentColor));
    UnLock;
  end;
end;

procedure TMain.ImageListBoxKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_DELETE: ImageDelClick(Self);
  end;
//  if Key = vk_key_a and (ssShift in Shift) then CheckAllClick(Self);
end;
procedure TMain.ShowitemindexClick(Sender: TObject);
begin
  ShowItemIndex.Checked := not ShowItemIndex.Checked;
  ImageListBox.Refresh;
end;

procedure TMain.Selectall1Click(Sender: TObject);
var i: Integer;
begin
  ImageListBox.Items.BeginUpdate;
  if ImageListBox.SelCount = ImageListBox.Count then
    for i := ImageListBox.Count - 1 downto 0 do ImageListBox.Selected[i] := false
  else
    for i := ImageListBox.Count - 1 downto 0 do ImageListBox.Selected[i] := true;
  ImageListBox.Items.EndUpdate;
end;

procedure TMain.FormDestroy(Sender: TObject);
var Reg: TRegistry;
    i: Integer;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_CURRENT_USER;
  if Reg.OpenKey('\Software\DxgEdit', true) then begin
    Reg.WriteBool('ShowItemIndex', ShowItemIndex.Checked);
    Reg.WriteBool('ShowAnimationBar', ToolBarAnimation.Visible);
    Reg.WriteBool('ShowUniqueNamesBar',  UniqueBar.Visible);
    Reg.WriteBool('ShowPatternBar', PatBar.Visible);
    Reg.WriteBool('ShowSkipBar', SkipBar.Visible);
    Reg.WriteInteger('Interval', Speed.Value); 
    for i := 0 to PopupMenu1.Items.Count - 2 do
      if PopupMenu1.Items[i].Checked then Reg.WriteInteger('Display', i);
    Reg.WriteBool('Center', PopupMenu1.Items[11].Checked);
    Reg.WriteString('Separator', Separator.Text);
    Reg.WriteBool('ShowPatternIndex', ShowPatternIndex.Checked);
    Reg.WriteBool('ShowPatternCrosses', ShowPatternCrosses.Checked);
    Reg.WriteInteger('CrossSize', CrossSize);
    Reg.WriteInteger('FontSize', FontSize);
    Reg.WriteInteger('WindowState', Ord(WindowState));
    if (WindowState = wsMaximized) then begin
      Width := 732;
      Height := 500;
      Left := (Screen.Width - Width) DIV 2;
      Top := (Screen.Height - Height) DIV 2;
    end;
    Reg.WriteInteger('Left', Left);
    Reg.WriteInteger('Top', Top);
    Reg.WriteInteger('Width', Width);
    Reg.WriteInteger('Height', Height);
  end;
  Reg.Free;
end;

procedure TMain.MakeNamesClick(Sender: TObject);
var i: Integer;
begin
  if (ImageListBox.Count = 0) then Exit;

  if MessageDlgEng(Format('This will rename all names to [Name]%s[Index].' + CrLf +
                          'Do you want to continue?', [Separator.Text]), mtWarning, [mbYes, mbNo], 0) = mrNo then Exit;

  for i := 0 to ImageListBox.Count - 1 do
    DXImageList.Items[i].Name := DXImageList.Items[i].Name + Separator.Text + IntToStr(i);
  UpdateImageListBox;
end;

procedure TMain.PlayClick(Sender: TObject);
var i,p : Integer;
begin
  i := ImageListBox.ItemIndex;
  if i < 0 then Exit;

  try
    p := DXImageList.Items[i].PatternCount;
  except
    p := 0;
  end;

  if p < 2 then begin
    DXTimer1.Enabled := false;
    MessageDlgEng('There must be more than one pattern' + CrLF +
                  'to start animation!', mtInformation, [mbOk], 0);
    Play.Down := false;
    Play.ImageIndex := 7;
    Exit;
  end;

  if Play.Down then begin
    Play.ImageIndex := 97;
    SpeedChange(nil);
    DXTimer1.Enabled := true;
  end else begin
    Play.ImageIndex := 7;
    DXTimer1.Enabled := false;
    //PaintImage;
  end;
end;

procedure TMain.DXTimer1Timer(Sender: TObject; LagCount: Integer);
var i, p: Integer;
begin
  i := ImageListBox.ItemIndex;
  if i < 0 then Exit;
  try
    p := DXImageList.Items[i].PatternCount;
  except
    p := 0;
  end;
  if p < 2 then begin
    DXTimer1.Enabled := false;
    MessageDlgEng('There must be more than one pattern' + CrLF +
                  'to start animation!', mtInformation, [mbOk], 0);
    Play.Down := false;
    Play.ImageIndex := 7;
    PaintImage;
    Exit;
  end;
  DrawPattern(i, FramePosition.Position);
  if FramePosition.Position < FramePosition.Max then
    FramePosition.Position := FramePosition.Position + 1  {Round(FramePosition.Position + FramePosition.Position * 24 DIV 1000) }
  else
    FramePosition.Position := FromFrame.Value;
  LabelPos.Caption := IntToStr(FramePosition.Position);
end;

procedure TMain.DrawPattern(ImageNo, PatternNo: Integer);
var Rec: TRect;
    Item: TPictureCollectionItem;
    Pic: TPicture;
begin
  if ImageNo > DXImageList.Items.Count - 1 then Exit;
  Item := DXImageList.Items[ImageNo];
  Rec := Item.PatternRects[PatternNo];

  Image.Left := ScrollBox1.ClientRect.Left;
  Image.Top := ScrollBox1.ClientRect.Top;
  Image.Width := ScrollBox1.ClientRect.Right;
  Image.Height := ScrollBox1.ClientRect.Bottom;
  Image.Picture.Bitmap.Width := Image.Width;
  Image.Picture.Bitmap.Height := Image.Height;

  Pic := TPicture.Create;
  Pic.Bitmap.Width := Item.Picture.Width ;
  Pic.Bitmap.Height := Item.Picture.Height;
  Pic.Bitmap.Canvas.Brush.Color := clBtnFace;
  Pic.Bitmap.Canvas.FillRect(Pic.Bitmap.Canvas.ClipRect);
  Pic.Bitmap.Canvas.Draw(0, 0, Item.Picture.Graphic);

  Image.Canvas.Lock;
  Image.Canvas.Brush.Color := clBtnFace;
  Image.Canvas.FillRect(Image.ClientRect);

  Rec := Rect(ScrollBox1.ClientOrigin.X, ScrollBox1.ClientOrigin.Y, Item.PatternWidth, Item.PatternHeight);

//  if Normal.Checked then begin
    // Nothing special to do....
//  end;

  if DWidth.Checked then begin
    Rec := Image.ClientRect;
    Rec.Bottom := Item.PatternHeight;
  end;

  if DHeight.Checked then begin
    Rec := Image.ClientRect;
    Rec.Right := Item.PatternWidth;
  end;

  if Fit.Checked then
    ScalePic(Item.PatternWidth, Item.PatternHeight, Image.Width, Image.Height, Rec.Right, Rec.Bottom);

  if Fitbigger.Checked then
    if (Scrollbox1.ClientWidth < Item.PatternWidth) or (ScrollBox1.ClientHeight < Item.PatternHeight) then
      ScalePic(Item.PatternWidth, Item.PatternHeight, Image.Width, Image.Height, Rec.Right, Rec.Bottom);

  if Stretch.Checked then begin
    ScrollBox1.AutoScroll := false;
    Image.Canvas.BrushCopy(Image.ClientRect, Pic.Bitmap, Item.PatternRects[PatternNo], Item.TransparentColor);
    Exit;
  end;

  if N200.Checked then begin
    Rec.Right := Item.PatternWidth * 2;
    Rec.Bottom := Item.PatternHeight * 2;
  end;

  if N300.Checked then begin
    Rec.Right := Item.PatternWidth * 3;
    Rec.Bottom := Item.PatternHeight * 3;
  end;

  if N500.Checked then begin
    Rec.Right := Item.PatternWidth * 5;
    Rec.Bottom := Item.PatternHeight * 5;
  end;

  if N50.Checked then begin
    Rec.Right := Item.PatternWidth DIV 2;
    Rec.Bottom := Item.PatternHeight DIV 2;
  end;

  if N25.Checked then begin
    Rec.Right := Item.PatternWidth DIV 4;
    Rec.Bottom := Item.PatternHeight DIV 4;
  end;

  if Center.Checked then begin
    Rec.Left := (Image.Width - Rec.Right) DIV 2;
    Rec.Top := (Image.Height - Rec.Bottom) DIV 2;
    if Rec.Left < 0 then Rec.Left := 0;
    If Rec.Top < 0 then Rec.Top := 0;
    Rec.Right := Rec.Left + Rec.Right;
    Rec.Bottom := Rec.Top + Rec.Bottom;
  end else
    Rec := Rect(0, 0, Rec.Right, Rec.Bottom);

  Image.Width := Rec.Right;
  Image.Height := Rec.Bottom;
  Image.Picture.Bitmap.Width := Image.Width;
  Image.Picture.Bitmap.Height := Image.Height;

  if Item.Transparent then 
    Image.Canvas.BrushCopy(Rec, Pic.Bitmap, Item.PatternRects[PatternNo], Item.TransparentColor)
  else
    Image.Canvas.BrushCopy(Rec, Pic.Bitmap, Item.PatternRects[PatternNo], 0);

  if (Image.Width > ScrollBox1.ClientWidth) or
     (Image.Height > ScrollBox1.ClientHeight) then
     ScrollBox1.AutoScroll := true
  else
     ScrollBox1.AutoScroll := false;

  Image.Canvas.UnLock;
  Pic.Free;
end;

procedure TMain.FramePositionChange(Sender: TObject);
var i: Integer;
begin
  i := ImageListBox.ItemIndex;
  if i < 0 then Exit;
  DrawPattern(i, FramePosition.Position);
  LabelPos.Caption := IntToStr(FramePosition.Position);
end;

procedure TMain.FromFrameChange(Sender: TObject);
begin
  if FromFrame.Value < 0 then FromFrame.Value := 0;
  if FromFrame.Value > ToFrame.Value then FromFrame.Value := ToFrame.Value; 
  FramePosition.Min := FromFrame.Value;
  FramePosition.Position := FramePosition.Min;
end;

procedure TMain.ToFrameChange(Sender: TObject);
begin
  if ToFrame.Value < 0 then FromFrame.Value := 0;
  if ToFrame.Value < FromFrame.Value then ToFrame.Value := FromFrame.Value;
  FramePosition.Max := ToFrame.Value;
end;

procedure TMain.SpeedChange(Sender: TObject);
begin
  DXTimer1.Enabled := false;
  DXTimer1.Interval := Speed.Value;
  if Play.Down then DXTimer1.Enabled := true;
end;

procedure TMain.AnimationClick(Sender: TObject);
begin
  ToolBarAnimation.Visible := Animation.Down;
  if not DXTimer1.Enabled then PaintImage; 
end;

procedure TMain.ScrollBox1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
 if ShiftDown then
   if WheelDelta < 0 then ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position + 5
     else ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position - 5
 else
   if WheelDelta < 0 then ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + 5
     else ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position - 5;
end;

procedure TMain.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if ssShift in Shift then ShiftDown := true;
  if Key = VK_F1 then HelpClick(nil);
end;

procedure TMain.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if not (ssShift in Shift) then ShiftDown := false;
end;

procedure TMain.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #1 then SelectAll1Click(nil);
  if Key = #12 then OpenButtonClick(nil);
  if Key = #19 then SaveButtonClick(nil);
end;

procedure TMain.HelpClick(Sender: TObject);
begin
  ShellExecute(0, 'OPEN', PChar(IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + Readme), nil, PChar(ExtractFileDir(Application.ExeName)), SW_NORMAL);
end;

procedure TMain.ShowpatternindexClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := not (Sender as TMenuItem).Checked;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.ShowpatterncrossesClick(Sender: TObject);
begin
  (Sender as TMenuItem).Checked := not (Sender as TMenuItem).Checked;
  if not DXTimer1.Enabled then PaintImage;
end;

procedure TMain.Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if GetTrans.Down then ColorPanel.Color := Image.Picture.Bitmap.Canvas.Pixels [x, y];
  ScrollBox1.SetFocus;
end;

procedure TMain.UpdatePreviewClick(Sender: TObject);
begin
  ImageListBoxClick(nil);
  PaintImage;
end;

procedure TMain.FormActivate(Sender: TObject);
begin
  if Paramcount > 0 then begin
    try
      DXImageList.Items.LoadFromFile(ParamStr(1));
      UpdateImageListBox;
    except
      MessageDlgEng(Format('Error opening file "%s"!' + CrLf +
                           'Make sure it is a valid DXG File.', [ParamStr(1)]), mtError, [mbOk], 0);                        
    end;
  end;
end;

end.

