(* ------------------- VECIN.INC -----------------------

  Include file to load a vector graphic
  from a VEC or VE2 file.

  Provides the following functions:

    function  OpenVecFile(filename: TFileName): ErrorCode;
    procedure CloseVecFile;
    function  ReadVecHeader: boolean;
    function  ReadOpCode: byte;
    function  ReadDotCount: byte;
    function  ReadValue: integer;

  Uses include file KERNEL2.INC.

  ---------------------------------------------------- *)
const
  BufSize = 128;

type
  TFileName  = string(.14.);
  BinaryFile = file;
  ErrorCode  = (ErrOk, ErrFileNotFound, ErrFormatNotSupported);
  VE2Header  = record
                 minX: integer;
                 maxX: integer;
                 minY: integer;
                 maxY: integer;
                 targetResolutionX: integer;
                 targetResolutionY: integer;
                 bytesXCoord: byte;
                 bytesYCoord: byte;
                 profileFlags: integer;
               end;

var
  fbuf:         Array(.1..BufSize.) of byte;
  fbufidx:      byte;
  recsread:     integer;
  vecfile:      BinaryFile;
  header:       VE2Header;

(* Forward declarations *)
function ReadValue: integer; forward;


(* Reads a byte from the buffer. Reads a block from disc
   as soon as the buffer is read to the end. *)
function ReadBuf: byte;
begin
  if fbufidx = BufSize then begin
    fbufidx := 1;
    BlockRead(vecfile, fbuf, 1, recsread); (* reads a block of 128 bytes *)
  end
  else
    fbufidx := succ(fbufidx);
  ReadBuf := fbuf(.fbufidx.);
end; (* ReadBuf *)


(* Opens a VEC file. *)
function OpenVecFile(filename: TFileName): ErrorCode;
var result: ErrorCode;
begin
  fbufidx := BufSize;

  Assign(vecfile, filename);
  (*$I-*)
  Reset(vecfile);
  (*$I+*)
  if IOResult <> 0 then
    result := ErrFileNotFound
  else
    result := ErrOk;
  
  OpenVecFile := result;
end; (* OpenVecFile *)


(* Closes the VEC/VE2 file previously opened. *)
procedure CloseVecFile;
begin
  Close(vecfile);
end; (* CloseVecFile *)


(* Reads and verifies the vector graphics file ident (should be 'VEC' or 'VE2').
   Returns the vector file type: 0=unknown, 1=VEC, 2=VE2 *)
function ReadFileType: byte;
var b: byte;
    fileType: byte;
begin
  fileType := 0;
  b := ReadBuf;
  if chr(b) = 'V' then begin
    b := ReadBuf;
    if chr(b) = 'E' then begin
      b := ReadBuf;
      if chr(b) = 'C' then begin
        fileType := 1; (* VEC *)
        header.bytesXCoord := 2; (* fixed size *)
        header.bytesYCoord := 2; (* fixed size *)
      end
      else begin
        if chr(b) = '2' then begin
          fileType := 2; (* VE2 *)
        end;
      end;
    end;
  end;
  ReadFileType := fileType;
end; (* ReadFileType *)


(* Reads a VE2 header. *)
procedure ReadVe2Header;
begin
  with header do begin
    minX := ReadValue;
    maxX := ReadValue;
    minY := ReadValue;
    maxY := ReadValue;
    targetResolutionX := ReadValue;
    targetResolutionY := ReadValue;
    bytesXCoord := ReadBuf;
    bytesYCoord := ReadBuf;
    profileFlags := ReadValue;
  end;
end;


(* Reads the vector graphics operation code. *)
function ReadOpCode: byte;
begin
  ReadOpCode := ReadBuf;
end; (* ReadOpCode *)


(* Reads the vector graphics operation's dot count. *)
function ReadDotCount: byte;
begin
  ReadDotCount := ReadBuf;
end; (* ReadDotCount *)


(* Reads an value (coordinate, width, radius, etc.). *)
function ReadValue;
var b: byte;
    i: integer;
begin
  b := ReadBuf;
  i := b;
  b := ReadBuf;
  i := i + 256 * b;
  ReadValue := i;
end; (* ReadX *)


(* Reads an X coordinate; input size depends on bytesXCoord. *)
function ReadX: integer;
var result: integer;
begin
  if header.bytesXCoord = 1 then begin
    result := ReadBuf;   (* 1 Byte *)
  end
  else begin
    result := ReadValue; (* 2 Bytes *)
  end;
  ReadX := result;
end;


(* Reads a Y coordinate; input size depends on bytesYCoord. *)
function ReadY: integer;
var result: integer;
begin
  if header.bytesYCoord = 1 then begin
    result := ReadBuf;   (* 1 Byte *)
  end
  else begin
    result := ReadValue; (* 2 Bytes *)
  end;
  ReadY := result;
end;


(* Reads a value; input size depends on the maximum of bytesXCoord
   and bytesYCoord. *)
function ReadMax: integer;
var result: integer;
    maxSize: byte;
begin
  maxSize := header.bytesXCoord;
  if header.bytesYCoord > maxSize then begin
    maxSize := header.bytesYCoord;
  end;
  if maxSize = 1 then begin
    result := ReadBuf;   (* 1 Byte *)
  end
  else begin
    result := ReadValue; (* 2 Bytes *)
  end;
  ReadMax := result;
end;
