{
    This file is part of Chentrah,
    Copyright (C) 2004-2009 Anton Rzheshevski (chebmaster@mail.ru).

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see http://www.gnu.org/licenses/

 ********************************************************************** }

{$mode delphi}
{$longstrings on}
unit un_process;

interface
 uses sysutils, Classes, process, math;
 
type

  { TExProcess }

  TExProcess = class
  protected
    p: TProcess;
    s: string;
    function _GetExitStatus(): integer;
  public
    constructor Create(commandline: string);
    procedure Execute;
    destructor Destroy; override;
  
    procedure OnReadLn(s: string); virtual;
    property ExitStatus: integer read _GetExitStatus;
  end;

  { TLoggedProcess }

  TLoggedProcess = class(TExProcess)
  public
    log: TStringList;
    constructor Create(commandline: string);
    destructor Destroy; override;
    procedure OnReadLn(s: string); override;
  end;

implementation

const buf_len = 3000;


{ TExProcess }

function TExProcess._GetExitStatus(): integer;
begin
  Result:=p.ExitStatus;
end;

constructor TExProcess.Create(commandline: string);
begin
  s:='';
  p:=TProcess.Create(nil);
  p.CommandLine:=commandline;
  p.Options:=[poUsePipes,poNoConsole];
end;

procedure TExProcess.Execute;
var
  buf: string;
  i, j, c, n: integer;
begin
  p.Execute;
  repeat
    SetLength(buf, buf_len);
    SetLength(buf, p.output.Read(buf[1], length(buf))); //waits for the process output
    Sleep(3);
    // cut the incoming stream to lines:
    s:=s + buf; //add to the accumulator
    repeat //detect the line breaks and cut.
      i:=Pos(#13, s);
      j:=Pos(#10, s);
      if i=0 then i:=j;
      if j=0 then j:=i;
      if j = 0 then Break; //there are no complete lines yet.
      OnReadLn(Copy(s, 1, min(i, j) - 1)); //return the line without the CR/LF characters
      s:=Copy(s, max(i, j) + 1, length(s) - max(i, j)); //remove the line from accumulator
    until false;
  until buf = '';
  if s <> '' then OnReadLn(s);
end;

destructor TExProcess.Destroy;
begin
  p.Free;
end;

procedure TExProcess.OnReadLn(s: string);
begin
  // Do nothing ^_^
end;

{ TLoggedProcess }

constructor TLoggedProcess.Create(commandline: string);
begin
  inherited Create(commandline);
  log:= TStringList.Create;
end;

destructor TLoggedProcess.Destroy;
begin
  log.Free;
  inherited Destroy;
end;

procedure TLoggedProcess.OnReadLn(s: string);
begin
  log.Add(s);
end;

end.

