unit TMS.ServerWizard.ToolsAPI.Utils;

{$I bcl.inc}

interface

{$IFDEF DELPHIXE2_LVL}

uses
  ToolsAPI;

  function CurrentProjectGroup : IOTAProjectGroup;
  function EnsureProjectNameUnique(const ProjectName : string) : string;
  function GetExistingModule(const Filename : string) : IOTAModule;
  function GetSourceEditorForModule(const Module : IOTAModule) : IOTASourceEditor;
  function GetEditorContents(const Editor: IOTASourceEditor) : string;
  procedure SetEditorContents(const Editor: IOTASourceEditor; const ExistingTextLength : Integer;
    const Text : string);

{$ENDIF}

implementation

{$IFDEF DELPHIXE2_LVL}

uses
  System.SysUtils;

function CurrentProjectGroup : IOTAProjectGroup;
var
  ModuleServices: IOTAModuleServices;
  Module: IOTAModule;
  i: integer;
begin
  Result := nil;

  ModuleServices := (BorlandIDEServices as IOTAModuleServices);
  for i := 0 to ModuleServices.ModuleCount - 1 do begin
    Module := ModuleServices.Modules[i];
    if Supports(Module, IOTAProjectGroup, Result) then
      Exit;
  end;
end;

function ProjectExists(const Group : IOTAProjectGroup; const ProjectName : string) : Boolean;
var
  I : Integer;
begin
  assert(Assigned(Group));

  Result := false;
  for I := 0 to Pred(Group.ProjectCount) do begin
    if SameText(ProjectName, ChangeFileExt(ExtractFileName(Group.Projects[i].FileName), '')) then
      Exit(true);
  end;
end;

function EnsureProjectNameUnique(const ProjectName : string) : string;
var
  Group : IOTAProjectGroup;
  I : Integer;
  TempName : string;
begin
  // If there's a project with that name already, add a number to it until it's unique
  Group := CurrentProjectGroup;
  if not Assigned(Group) then
    Exit(ProjectName); // No project group, name must be unique

  TempName := ProjectName;
  I := 2;
  while ProjectExists(Group, TempName) do begin
    TempName := ProjectName + IntToStr(I);
    Inc(I);
  end;

  Result := TempName;
end;

function GetExistingModule(const Filename : string) : IOTAModule;
var
  ModuleServices : IOTAModuleServices;
begin
  Result := nil;

  ModuleServices := (BorlandIDEServices as IOTAModuleServices);
  Result := ModuleServices.FindModule(Filename);
  // The filename is usually without an extension
  if not Assigned(Result) then
    Result := ModuleServices.FindModule(ChangeFileExt(Filename, '.pas'));
  if not Assigned(Result) then
    Result := ModuleServices.FindModule(ChangeFileExt(Filename, '.dpr'));
  if not Assigned(Result) then
    Result := ModuleServices.FindModule(ChangeFileExt(Filename, '.dfm'));
  if not Assigned(Result) then
    Result := ModuleServices.FindModule(ChangeFileExt(Filename, '.fmx'));
end;

// http://www.davidghoyle.co.uk/WordPress/?p=341
function GetSourceEditorForModule(const Module : IOTAModule) : IOTASourceEditor;
var
  i : Integer;
begin
  assert(Assigned(Module));
  Result := nil;

  for i := 0 to Pred(Module.GetModuleFileCount) do
    if Supports(Module.GetModuleFileEditor(i), IOTASourceEditor, Result) then
      Exit;
end;

// Courtesy of http://www.davidghoyle.co.uk/WordPress/?p=341
function GetEditorContents(const Editor: IOTASourceEditor) : string;
const
  ChunkSize = 16384;
var
  Reader : IOTAEditReader;
  Pos,
  BytesRead : Integer;
  Buffer : AnsiString;
  WholeStr : AnsiString;
begin
  // Based on EditAsString from http://www.davidghoyle.co.uk/WordPress/?p=341
  assert(Assigned(Editor));

  Result := '';
  Reader := Editor.CreateReader; // interface, auto-freed
  Pos := 0;
  repeat
    SetLength(Buffer, ChunkSize);
    BytesRead := Reader.GetText(Pos, PAnsiChar(Buffer), ChunkSize);
    SetLength(Buffer, BytesRead);
    WholeStr := WholeStr + Buffer;
    Inc(Pos, BytesRead);
  until BytesRead < ChunkSize;

  // Editor uses UTF8 internally!
  Result := UTF8ToString(RawByteString(WholeStr));
end;

procedure SetEditorContents(const Editor: IOTASourceEditor; const ExistingTextLength : Integer;
  const Text : string);
var
  Writer : IOTAEditWriter;
begin
  assert(Assigned(Editor));

  Writer := Editor.CreateWriter;
  assert(Writer.Position = 0);
  Writer.DeleteTo(ExistingTextLength);
  Writer.Insert(PAnsiChar(UTF8Encode(Text)));
end;

{$ENDIF}

end.
