{
   This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit UfrmMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ImgList, ExtCtrls, StdCtrls, UBrowserListView, FreeBitmap, FreeImage,
  ToolWin, GR32_Image, GR32_Layers, GR32, UUndoManage, FreeUtils, Menus,
  shlobj, clipbrd, TB2Item, TB2Dock, TB2Toolbar, vistaaltfixunit,
  BomeOneInstance, Udialog, Buttons, zAPIBalloon, UnViewColorBox;

const
  thisapptitle = 'nPhotoEdit (nView)';
  thisregname = 'nSeries\nView\PhotoEdit';

type
  Tcapturetype = (ctscreen, ctwindow, ctwindow2, ctiexplore, ctselect);

  PWorkImage = ^TWorkImage;
  TWorkImage = record
    idx:integer;
    bitmap:TBitmap;
    UndoManage1:TUndoManage;
    ratio:integer;
    posx,posy:single;
    centered:boolean;
    orgchanged:boolean;
  end;

  Timageprocess = procedure(var src:tbitmap) of object;

  Teffecttype = (etColor,etContrast,etRotate,etMosaic,
        etLayer,etResize,etAlbum,etfilter,etshadow,etspecial,etfont,etdraw);

  TfrmMain = class(TForm)
    ImgView321: TImgView32;
    PopupMenu1: TPopupMenu;
    mnuUndo: TMenuItem;
    ImageList1: TImageList;
    pmimgview: TPopupMenu;
    N3: TMenuItem;
    N4: TMenuItem;
    TBToolbar1: TTBToolbar;
    TBSubmenuItem1: TTBSubmenuItem;
    TBSubmenuItem3: TTBSubmenuItem;
    TBSubmenuItem2: TTBSubmenuItem;
    bsSkinSplitter2: TSplitter;
    bsSkinSplitter1: TSplitter;
    TBToolbar2: TTBToolbar;
    TBItem3: TTBItem;
    TBItem4: TTBItem;
    TBItem5: TTBItem;
    TBItem6: TTBItem;
    TBItem7: TTBItem;
    TBItem9: TTBItem;
    TBItem10: TTBItem;
    StatusBar1: TStatusBar;
    TBItem11: TTBItem;
    TBItem12: TTBItem;
    TBItem1: TTBSubmenuItem;
    TBItem13: TTBItem;
    N7: TMenuItem;
    N8: TMenuItem;
    N9: TMenuItem;
    TBItem14: TTBItem;
    PopupMenu2: TPopupMenu;
    N10: TMenuItem;
    TBItem15: TTBItem;
    Panel1: TPanel;
    Button1: TButton;
    N1: TTBItem;
    N5: TTBItem;
    N6: TTBSeparatorItem;
    N11: TTBItem;
    N2: TTBItem;
    mnuClipboard1: TTBItem;
    mnuClipboard2: TTBItem;
    mnuratio0: TTBItem;
    TBSubmenuItem5: TTBSubmenuItem;
    TBItem17: TTBItem;
    TBItem18: TTBItem;
    TBItem19: TTBItem;
    btnselectmode: TTBItem;
    btnmovemode: TTBItem;
    N12: TMenuItem;
    N13: TMenuItem;
    TBSubmenuItem6: TTBSubmenuItem;
    TBItem20: TTBItem;
    TBItem21: TTBItem;
    TBItem22: TTBItem;
    Panel2: TPanel;
    ProgressBar1: TProgressBar;
    BitBtn1: TBitBtn;
    Label1: TLabel;
    N14: TMenuItem;
    N15: TMenuItem;
    N16: TMenuItem;
    TBItem23: TTBItem;
    TBSubmenuItem7: TTBSubmenuItem;
    TBItem25: TTBItem;
    TBItem26: TTBItem;
    TBItem24: TTBItem;
    ImageList2: TImageList;
    TBItem28: TTBItem;
    N17: TMenuItem;
    N18: TMenuItem;
    N19: TMenuItem;
    N20: TMenuItem;
    N21: TMenuItem;
    TBSeparatorItem3: TTBSeparatorItem;
    TBItem29: TTBItem;
    Panel3: TPanel;
    ListView2: TListView;
    Panel4: TPanel;
    ColorBox1: TnViewColorBox;
    bsSkinStdLabel2: TLabel;
    N22: TMenuItem;
    N23: TMenuItem;
    N24: TMenuItem;
    N25: TMenuItem;
    TBItem30: TTBItem;
    TBSeparatorItem4: TTBSeparatorItem;
    TBItem33: TTBItem;
    TBItem34: TTBItem;
    N26: TMenuItem;
    N27: TMenuItem;
    N28: TMenuItem;
    N29: TMenuItem;
    TBItem35: TTBItem;
    N30: TMenuItem;
    N31: TMenuItem;
    N32: TMenuItem;
    N33: TMenuItem;
    N34: TMenuItem;
    TBSubmenuItem10: TTBSubmenuItem;
    TBItem2: TTBItem;
    btnresize: TTBItem;
    TBSubmenuItem8: TTBSubmenuItem;
    TBItem31: TTBItem;
    TBItem8: TTBItem;
    TBSubmenuItem11: TTBSubmenuItem;
    TBItem16: TTBItem;
    TBSeparatorItem1: TTBSeparatorItem;
    TBItem27: TTBItem;
    N35: TMenuItem;
    N36: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure ListView1SelectItem(Sender: TObject; Item: TListItem;
      Selected: Boolean);
    procedure FormDestroy(Sender: TObject);
    procedure mnuUndoClick(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
    procedure ImgView321MouseWheelDown(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure ImgView321MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure ImgView321MouseWheelUp(Sender: TObject; Shift: TShiftState;
      MousePos: TPoint; var Handled: Boolean);
    procedure ImgView321MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer; Layer: TCustomLayer);
    procedure ImgView321MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    procedure mnuClipboard1Click(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
    procedure mnuratio0Click(Sender: TObject);
    procedure N3Click(Sender: TObject);
    procedure N4Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure ListView1Resize(Sender: TObject);
    procedure bsSkinSplitter2CanResize(Sender: TObject;
      var NewSize: Integer; var Accept: Boolean);
    procedure TBItem1Click(Sender: TObject);
    procedure TBItem2Click(Sender: TObject);
    procedure FormShortCut(var Msg: TWMKey; var Handled: Boolean);
    procedure TBItem13Click(Sender: TObject);
    procedure TBItem1Popup(Sender: TTBCustomItem; FromLink: Boolean);
    procedure N8Click(Sender: TObject);
    procedure N9Click(Sender: TObject);
    procedure pmimgviewPopup(Sender: TObject);
    procedure TBItem14Click(Sender: TObject);
    procedure N10Click(Sender: TObject);
    procedure PopupMenu2Popup(Sender: TObject);
    procedure bsSkinSplitter1Moved(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure TBItem16Click(Sender: TObject);
    procedure TBSubmenuItem2Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure TBItem18Click(Sender: TObject);
    procedure TBItem17Click(Sender: TObject);
    procedure btnselectmodeClick(Sender: TObject);
    procedure N12Click(Sender: TObject);
    procedure N13Click(Sender: TObject);
    procedure ListView1DblClick(Sender: TObject);
    procedure TBItem20Click(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure ImgView321MouseLeave(Sender: TObject);
    procedure N14Click(Sender: TObject);
    procedure N16Click(Sender: TObject);
    procedure TBItem23Click(Sender: TObject);
    procedure TBItem25Click(Sender: TObject);
    procedure TBItem26Click(Sender: TObject);
    procedure TBItem28Click(Sender: TObject);
    procedure N18Click(Sender: TObject);
    procedure N21Click(Sender: TObject);
    procedure TBItem29Click(Sender: TObject);
    procedure N23Click(Sender: TObject);
    procedure ListView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: controls.TDragState; var Accept: Boolean);
    procedure ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure N24Click(Sender: TObject);
    procedure TBItem31Click(Sender: TObject);
    procedure TBItem33Click(Sender: TObject);
    procedure TBSubmenuItem1Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure N26Click(Sender: TObject);
    procedure N27Click(Sender: TObject);
    procedure ImgView321Resize(Sender: TObject);
    procedure N31Click(Sender: TObject);
    procedure TBItem8Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TBSubmenuItem8Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure TBSubmenuItem10Popup(Sender: TTBCustomItem;
      FromLink: Boolean);
    procedure TBItem27Click(Sender: TObject);
    procedure N35Click(Sender: TObject);
  private
    { Private declarations }
    BrowserListView1:TBrowserListView;
    BrowserListView2:TBrowserListView;

    OldMousePos: TPoint;
    MouseDragging: Boolean;
    xorg,yorg,xmov,ymov:integer;
    RBLayerSelect:TRubberbandLayer;
    selectionenabled:boolean;
    Fworkimageidx:integer;
    capturetype:Tcapturetype;
    loading:boolean;
    savestopped:boolean;
    blockselected:boolean;
    balloon:TzAPIBalloon;
    listview1:Tmylistview;
    isfittoscreen:boolean;
//    vistaaltfixonidle:TIdleEvent;

    procedure Setworkimageidx(value:integer);
    procedure setlastselectdata(idx:integer);
    procedure GetSelectBitmap(src:TBitmap;var dest:TBitmap32);
    procedure SetSelectBitmap(src:TBitmap32;var dest:TBitmap);
    function convertabsolutepos(x,y:integer):TPoint;
    procedure DrawTheRect;
    procedure Select(R:Trect);
    procedure RBResizingSelect(Sender: TObject;
       const OldLocation: TFloatRect; var NewLocation: TFloatRect;
       DragState: TDragState; Shift: TShiftState);

    procedure BrowserListView1OnInsert(Sender: TObject; Item: TListItem; Fbitmap:TFreeWinBitmap);
    procedure BrowserListView1OnDelete(Sender: TObject; Item: TListItem);
    procedure OpenEffectTool(effecttype:Teffecttype;title:string);

    procedure UndoManage1OnInsert(Sender: TObject;PUndoData1:PUndoData);
    procedure UndoManage1OnDelete(Sender: TObject;idx:integer);
    procedure loadfilelist(s:string);
    procedure browserfile(strlist:Tstringlist);
    procedure applicationOnMessage(var Msg: tagMSG; var Handled: Boolean);
    function get_toolbarpopupPos(toolbar:ttbtoolbar; item:TTBCustomItem): tpoint;
    function move_selectlayer(key,pitch:integer):boolean;
    function get_listitem(idx:integer):tlistitem;
    function Undofromimage(PWorkImage1:PWorkImage;tempsrcRect:TRect;name:string;resized:boolean):PUndoData;
    procedure load_image(idx:integer);
    procedure applicationOnIdle(Sender: TObject; var Done: Boolean);
    procedure OneInstance1InstanceStarted(Sender: TObject; params: TStringList);
    procedure WndProc(var Message : TMessage); override;
    procedure screencapture(wnd:thandle; capturetype:Tcapturetype);
    procedure set_config();
    procedure cancelc_browserlistload(Sender: TObject);
    procedure cancelc_save(Sender: TObject);
    procedure createrationmenu();
    procedure fittoscreen();
    function listviewchanged():boolean;
    procedure setlistviewchange(PWorkImage1:PWorkImage;value:boolean);
    procedure load_cursor();
    procedure listview1OnCompare(Sender: TObject; Item1,Item2: TListItem; Data: Integer; var Compare: Integer);
  public
    { Public declarations }
    function is_layerselected:boolean;
    procedure apply_listimages(isselected:boolean;
        imageprocess:Timageprocess;effecttype:Teffecttype;title:string);
    procedure ProgressTimer(Sender: TObject);
    procedure showballoon(title,msg:string;control:tcontrol;icontype:Tmsgdlgtype);
  published
    property workimageidx: integer read Fworkimageidx write Setworkimageidx;
  end;

  Pfiledata = ^Tfiledata;
  Tfiledata = record
    ratio:integer;
    posx,posy:single;
  end;

var
  frmMain: TfrmMain;
  workimagelist:TThreadList;
  appdata_path:string;
  OneInstance:TOneInstance;
  sortreverseorder: array[0..1] of boolean;
  sortcolumn:integer;
  lastfilelist:tlist;

implementation

uses Uconfig, Ufunction, UfrmEffect_Color, UfrmEffect_Contrast, UfrmEffect_Rotate,
  UfrmEffect_Mosaic, UfrmEffect_Layer, im_Clipboard,
  UfrmEffectBase, UfrmEffect_Resize, UfrmEffect_Album,
  UfrmEffect_Filter, UfrmEffect_Special, UfrmEffect_shadow, shellapi,
  Ufrmnewimage, UfrmEffect_font, Ufrmoption, Ufrmprogress, UfrmEffect_Draw, Ufrmratio, Uupdate,
  Ufrmabout, Ufrmsaveopt, Ufrmmerge, Ucapture, UfrmCaptureRect, Ufrmselect, UfrmGifAni;
{$R *.dfm}

{TForm1}

procedure clear_lastfilelist;
var
  i:integer;
begin
  for i:=0 to lastfilelist.Count-1 do
    dispose(Pfiledata(lastfilelist.Items[i]));
  lastfilelist.Clear;
end;

procedure workimagelist_add(PWorkImage1:PWorkImage);
var
  list:TList;
begin
list:=workimagelist.LockList;
try
  list.Add(PWorkImage1);
finally
  workimagelist.UnlockList;
end;
end;

procedure workimagelist_del(idx:integer);
var
  list:TList;
  i:integer;
begin
list:=workimagelist.LockList;
try
  for i:=0 to list.Count-1 do
   if TWorkImage(list.Items[i]^).idx=idx then begin
     TWorkImage(list.Items[i]^).bitmap.Free;
     TWorkImage(list.Items[i]^).UndoManage1.Free;
     list.Delete(i);
     break
   end;
finally
  workimagelist.UnlockList;
end;
end;

procedure workimagelist_get(idx:integer;var PWorkImage1:PWorkImage);
var
  list:TList;
  i:integer;
begin
PWorkImage1:=nil;
list:=workimagelist.LockList;
try
  for i:=0 to list.Count-1 do
   if TWorkImage(list.Items[i]^).idx=idx then begin
     PWorkImage1:=PWorkImage(list.Items[i]);
     break;
   end;
finally
  workimagelist.UnlockList;
end;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  updatefilecheck;
  OneInstance.OnInstanceStarted:=OneInstance1InstanceStarted;

  TVistaAltFix.Create(Self);
  sysutils.ForceDirectories(GetAppDirectory);

  self.Caption:=format(thisapptitle+' - 이미지,사진편집 효과 (%s)',[GetVersion(paramstr(0))]);

  load_strcmplogical;
  config.LoadFromFile(GetAppDirectory+'config_edit.ini');

  listview1:=Tmylistview.Create(self);
  listview1.Parent:=self;
  listview1.DragMode:=dmAutomatic;
  listview1.HideSelection:=true;
  listview1.ReadOnly:=true;
  listview1.MultiSelect:=true;
  listview1.Align:=alright;
  listview1.TabStop:=true;
  listview1.IconOptions.AutoArrange:=true;
  listview1.PopupMenu:=PopupMenu2;
  listview1.OnDblClick:=ListView1DblClick;
  listview1.OnDragDrop:=ListView1DragDrop;
  listview1.OnDragOver:=ListView1DragOver;
  listview1.OnResize:=ListView1Resize;
  listview1.OnSelectItem:=ListView1SelectItem;

  bsSkinSplitter1.Left:=listview1.Left-50;
  bsSkinSplitter1.Align:=alright;

  workimagelist:=TThreadList.Create;
  BrowserListView1:=TBrowserListView.Create(ListView1,config.c_listthumbsize);
  BrowserListView1.TextOutStyle:=tosAll;
  BrowserListView1.Setthumbspace(22);
  BrowserListView1.OnInsert:=BrowserListView1OnInsert;
  BrowserListView1.OnDelete:=BrowserListView1OnDelete;
  BrowserListView1.ExImageList:=self.ImageList2;

  BrowserListView2:=TBrowserListView.Create(ListView2,75);
  BrowserListView2.TextOutStyle:=tosNoDesc;
  BrowserListView2.Setthumbspace(22);
  workimageidx:=-1;

  ImgView321.Align:=alClient;

  self.Left:=config.window_left;
  self.Top:=config.window_top;
  self.Width:=config.window_width;
  self.Height:=config.window_height;

  if config.window_max then
    WindowState:=wsMaximized;
  listview1.Width:=config.ListView1width;

  application.OnMessage:=applicationOnMessage;
//  vistaaltfixonidle:=application.OnIdle;
  application.OnIdle:=applicationOnIdle;

  appdata_path:=GetSpecialPath(Handle,CSIDL_APPDATA);
  deletefiles(appdata_path+'\'+thisregname+'\temp\','*.*');

  if config.c_selectmode then btnselectmode.Checked:=true
  else btnmovemode.Checked:=true;

  set_config();
  balloon:=TzAPIBalloon.Create(self);
  createrationmenu();

  ColorBox1.Selected:=config.getvaluebyinteger('main_fillcolor',clwhite);

  load_cursor();
  lastfilelist:=tlist.Create;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  config.c_selectmode:=btnselectmode.Checked;
   if WindowState=wsNormal then begin
     config.window_left:=self.Left;
     config.window_top:=self.Top;
     config.window_width:=self.Width;
     config.window_height:=self.Height;
     config.window_max:=false;
   end else if WindowState=wsMaximized then
     config.window_max:=true;

  config.ListView1width:=listview1.Width;
  config.setvaluebyinteger('main_fillcolor',self.ColorBox1.Selected);

  config.SaveToFile(GetAppDirectory+'config_edit.ini');

  BrowserListView1.Free;
  BrowserListView2.Free;
  balloon.Free;

  clear_lastfilelist;
  lastfilelist.Free;

  checkupdate();
end;

procedure TfrmMain.BrowserListView1OnInsert(Sender: TObject; Item: TListItem; Fbitmap:TFreeWinBitmap);
var
  PThumbImage1:PThumbImage;
  PWorkImage1:PWorkImage;
  filedata:Pfiledata;
begin
  PThumbImage1:=PThumbImage(Item.Data);
  PThumbImage1.changed:=false;

  if PThumbImage1.imagetype=itfile then begin
//    if FBitmap.IsTransparent then
//      FBitmap.SetTransparentBg(nil);
    FBitmap.ConvertTo24Bits;
{
    if FBitmap.GetBitsPerPixel<32 then
      FBitmap.ConvertTo32Bits
    else begin
      FBitmap.ConvertTo24Bits;
      FBitmap.ConvertTo32Bits;
    end;
}
    New(PWorkImage1);
    PWorkImage1.idx:=PThumbImage1.idx;
    PWorkImage1.orgchanged:=false;
    if (PThumbImage1.filelistidx>=0) and (PThumbImage1.filelistidx<=lastfilelist.Count-1) then begin
      filedata:=Pfiledata(lastfilelist.Items[PThumbImage1.filelistidx]);
      PWorkImage1.ratio:=filedata.ratio;
      PWorkImage1.posx:=filedata.posx;
      PWorkImage1.posy:=filedata.posy;
      PWorkImage1.centered:=true;
    end else begin
      if config.enablelastratio then PWorkImage1.ratio:=config.ratio2
      else PWorkImage1.ratio:=100;
      PWorkImage1.posx:=0;
      PWorkImage1.posy:=0;
      PWorkImage1.centered:=false;
    end;

    PWorkImage1.bitmap:=TBitmap.Create;
    with PWorkImage1.bitmap do begin
      PixelFormat := pf24Bit; //pf32Bit;
      Width := FBitmap.GetWidth;
      Height := FBitmap.GetHeight;
      Canvas.Lock;
      FBitmap.Draw(Canvas.Handle, rect(0,0,Width,Height));
      Canvas.Unlock;
    end;
    PWorkImage1.UndoManage1:=TUndoManage.Create(PWorkImage1.idx);
    PWorkImage1.UndoManage1.maxundocount:=config.c_undomaxcount;
    PWorkImage1.UndoManage1.OnInsert:=UndoManage1OnInsert;
    PWorkImage1.UndoManage1.OnDelete:=UndoManage1OnDelete;
    workimagelist_add(PWorkImage1);

  end else if PThumbImage1.imagetype=itBitmapPointer then begin

    New(PWorkImage1);
    PWorkImage1.idx:=PThumbImage1.idx;
    PWorkImage1.orgchanged:=true;
    if config.enablelastratio then PWorkImage1.ratio:=config.ratio2
    else PWorkImage1.ratio:=100;
    PWorkImage1.posx:=0;
    PWorkImage1.posy:=0;
    PWorkImage1.centered:=false;
    
//    PWorkImage1.bitmap:=TBitmap.Create;
//    PWorkImage1.bitmap.Assign(PThumbImage1.bitmap);
//메모리 절약을 위해 새로 생성안함
    PWorkImage1.bitmap:=PThumbImage1.bitmap;

    PWorkImage1.UndoManage1:=TUndoManage.Create(PWorkImage1.idx);
    PWorkImage1.UndoManage1.maxundocount:=config.c_undomaxcount;
    PWorkImage1.UndoManage1.OnInsert:=UndoManage1OnInsert;
    PWorkImage1.UndoManage1.OnDelete:=UndoManage1OnDelete;
    workimagelist_add(PWorkImage1);

    PThumbImage1.changed:=true;
    if (config.c_keepselectdraw=false) and (RBLayerSelect<>nil) then
      FreeAndNil(RBLayerSelect);

  end else
    exit;

  //자동선택
//  if ListView1.Selected=nil then
//    item.Selected:=true;
end;

procedure TfrmMain.BrowserListView1OnDelete(Sender: TObject; Item: TListItem);
begin
  workimagelist_del(PThumbImage(Item.Data).idx);
  if workimageidx=PThumbImage(Item.Data).idx then workimageidx:=-1;
end;

procedure TfrmMain.UndoManage1OnInsert(Sender: TObject;PUndoData1:PUndoData);
begin
  if Fworkimageidx=TUndoManage(sender).undoidx then
    BrowserListView2.BrowserBitmapPointer(PUndoData1.name,PUndoData1.bitmap);
end;

procedure TfrmMain.UndoManage1OnDelete(Sender: TObject;idx:integer);
begin
  if csDestroying in ListView2.ComponentState then exit;
  if Fworkimageidx=TUndoManage(sender).undoidx then begin
    ListView2.Items.Delete(idx);
    ListView2.Arrange(arAlignTop);
  end;
end;

procedure TfrmMain.Setworkimageidx(value:integer);
begin
  Fworkimageidx:=value;
  if Fworkimageidx=-1 then ImgView321.Bitmap.Assign(nil);
end;

procedure TfrmMain.setlastselectdata(idx:integer);
var
  PWorkImage1:PWorkImage;
  p:tfloatpoint;
begin
  workimagelist_get(idx, PWorkImage1);
  if PWorkImage1=nil then exit;
  with ImgView321.GetViewportRect do
    p:=ImgView321.ControlToBitmap2(Point(left,top));
  PWorkImage1.posx:=p.X;
  PWorkImage1.posy:=p.Y;
  if isfittoscreen then
    PWorkImage1.ratio:=0
  else
    PWorkImage1.ratio:=round(imgview321.Scale*100);
end;

procedure TfrmMain.ListView1SelectItem(Sender: TObject; Item: TListItem;
  Selected: Boolean);
begin
  if blockselected then exit;
  if Selected=false then begin
    setlastselectdata(PThumbImage(Item.Data).idx);
    exit;
  end;
  if listview1.SelCount>1 then exit;
  load_image(PThumbImage(Item.Data).idx);
  Item.MakeVisible(false);
end;

procedure TfrmMain.load_image(idx:integer);
var
  PWorkImage1:PWorkImage;
  i,ratio:integer;
  PUndoData1:PUndoData;
begin
  screen.Cursor:=crHourglass;
  try
    workimagelist_get(idx, PWorkImage1);
    if PWorkImage1=nil then exit;

    ImgView321.Bitmap.Assign(PWorkImage1.bitmap);

    if config.enablelastratio=false then
      config.ratio2:=100;

    isfittoscreen:=false;
    if config.keepratio then ratio:=PWorkImage1.ratio
    else ratio:=config.ratio2;
    if ratio=0 then
      fittoscreen()
    else
      imgview321.Scale:=ratio / 100;

    BrowserListView2.Clear;
    for i:=0 to PWorkImage1.UndoManage1.getcount-1 do begin
      PUndoData1:=PWorkImage1.UndoManage1.getitem(i);
      BrowserListView2.BrowserBitmapPointer(PUndoData1.name,PUndoData1.bitmap);
    end;
    workimageidx:=idx;

    if PWorkImage1.centered then
      ImgView321.ScrollToPos(PWorkImage1.posx,PWorkImage1.posy);
    PWorkImage1.centered:=true;
  finally
    screen.Cursor:=crdefault;
  end;
end;

procedure TfrmMain.GetSelectBitmap(src:TBitmap;var dest:TBitmap32);
var
  tempsrcrect,tempdstrect:TRect;
begin
  if RBLayerSelect<>nil then begin
    tempsrcRect:=MakeRect(RBLayerSelect.Location, rrInside);
    with tempdstRect do begin
       Left := 0;
       Top := 0;
       Right := tempsrcRect.Right - tempsrcRect.Left;
       Bottom := tempsrcRect.Bottom - tempsrcRect.Top;
       dest.SetSize(Right, Bottom);
    end;
    dest.Draw(tempdstRect, tempsrcRect, src.Canvas.Handle);
  end else
    dest.Assign(src);
end;

procedure TfrmMain.SetSelectBitmap(src:TBitmap32;var dest:TBitmap);
var
  tempsrcrect,tempdstrect:TRect;
begin
  if RBLayerSelect<>nil then begin
    tempdstRect:=MakeRect(RBLayerSelect.Location, rrInside);
    with tempsrcrect do begin
       Left := 0;
       Top := 0;
       Right := tempdstRect.Right - tempdstRect.Left;
       Bottom := tempdstRect.Bottom - tempdstRect.Top;
    end;
    src.DrawTo(dest.Canvas.Handle, tempdstRect, tempsrcRect);
  end else
    src.AssignTo24(dest);
end;

function TfrmMain.Undofromimage(PWorkImage1:PWorkImage;
   tempsrcRect:TRect;name:string;resized:boolean):PUndoData;
var
  tempdstrect:TRect;
  bitmap:TBitmap;
  UndoData1:TUndoData;
begin
  bitmap:=TBitmap.Create;
  bitmap.PixelFormat:=pf24Bit; //pf32Bit
  with tempdstRect do begin
     Left := 0;
     Top := 0;
     Right := tempsrcRect.Right - tempsrcRect.Left;
     Bottom := tempsrcRect.Bottom - tempsrcRect.Top;
     bitmap.Width:=Right;
     bitmap.Height:=Bottom;
  end;
  bitmap.Canvas.CopyRect(tempdstRect,
      PWorkImage1.bitmap.Canvas,tempsrcRect);

  UndoData1.bitmap:=PWorkImage1.bitmap;
  UndoData1.targetrect:=tempsrcRect;
  UndoData1.name:=name;
  UndoData1.resized:=resized;

  result:=PWorkImage1.UndoManage1.addundo(bitmap,UndoData1);
  bitmap.Free;
end;

procedure TfrmMain.OpenEffectTool(effecttype:Teffecttype;title:string);
var
  PWorkImage1:PWorkImage;
  frmEffect:TfrmEffectBase;
  apply:integer;

  tempsrcRect:TRect;
  PUndoData1:PUndoData;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;
  case effecttype of
    etColor:begin
     frmEffect:=TfrmEffect_Color.Create(self);
    end;
    etContrast:begin
     frmEffect:=TfrmEffect_Contrast.Create(self);
    end;
    etRotate:begin
     frmEffect:=TfrmEffect_Rotate.Create(self);
     TfrmEffect_Rotate(frmEffect).fiximage:=RBLayerSelect<>nil;
    end;
    etMosaic:begin
     frmEffect:=TfrmEffect_Mosaic.Create(self);
    end;
    etLayer:begin
     frmEffect:=TfrmEffect_Layer.Create(self);
    end;
    etResize:begin
     //only whole image
     FreeAndNil(RBLayerSelect);
     frmEffect:=TfrmEffect_Resize.Create(self);
    end;
    etAlbum:begin
     //only whole image
     FreeAndNil(RBLayerSelect);
     frmEffect:=TfrmEffect_Album.Create(self);
    end;
    etfilter:begin
     frmEffect:=TfrmEffect_Filter.Create(self);
    end;
    etshadow:begin
     //only whole image
     FreeAndNil(RBLayerSelect);
     frmEffect:=TfrmEffect_shadow.Create(self);
    end;
    etspecial:begin
     frmEffect:=TfrmEffect_special.Create(self);
    end;
    etfont:begin
     frmEffect:=TfrmEffect_font.Create(self);
    end;
    etdraw:begin
     frmEffect:=TfrmEffect_Draw.Create(self);
    end;
  end;
 try
  frmEffect.Caption:=title;

  //select rect to bitmap
  GetSelectBitmap(PWorkImage1.bitmap,frmEffect.org_bitmap32);
  if (frmEffect.org_bitmap32.Width=0) or (frmEffect.org_bitmap32.Height=0) then begin
    MessageDlg('이미지에 선택한 영역이 잘못되었습니다.',mtError, [mbOk], 0);
    exit;
  end;

  apply:=frmEffect.ShowModal;

  if apply=mrOk then begin
    if RBLayerSelect<>nil then
      tempsrcRect:=MakeRect(RBLayerSelect.Location, rrInside)
    else
      tempsrcRect:=rect(0,0,PWorkImage1.Bitmap.Width,PWorkImage1.Bitmap.Height);
    PUndoData1:=Undofromimage(PWorkImage1,tempsrcRect,
      title+' 이전',
      (effecttype=etAlbum) or (effecttype=etResize) or (effecttype=etshadow) or (effecttype=etRotate) );
    setlistviewchange(PWorkImage1, true);

    SetSelectBitmap(frmEffect.org_bitmap32, PWorkImage1.bitmap);
    ImgView321.Bitmap.Assign(PWorkImage1.bitmap);
  end;
 finally
   freeandnil(frmEffect);
 end;
end;

function TfrmMain.is_layerselected:boolean;
begin
  result:=RBLayerSelect<>nil;
end;

procedure TfrmMain.apply_listimages(isselected:boolean;
   imageprocess:Timageprocess;effecttype:Teffecttype;title:string);
begin
  frmprogress:=Tfrmprogress.Create(self);
  try
    frmprogress.isselected:=isselected;
    frmprogress.imageprocess:=imageprocess;
    frmprogress.effecttype:=effecttype;
    frmprogress.title:=title;
    frmprogress.ShowModal;
    load_image(workimageidx);
  finally
    frmprogress.Free;
  end;
end;

procedure TfrmMain.ProgressTimer(Sender: TObject);
var
  i:integer;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
  tempsrcRect:trect;
begin
  (Sender as ttimer).Enabled:=false;

  if frmprogress.isselected then
    frmprogress.ProgressBar1.Max:=ListView1.SelCount
  else
    frmprogress.ProgressBar1.Max:=ListView1.Items.Count;
  frmprogress.ProgressBar1.Position:=0;
  for i:=0 to ListView1.Items.Count-1 do begin
   try
    if (frmprogress.isselected) and (ListView1.Items[i].Selected=false) then
      continue;
    frmprogress.ProgressBar1.Position:=frmprogress.ProgressBar1.Position+1;
    if frmprogress.stopped then break;
    application.ProcessMessages;
    PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
    workimagelist_get(PThumbImage1.idx, PWorkImage1);
    tempsrcRect:=rect(0,0,PWorkImage1.Bitmap.Width,PWorkImage1.Bitmap.Height);
    Undofromimage(PWorkImage1,tempsrcRect,
        frmprogress.title+' 이전',
        (frmprogress.effecttype=etAlbum) or (frmprogress.effecttype=etResize)
          or (frmprogress.effecttype=etshadow) or (frmprogress.effecttype=etRotate));
    PThumbImage1.changed:=true;
    listview1.UpdateItems(i,i);
    frmprogress.imageprocess(PWorkImage1.bitmap);
   except
     on E: Exception do MessageDlg(E.Message,mtError, [mbOk], 0);
   end;
  end;
  frmprogress.ModalResult:=mrok;
end;

procedure TfrmMain.mnuClipboard1Click(Sender: TObject);
var
  bitmap:TBitmap32;
  PWorkImage1:PWorkImage;
  tempsrcRect:TRect;
  PUndoData1:PUndoData;
begin
workimagelist_get(workimageidx, PWorkImage1);
if PWorkImage1=nil then exit;
bitmap:=TBitmap32.Create;
try
  //select rect to bitmap
  GetSelectBitmap(PWorkImage1.bitmap,bitmap);

  if RBLayerSelect<>nil then
    tempsrcRect:=MakeRect(RBLayerSelect.Location, rrInside)
  else
    tempsrcRect:=rect(0,0,PWorkImage1.Bitmap.Width,PWorkImage1.Bitmap.Height);

  case (Sender as TTBItem).Tag of
    1:begin
      CopyBitmap32ToClipboard(bitmap);
      bitmap.fillrect(0,0,bitmap.width,bitmap.height,color32(ColorBox1.Selected));
    end;
    2:begin
      CopyBitmap32ToClipboard(bitmap);
      exit;
    end;
    3:begin
      PasteBitmap32FromClipboard(bitmap);
      tempsrcRect.bottom:=tempsrcRect.top+bitmap.height;
      tempsrcRect.right:=tempsrcRect.left+bitmap.width;
      selectionenabled:=true;
      select(tempsrcRect);
      selectionenabled:=false;
    end;
  end;

  if true then begin
    //add undo
    PUndoData1:=Undofromimage(PWorkImage1,tempsrcRect,(Sender as TTBitem).Caption+' 이전',false);
    setlistviewchange(PWorkImage1, true);

    //apply real image
    SetSelectBitmap(bitmap, PWorkImage1.bitmap);
    ImgView321.Bitmap.Assign(PWorkImage1.bitmap);
  end;

finally
  bitmap.Free;
end;
end;

procedure TfrmMain.mnuUndoClick(Sender: TObject);
var
  PWorkImage1:PWorkImage;
  bitmap:TBitmap;
  i,idx:integer;
  flag:boolean;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;

  case (Sender as Tmenuitem).Tag of
    0: idx:=ListView2.Selected.Index;
    1:
      if ListView2.Items.Count=0 then
        exit
      else
        idx:=ListView2.Items[ListView2.Items.Count-1].Index;
    else
      exit;
  end;
  screen.Cursor:=crHourglass;
  bitmap:=TBitmap.Create;
  try
    bitmap.Assign(PWorkImage1.bitmap);
    if PWorkImage1.UndoManage1.getundo(bitmap,idx+1) then begin
      PWorkImage1.bitmap.Assign(bitmap);
      ImgView321.Bitmap.Assign(PWorkImage1.bitmap);
    end;
  finally
    bitmap.Free;
    screen.Cursor:=crdefault;
  end;

  if PWorkImage1.orgchanged then flag:=true
  else flag:=PWorkImage1.UndoManage1.getcount>0;
  setlistviewchange(PWorkImage1, flag);
end;

procedure TfrmMain.PopupMenu1Popup(Sender: TObject);
begin
  mnuUndo.Enabled:=ListView2.SelCount>0;
  N7.Enabled:=ListView2.Items.Count>0;
  N8.Enabled:=ListView2.Items.Count>0;
end;

{ImgView321 event handler}
procedure TfrmMain.ImgView321MouseWheelDown(Sender: TObject;
  Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
  if (ImgView321.Bitmap.Height*ImgView321.Scale) > ImgView321.ClientHeight then
    ImgView321.Scroll(0,50)
  else
    ImgView321.Scroll(50,0);
end;

procedure TfrmMain.ImgView321MouseWheelUp(Sender: TObject;
  Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
  if (ImgView321.Bitmap.Height*ImgView321.Scale) > ImgView321.ClientHeight then
    ImgView321.Scroll(0,-50)
  else
    ImgView321.Scroll(-50,0);
end;

function TfrmMain.convertabsolutepos(x,y:integer):TPoint;
var
  np1:tpoint;
begin
  np1.X:=x;
  np1.y:=y;
  result:=ImgView321.ControlToBitmap(np1);
end;

procedure TfrmMain.DrawTheRect;
 function NormalizeRect(R: TRect): TRect;
 begin
  with R do
    if Left > Right then
      if Top > Bottom then
        Result := Rect(Right,Bottom,Left,Top)
      else
        Result := Rect(Right,Top,Left,Bottom)
    else
      if Top > Bottom then
        Result := Rect(Left,Bottom,Right,Top)
      else
        Result := Rect(Left,Top,Right,Bottom);
 end;
var
  R:trect;
begin
  R:=rect(xorg,yorg,xmov,ymov);
  R:=normalizerect(R);
  with R do begin
    if left<0 then left:=0;
    if right>ImgView321.bitmap.width then right:=ImgView321.bitmap.width;
    if top<0 then top:=0;
    if bottom>ImgView321.bitmap.height then bottom:=ImgView321.bitmap.height;
  end;
  select(R);
end;

procedure TfrmMain.Select(R:Trect);
begin
  if RBLayerSelect=nil then
    RBLayerSelect:=TRubberBandLayer.Create(ImgView321.Layers);

  with RBLayerSelect do begin
    OnResizing := RBResizingSelect;
    Location := FloatRect(R);
//    Handles:=[rhFrame];
//    HandleFill:=color32(clgray);
//    HandleFrame:=color32(clgray);
    LayerOptions := LOB_VISIBLE or LOB_MOUSE_EVENTS;
    Scaled := True;
    Visible := True;
    BringToFront;
  end;
  ImgView321.Changed;
end;

procedure TfrmMain.RBResizingSelect(Sender: TObject;
  const OldLocation: TFloatRect; var NewLocation: TFloatRect;
  DragState: TDragState; Shift: TShiftState);
var
  CanCrop: Boolean;
  R: TRect;
  RectChanged: Boolean;
begin
  selectionenabled:=false;
  RectChanged := False;
  R:= MakeRect(NewLocation);
  if R.Left < 0 then begin
    R.Left := 0;
    RectChanged := True;
  end;
  if R.Top < 0 then begin
    R.Top := 0;
    RectChanged := True;
  end;
  with ImgView321.Bitmap do begin
    if R.Right > Width then begin
      R.Right := Width;
      RectChanged := True;
    end;
    if R.Bottom > Height then begin
      R.Bottom := Height;
      RectChanged := True;
    end;
    CanCrop := (R.Left <> 0) or (R.Top <> 0) or (R.Right <> Width)
      or (R.Bottom <> Height);
  end;
  if RectChanged then NewLocation := FloatRect(R);
end;

procedure TfrmMain.ImgView321MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
var
  np2:tpoint;
begin
  if ImgView321.Bitmap.Empty then exit;

  if Button=mbLeft then begin
    np2:=convertabsolutepos(x,y);
    Xorg:=np2.X; Yorg:=np2.y;
    if btnselectmode.Checked then begin
      Xmov:=np2.X; Ymov:=np2.y;
      selectionenabled:=true;
    end else begin
      OldMousePos := Point(X, Y);
      MouseDragging := True;
      imgview321.Cursor := crSizeAll;
    end;
  end;
end;

procedure TfrmMain.ImgView321MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer; Layer: TCustomLayer);
var
  np2:tpoint;
  rgb:TColor;
begin
//  if loading then screen.Cursor:=crHourglass;
  np2:=convertabsolutepos(x,y);
  if config.c_viewcolor and (imgview321.Bitmap.Empty=false) then begin
    if (np2.X>=0) and (np2.Y>=0) and
      (np2.X<imgview321.Bitmap.Width) and
        (np2.Y<imgview321.Bitmap.Height) then begin
      rgb:=WinColor(imgview321.Bitmap.PixelS[np2.X,np2.Y]);
      panel1.Color:=rgb;
      StatusBar1.Panels[4].Text:=
        format('R:%d G:%d B:%d',[(rgb) and $FF,
                                  (rgb shr  8) and $FF,
                                  (rgb shr 16) and $FF]);
    end;
  end;

  if btnselectmode.Checked and selectionenabled then
    StatusBar1.Panels[6].Text:=format('x:%d,y:%d -> x:%d,y:%d',[Xorg, Yorg, np2.X, np2.Y])
  else
    StatusBar1.Panels[6].Text:=format('x:%d,y:%d',[np2.X, np2.Y]);

  if btnselectmode.Checked then begin
    if selectionenabled=false then exit;
    if (np2.X-5 < Xorg) and (Xorg < np2.X+5) and
       (np2.Y-5 < Yorg) and (Yorg < np2.Y+5) then exit;
    Xmov:=np2.X; Ymov:=np2.Y;
    DrawTheRect;
  end else if MouseDragging then begin
    imgview321.Scroll(OldMousePos.X - X, OldMousePos.Y - Y);
    OldMousePos := Point(X, Y);
  end;
end;

procedure TfrmMain.ImgView321MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
var
  np2:tpoint;
begin
  if Button=mbLeft then begin
    np2:=convertabsolutepos(x,y);
    if (RBLayerSelect<>nil) and (Xorg=np2.X) and (Yorg=np2.Y) then begin
      FreeAndNil(RBLayerSelect);
      ImgView321.Changed;
    end;
    if btnselectmode.Checked then begin
      selectionenabled:=false;
    end else begin
      MouseDragging := False;
      imgview321.Cursor := crDefault;
    end;
  end;
end;

function TfrmMain.get_listitem(idx:integer):tlistitem;
var
  i:integer;
begin
  result:=nil;
  for i:=0 to listview1.Items.Count-1 do
    if PThumbImage(listview1.Items[i].Data).idx=idx then begin
       result:=listview1.Items[i];
       break;
    end;
end;

procedure TfrmMain.N1Click(Sender: TObject);
var
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
  s:string;
  FBitmap:TFreeWinBitmap;
  stream:TMemorystream;
  FreeMemoryIO1:TFreeMemoryIO;
  SaveDialog1:TmySavePictureDialog;
  flag:boolean;
  selectsaveflag:integer;
label reopendialog;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;
  PThumbImage1:=PThumbImage(get_listitem(PWorkImage1.idx).Data);

  if (sender as TTBItem).Tag=1 then begin
    s:=PThumbImage1.name;
    if (s<>'') and (MessageDlg('정말로 저장 하시겠습니까?', mtConfirmation, [mbYes, mbNo], 0) <> mrYes) then
      exit;
    if s='' then flag:=true
    else flag:=false;
  end else
    flag:=true;

  if flag then begin
reopendialog:
    s:=PThumbImage1.name;
    SaveDialog1:=TmySavePictureDialog.Create(self);
    SaveDialog1.Filter:=FIU_GetAllFilters2;
    if s='' then
      SaveDialog1.FilterIndex:=config.c_lastsavefilterindex
    else
      SaveDialog1.FilterIndex:=FIU_GetSelectidx(lowercase(ExtractFileExt(s)));
    SaveDialog1.InitialDir:=ExtractFilePath(s);
    SaveDialog1.FileName:=ChangeFileExt(ExtractFileName(s),'');
    SaveDialog1.ExtraCheckbox.Checked:=config.c_dialogpreview;
    try
      if SaveDialog1.Execute=false then exit;
      config.c_lastsavefilterindex:=SaveDialog1.FilterIndex;
      selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(FIU_GetSelectExt(SaveDialog1.FilterIndex)),false);
      s:=sysutils.ChangeFileExt(SaveDialog1.FileName,
              FIU_GetSelectExt(SaveDialog1.FilterIndex));
    finally
      config.c_dialogpreview:=SaveDialog1.ExtraCheckbox.Checked;
      SaveDialog1.Free;
    end;
    if sysutils.FileExists(s) then begin
      if MessageDlg(format('"%s" 파일이 이미 존재합니다.',[ExtractFileName(s)])+#13#10+'덮어 씌우시겠습니까?',
           mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
       goto reopendialog;
    end;
  end else
    selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(lowercase(ExtractFileExt(s))),false);

  FBitmap:=TFreeWinBitmap.Create;
  stream:=TMemorystream.Create;
  try
    PWorkImage1.bitmap.SaveToStream(stream);
    FreeMemoryIO1:=TFreeMemoryIO.Create(stream.Memory,stream.Size);
    try
      FBitmap.LoadFromMemory(FreeMemoryIO1);
    finally
      FreeMemoryIO1.Free;
    end;
    FBitmap.ConvertTo24Bits;
    if comparetext(ExtractFileExt(s),'.gif')=0 then
      FBitmap.ColorQuantize(FIQ_WUQUANT);
    if FBitmap.Save(s,selectsaveflag) then begin
      PThumbImage1.name:=s;
      PThumbImage1.time:=FileAge(PThumbImage1.name);
      PWorkImage1.orgchanged:=true;
      setlistviewchange(PWorkImage1, false);
      showballoon('알림','저장되었습니다.', self.ImgView321, mtInformation);
//      MessageDlg('저장되었습니다.',mtInformation, [mbOk], 0);
    end else
      showballoon('알림','저장에 실패하였습니다.', self.ImgView321, mterror);
//      MessageDlg('저장에 실패하였습니다.',mtError, [mbOk], 0);
  finally
    stream.Free;
    FBitmap.Free;
  end;
end;

procedure TfrmMain.N2Click(Sender: TObject);
var
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
  s:string;
  FBitmap:TFreeWinBitmap;
  stream:TMemorystream;
  FreeMemoryIO1:TFreeMemoryIO;
  i,k:integer;
  list:tlist;
  listitem:Tlistitem;
  SaveDialog1:TmySavePictureDialog;
  selectsaveflag:integer;
label reopendialog;
begin
 if MessageDlg('정말로 저장 하시겠습니까?',
       mtConfirmation, [mbYes, mbNo], 0) <> mrYes then exit;

savestopped:=false;
panel2.Visible:=true;
panel2.BringToFront;
BitBtn1.OnClick:=cancelc_save;
panel2.SetFocus;
FormResize(nil);
for i:=0 to self.ControlCount-1 do
  if self.Controls[i]<>Panel2 then
    self.Controls[i].Enabled:=false;
application.ProcessMessages;
list:=workimagelist.LockList;
try
  k:=0;
  for i:=0 to list.Count-1 do begin
    PWorkImage1:=PWorkImage(list.Items[i]);
    listitem:=get_listitem(PWorkImage1.idx);
    if ((Sender as TTBItem).Tag=1) and (listitem.Selected=false) then
      continue;
    PThumbImage1:=PThumbImage(listitem.Data);
    if ((Sender as TTBItem).Tag=3) and (PThumbImage1.changed=false) then
      continue;
    inc(k);
  end;
  ProgressBar1.Max:=k;
  ProgressBar1.Position:=0;
  k:=0;

  for i:=0 to list.Count-1 do begin
    if savestopped then exit;
    PWorkImage1:=PWorkImage(list.Items[i]);
    listitem:=get_listitem(PWorkImage1.idx);
    if ((Sender as TTBItem).Tag=1) and (listitem.Selected=false) then
      continue;

    PThumbImage1:=PThumbImage(listitem.Data);
    if ((Sender as TTBItem).Tag=3) and (PThumbImage1.changed=false) then
      continue;
    s:=PThumbImage1.name;

    if s='' then begin
reopendialog:
      label1.Caption:='이름이 없습니다. 다른이름으로 저장하세요.';
      application.ProcessMessages;
      SaveDialog1:=TmySavePictureDialog.Create(self);
      SaveDialog1.Filter:=FIU_GetAllFilters2;
      if s='' then
        SaveDialog1.FilterIndex:=config.c_lastsavefilterindex
      else
        SaveDialog1.FilterIndex:=FIU_GetSelectidx(lowercase(ExtractFileExt(s)));
      SaveDialog1.InitialDir:=ExtractFilePath(s);
      SaveDialog1.FileName:=ChangeFileExt(ExtractFileName(s),'');
      SaveDialog1.ExtraCheckbox.Checked:=config.c_dialogpreview;
      try
        if SaveDialog1.Execute=false then exit;
        config.c_lastsavefilterindex:=SaveDialog1.FilterIndex;
        selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(FIU_GetSelectExt(SaveDialog1.FilterIndex)),false);
        s:=sysutils.ChangeFileExt(SaveDialog1.FileName,
              FIU_GetSelectExt(SaveDialog1.FilterIndex));
      finally
        config.c_dialogpreview:=SaveDialog1.ExtraCheckbox.Checked;
        SaveDialog1.Free;
      end;
      if sysutils.FileExists(s) then begin
        if MessageDlg(format('"%s" 파일이 이미 존재합니다.',[ExtractFileName(s)])+#13#10+'덮어 씌우시겠습니까?',
            mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
         goto reopendialog;
      end;
    end else
      selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(lowercase(ExtractFileExt(s))),false);

    ProgressBar1.Position:=ProgressBar1.Position+1;
    label1.Caption:=ExtractFileName(s);
    application.ProcessMessages;

    FBitmap:=TFreeWinBitmap.Create;
    stream:=TMemorystream.Create;
    try
      PWorkImage1.bitmap.SaveToStream(stream);
      FreeMemoryIO1:=TFreeMemoryIO.Create(stream.Memory,stream.Size);
      try
        FBitmap.LoadFromMemory(FreeMemoryIO1);
      finally
        FreeMemoryIO1.Free;
      end;
      FBitmap.ConvertTo24Bits;
      if comparetext(ExtractFileExt(s),'.gif')=0 then
        FBitmap.ColorQuantize(FIQ_WUQUANT);
      if FBitmap.Save(s,selectsaveflag) then begin
        PThumbImage1.name:=s;
        PThumbImage1.time:=FileAge(PThumbImage1.name);
        PThumbImage1.changed:=false;
        PWorkImage1.orgchanged:=true;
      end else
        MessageDlg(format('%s 저장에 실패하였습니다.',[ExtractFileName(s)]),
           mtError, [mbOk], 0);
    finally
      stream.Free;
      FBitmap.Free;
    end;
    inc(k);
  end;
  if k=0 then
    showballoon('알림','저장할 것이 없습니다.', self.ImgView321, mtInformation)
//    MessageDlg('저장할 것이 없습니다.',mtError, [mbOk], 0)
  else
    showballoon('알림','모두 저장하였습니다.', self.ImgView321, mtInformation);
//    MessageDlg('모두 저장하였습니다.',mtInformation, [mbOk], 0);
finally
  workimagelist.UnlockList;
  panel2.Visible:=false;
  for i:=0 to self.ControlCount-1 do
    self.Controls[i].Enabled:=true;
end;
end;

procedure Tfrmmain.createrationmenu();
var
  i:integer;
  item:TTBCustomItem;
begin
  for i:=1 to 9 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=format('%d%%',[i*10]);
    item.Tag:=0;
    item.GroupIndex:=1;
    item.OnClick:=mnuratio0Click;
    TBSubmenuItem2.Add(item);
  end;
  for i:=1 to 10 do begin
    item:=TTBCustomItem.Create(self);
    item.Caption:=format('%d%%',[i*100]);
    item.Tag:=0;
    item.GroupIndex:=1;
    item.OnClick:=mnuratio0Click;
    if i=1 then item.ShortCut:=texttoshortcut('shift+1');
    TBSubmenuItem2.Add(item);
  end;
end;

procedure Tfrmmain.fittoscreen();
var
  ratio:Single;
  w,h,gap:integer;
begin
  isfittoscreen:=true;
  gap:=GetSystemMetrics(SM_CYHSCROLL)+17;
  w:=imgview321.Bitmap.Width;
  h:=imgview321.Bitmap.Height;
  if ((imgview321.Width-gap)>=w) and ((imgview321.Height-gap)>=h) then
    ratio:=1
  else begin
    ratio:=(imgview321.Width-gap) / w;
    if (imgview321.Height-gap) < (ratio*h) then begin
      ratio:=(imgview321.Height-gap) / h;
    end;
  end;
  imgview321.Scale:=ratio;
end;

procedure TfrmMain.mnuratio0Click(Sender: TObject);
var
  S: string;
  I: Integer;
begin
  if (sender as TTBCustomItem).Tag=1 then begin
    fittoscreen();
    config.ratio2:=0;
  end else begin
    S := (sender as TTBCustomItem).Caption;
    S := StringReplace(S, '%', '', [rfReplaceAll]);
    S := StringReplace(S, ' ', '', [rfReplaceAll]);
    if S = '' then Exit;
    I := StrToIntDef(S, -1);
    if (I < 1) or (I > 2000) then I:=Round(imgview321.Scale * 100)
    else imgview321.Scale:=I / 100;
    config.ratio2:=round(imgview321.Scale*100);
    isfittoscreen:=false;
  end;
end;

procedure TfrmMain.N3Click(Sender: TObject);
var
  NewScale: Single;
begin
  NewScale:=imgview321.Scale+((trunc(imgview321.Scale)+1) / 10);
  if NewScale>200 then NewScale:=200;
  imgview321.Scale:=NewScale;
  config.ratio2:=round(imgview321.Scale*100);
  isfittoscreen:=false;
end;

procedure TfrmMain.N4Click(Sender: TObject);
var
  NewScale: Single;
begin
  NewScale:=imgview321.Scale-((trunc(imgview321.Scale)+1) / 10);
  if NewScale<0.1 then NewScale:=0.1;
  imgview321.Scale:=NewScale;
  config.ratio2:=round(imgview321.Scale*100);
  isfittoscreen:=false;
end;

procedure TfrmMain.loadfilelist(s:string);
var
  strlist,strlist2,strlist3:tstringlist;
  i:integer;
  s1:string;
  filedata:Pfiledata;
begin
  if sysutils.FileExists(s)=false then exit;

  if comparetext(ExtractFileExt(s),'.txt')=0 then begin
    strlist:=tstringlist.Create;
    strlist2:=tstringlist.Create;
    strlist3:=tstringlist.Create;
    try
      strlist.LoadFromFile(s);
      for i:=0 to strlist.Count-1 do begin
        s1:=strlist.Strings[i];
        strlist2.Clear;
        SplitString(s1,strlist2,#9);
        if strlist2.Count=0 then continue;
        strlist3.Add(strlist2.Strings[0]);
        if strlist2.Count=4 then begin
          new(filedata);
          filedata.ratio:=strtointdef(strlist2.Strings[1],0);
          filedata.posx:=strtofloatdef(strlist2.Strings[2],0);
          filedata.posy:=strtofloatdef(strlist2.Strings[3],0);
          lastfilelist.Add(filedata);
        end;
      end;
      BrowserFile(strlist3);
    finally
      strlist.Free;
      strlist2.Free;
    end;
  end else begin
    strlist:=tstringlist.Create;
    strlist.Add(s);
    BrowserFile(strlist);
  end;
end;

procedure TfrmMain.browserfile(strlist:Tstringlist);
var
  i:integer;
begin
  loading:=true;
//  screen.Cursor:=crHourglass;
  panel2.Visible:=true;
  panel2.BringToFront;
  BitBtn1.OnClick:=cancelc_browserlistload;
  panel2.SetFocus;
  FormResize(nil);
  for i:=0 to self.ControlCount-1 do
    if self.Controls[i]<>Panel2 then
      self.Controls[i].Enabled:=false;
  ListView1.Items.BeginUpdate;
  BrowserListView1.BrowserFile(strlist,handle);
end;

procedure TfrmMain.FormShow(Sender: TObject);
begin
  DragAcceptFiles(Handle, True);
  if ParamStr(1)<>'' then loadfilelist(ParamStr(1));
end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//
end;

procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  i:integer;
  PThumbImage1:PThumbImage;
  strlist:Tstringlist;
  s:string;
  PWorkImage1:PWorkImage;
begin
  if ListView1.Items.Count>0 then begin
   strlist:=Tstringlist.Create;
   try
     setlastselectdata(workimageidx);
     for i:=0 to ListView1.Items.Count-1 do begin
       PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
       s:=PThumbImage1.name;
       workimagelist_get(PThumbImage1.idx, PWorkImage1);
       if PWorkImage1<>nil then begin
         s:=s+#9+inttostr(PWorkImage1.ratio)+#9+floattostr(PWorkImage1.posx)+#9+floattostr(PWorkImage1.posy);
       end;
       strlist.Add(s);
     end;
     strlist.SaveToFile(GetAppDirectory+'lastedit.txt');
   finally
     strlist.Free;
   end;
  end;

  if listviewchanged() then
    if MessageDlg('이미지가 변경된것이 있습니다. 그냥 종료하시겠습니까?',
         mtConfirmation, [mbYes, mbNo], 0) = mrNo then
       canclose:=false;
end;

procedure TfrmMain.applicationOnMessage(var Msg: tagMSG;
  var Handled: Boolean);
var
  wnd:thandle;
begin
  case Msg.message of
    wm_mousewheel:begin
        wnd:=windows.WindowFromPoint(mouse.CursorPos);
        if GetFocus<>wnd then begin
          windows.SetFocus(wnd);
          sendmessage(wnd, wm_mousewheel, Msg.wParam, Msg.lParam);
          Handled:=true;
        end;
    end;
  end;

end;

procedure TfrmMain.ListView1Resize(Sender: TObject);
begin
//  ListView1.Arrange(arAlignTop);
end;

procedure TfrmMain.bsSkinSplitter2CanResize(Sender: TObject;
  var NewSize: Integer; var Accept: Boolean);
begin
  accept:=false;
end;

procedure TfrmMain.TBItem1Click(Sender: TObject);
var
  s:string;
  strlist:tstringlist;
  OpenPictureDialog1:TmyOpenPictureDialog;
begin
  OpenPictureDialog1:=TmyOpenPictureDialog.Create(self);
  try
    OpenPictureDialog1.Filter := FIU_GetAllFilters;
    OpenPictureDialog1.InitialDir:=config.lastpath;
    OpenPictureDialog1.Options:=OpenPictureDialog1.Options+[ofAllowMultiSelect];
    OpenPictureDialog1.ExtraCheckbox.Checked:=config.c_dialogpreview;
    if OpenPictureDialog1.Execute=false then exit;
    config.lastpath:=sysutils.ExtractFilePath(OpenPictureDialog1.Files[0]);
    OpenPictureDialog1.Options:=OpenPictureDialog1.Options-[ofAllowMultiSelect];

    strlist:=Tstringlist.Create;
    strlist.Assign(OpenPictureDialog1.Files);
    BrowserFile(strlist);
  finally
    config.c_dialogpreview:=OpenPictureDialog1.ExtraCheckbox.Checked;
    OpenPictureDialog1.Free;
  end;
end;

procedure TfrmMain.TBItem2Click(Sender: TObject);
var
  effecttype:Teffecttype;
begin
  case (Sender as TTBItem).Tag of
    1:effecttype:=etColor;
    2:effecttype:=etContrast;
    3:effecttype:=etRotate;
    4:effecttype:=etMosaic;
    5:effecttype:=etLayer;
    7:effecttype:=etResize;
    8:effecttype:=etAlbum;
    9:effecttype:=etfilter;
    10:effecttype:=etshadow;
    11:effecttype:=etspecial;
    12:effecttype:=etfont;
    13:effecttype:=etdraw;
  end;
  OpenEffectTool(effecttype,(Sender as TTBItem).Caption);
end;

function Tfrmmain.get_toolbarpopupPos(toolbar:ttbtoolbar; item:TTBCustomItem): tpoint;
var
  pt:tpoint;
  r,r1,r2:trect;
  wnd:thandle;
  w,h:integer;
begin
  pt:=toolbar.ClientToScreen(point(0,0));
  r:=toolbar.View.Find(item).BoundsRect;
  w:=r.Right-r.Left;
  h:=r.Bottom-r.Top;
  r1.Left:=r.Left+pt.X;
  r1.Right:=r1.Left+w;
  r1.Top:=r.Top+pt.Y;
  r1.Bottom:=r1.Top+h;
  if windows.PtInRect(r1,mouse.CursorPos) then begin
    result.X:=r1.Left;
    result.Y:=r1.Bottom;
  end else begin
    wnd:=windows.WindowFromPoint(mouse.CursorPos);
    windows.GetWindowRect(wnd,r2);
    result.X:=mouse.CursorPos.X-5;
    result.Y:=r2.Bottom;
  end;
end;

function TfrmMain.move_selectlayer(key,pitch:integer):boolean;
var
  r:Tfloatrect;
begin
  result:=true;
      if (RBLayerSelect<>nil) then begin //(ImgView321.Focused) and
        r:=RBLayerSelect.Location;
        case key of
          vk_left:begin
            r.Left:=r.Left-pitch;
            r.Right:=r.Right-pitch;
          end;
          VK_RIGHT:begin
            r.Left:=r.Left+pitch;
            r.Right:=r.Right+pitch;
          end;
          VK_UP:begin
            r.Top:=r.Top-pitch;
            r.Bottom:=r.Bottom-pitch;
          end;
          VK_DOWN:begin
            r.Top:=r.Top+pitch;
            r.Bottom:=r.Bottom+pitch;
          end;
          else
            result:=false;
        end;
        if result then RBLayerSelect.Location:=r;
      end else
        result:=false;
end;

procedure TfrmMain.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  Handled:=true;
  if (GetKeyState(VK_CONTROL)<0) then begin
    case msg.CharCode of
      ord('Z'): mnuUndoClick(N7);
      else
        Handled:=move_selectlayer(msg.CharCode,config.c_ctrlmovepitch);
    end;
  end else if (GetKeyState(VK_SHIFT)<0) then begin
    Handled:=move_selectlayer(msg.CharCode,config.c_shiftmovepitch);

  end else
    Handled:=false;
end;

procedure TfrmMain.TBItem13Click(Sender: TObject);
begin
  loadfilelist(GetAppDirectory+'lastedit.txt');
end;

procedure TfrmMain.TBItem1Popup(Sender: TTBCustomItem; FromLink: Boolean);
begin
  TBItem13.Enabled:=FileExists(GetAppDirectory+'lastedit.txt');
end;

procedure TfrmMain.N8Click(Sender: TObject);
var
  PWorkImage1:PWorkImage;
begin
  if MessageDlg('모두 지우시겠습니까?',
       mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
   exit;
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1<>nil then
    PWorkImage1.UndoManage1.undolistclear;
end;

procedure TfrmMain.N9Click(Sender: TObject);
begin
  if RBLayerSelect<>nil then begin
    FreeAndNil(RBLayerSelect);
    ImgView321.Changed;
  end;
end;

procedure TfrmMain.pmimgviewPopup(Sender: TObject);
begin
  N9.Enabled:=RBLayerSelect<>nil;
  n3.Enabled:=not ImgView321.Bitmap.Empty;
  n4.Enabled:=n3.Enabled;
  N14.Enabled:=ListView2.Items.Count>0;
  n21.Enabled:=n3.Enabled;
  n23.Enabled:=n3.Enabled;
  N26.Enabled:=n3.Enabled;
  N27.Enabled:=n3.Enabled;
end;

procedure TfrmMain.TBItem14Click(Sender: TObject);
begin
  if listviewchanged() then
    if MessageDlg('이미지가 변경된것이 있습니다. 그래도 닫으시겠습니까?',
         mtConfirmation, [mbYes, mbNo], 0) = mrNo then
       exit;
  BrowserListView1.Clear;
end;

procedure TfrmMain.N10Click(Sender: TObject);
var
  i,ret:integer;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
  s:string;
begin
ListView1.Items.BeginUpdate;
try
  ret:=0;
  for i:=ListView1.Items.Count-1 downto 0 do begin
    if ListView1.Items[i].Selected=false then continue;
    PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
    workimagelist_get(PThumbImage1.idx, PWorkImage1);
    if PThumbImage1.changed and (ret<>mrAll) then begin
      s:=ExtractFileName(PThumbImage1.name);
      if s='' then s:='이름없음';
      s:=format('"%s" 이미지가 변경되었습니다. 그냥 제거 하시겠습니까?',[s]);
      ret:=MessageDlg(s, mtConfirmation, [mbYes, mbNo, mbAll], 0);
      if ret=mrNo then
        break;
    end;
    ListView1.Items[i].Delete;
  end;
  ListView1.Arrange(arAlignTop);
finally
  ListView1.Items.EndUpdate;
end;
end;

procedure TfrmMain.PopupMenu2Popup(Sender: TObject);
var
  c,t:integer;
begin
  c:=ListView1.SelCount;
  t:=ListView1.Items.Count;
  N10.Enabled:=c>0;
  N13.Enabled:=c>0;
  N16.Enabled:=(c=1) and (PThumbImage(ListView1.Selected.Data).name<>'');
  n17.Enabled:=t>0;
  n18.Enabled:=t>0;
  N12.Enabled:=t>0;
  N24.Enabled:=c=1;
  N25.Enabled:=c=1;
end;

procedure TfrmMain.bsSkinSplitter1Moved(Sender: TObject);
begin
  ListView1.Arrange(arAlignTop);
end;

procedure TfrmMain.Button1Click(Sender: TObject);
var
  PWorkImage1:PWorkImage;
  dest:tbitmap32;

  rbrite,gbrite,bbrite:extended;
  threshold:integer;

  p0:Pcolor32array;
  i,x,y:integer;
  r,g,b: byte;
  rr,gg,bb: byte;
  SS:Pcolor32;
  depth:integer;

  bitmap:Tbitmap;

  SR: TSearchRec;
  dir,s,s1:string;
  k:integer;
  strlist:tstringlist;
  PixelFormat:TPixelFormat;
begin
{
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;
  PixelFormat:=GetPixelFormat(PWorkImage1.bitmap);
  if PixelFormat=pf24bit then begin
    bitmap:=ReduceColors(PWorkImage1.bitmap, rmQuantize, dmFloydSteinberg, 8, 0);
  end else begin
    bitmap:=ReduceColors(PWorkImage1.bitmap, rmQuantize, dmFloydSteinberg, 24, 0);
  end;
  PWorkImage1.bitmap.Assign(bitmap);
  ImgView321.Bitmap.Assign(PWorkImage1.bitmap);
  bitmap.Free;
}
  exit;
  threshold:=0;
  depth:=20;

  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;

  dest:=tbitmap32.Create;
  GetSelectBitmap(PWorkImage1.bitmap,dest);

  SS := @dest.Bits[0];

  for y:=0 to dest.Height-1 do begin
    p0:=dest.scanline[y];
    for x:=0 to dest.Width-1 do begin
      b:=(p0[x] and $FF);
      g:=(p0[x] shr 8) and $FF;
      r:=(p0[x] shr 16) and $FF;

      //grayscale
      r:=(r+g+b) div 3;
      g:=r;
      b:=r;
      SS^ := $FF000000 + r shl 16 + g shl 8 + b;

      //sepia
      b:=(SS^ and $FF);
      g:=(SS^ shr 8) and $FF;
      r:=(SS^ shr 16) and $FF;
      rr:=r+(depth*2);
      gg:=g+depth;
      bb:=b;
      if rr <= ((depth*2)-1) then
        rr:=255;
      if gg <= (depth-1) then
        gg:=255;
      SS^ := $FF000000 + rr shl 16 + gg shl 8 + bb;

      inc(SS);
    end;
  end;

  ImgView321.Bitmap.Assign(dest);
  dest.Free;
end;

procedure TfrmMain.TBItem16Click(Sender: TObject);
begin
  frmoption:=Tfrmoption.Create(self);
  try
    if frmoption.ShowModal=mrok then
      set_config();
  finally
    frmoption.Free;
  end;
end;

procedure TfrmMain.set_config();
var
  list:TList;
  i:integer;
begin
  if config.c_viewcolor=false then begin
    panel1.Color:=StatusBar1.Color;
    StatusBar1.Panels[4].Text:='';
  end;
  ImgView321.Color:=config.c_defaultviewcolor;
  self.TBToolbar1.ShrinkMode:=TTBShrinkMode(config.c_toolbarshrinkmode+1);
  if TBToolbar1.ShrinkMode=tbsmNone then TBToolbar1.ShrinkMode:=TTBShrinkMode(2);
  self.TBToolbar2.ShrinkMode:=TTBShrinkMode(config.c_toolbarshrinkmode+1);
  if TBToolbar2.ShrinkMode=tbsmNone then TBToolbar2.ShrinkMode:=TTBShrinkMode(2);

  list:=workimagelist.LockList;
  try
    for i:=0 to list.Count-1 do
      PWorkImage(list.Items[i]).UndoManage1.maxundocount:=config.c_undomaxcount;
  finally
    workimagelist.UnlockList;
  end;
end;

procedure TfrmMain.TBSubmenuItem2Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
var
  i,v:integer;
  s:string;
  PWorkImage1:PWorkImage;
  ratio:integer;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1<>nil then ratio:=PWorkImage1.ratio
  else ratio:=config.ratio2;

  if ratio=0 then
    mnuratio0.Checked:=true
  else begin
    for i:=0 to TBSubmenuItem2.Count-1 do begin
      if TBSubmenuItem2.Items[i].Checked then
        TBSubmenuItem2.Items[i].Checked:=false;
      s:=TBSubmenuItem2.Items[i].Caption;
      s:=StringReplace(s, '%', '', [rfReplaceAll]);
      s:=StringReplace(s, ' ', '', [rfReplaceAll]);
      v:=StrToIntDef(s, -1);
      if ratio=v then begin
        TBSubmenuItem2.Items[i].Checked:=true;
        break;
      end;
    end;
  end;
end;

procedure TfrmMain.applicationOnIdle(Sender: TObject; var Done: Boolean);
var
  i,c:integer;
  flag,flag2:boolean;
  PThumbImage1:PThumbImage;
begin
  flag:=not ImgView321.Bitmap.Empty;
  flag2:=RBLayerSelect=nil;

  if (flag=false) and (flag2=false) then begin
    freeandnil(RBLayerSelect);
    flag2:=true;
  end;

  for i:=3 to TBToolbar1.Items.Count-1 do begin
    TBToolbar1.Items[i].Enabled:=flag;
  end;
  for i:=0 to TBToolbar2.Items.Count-3 do begin
    if (TBToolbar2.Items[i]=btnresize) or (TBToolbar2.Items[i]=TBItem9) then
      TBToolbar2.Items[i].Enabled:=flag and flag2
    else
      TBToolbar2.Items[i].Enabled:=flag;
  end;

  c:=ListView1.SelCount;
  StatusBar1.Panels[5].Text:=format('%d개 선택됨.',[c]);
  if c>0 then begin
    PThumbImage1:=PThumbImage(listview1.Selected.Data);
    StatusBar1.Panels[0].Text:=ExtractFileName(PThumbImage1.name);
  end;
  StatusBar1.Panels[1].Text:=format('확대,축소: %d %%',[round(ImgView321.Scale*100)]);
  StatusBar1.Panels[2].Text:=format('%d X %d',[ImgView321.Bitmap.Width,ImgView321.Bitmap.Height]);
  
//  vistaaltfixonidle(sender,done);
end;

procedure TfrmMain.TBItem17Click(Sender: TObject);
var
  bitmap:Tbitmap;
  i:integer;
begin
  frmnewimage:=Tfrmnewimage.Create(self);
  try
    if frmnewimage.ShowModal<>mrok then exit;
    bitmap:=Tbitmap.Create;
    try
      try
        bitmap.PixelFormat:=pf24Bit;
        bitmap.Width:=frmnewimage.SpinEdit1.Value;
        bitmap.Height:=frmnewimage.SpinEdit2.Value;
        bitmap.Canvas.Brush.Color:=frmnewimage.ColorBox1.Selected;
        bitmap.Canvas.FillRect(rect(0,0,bitmap.Width,bitmap.Height));
      except
        on E: Exception do begin
          bitmap.Free;
          MessageDlg(E.Message,mtError, [mbOk], 0);
          exit;
        end;
      end;
      BrowserListView1.BrowserBitmapPointer('',bitmap);
      for i:=0 to listview1.Items.Count-1 do
        listview1.Items[i].Selected:=false;
      if listview1.Items.Count>0 then
        listview1.Items[listview1.Items.Count-1].Selected:=true;
    finally
//      bitmap.Free;
    end;
  finally
    frmnewimage.Free;
  end;
end;

procedure TfrmMain.TBItem18Click(Sender: TObject);
var
  bmp:Tbitmap;
  i:integer;
begin
  bmp:=tbitmap.Create;
  try
    try
      bmp.PixelFormat:=pf24Bit;
      bmp.LoadFromClipboardFormat(cf_BitMap,
            ClipBoard.GetAsHandle(cf_Bitmap), 0);
    except
      on E: Exception do begin
        bmp.Free;
        MessageDlg(E.Message,mtError, [mbOk], 0);
        exit;
      end;
    end;
    BrowserListView1.BrowserBitmapPointer('',bmp);
    for i:=0 to listview1.Items.Count-1 do
      listview1.Items[i].Selected:=false;
    if listview1.Items.Count>0 then
      listview1.Items[listview1.Items.Count-1].Selected:=true;
  finally
//    bmp.Free;
  end;
end;

procedure Tfrmmain.OneInstance1InstanceStarted(Sender: TObject; params: TStringList);
begin
  if params.Count>0 then
    loadfilelist(params.Strings[0]);
end;

procedure TfrmMain.btnselectmodeClick(Sender: TObject);
begin
  case (sender as TTBCustomItem).Tag of
    1:begin
      btnselectmode.Checked:=true;
    end;
    2:begin
      btnmovemode.Checked:=true;
      if RBLayerSelect<>nil then FreeAndNil(RBLayerSelect);
    end;
  end;
end;

procedure TfrmMain.N12Click(Sender: TObject);
begin
  blockselected:=true;
  ListView1.Items.BeginUpdate;
  try
    ListView1.SelectAll;
  finally
    ListView1.Items.EndUpdate;
    blockselected:=false;
  end;
end;

procedure TfrmMain.N13Click(Sender: TObject);
var
  bitmap:TBitmap;
  i,idx:integer;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
begin
  if ListView1.SelCount>1 then
    if MessageDlg('선택항목들을 바로 이전 작업까지 복구 하시겠습니까?',
        mtConfirmation, [mbYes, mbNo], 0)=mrNo then
    exit;

 Screen.Cursor:=crHourglass;
 try
  for i:=ListView1.Items.Count-1 downto 0 do begin
    if ListView1.Items[i].Selected=false then continue;
    PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
    workimagelist_get(PThumbImage1.idx, PWorkImage1);

    bitmap:=TBitmap.Create;
    screen.Cursor:=crHourglass;
    try
      bitmap.Assign(PWorkImage1.bitmap);
      idx:=PWorkImage1.UndoManage1.getcount-1;
      if PWorkImage1.UndoManage1.getundo(bitmap,idx+1) then begin
        PWorkImage1.bitmap.Assign(bitmap);
        if PThumbImage(ListView1.Items[i].Data).idx=workimageidx then
          ImgView321.Bitmap.Assign(PWorkImage1.bitmap);
      end;
    finally
      bitmap.Free;
      screen.Cursor:=crdefault;
    end;
    if PWorkImage1.orgchanged then PThumbImage1.changed:=true
    else PThumbImage1.changed:=PWorkImage1.UndoManage1.getcount>0;
    listview1.UpdateItems(i,i);
  end;
 finally
  Screen.Cursor := crdefault;
 end;
end;

procedure TfrmMain.ListView1DblClick(Sender: TObject);
var
  pt:tpoint;
  listitem:Tlistitem;
begin
  pt:=mouse.CursorPos;
  pt:=listview1.ScreenToClient(pt);
  listitem:=listview1.GetItemAt(pt.X,pt.Y);
  if listitem<>nil then begin
    if listitem.Selected then
      listitem.Selected:=false;
    listitem.Selected:=true;
  end;
end;

procedure TfrmMain.TBItem20Click(Sender: TObject);
var
  shortcut:Tshortcut;
  lVKey: word;
  lvShift: TShiftstate;
  lModifier: UINT;
  s:string;
begin
  shortcut:=TextToShortcut(config.c_screencapture_hotkey);
  lModifier := 0;
  ShortcutToKey(shortcut, lvKey, lvShift);
  if ssShift in lvShift  then lModifier := lModifier or MOD_SHIFT;
  if ssAlt in lvShift then lModifier := lModifier or MOD_ALT;
  if ssCtrl in lvShift then lModifier := lModifier or MOD_CONTROL;

  UnregisterHotKey(Handle, 0);
  if RegisterHotKey(Handle,0,lModifier,LOBYTE(lVKey))=False then begin
    MessageDlg(format('%s 키 등록에 실패했습니다. 다른 키를 프로그램설정에서 변경해보시기 바랍니다.',[config.c_screencapture_hotkey])
     , mtError, [mbok], 0);
  end else begin
    if (Sender as TTBItem).Tag=0 then
      capturetype:=ctwindow
    else if (Sender as TTBItem).Tag=2 then
      capturetype:=ctwindow2
    else if (Sender as TTBItem).Tag=1 then
      capturetype:=ctscreen
    else if (Sender as TTBItem).Tag=4 then
      capturetype:=ctselect
    else
      capturetype:=ctiexplore;
    if capturetype=ctiexplore then
      s:=format('인터넷 익스플로러 윈도우에 가신후 "%s" 키를 누르시면 됩니다.',[config.c_screencapture_hotkey])
    else if capturetype=ctselect then
      s:=format('캡쳐를 원하는 화면에 가신후 "%s" 키를 누르신후 마우스 드래그로 영역을 선택하시면 됩니다.',[config.c_screencapture_hotkey])
    else
      s:=format('캡쳐를 원하는 윈도우에 가신후 "%s" 키를 누르시면 됩니다.',[config.c_screencapture_hotkey]);

    showballoon('알림',s, self.ImgView321, mtInformation);
//    MessageDlg(format('%s 키를 캡쳐를 원하는 윈도우에 가신후 누르시면 됩니다.',[config.c_screencapture_hotkey]), mtInformation, [mbok],0);
  end;
end;

procedure TfrmMain.WndProc(var Message: TMessage);
var
  sourceBitmap:tbitmap;
  i:integer;
  pcFileName: PChar;
  iSize, iFileCount: integer;
  strlist:tstringlist;
  wnd:thandle;
begin
  with Message do
    case msg of
      WM_ACTIVATE:begin
        with TWMActivate(Message) do
          if Active=WA_INACTIVE then begin
             if assigned(balloon) then
               balloon.Close;
          end;
      end;

      WM_HotKey:begin
        case capturetype of
          ctwindow:screencapture(windows.GetForegroundWindow,capturetype);
          ctwindow2:screencapture(GetForegroundWindow,capturetype);
          ctscreen:screencapture(GetDesktopWindow,capturetype);
          ctselect:screencapture(GetForegroundWindow,capturetype);
          ctiexplore:screencapture(GetForegroundWindow,capturetype);
        end;
        if capturetype<>ctiexplore then begin
          Application.Restore;
          if self.WindowState = wsMinimized then
            self.WindowState := wsNormal;
          self.Visible := True;
          ForceForegroundWindow(handle);
        end;
        UnregisterHotKey(Handle, 0);
      end;
      wm_user+10000:begin
        for i:=0 to self.ControlCount-1 do
          self.Controls[i].Enabled:=true;
        for i:=0 to ListView1.Items.Count-1 do
          if ListView1.Items[i].Selected then
            ListView1.Items[i].Selected:=false;
        if ListView1.Items.Count>0 then
          ListView1.Items[ListView1.Items.Count-1].Selected:=true;
        ListView1.Items.EndUpdate;
        panel2.Visible:=false;
        clear_lastfilelist();        
        loading:=false;
//        screen.Cursor:=crdefault;
      end;
      wm_user+10001:begin
        self.ProgressBar1.Max:=wparam;
        self.ProgressBar1.Position:=lparam;        
      end;
      wm_user+10002:begin
        self.Label1.Caption:=pchar(wparam);
      end;

      WM_DROPFILES:begin
        if Panel2.Visible then begin
          messagedlg('작업중입니다...', mtError, [mbok],0);
          exit;
        end;
        strlist:=tstringlist.Create;
        pcFileName := ''; // to avoid compiler warning message
        iFileCount := DragQueryFile(Message.wParam, $FFFFFFFF, pcFileName, 255);
        for i := 0 to iFileCount - 1 do begin
          iSize := DragQueryFile(Message.wParam, i, nil, 0) + 1;
          pcFileName := StrAlloc(iSize);
          DragQueryFile(Message.wParam, i, pcFileName, iSize);
          strlist.Add(pcFileName);
          StrDispose(pcFileName);
        end;
        windows.SetForegroundWindow(handle);
        BrowserFile(strlist);
        DragFinish(Message.wParam);
      end;

    end;
  inherited;
end;

procedure TfrmMain.screencapture(wnd:thandle; capturetype:Tcapturetype);
var
  sourceBitmap:tbitmap;
  i:integer;
begin
  sourceBitmap:=tbitmap.Create;
  try
    try
     case capturetype of
       ctwindow: g_windowcapture(wnd,sourceBitmap);
       ctwindow2,ctscreen: g_screencapture2(wnd, sourceBitmap);
       ctselect: g_selectcapture(wnd, sourceBitmap);
 {      ctiexplore:
         if g_iexplorecapture2(wnd,sourceBitmap,false)=false then
           exit;}
     end;
     if (sourceBitmap.Width<=0) or (sourceBitmap.Height<=0) then begin
       sourceBitmap.Free;
       exit;
     end;
    except
      on E: Exception do begin
        sourceBitmap.Free;
        MessageDlg(E.Message,mtError, [mbOk], 0);
        exit;
      end;
    end;
    BrowserListView1.BrowserBitmapPointer('',sourceBitmap);
    for i:=0 to listview1.Items.Count-1 do
      listview1.Items[i].Selected:=false;
    if listview1.Items.Count>0 then
      listview1.Items[listview1.Items.Count-1].Selected:=true;
  finally
//    sourceBitmap.Free;
  end;
end;

procedure TfrmMain.FormResize(Sender: TObject);
begin
  if panel2.Visible then begin
    panel2.Left:=(self.ClientWidth div 2)-(panel2.Width div 2);
    panel2.Top:=(self.ClientHeight div 2)-(panel2.Height div 2);
  end;
end;

procedure TfrmMain.ImgView321MouseLeave(Sender: TObject);
begin
//  if loading then screen.Cursor:=crHourglass;
end;

procedure TfrmMain.cancelc_browserlistload(Sender: TObject);
begin
  BrowserListView1.ClearThread;
end;

procedure TfrmMain.cancelc_save(Sender: TObject);
begin
  savestopped:=true;
end;

procedure TfrmMain.N14Click(Sender: TObject);
begin
  mnuUndoClick(n7);
end;

procedure TfrmMain.N16Click(Sender: TObject);
var
  PThumbImage1:PThumbImage;
begin
  if ListView1.Selected=nil then exit;
  PThumbImage1:=PThumbImage(ListView1.Selected.Data);
  ShellExecute(0, 'open', pchar(ExtractFilePath(PThumbImage1.name)), nil, nil, SW_SHOW);
end;

procedure TfrmMain.TBItem23Click(Sender: TObject);
var
  f: THandle;
  buffer: array [0..MAX_PATH] of Char;
  i, numFiles: Integer;
  s,s1:string;
  strlist:tstringlist;
begin
  if not Clipboard.HasFormat(CF_HDROP) then begin
    MessageDlg('클립보드안에 파일리스트가 없습니다.'
      +#13#10+'윈도우탐색기등에서 Ctrl+C로 복사된 파일,폴더리스트만 가능합니다.', mterror, [mbOk],0);
    Exit;
  end;

  strlist:=tstringlist.Create;
  Clipboard.Open;
  try
    f := Clipboard.GetAsHandle(CF_HDROP);
    if f <> 0 then begin
      numFiles := DragQueryFile(f, $FFFFFFFF, nil, 0);
      for i := 0 to numfiles - 1 do begin
        buffer[0] := #0;
        DragQueryFile(f, i, buffer, SizeOf(buffer));
        s:=buffer;
        strlist.Add(s);
      end;
      BrowserFile(strlist);
    end;
  finally
    Clipboard.Close;
//    strlist.Free;
  end;
end;

procedure TfrmMain.TBItem25Click(Sender: TObject);
begin
  ShellExecute(0, 'open', 'http://iblogbox.com/nview', nil, nil, SW_SHOW);
end;

procedure TfrmMain.TBItem26Click(Sender: TObject);
begin
  ShellExecute(0, 'open', 'http://boom4u.net/lyrics', nil, nil, SW_SHOW);
end;

procedure TfrmMain.showballoon(title,msg:string;control:tcontrol;icontype:Tmsgdlgtype);
begin
  if config.c_enableballoon=false then exit;
  case icontype of
    mtWarning:balloon.BalloonIcon:=bWarning;
    mtError:balloon.BalloonIcon:=bError;
    mtInformation:balloon.BalloonIcon:=bInfo;
  end;
  balloon.Title:=title;
  balloon.Prompt.Clear;
  balloon.Prompt.Add(msg);
  balloon.AutoCloseMode:=acAction;
  balloon.Show(control);
end;

procedure TfrmMain.TBItem28Click(Sender: TObject);
begin
  frmratio:=Tfrmratio.Create(self);
  try
    frmratio.spinedit1.Value:=config.userratio;
    if frmratio.ShowModal=mrok then begin
      config.userratio:=frmratio.spinedit1.Value;
      config.ratio2:=frmratio.spinedit1.Value;
      imgview321.Scale:=config.ratio2 / 100;
      isfittoscreen:=false;
    end;
  finally
    frmratio.Free;
  end;
end;

function TfrmMain.listviewchanged():boolean;
var
  i:integer;
  PThumbImage1:PThumbImage;
begin
  result:=false;
  for i:=0 to listview1.Items.Count-1 do begin
    PThumbImage1:=PThumbImage(listview1.Items[i].Data);
    if PThumbImage1.changed then begin
      result:=true;
      break;
    end;
  end;
end;

procedure TfrmMain.setlistviewchange(PWorkImage1:PWorkImage;value:boolean);
var
  i:integer;
  PThumbImage1:PThumbImage;
begin
  for i:=0 to listview1.Items.Count-1 do begin
    PThumbImage1:=PThumbImage(listview1.Items[i].Data);
    if PThumbImage1.idx=PWorkImage1.idx then begin
      PThumbImage1.changed:=value;
      ListView1.UpdateItems(i,i);
      break;
    end;
  end;
end;

procedure TfrmMain.N18Click(Sender: TObject);
var
  i,ret,tag:integer;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
  s:string;
begin
  if MessageDlg('정말로 제거 하시겠습니까?',
     mtConfirmation, [mbYes, mbNo], 0) <> mrYes then exit;

ListView1.Items.BeginUpdate;
try
  tag:=(Sender as tmenuitem).Tag;
  ret:=0;
  for i:=ListView1.Items.Count-1 downto 0 do begin
    PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
    if ((tag=0) and (PThumbImage1.changed)) or ((tag=1) and (PThumbImage1.changed=false)) then begin
      workimagelist_get(PThumbImage1.idx, PWorkImage1);
      if PThumbImage1.changed and (ret<>mrAll) then begin
        s:=ExtractFileName(PThumbImage1.name);
        if s='' then s:='이름없음';
        s:=format('"%s" 이미지가 변경되었습니다. 그냥 제거 하시겠습니까?',[s]);
        ret:=MessageDlg(s, mtConfirmation, [mbYes, mbNo, mbAll], 0);
        if ret=mrNo then
          break;
      end;
      ListView1.Items[i].Delete;
    end;
  end;
  ListView1.Arrange(arAlignTop);
finally
  ListView1.Items.EndUpdate;
end;
end;

procedure TfrmMain.N21Click(Sender: TObject);
var
  PWorkImage1:PWorkImage;
  i:integer;
  listitem:tlistitem;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1<>nil then begin
    for i:=ListView1.Items.Count-1 downto 0 do begin
      if ListView1.Items[i].Selected then
        ListView1.Items[i].Selected:=false;
    end;
    listitem:=get_listitem(PWorkImage1.idx);
    if listitem<>nil then begin
      listitem.Selected:=true;
    end;
  end;
end;

procedure TfrmMain.TBItem29Click(Sender: TObject);
begin
  frmabout:=Tfrmabout.Create(self);
  try
    frmabout.Caption:=self.Caption;
    frmabout.ShowModal;
  finally
    frmabout.Free;
  end;
end;

procedure TfrmMain.load_cursor();
const
  CUR_LIST: array [0 .. 14] of string = ('CUR_PEN', 'CUR_BRUSH', 'CUR_ERASER',
    'CUR_SHAPE', 'CUR_SHAPE', 'CUR_SHAPE', 'CUR_SHAPE', 'CUR_TEXT',
    'CUR_SELCOLOR', 'CUR_FILL', 'CUR_SHAPE', 'CUR_SELECTIMAGE', 'CUR_ZOOM',
    'CUR_DRAG_DOWN', 'CUR_DRAG_MOVE');
var
  i:Integer;
begin
  for i := 0 to High(CUR_LIST) do
    Screen.Cursors[i + 1]:=LoadCursor(HInstance, PChar(CUR_LIST[i]));
end;

procedure TfrmMain.N23Click(Sender: TObject);
begin
  if RBLayerSelect<>nil then
    FreeAndNil(RBLayerSelect);
  xorg:=0;
  yorg:=0;
  Xmov:=ImgView321.Bitmap.Width;
  Ymov:=ImgView321.Bitmap.Height;
  DrawTheRect;
  ImgView321.Changed;
end;

procedure TfrmMain.ListView1DragOver(Sender, Source: TObject; X,
  Y: Integer; State: controls.TDragState; var Accept: Boolean);
var
  listitem:Tlistitem;
  i:integer;
begin
   if (y < 15) then begin
     for i:=0 to 1 do
       SendMessage(listview1.Handle,WM_VSCROLL,SB_LINEUP,0);
     listview1.Invalidate;
   end
   else if (listview1.Height - y < 15) then begin
     for i:=0 to 1 do
       SendMessage(listview1.Handle,WM_VSCROLL,SB_LINEDOWN,0);
     listview1.Invalidate;
   end;

  accept:=false;
//  if source<>listview1 then exit;
  listitem:=listview1.GetItemAt(x,y);
  if (listitem=nil) or (listitem.Selected) then exit;
  accept:=true
end;

procedure TfrmMain.ListView1DragDrop(Sender, Source: TObject; X,
  Y: Integer);
var
  i,j:integer;
  list:tlist;
  PThumbImage1:PThumbImage;
  listitem:Tlistitem;
  s:string;
begin
  listitem:=listview1.GetItemAt(x,y);
  if listitem=nil then exit;
  if listitem.Selected then exit;

  blockselected:=true;
  list:=tlist.Create;
  try
   for i:=0 to listview1.Items.Count-1 do begin
     if listview1.Items[i].Selected then begin
       list.Add(PThumbImage(listview1.Items[i].Data));
       listview1.Items[i].Data:=nil;
     end;
   end;
   listview1.DeleteSelected;

   j:=listitem.Index;
   for i:=list.Count-1 downto 0 do begin
     PThumbImage1:=PThumbImage(list.Items[i]);
     listitem:=listview1.Items.Insert(j);
     listitem.Caption:='';
     listitem.Data:=PThumbImage1;
     listitem.Selected:=true;
     if i=0 then listitem.Focused:=true;
   end;
   sortcolumn:=-1;
   listview1.OnCompare:=nil;
   listview1.AlphaSort;
  finally
    list.Free;
    blockselected:=false;
  end;
end;

procedure TfrmMain.N24Click(Sender: TObject);
var
  PThumbImage1:PThumbImage;
  i:integer;
  listitem:Tlistitem;
  s:string;
begin
  if listview1.SelCount<>1 then exit;
  if (Sender as tmenuitem).Tag=0 then begin
    i:=listview1.Selected.Index-1;
    if i<0 then exit;
  end else begin
    i:=listview1.Selected.Index+1;
    if i>listview1.Items.Count-1 then exit;
  end;
  blockselected:=true;
  PThumbImage1:=PThumbImage(listview1.Selected.Data);
  listview1.Selected.Data:=nil;
  listview1.Selected.Delete;
  listitem:=listview1.Items.Insert(i);
  listitem.Caption:='';
  listitem.Data:=PThumbImage1;
  listitem.Selected:=true;
  listitem.Focused:=true;
  sortcolumn:=-1;
  listview1.OnCompare:=nil;
  listview1.AlphaSort;
  listitem.MakeVisible(false);
  blockselected:=false;
end;

procedure TfrmMain.TBItem31Click(Sender: TObject);
var
  PThumbImage1:PThumbImage;
  PWorkImage1:PWorkImage;
  i,x,y:integer;
  bitmap:Tbitmap;
  onlyselected:boolean;
begin
  frmselect:=Tfrmselect.Create(self);
  try
    if frmselect.ShowModal<>mrok then exit;
    onlyselected:=frmselect.RadioButton2.Checked;
  finally
    frmselect.Free;
  end;

  frmmerge:=Tfrmmerge.Create(self);
  try
    for i:=0 to ListView1.Items.Count-1 do begin
      if onlyselected and (ListView1.Items[i].Selected=false) then
        continue;
      PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
      workimagelist_get(PThumbImage1.idx, PWorkImage1);
      frmmerge.sizelist.Add(PWorkImage1);
    end;
    if frmmerge.sizelist.Count<2 then begin
      MessageDlg('2개 이상의 이미지를 선택해주세요.',mtInformation, [mbOk], 0);
      exit;
    end;

    if frmmerge.ShowModal=mrok then begin

      screen.Cursor:=crHourglass;
      bitmap:=Tbitmap.Create;
      try
       try
        bitmap.PixelFormat:=pf24Bit;
        bitmap.Width:=frmmerge.SpinEdit2.Value;
        bitmap.Height:=frmmerge.SpinEdit3.Value;
        bitmap.Canvas.Brush.Color:=frmmerge.ColorBox1.Selected;
        bitmap.Canvas.FillRect(rect(0,0,bitmap.Width,bitmap.Height));

        x:=0;
        y:=0;
        for i:=0 to frmmerge.sizelist.Count-1 do begin
          PWorkImage1:=PWorkImage(frmmerge.sizelist.Items[i]);
          if frmmerge.CheckBox1.Checked then begin
            if frmmerge.ComboBox1.ItemIndex=0 then begin
              x:=(bitmap.Width div 2)-(PWorkImage1.bitmap.Width div 2);
            end else begin
              y:=(bitmap.Height div 2)-(PWorkImage1.bitmap.Height div 2);
            end;
          end;

          bitmap.Canvas.Draw(x,y,PWorkImage1.bitmap);

          if frmmerge.ComboBox1.ItemIndex=0 then begin  //세로
            y:=y+PWorkImage1.bitmap.Height;
            y:=y+frmmerge.SpinEdit1.Value;
          end else begin //가로
            x:=x+PWorkImage1.bitmap.Width;
            x:=x+frmmerge.SpinEdit1.Value;
          end;
        end;
       except
         on E: Exception do begin
           bitmap.Free;
           MessageDlg(E.Message,mtError, [mbOk], 0);
           exit;
         end;
       end;
        BrowserListView1.BrowserBitmapPointer('',bitmap);
        for i:=0 to listview1.Items.Count-1 do
          listview1.Items[i].Selected:=false;
        if listview1.Items.Count>0 then
          listview1.Items[listview1.Items.Count-1].Selected:=true;
      finally
//        bitmap.Free;
        screen.Cursor:=crdefault;
      end;

    end;
  finally
    frmmerge.Free;
  end;
end;

procedure TfrmMain.TBItem33Click(Sender: TObject);
var
  f:FREE_IMAGE_FORMAT;
  s:string;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
begin
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then exit;
  PThumbImage1:=PThumbImage(get_listitem(PWorkImage1.idx).Data);
  s:=PThumbImage1.name;

  f:=FIU_GetFIFType2(lowercase(ExtractFileExt(s)));
  case f of
    FIF_BMP,FIF_JPEG,FIF_PNG,FIF_TIFF:begin
      frmsaveopt:=Tfrmsaveopt.Create(self);
      try
        frmsaveopt.selectformat:=f;
        if frmsaveopt.ShowModal=mrok then ;
      finally
        frmsaveopt.Free;
      end;
    end;
  end;
end;

procedure TfrmMain.TBSubmenuItem1Popup(Sender: TTBCustomItem; FromLink: Boolean);
var
  f:FREE_IMAGE_FORMAT;
  s,ext:string;
  PWorkImage1:PWorkImage;
  PThumbImage1:PThumbImage;
begin
  TBItem33.Caption:='이미지 저장 옵션';
  TBItem33.Enabled:=false;
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1<>nil then begin
    PThumbImage1:=PThumbImage(get_listitem(PWorkImage1.idx).Data);
    s:=PThumbImage1.name;
    ext:=lowercase(ExtractFileExt(s));
    if (length(ext)>0) and (ext[1]='.') then
      delete(ext,1,1);
    f:=FIU_GetFIFType2(ext);
    case f of
      FIF_BMP,FIF_JPEG,FIF_PNG,FIF_TIFF:begin
        TBItem33.Caption:=format('"%s" 이미지 저장 옵션',[ext]);
        TBItem33.Enabled:=true;
      end;
    end;
  end;
end;

procedure TfrmMain.N26Click(Sender: TObject);
begin
  mnuClipboard1Click(mnuClipboard1);
end;

procedure TfrmMain.N27Click(Sender: TObject);
begin
  mnuClipboard1Click(mnuClipboard2);
end;

procedure TfrmMain.ImgView321Resize(Sender: TObject);
begin
  if isfittoscreen then
    fittoscreen();
end;

procedure TfrmMain.listview1OnCompare(Sender: TObject; Item1,
  Item2: TListItem; Data: Integer; var Compare: Integer);
var
	i: integer;
  data1,data2:PThumbImage;
begin
  i:=0;
  data1:=PThumbImage(Item1.Data);
  data2:=PThumbImage(Item2.Data);
	case sortcolumn of
   0:begin
     i:=_comparetext(ExtractFileName(data1.name),ExtractFileName(data2.name));
     if sortreverseorder[sortcolumn] then i:=-i;
   end;
   1:begin
    	if data1.time>data2.time then i:=-1
      else if data1.time<data2.time then i:=1
      else i:=0;
    	if sortreverseorder[sortcolumn] then i:=-i;
   end;
  end;

  if (sortcolumn<>0) and (i=0) then begin
    i:=_comparetext(ExtractFileName(data1.name),ExtractFileName(data2.name));
    if sortreverseorder[sortcolumn] then i:=-i;
  end;
  
  Compare:=i;
end;

procedure TfrmMain.N31Click(Sender: TObject);
begin
  case (sender as tmenuitem).Tag of
    0:begin
      sortcolumn:=0;
      sortreverseorder[0]:=false;
    end;
    1:begin
      sortcolumn:=0;
      sortreverseorder[0]:=true;
    end;
    2:begin
      sortcolumn:=1;
      sortreverseorder[1]:=false;
    end;
    3:begin
      sortcolumn:=1;
      sortreverseorder[1]:=true;
    end;
  end;
  listview1.OnCompare:=listview1OnCompare;
  listview1.AlphaSort;
end;

procedure TfrmMain.TBItem8Click(Sender: TObject);
var
  i:integer;
  PThumbImage1:PThumbImage;
  PWorkImage1:PWorkImage;
  onlyselected:boolean;
  gifdata:Pgifdata;
begin
  frmselect:=Tfrmselect.Create(self);
  try
    if frmselect.ShowModal<>mrok then exit;
    onlyselected:=frmselect.RadioButton2.Checked;
  finally
    frmselect.Free;
  end;

  frmGifAni:=TfrmGifAni.Create(self);
  try
    for i:=0 to ListView1.Items.Count-1 do begin
      if onlyselected and (ListView1.Items[i].Selected=false) then
        continue;
      PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
      workimagelist_get(PThumbImage1.idx, PWorkImage1);
      frmGifAni.imglist.Add(PWorkImage1);
      new(gifdata);
      gifdata.idx:=frmGifAni.imglist.Count-1;
      gifdata.name:=PThumbImage1.name;
      gifdata.transparent:=false;
      gifdata.left:=0;
      gifdata.top:=0;
      gifdata.delay:=frmGifAni.SpinEdit4.Value;
      gifdata.disposal:=frmGifAni.ComboBox2.ItemIndex;
      frmGifAni.giflist.Add(gifdata)
    end;
    frmGifAni.ShowModal;
  finally
    frmGifAni.Free;
  end;
end;

procedure TfrmMain.TBSubmenuItem8Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
begin
  TBItem31.Enabled:=listview1.Items.Count>0;
  TBItem8.Enabled:=listview1.Items.Count>0;
end;

procedure TfrmMain.TBSubmenuItem10Popup(Sender: TTBCustomItem;
  FromLink: Boolean);
var
  flag,flag2:boolean;
begin
  flag:=not ImgView321.Bitmap.Empty;
  flag2:=RBLayerSelect=nil;
  if (flag=false) and (flag2=false) then begin
    freeandnil(RBLayerSelect);
    flag2:=true;
  end;
  TBItem7.Enabled:=flag and flag2;
end;

procedure TfrmMain.TBItem27Click(Sender: TObject);
var
  i,idx:integer;
  PWorkImage1:PWorkImage;
  listitem:tlistitem;
begin
  if listview1.Items.Count=0 then
    exit;
  workimagelist_get(workimageidx, PWorkImage1);
  if PWorkImage1=nil then
    idx:=0
  else begin
    listitem:=get_listitem(PWorkImage1.idx);
    if listitem=nil then idx:=0
    else idx:=listitem.Index+1;
  end;
  if idx>listview1.Items.Count-1 then
    idx:=0;
  for i:=ListView1.Items.Count-1 downto 0 do begin
    if ListView1.Items[i].Selected then
     ListView1.Items[i].Selected:=false;
  end;
  listview1.Items[idx].Selected:=true;
end;

procedure TfrmMain.N35Click(Sender: TObject);
type
  T_proc_imageshack_upload = procedure (strlist:tstringlist); stdcall;
var
  DllHandle:thandle;
  proc_imageshack_upload:T_proc_imageshack_upload;
  strlist:tstringlist;
  PThumbImage1:PThumbImage;
  i:integer;
  flag:boolean;
begin
strlist:=tstringlist.Create;
try
  Screen.Cursor:=crHourGlass;
  try
    flag:=false;
    for i:=ListView1.Items.Count-1 downto 0 do begin
      if ListView1.Items[i].Selected=false then continue;
      PThumbImage1:=PThumbImage(ListView1.Items[i].Data);
      if (PThumbImage1.name='') or (PThumbImage1.changed) then begin
        if flag=false then begin
          flag:=true;
          MessageDlg('아직 저장되지 않았거나 변경후 저장되지 않은 이미지가 있습니다.'
                 +#13#10+'해당 이미지들은 업로드에서 제외됩니다.',mtinformation, [mbOk], 0);
        end;
        continue;
      end;
      if sysutils.FileExists(PThumbImage1.name)=false then continue;
      strlist.Add(PThumbImage1.name);
    end;
  finally
    Screen.Cursor:=crdefault;
  end;
{
  if strlist.Count=0 then begin
    MessageDlg('선택한 파일이 없습니다.',mterror, [mbOk], 0);
    exit;
  end;
}
  DllHandle:=LoadLibrary(PChar(GetAppDirectory2+'libupload.dll'));
  if DllHandle>0 then begin
    try
      proc_imageshack_upload:=GetProcAddress(DllHandle, 'proc_imageshack_upload');
      if assigned(proc_imageshack_upload) then begin
{        if strlist.Count>0 then
          if MessageDlg(format('%d개의 파일을 무료이미지 업로드 하시겠습니까? ',[strlist.Count]),
             mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
           exit;}
        proc_imageshack_upload(strlist);
      end else
        MessageDlg('오류입니다.',mterror, [mbOk], 0);
    finally
      freelibrary(DllHandle);
    end;
  end else
    MessageDlg('필요한 라이브러리를 읽을 수 없습니다. 프로그램 재설치가 필요할 수 있습니다.',mterror, [mbOk], 0);
finally
  strlist.Free;
end;
end;

end.
