unit ProcsAndTypes;

interface

Uses
 Registry,
 Windows,
 Classes,
 SysUtils,
 Menus,
 Engine,dialogs,graphics;

Type
 TWindowMode = (wmAOT, wmNormal, wmPTD);
 TARUExcept = Record
  SnipWin: Boolean;
  OI: Boolean;
  Palette: Boolean;
  VarWin: Boolean;
  ObjBrowser: Boolean;
 end;
 TSnapping = record
  Main: Boolean;
  SnipWin: Boolean;
  OI: Boolean;
  Palette: Boolean;
  VarWin: Boolean;
  ObjBrowser: boolean;
 end;
 TToolwindows = Record
  AutoRollUp: Boolean;
  ARUExcept: TARUExcept;
  Snapping: TSnapping;
 end;
 TFormPanelOptions = record
  ShowGrid: Boolean;
  GridSpacingX: Integer;
  GridSpacingY: Integer;
  GridColor: TColor;
  SnapToGrid: Boolean;
  ShowDot: Boolean;
 end;
 TVisualOptions = record
  ShowGrid: Boolean;
  GridSpacingX: Integer;
  GridSpacingY: Integer;
  GridColor: TColor;
  SnapToGrid: Boolean;
  ShowDot: Boolean;
  FormPanelOptions: TFormPanelOptions;
 end;
 TFiles = Record
  ShowFullPathInCaption: Boolean;
  LoadLastOnStartup: boolean;
  CMLIndent: String;
  RecentLength: Byte;
  DefaultFolder: String;
 end;
 TOI = Record
  NonFontColor: TColor;
  NonBackgroundColor: TColor;
  RequiredFontColor: TColor;
  RequiredBackgroundColor: TColor;
  FontColor: TColor;
  BackgroundColor: TColor;
 end;
 TCustomColors = Record
  Colors: Array[0 .. 15] of String;
 end;
 TOptions = Record
  CustomColors: TCustomColors;
  Files: TFiles;
  OI: TOI;
  ToolWindows: TToolWindows;
  Visual: TVisualOptions;
 end;
 TOnOpenRecent = procedure(Filename: String) of Object;
 TRecent = Record
  Filename: String;
 end;
 TRecentList = Class(TObject)
 private
  fList: Array of TRecent;
  fParentMenuItem: TMenuItem;
  fOnOpenRecent: TOnOpenRecent;
  fMaxLimit: Byte;
  function GETCOUNT: Cardinal;
  procedure SetMaxLimit(const Value: Byte);
 public
  Constructor Create(ParentMenuItem: TMenuItem; OnOpenRecent: TOnOpenRecent; LoadRightAway: Boolean = false);
  Procedure Add(Filename: String);
  Procedure Delete(Filename: String);
  Procedure SaveToReg;
  Procedure LoadFromReg;
  Property Count: Cardinal read GETCOUNT;
  Property MaxLimit: Byte read fMaxLimit write SetMaxLimit;
  Procedure Clear;
  Procedure BuildMenu;
  Procedure OnMenuItemClick(Sender: TObject);
 end;
 TOnDrawSelected = procedure(Node: TEdRawNode) of object;
 TOnDrawDeSelected = Procedure(Node: TEdRawNode) of Object;
 TOnSelect = Procedure(NodesToSelect: TEdRawNodes) of Object;
 TSelect = Class(TObject)
 private
  fList: TEdRawNodes;
  fOnDrawDeSelected: TOnDrawDeSelected;
  fOnDrawSelected: TOnDrawSelected;
  fOnSelect: TOnSelect;
  function GETCOUNT: Cardinal;
  function GETCurrentSelectedNode: TEdRawNode;
  procedure SETCurrentSelectedNode(const Value: TEdRawNode);
  function GETNODE(Index: Integer): TEdRawNode;
 public
  Procedure AddToSelect(Node: TEdRawNode);
  Procedure Delete(Index: Integer);
  Procedure Clear;
  Procedure Reload;
  Function GetSelected(Var Nodes: TEdRawNodes): boolean;
  Property Node[Index: Integer]: TEdRawNode read GETNODE; default;
  Procedure UpdateSelected;
 published
  Property Count: Cardinal read GETCOUNT;
  Property CurrentSelectedNode: TEdRawNode read GETCurrentSelectedNode write SETCurrentSelectedNode;
  Property OnDrawSelected: TOnDrawSelected read fOnDrawSelected write fOnDrawSelected;
  Property OnDrawDeSelected: TOnDrawDeSelected read fOnDrawDeSelected write fOnDrawDeSelected;
  Property OnSelect: TOnSelect read fOnSelect write fOnSelect;
 end;
 TClipboard = Class(TObject)
 private
  fList: Array of String;
  FOnClear: TNotifyevent;
  FOnNewAddition: TNotifyEvent;
    fNodeType: TNodeType;
  function GETCOUNT: Cardinal;
  procedure SetOnClear(const Value: TNotifyevent);
  procedure SetOnNewAddition(const Value: TNotifyEvent);
 public
  Constructor Create;
  Property Count: Cardinal read GETCOUNT;
  Procedure AddToClipboard(CML: String);
  Procedure Clear;
  Property OnClear: TNotifyevent read FOnClear write SetOnClear;
  Property OnNewAddition: TNotifyEvent read FOnNewAddition write SetOnNewAddition;
  Property NodeType: TNodeType read fNodeType write fNodeType;
  Function ProvideCML: String;
 end;

 Procedure LoadCustomColors(Var ColorDlg: TColorDialog);
 Procedure SaveCustomColors(Var ColorDlg: TColorDialog);
 Procedure InitOptions;
 Procedure SaveOptions;
 Procedure LoadOptions;
 procedure StrToClipbrd(StrValue: string);
 function GetStrFromClipbrd: string;
 Function ColorToRGB(Color: TColor): String;
 Function RGBToColor(RGB: String): TColor;

Const
 RegLocation = '\Software\The CoolMon Project\CoolMon2\Editor\';


implementation

Uses Main, clipbrd;

Function ColorToRGB(Color: TColor): String;
Var
 s: String;
 RS, GS, BS: String;
begin
 Result := '$FFFFFF';
 S := ColorToString(Color);
 If length(S) = 0 then exit;
 If S[1] = '$' Then begin
  BS := Copy(S, 4, 2);
  GS := Copy(S, 6, 2);
  RS := Copy(S, 8, 2);
  Result := '$' + RS + GS + BS;
 End
  else
 begin
  If uppercase(copy(S, 1, 2)) = 'CL' then begin
   Result := copy(S, 3, length(s));
  end;
 end;
end;

Function RGBToColor(RGB: String): TColor;
Begin
 Result := clWhite;
 If length(RGB) = 0 then exit;
 If RGB[1] = '$' then begin
  If length(RGB) = 7 then begin
   // RGB
   RGB := '$00' + Copy(RGB, 6, 2) + Copy(RGB, 4, 2) + Copy(RGB, 2, 2);
  end;
  // ABGR is not checked because it basically should be converted later
 end
  else
 begin
  // Color name
  If uppercase(copy(rgb, 1, 2)) <> 'CL' then begin
   RGB := 'cl' + RGB;
  end;
 end;
 Try
  Result := StringToColor(RGB);
 except
  on EConvertError do begin
   Result := clWhite;
  end;
 end;
End;

Procedure LoadCustomColors(Var ColorDlg: TColorDialog);
Var
 I: Integer;
Begin
 ColorDlg.CustomColors.Clear;
 For I := 0 to 15 do begin
  ColorDlg.CustomColors.Add(Options.CustomColors.Colors[I]);
 end;
end;

Procedure SaveCustomColors(Var ColorDlg: TColorDialog);
Var
 I: Integer;
Begin
 For I := 0 to ColorDlg.CustomColors.Count - 1 do begin
  Options.CustomColors.Colors[I] := ColorDlg.CustomColors[I];
 end;
end;

procedure StrToClipbrd(StrValue: string);
var
  hMem: THandle;
  pMem: PChar;
begin
  hMem := GlobalAlloc(GHND or GMEM_SHARE, Length(StrValue) + 1);
  if hMem <> 0 then
  begin
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      StrPCopy(pMem, StrValue);
      GlobalUnlock(hMem);
      if OpenClipboard(0) then
      begin
        EmptyClipboard;
        SetClipboardData(CF_TEXT, hMem);
        CloseClipboard;
      end
      else
        GlobalFree(hMem);
    end
    else
      GlobalFree(hMem);
  end;
end;

function GetStrFromClipbrd: string;
begin
  if Clipboard.HasFormat(CF_TEXT) then
    Result := Clipboard.AsText
  else
  begin
    ShowMessage('There is no text in the Clipboard!');
    Result := '';
  end;
end;

Procedure InitOptions;
Begin
 Options.Files.ShowFullPathInCaption := false;
 Options.Files.LoadLastOnStartup := false;
 Options.Files.CMLIndent := '  ';
 Options.Files.RecentLength := 1;
 Options.Files.DefaultFolder := '';
 Options.Visual.ShowGrid := True;
 Options.Visual.GridSpacingX := 20;
 Options.Visual.GridSpacingY := 20;
 Options.Visual.GridColor := clred;
 Options.Visual.SnapToGrid := true;
 Options.Visual.ShowDot := true;
 Options.Visual.FormPanelOptions.ShowGrid := true;
 Options.Visual.FormPanelOptions.GridSpacingX := 10;
 Options.Visual.FormPanelOptions.GridSpacingY := 10;
 Options.Visual.FormPanelOptions.GridColor := clred;
 Options.Visual.FormPanelOptions.SnapToGrid := true;
 Options.Visual.FormPanelOptions.ShowDot := true;
 Options.OI.RequiredFontColor := clRed;
 Options.OI.RequiredBackgroundColor := clWhite;
 Options.OI.FontColor := clGreen;
 Options.OI.BackgroundColor := clWhite;
 Options.OI.NonFontColor := clWhite;
 Options.OI.NonBackgroundColor := clRed;
 Options.ToolWindows.AutoRollUp := False;
 Options.ToolWindows.ARUExcept.SnipWin := false;
 Options.ToolWindows.ARUExcept.OI := false;
 Options.ToolWindows.ARUExcept.Palette := False;
 Options.ToolWindows.ARUExcept.VarWin := false;
 Options.ToolWindows.ARUExcept.ObjBrowser := false;
 Options.ToolWindows.Snapping.Main := true;
 Options.ToolWindows.Snapping.SnipWin := true;
 Options.ToolWindows.Snapping.OI := true;
 Options.ToolWindows.Snapping.Palette := true;
 Options.ToolWindows.Snapping.VarWin := true;
 Options.ToolWindows.Snapping.ObjBrowser := true;
end;

Procedure SaveOptions;
Var
 Reg: TRegistry;
begin
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Reg.OpenKey(RegLocation + 'Options', true);
 Reg.WriteBool('Files.ShowFullPathInCaption', Options.Files.ShowFullPathInCaption);
 Reg.WriteBool('Files.LoadLastOnStartup', Options.Files.LoadLastOnStartup);
 Reg.WriteString('Files.CMLIndent', Options.Files.CMLIndent);
 Reg.WriteInteger('Files.RecentLength', Options.Files.RecentLength);
 Reg.WriteString('Files.DefaultFolder', Options.Files.DefaultFolder);
 Reg.WriteBool('Visual.ShowGrid', Options.Visual.ShowGrid);
 Reg.WriteInteger('Visual.GridSpacingX', Options.Visual.GridSpacingX);
 Reg.WriteInteger('Visual.GridSpacingY', Options.Visual.GridSpacingY);
 Reg.WriteInteger('Visual.GridColor', Options.Visual.GridColor);
 Reg.WriteBool('Visual.SnapToGrid', Options.Visual.SnapToGrid);
 Reg.WriteBool('Visual.ShowDot', Options.Visual.ShowDot);
 Reg.WriteBool('Visual.FormPanelOptions.ShowGrid', Options.Visual.FormPanelOptions.ShowGrid);
 Reg.WriteInteger('Visual.FormPanelOptions.GridSpacingX', Options.Visual.FormPanelOptions.GridSpacingX);
 Reg.WriteInteger('Visual.FormPanelOptions.GridSpacingY', Options.Visual.FormPanelOptions.GridSpacingY);
 Reg.WriteInteger('Visual.FormPanelOptions.GridColor', Options.Visual.FormPanelOptions.GridColor);
 Reg.WriteBool('Visual.FormPanelOptions.SnapToGrid', Options.Visual.FormPanelOptions.SnapToGrid);
 Reg.WriteBool('Visual.FormPanelOptions.ShowDot', Options.Visual.FormPanelOptions.ShowDot);
 Reg.WriteInteger('OI.RequiredFontColor', Options.OI.RequiredFontColor);
 Reg.WriteInteger('OI.RequiredBackgroundColor', Options.OI.RequiredBackgroundColor);
 Reg.WriteInteger('OI.FontColor', Options.OI.FontColor);
 Reg.WriteInteger('OI.BackgroundColor', Options.OI.BackgroundColor);
 Reg.WriteInteger('OI.NonFontColor', Options.OI.NonFontColor);
 Reg.WriteInteger('OI.NonBackgroundColor', Options.OI.NonBackgroundColor);
 Reg.WriteBool('ToolWindows.AutoRollUp', Options.ToolWindows.AutoRollUp);
 Reg.WriteBool('ToolWindows.ARUExcept.SnipWin', Options.ToolWindows.ARUExcept.SnipWin);
 Reg.WriteBool('ToolWindows.ARUExcept.OI', Options.ToolWindows.ARUExcept.OI);
 Reg.WriteBool('ToolWindows.ARUExcept.Palette', Options.ToolWindows.ARUExcept.Palette);
 Reg.WriteBool('ToolWindows.ARUExcept.VarWin', Options.ToolWindows.ARUExcept.VarWin);
 Reg.WriteBool('ToolWindows.ARUExcept.ObjBrowser', Options.ToolWindows.ARUExcept.ObjBrowser);
 Reg.WriteBool('ToolWindows.Snapping.Main', Options.ToolWindows.Snapping.Main);
 Reg.WriteBool('ToolWindows.Snapping.SnipWin', Options.ToolWindows.Snapping.SnipWin);
 Reg.WriteBool('ToolWindows.Snapping.OI', Options.ToolWindows.Snapping.OI);
 Reg.WriteBool('ToolWindows.Snapping.Palette', Options.ToolWindows.Snapping.Palette);
 Reg.WriteBool('ToolWindows.Snapping.VarWin', Options.ToolWindows.Snapping.VarWin);
 Reg.WriteBool('ToolWindows.Snapping.ObjBrowser', Options.ToolWindows.Snapping.ObjBrowser);
 Reg.CloseKey;
 FreeAndNil(Reg);
end;

Procedure LoadOptions;
Var
 Reg: TRegistry;
begin
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 If Reg.Openkey('\Software\The coolmon project\PlugIn Management', false) then begin
  oeMain.PMLocation := Reg.ReadString('');
 end;
 If not Reg.OpenKey(RegLocation + 'Options', false) then begin
  FreeAndNil(Reg);
  exit;
 end;
 If Reg.ValueExists('Files.ShowFullPathInCaption') then begin
  Options.Files.ShowFullPathInCaption := Reg.ReadBool('Files.ShowFullPathInCaption');
 end;
 If Reg.ValueExists('Files.LoadLastOnStartUp') then begin
  Options.Files.LoadLastOnStartup := Reg.ReadBool('Files.LoadLastOnStartup');
 end;
 If Reg.ValueExists('Files.CMLIndent') then begin
  Options.Files.CMLIndent := Reg.ReadString('Files.CMLIndent');
 end;
 If Reg.ValueExists('Files.RecentLength') then begin
  Options.Files.RecentLength := Reg.ReadInteger('Files.RecentLength');
 end;
 If Reg.ValueExists('Files.DefaultFolder') then begin
  Options.Files.DefaultFolder := Reg.ReadString('Files.DefaultFolder');
 end;
 If Reg.ValueExists('Visual.ShowGrid') then begin
  Options.Visual.ShowGrid := Reg.ReadBool('Visual.ShowGrid');
 end;
 If Reg.ValueExists('Visual.GridSpacingX') then begin
  Options.Visual.GridSpacingX := Reg.ReadInteger('Visual.GridSpacingX');
 end;
 If Reg.ValueExists('Visual.GridSpacingY') then begin
  Options.Visual.GridSpacingY := Reg.ReadInteger('Visual.GridSpacingY');
 end;
 If Reg.ValueExists('Visual.GridColor') then begin
  Options.Visual.GridColor := Reg.ReadInteger('Visual.GridColor');
 end;
 If Reg.ValueExists('Visual.SnapToGrid') then begin
  Options.Visual.SnapToGrid := Reg.ReadBool('Visual.SnapToGrid');
 end;
 If Reg.ValueExists('Visual.ShotDot') then begin
  Options.Visual.SnapToGrid := Reg.ReadBool('Visual.ShowDot');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.ShowGrid') then begin
  Options.Visual.FormPanelOptions.ShowGrid := Reg.ReadBool('Visual.FormPanelOptions.ShowGrid');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.GridSpacingX') then begin
  Options.Visual.FormPanelOptions.GridSpacingX := Reg.ReadInteger('Visual.FormPanelOptions.GridSpacingX');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.GridSpacingY') then begin
  Options.Visual.FormPanelOptions.GridSpacingY := Reg.ReadInteger('Visual.FormPanelOptions.GridSpacingY');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.GridColor') then begin
  Options.Visual.FormPanelOptions.GridColor := Reg.ReadInteger('Visual.FormPanelOptions.GridColor');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.SnapToGrid') then begin
  Options.Visual.FormPanelOptions.SnapToGrid := Reg.ReadBool('Visual.FormPanelOptions.SnapToGrid');
 end;
 If Reg.ValueExists('Visual.FormPanelOptions.ShotDot') then begin
  Options.Visual.FormPanelOptions.SnapToGrid := Reg.ReadBool('Visual.FormPanelOptions.ShowDot');
 end;
 If Reg.ValueExists('OI.RequiredFontColor') then begin
  Options.OI.RequiredFontColor := Reg.ReadInteger('OI.RequiredFontColor');
 end;
 If Reg.ValueExists('OI.RequiredBackgroundColor') then begin
  Options.OI.RequiredBackgroundColor := Reg.ReadInteger('OI.RequiredBackgroundColor');
 end;
 If Reg.ValueExists('OI.FontColor') then begin
  Options.OI.FontColor := Reg.ReadInteger('OI.FontColor');
 end;
 If Reg.ValueExists('OI.BackgroundColor') then begin
  Options.OI.BackgroundColor := Reg.ReadInteger('OI.BackgroundColor');
 end;
 If Reg.ValueExists('OI.NonFontColor') then begin
  Options.OI.NonFontColor := Reg.ReadInteger('OI.NonFontColor');
 end;
 If Reg.ValueExists('OI.NonBackgroundColor') then begin
  Options.OI.NonBackgroundColor := Reg.ReadInteger('OI.NonBackgroundColor');
 end;
 If Reg.ValueExists('Toolwindows.AutoRollUp') then begin
  Options.ToolWindows.AutoRollUp := Reg.ReadBool('ToolWindows.AutoRollUp');
 end;
 If Reg.ValueExists('ToolWindows.ARUExcept.SnipWin') then begin
  Options.ToolWindows.ARUExcept.SnipWin := Reg.ReadBool('ToolWindows.ARUExcept.SnipWin');
 end;
 If Reg.ValueExists('ToolWindows.ARUExcept.OI') then begin
  Options.ToolWindows.ARUExcept.OI := Reg.ReadBool('ToolWindows.ARUExcept.OI');
 end;
 If Reg.ValueExists('ToolWindows.ARUExcept.Palette') then begin
  Options.ToolWindows.ARUExcept.Palette := Reg.ReadBool('ToolWindows.ARUExcept.Palette');
 end;
 If Reg.ValueExists('ToolWindows.ARUExcept.Varwin') then begin
  Options.ToolWindows.ARUExcept.VarWin := Reg.ReadBool('ToolWindows.ARUExcept.VarWin');
 end;
 If Reg.ValueExists('ToolWindows.ARUExcept.ObjBrowser') then begin
  Options.ToolWindows.ARUExcept.ObjBrowser := Reg.ReadBool('ToolWindows.ARUExcept.ObjBrowser');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.Main') then begin
  Options.ToolWindows.Snapping.Main := Reg.ReadBool('ToolWindows.Snapping.Main');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.SnipWin') then begin
  Options.ToolWindows.Snapping.SnipWin := Reg.ReadBool('ToolWindows.Snapping.SnipWin');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.OI') then begin
  Options.ToolWindows.Snapping.OI := Reg.ReadBool('ToolWindows.Snapping.OI');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.Palette') then begin
  Options.ToolWindows.Snapping.Palette := Reg.ReadBool('ToolWindows.Snapping.Palette');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.VarWin') then begin
  Options.ToolWindows.Snapping.VarWin := Reg.ReadBool('ToolWindows.Snapping.VarWin');
 end;
 If Reg.ValueExists('ToolWindows.Snapping.ObjBrowser') then begin
  Options.ToolWindows.Snapping.ObjBrowser := Reg.ReadBool('ToolWindows.Snapping.ObjBrowser');
 end;
 Reg.CloseKey;
 FreeAndNil(Reg);
end;

{ TRecentList }

procedure TRecentList.Add(Filename: String);
Var
 I: Integer;
begin
 If filename = '' then exit;
 For I := 0 to count - 1 do begin
  If uppercase(filename) = uppercase(fList[I].Filename) then exit;
 end;
 If Count < MaxLimit then begin
  SetLength(fList, Count + 1);
  fList[Length(fList)-1].Filename := Filename;
 end
  else
 begin
  For I := count -1 downto 1 do begin
   fList[I] := fList[I-1];
  end;
  fList[0].Filename := Filename;
 end;
end;

procedure TRecentList.BuildMenu;
Var
 MI: TMenuItem;
 I: Integer;
begin
 fParentMenuItem.Clear;
 For I := 0 to Count - 1 do begin
  MI := TMenuItem.Create(fParentMenuItem);
  MI.Caption := IntToStr(I+1) + '. ' + fList[I].Filename;
  MI.OnClick := OnMenuItemClick;
  MI.Tag := I;
  fParentMenuItem.Add(MI);
 end;
 If count = 0 then begin
  fParentMenuItem.Visible := false;
 end
  else
 begin
  fParentMenuItem.Visible := true;
 end;
end;

procedure TRecentList.Clear;
begin
 SetLength(fList, 0);
end;

constructor TRecentList.Create(ParentMenuItem: TMenuItem;
  OnOpenRecent: TOnOpenRecent; LoadRightAway: Boolean = false);
begin
 MaxLimit := 5;
 fParentMenuItem := ParentMenuItem;
 fOnOpenRecent := OnOpenRecent;
 If LoadRightAway then LoadFromReg;
end;

procedure TRecentList.Delete(Filename: String);
Var
 Sel, I: Integer;
begin
 Sel := -1;
 For I := 0 to count - 1 do begin
  If uppercase(fList[I].Filename) = uppercase(filename) then begin
   Sel := i;
   break;
  end;
 end;
 If Sel = -1 then exit;
 For I := Sel to Count - 2 do begin
  fList[I] := fList[I+1];
 end;
 SetLength(fList, length(fList)-1);
 BuildMenu;
end;

function TRecentList.GETCOUNT: Cardinal;
begin
 Result := length(fList);
end;

procedure TRecentList.LoadFromReg;
Var
 Reg: TRegistry;
 I: Integer;
 List: TStringList;
begin
 Clear;
 List := TStringList.Create;
 Reg := TREgistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 If Reg.OpenKey(RegLocation + 'Recent', false) then begin
  Reg.GetValueNames(List);
  For I := 0 to List.Count - 1 do begin
   If reg.valueexists(IntToStr(I)) then begin
    Add(Reg.ReadString(IntToStr(I)));
   end;
  end;
 end;
 Reg.CloseKey;
 FreeAndNil(Reg);
 FreeAndnil(List);
 BuildMenu;
end;

procedure TRecentList.OnMenuItemClick(Sender: TObject);
Var
 Sel: Integer;
begin
 Sel := (sender as TMenuItem).Tag;
 If not Assigned(fOnOpenRecent) then exit;
 fOnOpenRecent(fList[Sel].Filename);
 Delete(fList[Sel].Filename);
end;

procedure TRecentList.SaveToReg;
Var
 Reg: TRegistry;
 I: Integer;
 List: TStringList;
begin
 List := TStringList.Create;
 Reg := TRegistry.Create;
 Reg.RootKey := HKEY_CURRENT_USER;
 Reg.OpenKey(RegLocation + 'Recent', true);
 Reg.GetValueNames(List);
 For I := 0 to List.count - 1 do begin
  Reg.DeleteValue(List[I]);
 end;
 For I := 0 to Count - 1 do begin
  Reg.WriteString(IntToStr(I), fList[I].Filename);
 end;
 Reg.CloseKey;
 FreeAndNil(List);
 FreeAndNil(Reg);
end;

procedure TRecentList.SetMaxLimit(const Value: Byte);
begin
 fMaxLimit := Value;
 If Value < Count then begin
  SetLength(fList, Value);
  SaveToReg;
  BuildMenu;
 end;
end;

{ TSelect }

procedure TSelect.AddToSelect(Node: TEdRawNode);
Var
 I: Integer;
begin
 If Count > 0 then begin
  If fList[0] = Node then exit;
 end;
 For I := 1 to count - 1 do begin
  If node = fList[I] then begin
   Delete(I);
   exit;
  end;
 end;
 SetLength(fList, Length(fList) + 1);
 fList[Length(fList)-1] := Node;
 If assigned(fOnDrawSelected) then begin
  fOnDrawSelected(Node);
 end;
 If assigned(fOnSelect) then begin
  fOnSelect(fList);
 end;
end;

procedure TSelect.Clear;
Var
 I: Integer;
begin
 For I := Count - 1 downto 0 do begin
  Delete(I);
 end;
end;

procedure TSelect.Delete(Index: Integer);
Var
 I: Integer;
begin
 If assigned(fOnDrawDeSelected) then begin
  fOnDrawDeSelected(fList[Index]);
 end;
 For I := Index to count - 2 do begin
  fList[I] := fList[I + 1];
 end;
 SetLength(fList, length(fList) - 1);
 If assigned(fOnSelect) then begin
  If count > 0 then begin
   fOnSelect(fList);
  end
   else
  begin
   fOnSelect(nil);
  end;
 end;
end;

function TSelect.GETCOUNT: Cardinal;
begin
 Result := length(flist);
end;

function TSelect.GETCurrentSelectedNode: TEdRawNode;
begin
 If Count = 0 then result := nil
  else Result := fList[0]; 
end;

function TSelect.GETNODE(Index: Integer): TEdRawNode;
begin
 Result := fList[Index];
end;

function TSelect.GetSelected(var Nodes: TEdRawNodes): boolean;
Var
 I: Integer;
begin
 If count = 0 then begin
  result := false;
  exit;
 end;
 Result := true;
 SetLength(Nodes, count);
 For I := 0 to count - 1 do begin
  Nodes[I] := fList[I];
 end;
end;

procedure TSelect.Reload;
begin
 If Assigned(fOnSelect) then begin
  fOnSelect(fList);
 end;
end;

procedure TSelect.SETCurrentSelectedNode(const Value: TEdRawNode);
Var
 I: Integer;
begin
 If Count = 1 then begin
  If fList[0] = Value then begin
   // Node is already the only one selected, so no need to reload it
   exit;
  end;
 end;
 If assigned(fOnDrawDeSelected) then begin
  For I := 0 to Count - 1 do begin
   fOnDrawDeSelected(fList[I]);
  end;
 end;
 SetLength(fList, 1);
 fList[0] := Value;
 If Assigned(fOnDrawSelected) then begin
  fOnDrawSelected(Value);
 end;
 If Debug then Showmessage('About to run assigned select event');
 If Assigned(fOnSelect) then begin
  fOnSelect(fList);
 end;
end;

procedure TSelect.UpdateSelected;
begin
 If Assigned(fOnSelect) then begin
  fOnSelect(fList);
 end;
end;

{ TClipboard }

procedure TClipboard.AddToClipboard(CML: String);
begin
 SetLength(fList, count + 1);
 fList[Count - 1] := CML;
 If assigned(fOnNewAddition) then begin
  fOnNewAddition(Self);
 end;
end;

procedure TClipboard.Clear;
begin
 Setlength(fList, 0);
 NodeType := ntUndefined;
 If assigned(fOnClear) then begin
  fOnClear(Self);
 end;
end;

constructor TClipboard.Create;
begin
 Clear;
end;

function TClipboard.GETCOUNT: Cardinal;
begin
 Result := Length(fList);
end;

function TClipboard.ProvideCML: String;
Var
 I: Integer;
begin
 Result := '<cml>';
 For I := 0 to count - 1 do begin
  Result := Result + #13#10 + fList[I];
 end;
 Result := Result + #13#10 + '</cml>';
end;

procedure TClipboard.SetOnClear(const Value: TNotifyevent);
begin
  FOnClear := Value;
end;

procedure TClipboard.SetOnNewAddition(const Value: TNotifyEvent);
begin
  FOnNewAddition := Value;
end;

end.
