(* VEC Reader - reads VEC and VE2 vector graphic files and displays them on the
   screen. The diashow function displays all VEC/VE2 files on disc one after
   another until a key is pressed. *)

(* Version 4.2 *)
program VecReader;
(*$I KERNEL2.INC*)
(*$I GRAPHLB2.INC*)
(*$I CONVERT.INC*)
(*$I INPUT2.INC*)
(*$I BOX.INC*)
(*$I FORM2.INC*)
(*$I VECIN2.INC*)

const
  SearchFirst: Integer = $11;
  SearchNext : Integer = $12;
  SetDMA     : Integer = $1A;
  mode       : Byte = 0;      (* Drawing mode *)
  MaxFiles = 100;

label
  byebye;

var
  FileName:     String(.14.);
  DiashowDelay: Integer; (* Delay between diashow pictures in seconds *)
  ErrCode:      Integer; (* Error code for Val *)
  fileType:     Byte;    (* 1=VEC, 2=VE2 *)
  action:       (ActionCancel, ActionDiashow, ActionDisplayFile);
  intValue:     Integer;
  formField:    FieldPtr;
  s:            WorkString;
  finish:       Boolean;


(* Initializes the form elements. This procedure is called from InitForm. *)
procedure InitFormElements;
begin
  case formIdx of
    1: begin
          (* Field 1 *)
          AddField(FTFileName, 14, 'Name of VEC/VE2 file', 3, 7, 25, 7, false);

          (* Button 1 *)
          NewAndLinkWithPrevElement;
          AddButton(Ok, 41, 6, 17, 'OK');

          (* Field 2 *)
          NewAndLinkWithPrevElement;
          AddField(FTNumNatural, 3, 'Diashow pause', 3, 10, 18, 10, false);

          (* Button 2 *)
          NewAndLinkWithPrevElement;
          AddButton(Ok, 41, 9, 17, 'Start diashow');

          (* Button 3 *)
          NewAndLinkWithPrevElement;
          AddButton(Cancel, 3, 17, 15, 'Cancel');
       end;
   end; (* case *)
end; (* InitFormElements *)


(* Reads and displays a VEC file. *)
procedure ReadVecFile;
var opCode: Byte;
    count:  Byte;
    x1:     Integer;
    y1:     Integer;
    x2:     Integer;
    y2:     Integer;
    coords: point_array;

  (* Reads coordinates for multi-point functions. *)
  procedure ReadCoords;
  var i: byte;
  begin
    for i := 0 to count - 1 do begin
        x1 := ReadX;
        y1 := ReadY;
        coords(.i,0.) := x1;
        coords(.i,1.) := y1;
    end;
  end; (* ReadCoords *)
begin
  if OpenVecFile(FileName) = ErrOk then begin
    fileType := ReadFileType;
    if fileType <> 0 then begin
      if fileType = 2 then begin
        ReadVe2Header;
      end;
      repeat
        opCode := ReadOpCode;
        if (opCode > 9) and (opCode < 99) then begin
          count := ReadDotCount;
        end;
        case opCode of
           0: (* Dot *) begin
              x1 := ReadX;
              y1 := ReadY;
              Plot(x1, y1, mode);
              end;
           1: (* Line         *) begin
              x1 := ReadX;
              y1 := ReadY;
              x2 := ReadX;
              y2 := ReadY;
              Line(x1, y1, x2, y2, mode);
              end;
           2: (* Box          *) begin
              x1 := ReadX;
              y1 := ReadY;
              x2 := ReadX;
              y2 := ReadY;
              Box(x1, y1, x2, y2, mode);
              end;
           3: (* Square       *) begin
              x1 := ReadX;
              y1 := ReadY;
              x2 := ReadMax; (* width *)
              Square(x1, y1, x2, mode);
              end;
           4: (* Ellipse      *) begin
              x1 := ReadX;
              y1 := ReadY;
              x2 := ReadX; (* radius x *)
              y2 := ReadY; (* radius y *)
              Ellipse(x1, y1, x2, y2, mode);
              end;
           5: (* Circle       *) begin
              x1 := ReadX;
              y1 := ReadY;
              x2 := ReadMax; (* radius *)
              Circle(x1, y1, x2, mode);
              end;
          10: (* Multi-Dot    *) begin
                ReadCoords;
                poly_plot(count, coords, mode);
              end;
          11: (* Multi-Line   *) begin
                ReadCoords;
                poly_line(count, coords, mode);
              end;
          12: (* Polygon-Fill *) begin
                ReadCoords;
                (* poly_fill(count, coords, mode); *)
                poly_line(count, coords, mode);
              end;
          99: (* End *) begin
              end;
          else WriteLn('Unknown OpCode: ', opCode);
        end;
      until opCode = 99;
    end
    else begin
      WriteLn('File ', FileName, ' is not a VEC/VE2 file.');
    end;
    CloseVecFile;
  end
  else begin
    WriteLn('Could not open ', FileName);
    WriteLn;
  end;
end; (* ReadVecFile *)


(* Display diashow *)
procedure Diashow;
label
  ExitDiashow;
var
  run:       Boolean;
  i, j:      Integer;
  FileNames: array(.1 .. MaxFiles.) of string(.14.);
  fileCount: Integer;
  ch:        Char;

  (* Reads VEC filenames into the FileNames array.
     Returns the number of files found. *)
  function ReadDirectory: Integer;
  var
    error, loop, start: Integer;
    FCB: array(.0 ..  26.) of Byte absolute $0060;
    DMA: array(.0 .. 266.) of Byte;
    idx: Integer;

    (* Copies a filename from the DMA array to the FileName variable. *)
    procedure DMAtoFileName(start: Integer);
    var
      loop: Integer;
      ch  : Char;
    begin
      FileName := '';
      for loop := start + 1 to start + 8 do begin (* copy filename *)
        ch := Char( Mem(.Addr(DMA) + loop.) );
        if ch <> ' ' then begin
          FileName := FileName + ch;
        end;
      end;
      FileName := FileName + '.';
      for loop := start + 9 to start + 11 do begin (* copy extension *)
        ch := Char( Mem(.Addr(DMA) + loop.) );
        if ch <> ' ' then begin
          FileName := FileName + ch;
        end;
      end;
    end; (* DMAtoFileName *)

  begin
    error := BDos(SetDMA, Addr(DMA));
    FCB(.0.) := 0;
    (* filter: files with extension mask VE? only *)
    for loop := 1 to 8 do
      FCB(.loop.) := ord('?');
    FCB(. 9.) := ord('V');
    FCB(.10.) := ord('E');
    FCB(.11.) := ord('?'); (* 'C' or '2' expected *)

    idx := 1;
    error:= BDos(SearchFirst, Addr(FCB));
    if error <> 255 then begin
      start := error * 32;
      DMAtoFileName(start);
      FileNames(.idx.) := FileName;
      idx := succ(idx);
    end;
    repeat
      error := BDos(SearchNext);
      start := error * 32;
      if error <> 255 then begin
        DMAtoFileName(start);
        FileNames(.idx.) := FileName;
        idx := succ(idx);
        if idx > MaxFiles then
          error := 255; (* exit loop *)
      end
    until error = 255;

    ReadDirectory := pred(idx);
  end; (* ReadDirectory *)

begin (* main procedure *)
  fileCount := ReadDirectory;
  if fileCount > MaxFiles then begin
    fileCount := MaxFiles;
  end;
  run := true;

  while run do begin
    for i := 1 to fileCount do begin
      FileName := FileNames(.i.);
      ClrScr;
      ReadVecFile;
      for j := 1 to DiashowDelay do begin
        Delay(1000);
        if KeyPressed then begin
          Read(kbd, ch);
          goto ExitDiashow;
        end;
      end; (* for j *)
    end; (* for i *)
  end; (* while *)
ExitDiashow:
end; (* Diashow *)

(* Main program *)
begin
  repeat
    (* get the name of the VEC/VE2 file, or the diashow parameters, respectively *)
    DiashowDelay := 4; (* initialize to 4 seconds *)
    if ParamCount > 0 then begin
      FileName := ParamStr(1); (* first commandline parameter treated as filename *)
      if (FileName = 'D') or (FileName = 'd') then
        action := ActionDiashow
      else
        action := ActionDisplayFile;
  
      if ParamCount > 1 then begin
        Val(ParamStr(2), DiashowDelay, ErrCode);
        if ErrCode <> 0 then begin
          DiashowDelay := 4; (* default delay between pictures of 4 seconds *)
        end;
      end;
    end
    else begin
      ClrScr;
      DrawBox(1, 1, 90, 3);
      GotoXY(28, 2);
      Write('VEC/VE2 file reader V4.2 by Bernd Bock');
      GotoXY(22, 10);
      Write('seconds');
  
      Mark(form_HeapTop);
      InitForm(1);
      SetMessageLine(22);
      finish := false;
      
      repeat
        ProcessForm;
    
        if FormCancelled then begin
          action := ActionCancel;
          finish := true;
        end else begin
          if IsActivated(2) then begin (* Button 2 = Start diashow *)
            action := ActionDiashow;
            formField := GetField(2);  (* Field 2 = Diashow pause *)
            intValue := CharPtrToInteger(formField^.txt);
            if intValue > 0 then
                DiashowDelay := intValue;
            finish := true;
          end else begin (* Ok button activated *)
            action := ActionDisplayFile;
            formField := GetField(1); (* Field 1 = VEC/VE2 filename *)
            CharPtrToString(formField^.txt, s);
            FileName := s;
            if Length(FileName) = 0 then begin
              GotoXY(1, 22); Write('Please enter a VEC/VE2 filename.');
            end else begin
              finish := true;
            end;
          end;
        end;
      until finish;
      
      Release(form_HeapTop);
    end;
  
    Write(chr(27), '0'); (* switch off status bar *)
    ClrScr;
    GraphInit;
    HideCursor;
  
    case action of
      ActionDiashow:     Diashow;
      ActionDisplayFile: ReadVecFile;
    end;
  
    if action <> ActionCancel then begin
      Beep;
      WaitForKey;
    end;
    
    Write(chr(27), '1'); (* switch on status bar *)
    ShowCursor;
  until (action = ActionCancel) or (ParamCount > 0);
end.
