{

    Copyright 2004 Marianne Wartoft, marianne at wartoft dot nu, and Henrik Arro
    http://www.wartoft.nu, http://www.aw.nu

    This file is part of Sebran.

    Sebran 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.

    Sebran 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 Sebran; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

}


unit Fileread;
{Written by Henrik Arro}

interface

uses
  SysUtils, Dialogs, Forms, Controls;

const
  MaxBufSize = 512;

type
  EInternalError = class(Exception)
  public
    constructor Create(const Msg: string);
  end;
  EFileNotFound = class(EInOutError);
  EFileOpenFailed = class(EInOutError);

  TBufSize = 0 .. MaxBufSize;

  TByteFile = class
    public
      constructor Create(const InputFileName: string);
      destructor Destroy; override;
      function ReadByte: Byte;
      function ReadSmallint: Smallint;
      function ReadLongint: Longint;
      procedure ReadString(var ResultString: string);
      function Eof: Boolean;
    private
      InputFile: File;
      Buf: array[0 .. MaxBufSize - 1] of Byte;
      BufSize: TBufSize;
      BufIndex: TBufSize;
      procedure ReadBuffer;
  end;

  procedure Assert(Test: Boolean; const Msg: string);
  Function Dekryptera(str: String): String;

implementation

uses
  WinProcs;

constructor EInternalError.Create(const Msg: string);
begin
  inherited Create('Internal error: ' + Msg);
end;

procedure Assert(Test: Boolean; const Msg: string);
begin
  if not Test then
    raise EInternalError.Create(Msg);
end;


{ TByteFile }

constructor TByteFile.Create(const InputFileName: string);
begin
  inherited Create;

  if FileExists(InputFileName) then begin
    FileMode := 0; // Öppna i Read-only läge
    AssignFile(InputFile, InputFileName)

  end else
    raise EFileNotFound.Create(Format('File "%s" not found.', [InputFileName]));

  try
    Reset(InputFile, 1);
  except on E: EInOutError do
    raise EFileOpenFailed.Create(Concat('File open failed: ', E.Message));
  end;

  BufSize := 0;
  BufIndex := 0;
end;

(*
  end else begin
      Screen.Cursor := crDefault;
      MessageDlg(Concat('The file ', InputFileName, ' is missing. Reinstall Seterra.'), mtError, [mbOK], 0);
      Application.Terminate;
  end;
*)

destructor TByteFile.Destroy;
begin
  try
    CloseFile(InputFile);
  except
    on EInOutError do
      { Do nothing. This is in case the file is not open. }
  end;
  Inherited Destroy;
end;

function TByteFile.ReadByte: Byte;
begin
  if BufIndex >= BufSize then
    ReadBuffer;
  Result := Buf[BufIndex];
  BufIndex := BufIndex + 1;
end;

function TByteFile.ReadSmallint: Smallint;
var
  lobyte, hibyte: Byte;
begin
  lobyte := ReadByte;
  hibyte := ReadByte;

  Result := Word(hibyte) * 256 + lobyte;
end;

function TByteFile.ReadLongint: Longint;
var
  lobyte, hibyte: Byte;
  loword, hiword: Word;
begin
  { Read the low word. }
  lobyte := ReadByte;
  hibyte := ReadByte;
  loword := Word(hibyte) * 256 + lobyte;

  { Read the high word. }
  lobyte := ReadByte;
  hibyte := ReadByte;
  hiword := Word(hibyte) * 256 + lobyte;

  Result := MAKELONG(loword, hiword);
end;

procedure TByteFile.ReadString(var ResultString: string);
var
  b, b2: Byte;
  intCode, pos: Integer;
  code: string;
  StringLength: Byte;
  i,j: Byte;
  temp: string;
begin
  { Read the string length stored in the first byte. }
  stringLength := ReadByte;

  { Store the string length. }
  {$IFDEF VER90}
  SetLength(ResultString, StringLength);
  {$ELSE}
  ResultString[0] := Chr(StringLength);
  {$ENDIF}

  if StringLength > 0 then
  begin
    { Read the actual string. }
    for i := 1 to StringLength do
    begin
      temp := '';
      Readbyte;
      for j:=1 to 5 do
      begin
           Temp := concat(Temp, chr(readbyte))
      end;
      Val(Temp, intCode, pos);
      temp := concat('',WideChar(intCode));
      ResultString[i] := temp[1];
    end;
  end;
  ResultString := Dekryptera(ResultString);
end;

function TByteFile.Eof: Boolean;
begin
  Result := System.Eof(InputFile) and (BufIndex >= BufSize);
end;

{$IFDEF VER90}
procedure TByteFile.ReadBuffer;
var
  TempBufSize: Integer;
begin
  { The temporary variable is necessary since BufSize may be smaller than
    a word (if it less than 256), and BlockRead expects us to pass a word
    size parameter. We know that TempBufSize will fit in a TBufSize variable,
    since the largest possible block size is MaxBufSize, so the cast is OK. }
  BlockRead(InputFile, Buf, MaxBufSize, TempBufSize);
  if TempBufSize = 0 then
    raise EInOutError.Create('Read beyond end of file');
  BufSize := TBufSize(TempBufSize);
  BufIndex := 0;
end;
{$ELSE}
procedure TByteFile.ReadBuffer;
var
  TempBufSize: Word;
begin
  { The temporary variable is necessary since BufSize may be smaller than
    a word (if it less than 256), and BlockRead expects us to pass a word
    size parameter. We know that TempBufSize will fit in a TBufSize variable,
    since the largest possible block size is MaxBufSize, so the cast is OK. }
  BlockRead(InputFile, Buf, MaxBufSize, TempBufSize);
  if TempBufSize = 0 then
    raise EInOutError.Create('Read beyond end of file');
  BufSize := TBufSize(TempBufSize);
  BufIndex := 0;
end;
{$ENDIF}


Function Dekryptera(str: String): String;
var
    i: Integer;
    NyStr: String;

begin
     {NyStr := '';
     For i := 1 to Length(str) do begin
         NyStr := Concat(NyStr, Chr(Ord(str[i]) + 21));
     end;   }
     Dekryptera := str;
end;

end.
