{********************************************************

 SlavaNap source code.

 Copyright 2001,2002 by SlavaNap development team
 Released under GNU General Public License

 Latest version is available at
 http://www.slavanap.org

**********************************************************

 Unit: Class_DoubleCmdList

 TNapDoubleCmd and TNapDoubleCmdList Declarations

*********************************************************}
unit Class_DoubleCmdList;

interface

uses
  Windows, Classes2, SysUtils, Class_Cmdlist;

{$I Defines.pas}

type
  TNapDoubleCmd = record
    Id1, Id2: Integer;
    Cmd1, Cmd2: string;
  end;
  PNapDoubleCmd = ^TNapDoubleCmd;
  TNapDoubleCmdList = class(TMyList)
    function Add(Value: TNapDoubleCmd): Integer;
    procedure Insert(Index: Integer; Value: TNapDoubleCmd);
    procedure Clear; override;
    procedure Delete(Index: Integer);
    procedure AddDoubleCmd(Id1, Id2: Integer; Cmd1, Cmd2: string);
    function Cmd(Index: Integer): TNapDoubleCmd;
    function Cmd1(Index: Integer): TNapCmd;
    function Cmd2(Index: Integer): TNapCmd;
    constructor Create;
    destructor Destroy; override;
  end;

function CreateDoubleCmdList: TNapDoubleCmdList;
procedure FreeDoubleCmdList(List: TNapDoubleCmdList);
{$IFNDEF DISABLE_MEMORY_MANAGER}
procedure ExpireDoubleCmdLists;
{$ENDIF}

var
  Count_NapDoubleCmdList,
    Count_NapDoubleCmdList_Max: Integer;
  Count_NapDoubleCmdList_Items,
    Count_NapDoubleCmdList_Items_Max: Integer;

implementation

uses Vars, Thread, STypes, Memory_Manager;

{$IFNDEF DISABLE_MEMORY_MANAGER}
var
  Lists, Items: TMyList;
{$ENDIF}

function CreateDoubleCmdList: TNapDoubleCmdList;
begin
{$IFNDEF DISABLE_MEMORY_MANAGER}
  if Lists.Count > 0 then
  begin
    Result := Lists.Items[Lists.Count - 1];
    Lists.Delete(Lists.Count - 1);
  end
  else
{$ENDIF}
    Result := TNapDoubleCmdList.Create;
end;

procedure FreeDoubleCmdList(List: TNapDoubleCmdList);
begin
{$IFDEF DISABLE_MEMORY_MANAGER}
  List.Clear;
  List.Free;
{$ELSE}
  List.Clear;
  Lists.Add(List);
{$ENDIF}
end;

function CreateItem: PNapDoubleCmd;
var
  Data: PNapDoubleCmd;
begin
{$IFNDEF DISABLE_MEMORY_MANAGER}
  if Items.Count > 0 then
  begin
    Data := Items.Items[Items.Count - 1];
    Items.Delete(Items.Count - 1);
  end
  else
  begin
{$ENDIF}
    Data := AllocMem(SizeOf(TNapDoubleCmd));
    Pointer(Data^.Cmd1) := nil;
    Pointer(Data^.Cmd2) := nil;
    Inc(Count_NapDoubleCmdList_Items);
    if Count_NapDoubleCmdList_Items > Count_NapDoubleCmdList_Items_Max then
      Count_NapDoubleCmdList_Items_Max := Count_NapDoubleCmdList_Items;
{$IFNDEF DISABLE_MEMORY_MANAGER}
  end;
{$ENDIF}
  Result := Data;
end;

procedure FreeItem(Item: PNapDoubleCmd);
begin
  if Pointer(Item^.Cmd1) <> nil then
    SetLength(Item^.Cmd1, 0);
  if Pointer(Item^.Cmd2) <> nil then
    SetLength(Item^.Cmd2, 0);
  Finalize(Item^);
  FreeMem(Item, SizeOf(TNapDoubleCmd));
  Dec(Count_NapDoubleCmdList_Items);
end;

procedure DeleteItem(Item: PNapDoubleCmd);
begin
{$IFDEF DISABLE_MEMORY_MANAGER}
  FreeItem(Item);
{$ELSE}
  if Pointer(Item^.Cmd1) <> nil then
    SetLength(Item^.Cmd1, 0);
  if Pointer(Item^.Cmd2) <> nil then
    SetLength(Item^.Cmd2, 0);
  Items.Add(Item);
{$ENDIF}
end;

{$IFNDEF DISABLE_MEMORY_MANAGER}

procedure ExpireDoubleCmdLists;
var
  List: TNapDoubleCmdList;
  Item: PNapDoubleCmd;
begin
  if Lists.Count > 1000 then
    while (Lists.Count * 3) > Count_NapDoubleCmdList do
    try
      List := Lists.Items[Lists.Count - 1];
      Lists.Delete(Lists.Count - 1);
      List.Free;
    except
    end;
  if Items.Count > 10000 then
    while (Items.Count * 3) > Count_NapDoubleCmdList_Items do
    try
      Item := Items.Items[Items.Count - 1];
      Items.Delete(Items.Count - 1);
      FreeItem(Item);
    except
    end;
end;
{$ENDIF}

{* * * * *  TNapDoubleCmdList  * * * * *}

function TNapDoubleCmdList.Add(Value: TNapDoubleCmd): Integer;
var
  Data: PNapDoubleCmd;
begin
  Data := CreateItem;
  with Data^ do
  begin
    Cmd1 := Value.Cmd1;
    Cmd2 := Value.Cmd2;
    Id1 := Value.Id1;
    Id2 := Value.Id2;
  end;
  Result := inherited Add(Data);
end;

procedure TNapDoubleCmdList.Insert(Index: Integer; Value: TNapDoubleCmd);
var
  Data: PNapDoubleCmd;
begin
  Data := CreateItem;
  with Data^ do
  begin
    Cmd1 := Value.Cmd1;
    Cmd2 := Value.Cmd2;
    Id1 := Value.Id1;
    Id2 := Value.Id2;
  end;
  inherited Insert(Index, Data);
end;

procedure TNapDoubleCmdList.Clear;
begin
  while Count > 0 do
    Delete(Count - 1);
  inherited Clear;
end;

procedure TNapDoubleCmdList.Delete(Index: Integer);
begin
  if (Index < 0) or (Index >= Count) then Exit;
  if Items[Index] <> nil then
    DeleteItem(Items[Index]);
  inherited Delete(Index);
end;

procedure TNapDoubleCmdList.AddDoubleCmd(Id1, Id2: Integer; Cmd1, Cmd2: string);
var
  Data: TNapDoubleCmd;
begin
  Data.Id1 := Id1;
  Data.Id2 := Id2;
  Data.Cmd1 := Cmd1;
  Data.Cmd2 := Cmd2;
  Add(Data);
end;

function TNapDoubleCmdList.Cmd(Index: Integer): TNapDoubleCmd;
var
  Data: TNapDoubleCmd;
begin
  if (Index >= 0) and (Index < Count) then
  begin
    Data := TNapDoubleCmd(Items[Index]^);
    Result := Data;
    Exit;
  end;
  Data.Id1 := -1;
  Data.Cmd1 := '';
  Data.Id2 := -1;
  Data.Cmd2 := '';
  Result := Data;
end;

function TNapDoubleCmdList.Cmd1(Index: Integer): TNapCmd;
var
  Data: TNapCmd;
  Item: PNapDoubleCmd;
begin
  if (Index >= 0) and (Index < Count) then
  begin
    Item := Items[Index];
    Data.Id := Item^.Id1;
    Data.Cmd := Item^.Cmd1;
    Result := Data;
    Exit;
  end;
  Data.Id := -1;
  Data.Cmd := '';
  Result := Data;
end;

function TNapDoubleCmdList.Cmd2(Index: Integer): TNapCmd;
var
  Data: TNapCmd;
  Item: PNapDoubleCmd;
begin
  if (Index >= 0) and (Index < Count) then
  begin
    Item := Items[Index];
    Data.Id := Item^.Id2;
    Data.Cmd := Item^.Cmd2;
    Result := Data;
    Exit;
  end;
  Data.Id := -1;
  Data.Cmd := '';
  Result := Data;
end;

constructor TNapDoubleCmdList.Create;
begin
  Inc(Count_NapDoubleCmdList);
  if Count_NapDoubleCmdList > Count_NapDoubleCmdList_Max then
    Count_NapDoubleCmdList_Max := Count_NapDoubleCmdList;
  inherited Create;
end;

destructor TNapDoubleCmdList.Destroy;
begin
  Clear;
  Dec(Count_NapDoubleCmdList);
  inherited Destroy;
end;

{$IFNDEF DISABLE_MEMORY_MANAGER}

procedure ClearDoubleCmdLists;
var
  I: Integer;
  P: PNapDoubleCmd;
begin
  for I := 0 to Lists.Count - 1 do
    TNapDoubleCmdList(Lists.Items[I]).Free;
  Lists.Clear;
  for I := 0 to Items.Count - 1 do
  begin
    P := Items.Items[I];
    FreeItem(P);
  end;
  Items.Clear;
end;
{$ENDIF}

initialization
  begin
    Count_NapDoubleCmdList := 0;
    Count_NapDoubleCmdList_Max := 0;
    Count_NapDoubleCmdList_Items := 0;
    Count_NapDoubleCmdList_Items_Max := 0;
{$IFNDEF DISABLE_MEMORY_MANAGER}
    Lists := TMyList.Create;
    Items := TMyList.Create;
{$ENDIF}
  end;

{$IFNDEF DISABLE_MEMORY_MANAGER}
finalization
  begin
    ClearDoubleCmdLists;
    Lists.Free;
    Items.Free;
  end;
{$ENDIF}
end.
