unit UnitFrmEditHistory;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, UnitClipQueue, ComCtrls, ExtCtrls, {xpman,} Menus, Buttons,
  ImgList, UnitFrameClipDisplay, UnitFramePermanentClips, UnitFrameImport,
  Vcl.CategoryButtons;

type
  TfrmEditHistory = class(TForm)
    {$REGION 'default'}
    pcPages: TPageControl;
    tsPopup: TTabSheet;
    RemovedFindDialog1: TFindDialog;
    Panel2: TPanel;
    pmDelete: TPopupMenu;
    DeleteClip1: TMenuItem;
    DestroyClip1: TMenuItem;
    btnRemovedConfig: TSpeedButton;
    TabSheet1: TTabSheet;
    Label2: TLabel;
    Panel4: TPanel;
    pmExport: TPopupMenu;
    SaveallSelected1: TMenuItem;
    N1: TMenuItem;
    SaveallTXT1: TMenuItem;
    SaveallBMP1: TMenuItem;
    SaveallRichText1: TMenuItem;
    sdExport: TSaveDialog;
    odExport: TOpenDialog;
    FrameClipDisplay2: TFrameClipDisplay;
    tsPermanent: TTabSheet;
    N3: TMenuItem;
    MIRemoveAllClips1: TMenuItem;
    FramePermanentClips1: TFramePermanentClips;
    tsImport: TTabSheet;
    FrameImport1: TFrameImport;
    pmHistory: TPopupMenu;
    MIEdit1: TMenuItem;
    MICopy1: TMenuItem;
    MIRemove1: TMenuItem;
    N2: TMenuItem;
    MIExportTo1: TMenuItem;
    MIMore1: TMenuItem;
    N4: TMenuItem;
    MIDeleteAll1: TMenuItem;
    MIDestroySelected1: TMenuItem;
    cbxHistory: TComboBox;
    pcHistory: TPageControl;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    lbRemovedList: TListBox;
    pnl1: TPanel;
    btnTop: TSpeedButton;
    btnUp: TSpeedButton;
    btnDown: TSpeedButton;
    btnBottom: TSpeedButton;
    lbPopupQueue: TListBox;
    btnFind: TSpeedButton;
    CategoryButtons1: TCategoryButtons;
    pcHelp: TPageControl;
    tsHelpPopup: TTabSheet;
    tsHelpRemoved: TTabSheet;
    tsHelpCommandMenu: TTabSheet;
    tsHelpPermanent: TTabSheet;
    lblhelp: TLabel;
    txtCommands: TRichEdit;
    Label3: TLabel;
    Label4: TLabel;
    Label1: TLabel;
    Label5: TLabel;
    tsHelpSystemGroup: TTabSheet;
    Label6: TLabel;
    tsHelpPermanentGroups: TTabSheet;
    Label7: TLabel;
    tsHelpGlobalHotkeys: TTabSheet;
    Label8: TLabel;
    tsHelpAboutDatabases: TTabSheet;
    Label9: TLabel;
    ImageList1: TImageList;
    pnl2: TPanel;
    lblPopupClips: TLabel;
    Label10: TLabel;
    lblPopupClipsSize: TLabel;
    Label12: TLabel;
    lblRemovedClipsSize: TLabel;
    tsThumbDrives: TTabSheet;
    Label11: TLabel;
    tsSharedGroups: TTabSheet;
    Label13: TLabel;
    tsFormMode: TTabSheet;
    Label14: TLabel;
    tsExternal: TTabSheet;
    ScrollBox1: TScrollBox;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    tsJScriptMain: TTabSheet;
    ScrollBox2: TScrollBox;
    Label20: TLabel;
    Label19: TLabel;
    Label21: TLabel;
    tsDateCommand: TTabSheet;
    Memo1: TMemo;
    tsJScriptComm: TTabSheet;
    ScrollBox3: TScrollBox;
    Label26: TLabel;
    Label27: TLabel;
    Label28: TLabel;
    Label24: TLabel;
    Label25: TLabel;
    Label29: TLabel;
    Label30: TLabel;
    Label22: TLabel;
    Label23: TLabel;
    Label31: TLabel;
    Label32: TLabel;
    Label33: TLabel;
    Label34: TLabel;
    Label35: TLabel;
    tsJScriptPurpose: TTabSheet;
    ScrollBox4: TScrollBox;
    Label36: TLabel;
    procedure FormShow(Sender: TObject);







    procedure btnRemovedConfigClick(Sender: TObject);
    procedure lbRemovedListDrawItem(Control: TWinControl; Index: Integer; Rect: TRect;
      State: TOwnerDrawState);
    procedure lbRemovedListClick(Sender: TObject);
    procedure lbRemovedListMeasureItem(Control: TWinControl; Index: Integer;
      var Height: Integer);
    procedure RemovedFindDialog1Show(Sender: TObject);
    procedure RemovedFindDialog1Find(Sender: TObject);
    procedure RemovedCreatePlainTextClick(Sender: TObject);
    procedure RemovedCreateClipClick(Sender: TObject);

    procedure lbPopupQueueClick(Sender: TObject);





    procedure btnTopClick(Sender: TObject);
    procedure btnUpClick(Sender: TObject);
    procedure btnDownClick(Sender: TObject);
    procedure btnBottomClick(Sender: TObject);
    procedure lbPopupQueueDrawItem(Control: TWinControl; Index: Integer; Rect: TRect;
      State: TOwnerDrawState);
    procedure lbPopupQueueKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure lbPopupQueueMeasureItem(Control: TWinControl; Index: Integer;
      var Height: Integer);




    procedure FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure pcPagesChange(Sender: TObject);


    procedure odExportCanClose(Sender: TObject; var CanClose: Boolean);

    procedure FormCreate(Sender: TObject);

    procedure lbMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure pmHistoryPopup(Sender: TObject);
    procedure MIEdit1Click(Sender: TObject);
    procedure MICopy1Click(Sender: TObject);
    procedure MIRemove1Click(Sender: TObject);
    procedure MIDestroySelected1Click(Sender: TObject);
    procedure MIDeleteAll1Click(Sender: TObject);
    procedure MIExportTo1Click(Sender: TObject);
    procedure cbxHistoryChange(Sender: TObject);

    procedure changeHistoryPage(index : integer);
    procedure btnFindClick(Sender: TObject);
    procedure CategoryPanel3Expand(Sender: TObject);
    procedure CategoryButtons1Categories0Items0Click(Sender: TObject);
    procedure CategoryButtons1Categories0Items1Click(Sender: TObject);
    procedure CategoryButtons1ButtonClicked(Sender: TObject;
      const Button: TButtonItem);
    procedure lblPopupClipsClick(Sender: TObject);


    {$ENDREGION}
  private
    { Private declarations }
        fskipconfirmationonce : boolean;
    	maxpopupheader, maxremovedheader : integer;
        ci : TClipItem;
        clickedLB : TListBox;
        ignoreRemovedUpdates : boolean;
        function RemovedClickedClip : TClipItem;

        function IsSafeToMove : boolean;
        procedure SaveTextItemsOrder;
        procedure NewRemovedClipEvent(Sender : TObject);
        procedure SkipConfirmationOnce;
        procedure refreshHistory;
  protected
        procedure CreateParams(var Params: TCreateParams); override;
  public
    { Public declarations }
        procedure ShowRemoved;
        procedure ShowPermanent; overload;
        procedure ShowPermanent(groupID : integer; clipID : integer); overload;
        procedure ShowPermanent(group : string); overload;
        procedure ShowPermanent(groupID : integer); overload;
        procedure ShowPermanent(ci : TClipITem); overload;
        procedure ShowPermenentAs(plaintext : string);
        procedure ShowPermanentSystem;
        procedure ShowPermanentFormMode;
        procedure ShowPopup;
        procedure ShowPopupModal;


        procedure FlushPopup;
        procedure FlushRemoved;
  end;

var
  frmEditHistory: TfrmEditHistory;

implementation

{$R *.dfm}

uses StrUtils, Clipbrd, UnitFrmHotKey, UnitFrmConfig,
  UnitFrmClipboardManager, UnitPaste, Math, UnitMisc, UnitFrmEditItem,
  UnitFrmEditTextExternal, UnitToken, UnitFrmPermanentNew, INIFiles, UnitKeyboardQuery, UnitListBoxMover,
  {$WARN UNIT_PLATFORM OFF} VCL.FileCtrl, {$WARN UNIT_PLATFORM ON}
  UnitSpecialPaths, UnitFrmMainPopup, UnitPopupGenerate, UnitFrmDebug,
  UnitClipDatabase, UnitFrmPermanentEdit;

{ TfrmNewEditHistory }
procedure TfrmEditHistory.SkipConfirmationOnce;
begin
    self.fskipconfirmationonce := true;
end;
procedure TfrmEditHistory.FlushPopup;
begin
    ClipQueue.ClearQueue;
    lbPopupQueue.Items.Clear;
    FrameClipDisplay2.ShowClip('');

    self.FormShow(self);
end;
procedure TfrmEditHistory.FlushRemoved;
begin
    RemovedQueue.ClearQueue;
    lbRemovedList.Items.Clear;
    FrameClipDisplay2.ShowClip('');

    self.FormShow(self);
end;

procedure TfrmEditHistory.CreateParams(var Params: TCreateParams);
begin
    inherited CreateParams(Params);
    // allow context taskbar context menu and
    // show me on the taskbar - independant of main form
    with Params do begin
        ExStyle := ExStyle or WS_EX_APPWINDOW;
        WndParent := GetDesktopwindow;
    end;
end;

procedure TfrmEditHistory.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    RemovedQueue.ClearClipCache;
    lbPopupQueue.Clear;
    RemovedFindDialog1.CloseDialog;
end;
procedure TfrmEditHistory.FormCreate(Sender: TObject);
    procedure FormatTheHelpText;
    var
        s : string;
        line : string;
    begin
        s := txtCommands.Text;
        txtCommands.Text := '';
        txtCommands.Lines.Clear;
        UnitToken.TokenString(s, '{', false);

        while s <> '' do begin
            line := UnitToken.TokenString(s,'}', false);
            with txtCommands do begin
                SelStart := length(txtCommands.Text);
                SelAttributes.Style := [fsBold];
                Lines.Add(line);
                SelAttributes.Style := [];
                line := UnitToken.TokenString(s, '{', false);
                lines.Add(line);
            end;
        end;
    end;
var
    i : integer;
begin
    FrameClipDisplay2.Color := clWhite;
    FrameClipDisplay2.SetScrollbars(ssVertical);
    FrameClipDisplay2.Enabled := true;
    FrameClipDisplay2.NoRawHTML := true;

    RemovedQueue.addNewClipListener(NewRemovedClipEvent);

    FormatTheHelpText;

    for i := 0 to pcHistory.PageCount - 1 do begin
        pcHistory.Pages[i].TabVisible := false;
    end;
    pcHistory.ActivePageIndex := 0;

    for i := 0 to pcHelp.PageCount - 1 do begin
        pcHelp.Pages[i].TabVisible := false;
    end;
    pcHelp.ActivePageIndex := tsHelpPopup.PageIndex;
    CategoryButtons1.SelectedItem :=   CategoryButtons1.Categories[0].Items[0];

    
end;
procedure TfrmEditHistory.NewRemovedClipEvent(Sender : TObject);
begin
    if ignoreRemovedUpdates then EXIT;

    if (self.Showing) and (pcPages.ActivePageIndex=tsPopup.PageIndex) then begin
        self.FormShow(nil);
        lbRemovedList.Invalidate;
    end;
end;
procedure TfrmEditHistory.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
    if (KEY = VK_ESCAPE) then begin
        self.ModalResult := mrok;
        self.close;
    end;
end;
procedure TfrmEditHistory.FormShow(Sender: TObject);
var i : longint;
    procedure AddItems(clips : TClipQueue; listbox : TListBox);
    var i : integer;
        s : string;
        ci : TClipItem;
    begin
        for i := 0 to (clips.GetQueueCount - 1) do begin
            ci := clips.GetClipItem(i);
            s := ci.GetAsPlaintext;
            if ci.GetFormatType = FT_PICTURE then begin
            	s := ci.GetFormatName; 
            end;

            listbox.Items.AddObject(LeftStr(s,300), TObject(ci) );
        end;
    end;

begin
    if (pcPages.ActivePageIndex = tsPopup.PageIndex) then begin
        self.refreshHistory;
    end;

    if pcPages.ActivePageIndex = tsPermanent.PageIndex then begin
        FramePermanentClips1.loadPermanent;
    end;

    if pcPages.ActivePageIndex = tsImport.PageIndex then begin
        FrameImport1.load;
    end;
end;
procedure TfrmEditHistory.pcPagesChange(Sender: TObject);
begin
    maxpopupheader := 0;
    maxremovedheader := 0;

    self.FormShow(sender);
end;


procedure TfrmEditHistory.pmHistoryPopup(Sender: TObject);
begin
    MICopy1.Enabled := clickedLB.SelCount = 1;
    MIEdit1.Enabled := clickedLB.SelCount = 1;

    MIDestroySelected1.Enabled := clickedLB = lbPopupQueue;
end;

procedure TfrmEditHistory.SaveTextItemsOrder;
var i, index : longint;
    ci : TClipItem;
begin
    for i := (lbPopupQueue.Items.count - 1) downto 0 do begin
        ci := TClipItem(lbPopupQueue.items.Objects[i]);
        index := ClipQueue.IndexOf(ci);
        if (i <> index) then begin
            ClipQueue.Move(index, i);
        end;
    end;
end;

procedure TfrmEditHistory.ShowPopup;
begin
	pcPages.ActivePageIndex := tsPopup.PageIndex;
    changeHistoryPage(0);
    self.show;
end;
procedure TfrmEditHistory.ShowPopupModal;
begin
    pcPages.ActivePageIndex := tsPopup.PageIndex;
    changeHistoryPage(0);
    self.ShowModal;
end;
procedure TfrmEditHistory.ShowRemoved;
begin
	pcPages.ActivePageIndex := tsPopup.PageIndex;
    changeHistoryPage(1);
    self.Show;
end;
procedure TfrmEditHistory.ShowPermanent;
begin
    pcPages.ActivePageIndex := tsPermanent.PageIndex;
    self.Show;
end;
procedure TFrmEditHistory.ShowPermanentSystem;
begin
    self.showPermanent;
    FramePermanentClips1.ShowPermGroup(SYSTEM_FOLDER);
end;
procedure TFrmEditHistory.ShowPermanentFormMode;
begin
    self.showPermanent;
    FramePermanentClips1.ShowPermGroup(FORM_MODE_FOLDER);
end;
procedure TFrmEditHistory.ShowPermanent(group : string);
begin
    ShowPermanent;
    FramePermanentClips1.ShowPermGroup(group);
end;
procedure TFrmEditHistory.ShowPermanent(groupID : integer);
begin
    ShowPermanent;
    self.ShowPermanent(FrmPermanent.PermFoldersGetItem(groupID));
end;
procedure TFrmEditHistory.ShowPermanent(ci : TClipITem);
var mr : integer;
begin
    self.ShowPermanent(FrmPermanent.GetPermanentPath);
    FramePermanentClips1.positionPermanentEdit;
    FrmPermanentEdit.SetNewItem(ci, mr);
    if (mr = mrOk) then begin
        FramePermanentClips1.loadPermanent;
        self.ShowPermanent(FrmPermanent.GetPermanentPath);
    end;
end;
procedure TFrmEditHistory.ShowPermenentAs(plaintext : string);
begin
    self.ShowPermanent(FrmPermanent.GetPermanentPath);
    FramePermanentClips1.positionPermanentEdit;
    FrmPermanentEdit.SetNewItem(plaintext,'');
end;
procedure TFrmEditHistory.ShowPermanent(groupID : integer; clipID : integer);
begin
    self.ShowPermanent;
    if groupID = -1 then begin
        FramePermanentClips1.ShowPermGroup(FrmPermanent.GetPermanentPath, clipID);
    end else begin
        FramePermanentClips1.ShowPermGroup(FrmPermanent.PermFoldersGetItem(groupID), clipID);
    end;
end;


procedure TFrmEditHistory.changeHistoryPage(index : integer);
begin
    pcHistory.ActivePageIndex := index;
    self.cbxHistory.ItemIndex := index;

    if (index = tsPopup.PageIndex) then begin
        clickedLB := lbPopupQueue;
        btnFind.Visible := false;

        if lbPopupQueue.Count <> ClipQueue.GetQueueCount then begin
            self.refreshHistory;
        end;
    end else begin
        clickedLB := lbRemovedList;
        btnFind.Visible := true;

        if lbRemovedList.Count <> RemovedQueue.GetQueueCount then begin
            self.refreshHistory;
        end;

    end;
end;


///
/// History
///


procedure TfrmEditHistory.refreshHistory;
var
    b : boolean;
    i : integer;
    s : string;
    ci : TClipItem;
begin
    FrameClipDisplay2.ShowClip('');



    lblPopupClipsSize.Caption := Format('%d',[ClipQueue.GetQueueSize]);
    lblRemovedClipsSize.Caption := Format('%d',[RemovedQueue.getQueueSize]);

    FrmDebug.AppendLog('refresh - popup count='+IntToStr(ClipQueue.GetQueueCount));
    FrmDebug.AppendLog('refresh - removed count='+IntToStr(RemovedQueue.GetQueueCount));
    FrmDebug.AppendLog('refresh - db count ='+IntToStr(TClipDatabase.getCountRemoved));

    if cbxHistory.ItemIndex = 1 then begin

        lbRemovedList.Items.Clear;
        lbRemovedList.Items.BeginUpdate;

        RemovedQueue.PreloadCache;

        for i := (RemovedQueue.GetQueueCount - 1) downto 0 do begin
            lbRemovedList.Items.Add('TEST TEXT HERE');
        end;
        lbRemovedList.Items.EndUpdate;

    end else begin
        lbPopupQueue.Items.Clear;
        lbPopupQueue.Items.BeginUpdate;
        for i := 0 to (ClipQueue.GetQueueCount - 1) do begin
            ci := ClipQueue.GetClipItem(i);
            s := ci.GetAsPlaintext;
            if (ci.GetFormatType = FT_PICTURE) then begin
                s := ci.GetFormatName;
            end;

            lbPopupQueue.Items.Add(LeftStr(s,300));
        end;
        lbPopupQueue.Items.EndUpdate;
    end;
end;
procedure TfrmEditHistory.MICopy1Click(Sender: TObject);
var
    cix : TClipItem;
    i, x : integer;
begin
    for i :=0 to clickedLB.Count-1 do begin
        if (clickedLB.Selected[i]) then begin
            if (clickedLB = lbPopupQueue) then begin
                x := i;
            end else begin
                cix := RemovedQueue.GetItemClip(i)
            end;
            BREAK;
        end;
    end;

    if (clickedLB = lbRemovedList) then begin
        ClipQueue.InsertAtStart(cix);
        // using event notifications instead
        //self.refreshHistory;
    end else begin
        Paste.SetClipboardOnlyOnce;
        Paste.SendClip(ClipQueue.GetClipItem(x));
    end;
end;
procedure TfrmEditHistory.MIDeleteAll1Click(Sender: TObject);
var
    s : string;
begin
    if (clickedLB = lbPopupQueue) then begin
        s := 'Delete all Popup Clips?'
    end else begin
        s := 'Delete all Removed Clips?';
    end;
    if not (MessageDlg(s, mtConfirmation, [mbyes, mbno],0) = mrYes) then
    EXIT;

    if (clickedLB = lbPopupQueue) then begin
        ClipQueue.ClearQueue;
    end else begin
        RemovedQueue.ClearQueue;
    end;

    self.refreshHistory;
end;
procedure TfrmEditHistory.MIDestroySelected1Click(Sender: TObject);
var
    i : integer;
begin
    if not (MessageDlg('Destroy: Permanently delete the selected clips?', mtConfirmation, [mbyes, mbno],0) = mrYes) then
    EXIT;

    TClipDatabase.StartBatch;
    for i:= clickedLB.count-1 downto 0 do begin
        if clickedLB.Selected[i] then begin
            ClipQueue.DestroyItem(i);
        end;
    end;
    TClipDatabase.EndBatch;

    self.refreshHistory;
end;
procedure TfrmEditHistory.MIEdit1Click(Sender: TObject);
var
    ci : TClipItem;
begin
    if (clickedLB = lbPopupQueue) then begin
        ci := ClipQueue.GetClipItem(lbPopupQueue.itemindex);
    end else begin
        ci := RemovedQueue.GetItemClip(lbRemovedList.ItemIndex)
    end;


    if frmConfig.cbEditClipWindow.checked then begin
        FrmEditItem.SetText(ci.GetAsPlaintext, nil);
        FrmMainPopup.ShowPreviewEditForm;
    end else begin
        frmEditTextExternal.EditClip(ci);
        self.Show;
    end;

    if (clickedLB = lbRemovedList) then begin
        myfree(ci);
    end;
end;
procedure TfrmEditHistory.MIExportTo1Click(Sender: TObject);
var s, num : string;
    i,j : integer;
    ci : TClipItem;
begin
    s := SpecialPaths.GetMyDocs;
    if not VCL.FileCtrl.SelectDirectory(
        'Save as [Text, RichText, Pictures] in a Single Folder',
        WideString(''),
        s,
        [sdNewFolder, sdShowEdit, sdShowShares, sdNewUI, sdValidateDir],
        self
    ) then
    EXIT;

    for i := 0 to clickedLB.count - 1 do begin
        if clickedLB.Selected[i] then begin
            j := 0;
            repeat
                inc(j);
                num := Format('%.4d',[j]);
            until   not (
                FileExists(IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.txt') or
                FileExists(IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.rtf') or
                FileExists(IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.bmp')
            );

            if (clickedLB = lbPopupQueue) then begin
                ci := ClipQueue.GetClipItem(i);
            end else begin
                ci := RemovedQueue.GetItemClip(i);
            end;

            case ci.GetFormatType  of
            FT_RICHTEXT: begin
                frmEditTextExternal.SaveClip(
                    IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.rtf',
                    ci
                );
            end;
            FT_PICTURE: begin
                frmEditTextExternal.SaveClip(
                    IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.bmp',
                    ci
                );
            end;
            else begin
                frmEditTextExternal.SaveClip(
                    IncludeTrailingPathDelimiter(s) + 'PopupClip'+num+'.txt',
                    ci
                );
            end;
            end;
            if (clickedLB = lbRemovedList) then begin
                myfree(ci);
            end;
        end;
    end;

    if MessageDlg('Clips saved to folder: ' + s +#13#10#13#10 +
                'Open this folder in Explorer?',
                mtConfirmation, [mbYes, mbNo],0,mbYes
    ) = mrYes then begin
        Paste.SendMacro(KEYS_STR+'[RUN]'+ s);
    end;
end;
procedure TfrmEditHistory.MIRemove1Click(Sender: TObject);
var
    i : integer;
begin
    if not(MessageDlg('Delete the selected clips?', mtConfirmation, [mbyes, mbno],0) = mrYes) then
    EXIT;


    ignoreRemovedUpdates := true;
    for i:= clickedLB.count-1 downto 0 do begin
        if clickedLB.Selected[i] then begin
            if (clickedLB = lbPopupQueue) then begin
                ClipQueue.DeleteItem(i);
            end else begin
                RemovedQueue.DeleteItem(i);
            end;
        end;
    end;
    ignoreRemovedUpdates := false;


    self.refreshHistory;
end;


function TfrmEditHistory.IsSafeToMove: boolean;
var ci : TClipItem;
begin
    result := true;
end;



procedure TfrmEditHistory.btnBottomClick(Sender: TObject);
var i, x : integer;
begin
    if (IsSafeToMove) then begin
        i := lbPopupQueue.ItemIndex;
        x := lbPopupQueue.Count - 1;
        ClipQueue.Move(i, x);
        self.refreshHistory;
        lbPopupQueue.ItemIndex := x;
    end;
end;
procedure TfrmEditHistory.btnDownClick(Sender: TObject);
var i, x : integer;
begin
    if (IsSafeToMove) then begin
        i := lbPopupQueue.ItemIndex;
        x := i + 1;
        ClipQueue.Move(i, x);
        self.refreshHistory;
        lbPopupQueue.ItemIndex := x;
    end;
end;

procedure TfrmEditHistory.btnTopClick(Sender: TObject);
var i, x : integer;
begin
    if (IsSafeToMove) then begin
        i := lbPopupQueue.ItemIndex;
        x := 0;
        ClipQueue.Move(i, x);
        self.refreshHistory;
        lbPopupQueue.ItemIndex := x;
    end;
end;
procedure TfrmEditHistory.btnUpClick(Sender: TObject);
var i, x : integer;
begin
    if (IsSafeToMove) then begin
        i := lbPopupQueue.ItemIndex;
        x := i - 1;
        ClipQueue.Move(i, x);
        self.refreshHistory;
        lbPopupQueue.ItemIndex := x;
    end;
end;



//
//  Removed Clips Functions
//










procedure TfrmEditHistory.CategoryButtons1ButtonClicked(Sender: TObject;
  const Button: TButtonItem);
var s : string;
    i : integer;
begin
    s := button.Caption;

    for i := 0 to pcHelp.PageCount-1 do begin
        if (s = pcHelp.Pages[i].Caption) then begin
            pcHelp.ActivePageIndex := i;
            BREAK;
        end;
    end;

(*
    if (s = 'Popup') then begin
        pcHelp.ActivePageIndex := tsHelpPopup.PageIndex;
    end else if (s = 'Removed') then begin
        pcHelp.ActivePageIndex := tsHelpRemoved.PageIndex;
    end else if (s = 'Permanent Clips') then begin
        pcHelp.ActivePageIndex := tsHelpPermanent.PageIndex;
    end else if (s = 'Permanent Groups') then begin
        pcHelp.ActivePageIndex := tsHelpPermanentGroups.PageIndex;
    end else if (s = '_System Group') then begin
        pcHelp.ActivePageIndex := tsHelpSystemGroup.PageIndex;
    end else if (s = 'Command Menu Reference') then begin
        pcHelp.ActivePageIndex := tsHelpCommandMenu.PageIndex;
    end else if (s = 'Global Hotkeys') then begin
        pcHelp.ActivePageIndex := tsHelpGlobalHotkeys.PageIndex;
    end else if (s = 'About Databases') then begin
        pcHelp.ActivePageIndex := tsHelpAboutDatabases.PageIndex;
    end else if (s = 'Thumb / External Drives') then begin
        pcHelp.ActivePageIndex := tsThumbDrives.PageIndex;
    end else if (s = 'Shared Permanent Groups') then begin
        pcHelp.ActivePageIndex := tsSharedGroups.PageIndex;
    end else if (s = '_Form Mode Group') then begin
        pcHelp.ActivePageIndex := tsFormMode.PageIndex;
    end else if (s = 'External Programs') then begin
        pcHelp.ActivePageIndex := tsExternal.PageIndex;
    end else if (s = 'Purpose') then begin
        pcHelp.ActivePageIndex := tsJScriptPurpose.PageIndex;
    end else if (s = ts'Purpose') then begin
        pcHelp.ActivePageIndex := tsJavaScript.PageIndex;

    end else if (s = 'Date Command') then begin
        pcHelp.ActivePageIndex := tsDateCommand.PageIndex;
    end;
*)
end;

procedure TfrmEditHistory.CategoryButtons1Categories0Items0Click(
  Sender: TObject);
begin
    pcHelp.ActivePageIndex := tsHelpPopup.PageIndex;
end;

procedure TfrmEditHistory.CategoryButtons1Categories0Items1Click(
  Sender: TObject);
begin
pcHelp.ActivePageIndex := tsHelpRemoved.PageIndex;
end;

procedure TfrmEditHistory.CategoryPanel3Expand(Sender: TObject);
begin
    txtCommands.Align := alNone;
    txtCommands.Align := alClient;
end;

procedure TfrmEditHistory.btnFindClick(Sender: TObject);
begin
    RemovedFindDialog1.Execute(self.Handle);
end;

procedure TfrmEditHistory.btnRemovedConfigClick(Sender: TObject);
begin
    frmconfig.pcPanels.ActivePageIndex := frmconfig.tsHistory.PageIndex;
    frmconfig.Show;
end;



function TfrmEditHistory.RemovedClickedClip: TClipItem;
var i : integer;
begin
    result := nil;
    if lbRemovedList.ItemIndex = -1 then EXIT;

    i := lbRemovedList.ItemIndex;
    result := RemovedQueue.GetItemClip(i);
end;



procedure TfrmEditHistory.RemovedCreateClipClick(Sender: TObject);
begin
    MyFree(ci);
    ci := self.RemovedClickedClip;
    if (ci<>nil) then
        frmEditHistory.ShowPermanent(ci);
end;
procedure TfrmEditHistory.RemovedCreatePlainTextClick(Sender: TObject);
begin
    MyFree(ci);
    ci := self.RemovedClickedClip;
    frmEditHistory.ShowPermenentAs(ci.GetAsPlaintext);
end;


procedure TfrmEditHistory.RemovedFindDialog1Find(Sender: TObject);
var i,j, a,b, textIndex : integer;
    s, findText : string;

    pc : PChar;
    op : TStringSearchOptions;
    cl : TClipList;
    reversed : boolean;
label EXIT_CODE;
begin
    if lbRemovedList.Count = 0 then EXIT;

    // select the first item in the list by default
    // translate the index because RemovedCach is stored oldest first
    if lbRemovedList.itemindex = -1 then begin
        lbRemovedList.ItemIndex := 0;
        lbRemovedListClick(lbRemovedList);
    end;
    i := clickedLB.ItemIndex;

    findText := RemovedFindDialog1.FindText;
    findText := StringReplace(findText, chr($20), chr($a0),[rfReplaceAll]);

    op := [soDown];
    if frMatchCase in RemovedFindDialog1.options then op := op + [soMatchCase];
    if frwholeword in RemovedFindDialog1.options then op := op + [soWholeWord];

    reversed := not (frDown in RemovedFindDialog1.Options);

    if (reversed) then begin
        a := 0;
        b := i;
        TClipDatabase.StartTextOnlyData(a,b-1,reversed);
        for j := b-1 downto a do begin
            TClipDatabase.LoadNextText(s);
            pc := TextPos(PCHar(s), PChar(findText));
            if pc <> nil then begin
                lbRemovedList.ClearSelection;
                lbRemovedList.Selected[j] := true;
                lbRemovedList.ItemIndex := j;
                lbRemovedList.TopIndex := j;
                lbRemovedListClick(lbRemovedList);
                 goto EXIT_CODE;
            end;
        end;
    end else begin
        a := i;
        b := lbRemovedList.Count - 1;
        TClipDatabase.StartTextOnlyData(a+1,b,reversed);
        for j := a+1 to b do begin
            TClipDatabase.LoadNextText(s);
            pc := TextPos(PChar(s), PChar(findText));
            if pc <>nil then begin
                lbRemovedList.ClearSelection;
                lbRemovedList.Selected[j] := true;
                lbRemovedList.ItemIndex := j;
                lbRemovedList.TopIndex := j;
                lbRemovedListClick(lbRemovedList);
                goto EXIT_CODE;
            end;
        end;
    end;
EXIT_CODE:
    TClipDatabase.EndTextOnlyData;
end;
procedure TfrmEditHistory.RemovedFindDialog1Show(Sender: TObject);
begin
    SetForegroundWindow(RemovedFindDialog1.Handle)
end;







procedure TfrmEditHistory.lbPopupQueueClick(Sender: TObject);
var ci : TClipItem;
begin

    ci := ClipQueue.GetClipItem(lbPopupQueue.itemindex);
    if (ci <> nil) then begin
        FrameClipDisplay2.ShowClip(ci);
    end;
end;
procedure TfrmEditHistory.lbPopupQueueDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var ci : TClipItem;
    th, h, headerwd : integer;
    c, bc : TColor;
    header : string;
    s : string;
    bmp : TBitmap;
const HEADER_WIDTH = 80;
begin
    // height of rectangle & height of text on the listbox
    h := (rect.Bottom - rect.top) + 1;
    th := lbPopupQueue.Canvas.TextHeight('ALKJDFIOJ');
    headerwd  := lbRemovedList.Canvas.TextWidth(' ');

    bc := lbPopupQueue.Canvas.Brush.Color;
    lbPopupQueue.Canvas.Brush.Color := clWhite;
    lbPopupQueue.Canvas.FillRect(rect);
    lbPopupQueue.Canvas.Brush.Color := bc;

    //
    // draw the icon leaving enough pixels above and below
    // for the selection outline
    //


    ci := ClipQueue.GetClipItem(index);
    if (ci <> nil) then begin
    	//s := ci.GetAsText;
        s := lbPopupqueue.Items.Strings[index];
        DrawIconEX(
            lbPopupQueue.Canvas.Handle, rect.Left+2, rect.Top+1,ci.CData.GetHICON,
            h-2, h-2,
            0,0,DI_NORMAL);

		case ci.GetFormatType of
            FT_PICTURE:		bmp := FrmClipboardManager.iPic.Picture.Bitmap;
            FT_HTML: 		bmp  := FrmClipboardManager.iFormat.Picture.Bitmap;
            FT_RICHTEXT:	bmp := FrmClipboardManager.iFormat.Picture.Bitmap;
            FT_FILE: 		bmp := FrmClipboardManager.iFiles.Picture.Bitmap;
            else
            	bmp := FrmClipboardManager.iText.Picture.Bitmap;
        end;

        lbPopupQueue.Canvas.Draw(rect.Left+h, rect.Top+1, bmp);
        //s := UnitMisc.GetCliptypeSymbol(ci.GetFormat) + ' ' + s;
        //s := '['+ci.GetFormatName(false) + ']: ' + s;
        header := ' ';
    end else begin
        s := lbPopupqueue.Items.Strings[index];
    end;

    // leave a space for the icon
    // center the text if possible
    if (h  <=  th) then begin
        lbPopupqueue.Canvas.TextOut(
            rect.Left + h*2 , rect.Top, header);
        lbPopupqueue.Canvas.TextOut(
            rect.Left + h*2 + headerwd, rect.Top, s);
    end else begin
        lbPopupqueue.Canvas.TextOut(
            rect.Left + h*2 , floor((h-th)/2) + rect.Top, header);
        lbPopupqueue.Canvas.TextOut(
            rect.Left + h*2 + headerwd, floor((h-th)/2) + rect.Top, s);
    end;


    //
    // Draw/Clear the selection outline
    //
    c := lbPopupQueue.Canvas.Brush.color;
    if (odSelected in state) then begin
        lbPopupQueue.Canvas.Brush.Color := clHighlight;
        lbPopupQueue.Canvas.FrameRect(rect);
    end else begin
        lbPopupqueue.Canvas.Brush.color := clWindow;
        lbPopupQueue.Canvas.FrameRect(rect);
    end;
    lbPopupQueue.Canvas.Brush.color := c;
end;
procedure TfrmEditHistory.lbPopupQueueKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
//    if (key = Windows.VK_DELETE) then begin
//        self.btnDelete.Click;
//    end;
end;
procedure TfrmEditHistory.lbPopupQueueMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer);
var ci : TClipItem;
    s : string;
begin
    height := math.max(18, lbPopupQueue.Canvas.TextHeight('ALKJDIOJ')+4);

    ci := ClipQueue.GetClipItem(index);
    if (ci <> nil) then begin
        s := '['+ci.GetFormatName(false) + ']: ';
        maxpopupheader := max(canvas.TextWidth(s), maxpopupheader);
    end;
end;

procedure TfrmEditHistory.lblPopupClipsClick(Sender: TObject);
begin
    FrmConfig.Show;
    FrmConfig.showPage(FrmConfig.tsHistory);
end;

procedure TfrmEditHistory.lbMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var i : integer;
begin
    clickedLB := TListBox(Sender);

    case button of
    mbLeft:
        begin

        end;
    mbRight:
        begin
            i := clickedLB.ItemAtPos(point(x,y),true);
            if not clickedLB.Selected[i] then begin
                clickedLB.Selected[i] := true;
            end;

            pmHistory.Popup(mouse.CursorPos.X+5,mouse.CursorPos.Y+5);
        end;
    end;
end;

procedure TfrmEditHistory.lbRemovedListClick(Sender: TObject);
var i : integer;
begin
    myfree(ci);
    i := lbRemovedList.ItemIndex;
    ci := TClipItem.Create;
    TClipDatabase.LoadRemoved(ci, i);
    FrameClipDisplay2.ShowClip(ci);
end;
procedure TfrmEditHistory.lbRemovedListDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var ci : TClipItem;
    th, h, headerwd : integer;
    c, bc : TColor;
    header, s, s2 : string;

    bmp : TBitmap;
    pd : TPagedData;
    ti : integer;
const HEADER_WIDTH = 120;
begin
    // height of rectangle & height of text on the listbox
    h := (rect.Bottom - rect.top) + 1;
    th := lbRemovedList.Canvas.TextHeight('ALKJDFIOJ');
    headerwd  := lbRemovedList.Canvas.TextWidth('99-99-99: ');

    bc := lbRemovedList.Canvas.Brush.Color;
    lbRemovedList.Canvas.Brush.Color := clWhite;
    lbRemovedList.Canvas.FillRect(rect);
    lbRemovedList.Canvas.Brush.Color := bc;
    //
    // draw the icon leaving enough pixels above and below
    // for the selection outline
    //
//    ti  := (lbRemovedList.Count - 1) - index;
    ti := index;
    pd := RemovedQueue.GetPagedData(ti);

    if (true) then begin
        DrawIconEX(
            lbRemovedList.Canvas.Handle, rect.Left+2, rect.Top+1, pd.icon,
            h-2, h-2,
            0,0,DI_NORMAL);

		case pd.FormatType of
            FT_PICTURE:		bmp := FrmClipboardManager.iPic.Picture.Bitmap;
            FT_HTML: 		bmp  := FrmClipboardManager.iFormat.Picture.Bitmap;
            FT_RICHTEXT:	bmp := FrmClipboardManager.iFormat.Picture.Bitmap;
            FT_FILE: 		bmp := FrmClipboardManager.iFiles.Picture.Bitmap;
            else
            	bmp := FrmClipboardManager.iText.Picture.Bitmap;
        end;

        lbRemovedList.Canvas.Draw(rect.Left+h, rect.Top+1, bmp);

        try
            DateTimeToString(s2, 'mm-dd-yy', pd.FileDate);
        except
        end;

        header := s2 + '' ;
        s := pd.AsText;
    end;

    // leave a space for the icon
    // center the text if possible
    if (h  <=  th) then begin
        lbRemovedList.Canvas.TextOut(
            rect.Left + h*2+2, rect.Top, header);
        lbRemovedList.Canvas.TextOut(
            rect.Left + h*2 + 4 + headerwd, rect.Top, s);
    end else begin
        lbRemovedList.Canvas.TextOut(
            rect.Left + h*2+2, floor((h-th)/2) + rect.Top, header);
        lbRemovedList.Canvas.TextOut(
            rect.Left + h*2 + 4 +headerwd, floor((h-th)/2) + rect.Top, s);
    end;


    //
    // Draw/Clear the selection outline
    //
    c := lbRemovedList.Canvas.Brush.color;
    if (odSelected in state) then begin
        lbRemovedList.Canvas.Brush.Color := clHighlight;
        lbRemovedList.Canvas.FrameRect(rect);
    end else begin
        lbRemovedList.Canvas.Brush.color := clWindow;
        lbRemovedList.Canvas.FrameRect(rect);
    end;
    lbRemovedList.Canvas.Brush.color := c;

end;
procedure TfrmEditHistory.lbRemovedListMeasureItem(Control: TWinControl; Index: Integer; var Height: Integer);
begin
    height := math.max(16, lbRemovedList.Canvas.TextHeight('ALKJDIOJ')+4);
end;


procedure TfrmEditHistory.cbxHistoryChange(Sender: TObject);
begin
    changeHistoryPage(cbxHistory.ItemIndex);
end;

procedure TfrmEditHistory.odExportCanClose(Sender: TObject; var CanClose: Boolean);
begin
    CanClose := true;
end;

end.
