unit ufHTML;
{$INCLUDE 'Filters.inc'}

interface

uses
  SysUtils, Classes,
  uFilter;

type
  TFilterHTML = class(TFilter)
  public
    class function ID: string; override;
    class function Name: string; override;
    procedure Clear; override;
    function IsSupported(const FileName, Content: string): boolean; override;
    function Execute(const FileName, Content: string): string; override;
  end;

implementation

uses
  Windows,
  {$INCLUDE 'DelphiFarUnits.inc'} ,
  uSystem, uStrings, uMessages;

{ TFilterHTML }

procedure TFilterHTML.Clear;
begin
  inherited;
  Description := GetMsg(MFilterHTMLDescription);
  FileMasks.Add('*.htm');
  FileMasks.Add('*.html');
  FileMasks.Add('*.xhtml');
end;

function TFilterHTML.Execute(const FileName, Content: string): string;
const
  ELinksContentType = '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>';
var
  ELinksFileName: string;
  ELinksArguments: string;
  ContentFileName: string;
  CurrentWorkingDirectory: string;
  Stream: TMemoryStream;
  UtfStr: AnsiString;
  ResultCode: DWORD;
  Progress: TFarProgress;
begin
  ELinksFileName := ExtractFilePath(TFarPlugin.Instance.PluginFileName) + 'elinks\elinks.exe';
  if not FileExists(ELinksFileName) then
    ELinksFileName := 'elinks.exe';
  ContentFileName := SystemTempFile(SystemTempDir, 'htmlpage', '.htm');
  try
    ELinksArguments := ''
      + ' --dump 1'
      + ' --dump-width ' + IntToStr(TFarScreen.Width)
      + ' --dump-charset utf8'
      + ' --no-connect 1'
      + ' --no-home 1'
      + ' ' + AnsiQuotedStr(ExtractFileName(ContentFileName), '"')
      ;
    Stream := TMemoryStream.Create;
    try
      if (Content <> '') and (Content[1] = #$feff) then
        UtfStr := StringToAnsiEncodedUtf8(ELinksContentType + Copy(Content, 2, MaxInt))
      else
        UtfStr := StringToAnsiEncodedUtf8(ELinksContentType + Content);
      if UtfStr <> '' then
        Stream.WriteBuffer(UtfStr[1], Length(UtfStr));
      Stream.SaveToFile(ContentFileName);
      Stream.Clear;
      CurrentWorkingDirectory := GetCurrentDir;
      try
        if not SetCurrentDir(ExtractFilePath(ContentFileName)) then
          raise EFilterError.Create(GetMsg(MFailedToChangeCWD) + #13#10 + ExtractFilePath(ContentFileName));
        Progress := TFarProgress.Create;
        try
          Progress.Show([GetMsg(MTitle), GetMsg(MCallingElinks), Progress.BuildProgressBar(0, 1)]);
          if not GetConsoleOutput(AnsiQuotedStr(ELinksFileName, '"') + ' ' + ELinksArguments, Stream, nil, ResultCode, SW_HIDE) then
            raise EFilterError.Create(GetMsg(MFailedToExecuteELinks) + #13#10 + ELinksFileName + #13#10 + ELinksArguments);
        finally
          FreeAndNil(Progress);
        end;
      finally
        SetCurrentDir(CurrentWorkingDirectory);
      end;
      if ResultCode <> 0 then
        raise EFilterError.CreateFmt(GetMsg(MFailedToExecuteELinks_ResultCode), [ResultCode]);
      SetLength(UtfStr, Stream.Size);
      if Stream.Size > 0 then
        Move(Stream.Memory^, UtfStr[1], Stream.Size);
      Result := AnsiEncodedUtf8ToString(UtfStr);
    finally
      FreeAndNil(Stream);
    end;
  finally
    if FileExists(ContentFileName) then
      SysUtils.DeleteFile(ContentFileName);
  end;
end;

class function TFilterHTML.ID: string;
begin
  Result := 'html';
end;

function TFilterHTML.IsSupported(const FileName, Content: string): boolean;
begin
  Result := False;
  if inherited IsSupported(FileName, Content) then
  begin
    Result := True;
  end;
end;

class function TFilterHTML.Name: string;
begin
  Result := GetMsg(MFilterHTMLName);
end;

initialization
  TRegisteredFilters.Add(TFilterHTML);

end.
