{******************************************************************************
*
*  Copyright © POV-Team(tm) 1996. All Rights Reserved.
*  This Editor DLL code is Copyright 1996 Christopher J. Cason.
*  Author : Christopher J. Cason.
*
*  from Persistence of Vision Raytracer(tm)
*  Copyright 1996 Persistence of Vision Team
*
* The terms POV-Ray, POV, and Persistence of Vision Raytracer are trademarks
* of the Persistence of Vision Team.
*---------------------------------------------------------------------------
*  NOTICE: This source code file is provided so that users may experiment
*  with enhancements to POV-Ray(tm) and to port the software to platforms other
*  than those supported by the POV-Ray Team.  There are strict rules under
*  which you are permitted to use this file.  The rules are in the file
*  named POVLEGAL.DOC which should be distributed with this file. If
*  POVLEGAL.DOC is not available or for more info please contact the POV-Ray(tm)
*  Team Coordinator by leaving a message in CompuServe's POVRAY Forum.
*  The latest version of POV-Ray may be found there as well.
*  POV-Ray files may also be found on the world wide web at www.povray.org.
*
* POV-Ray is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*******************************************************************************}

// This code is not commented enough or as much as I'd like. It also needs
// a major cleanup. However, after all, this is volunteer work and I've
// not got the time to do so now. Rather than further delay the release,
// here it is.

unit DllInterface ;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Dialogs,
  Forms,
  OvcBase,
  OvcData,
  OvcEditU,
  OvcConst,
  OvcEdit,
  OvcExcpt,
  ClassTPovEdit,
  ClassTFindDlg,
  ClassTReplDlg,
  ClassTStatusForm ;

type
  THandleRec = record
    FileMenu : THandle ;
    EditMenu : THandle ;
    SearchMenu : THandle ;
    InsertMenu : THandle ;
    OptionsMenu : THandle ;
    AppearanceMenu : THandle ;
    StatusHandle : THandle ;
  end ;

  EditPointers = record
    Init : Pointer ;
    Destroy : Pointer ;
    Show : Pointer ;
    SelectEditor : Pointer ;
    CreateEditor : Pointer ;
    GetHandles : Pointer ;
    UpdateMenus : Pointer ;
    Dispatch : Pointer ;
    GetEditor : Pointer ;
    ReleaseEditor : Pointer ;
    GetTitle : Pointer ;
    CanClose : Pointer ;
    SetActive : Pointer ;
    OpenFile : Pointer ;
    GetLine : Pointer ;
    Seek : Pointer ;
    SaveFile : Pointer ;
    OpenInNew : Pointer ;
    SaveSettings : Pointer ;
  end ;

  PInteger = ^Integer ;
  PLongInt = ^LongInt ;
  PBoolean = ^Boolean ;
  PTHandleRec = ^THandleRec ;
  PEditPointers = ^EditPointers ;

function EditGetVersion (SizeOfRec : Integer ; EditPointer : PEditPointers) : Integer ; stdcall ;
exports EditGetVersion name 'EditGetVersion' ;

implementation

procedure DllShowMessage (E : Exception ; Str : String) ;
begin
  Application.MessageBox (PChar (Str + ' : ' + E.Message), PChar ('POV-Ray Editor'), MB_ICONEXCLAMATION) ;
end ;

procedure EditInit (Handle : THandle) ; stdcall ;
begin
end ;

function EditCreateEditor (hWndMain : THandle ; hWndTabbed : THandle ; Home : PChar) : THandle ; stdcall ;
begin
  Result := 0 ;
  try
    if Uppercase (ExtractFileName (Application.ExeName)) <> 'PVENGINE.EXE' then
      exit ;
    PovEdit := TPovEdit.Create (hWndMain, hWndTabbed, Home) ;
    Result := PovEdit.Handle ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditCreateEditor') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditDestroy ; stdcall ;
begin
end ;

procedure EditShow (State : Boolean) ; stdcall ;
begin
  try
    if State then
    begin
      PovEdit.Show ;
      if PovEdit.Editor.CanFocus then
        PovEdit.Editor.SetFocus ;
    end
    else
      PovEdit.Hide ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditShow') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditGetHandles (HandleRec : PTHandleRec) ; stdcall ;
begin
  try
    with HandleRec^ do
    begin
      FileMenu := PovEdit.FileMenu.Handle ;
      EditMenu := PovEdit.EditMenu.Handle ;
      SearchMenu := PovEdit.SearchMenu.Handle ;
      InsertMenu := PovEdit.InsertMenu.Handle ;
      OptionsMenu := PovEdit.OptionsMenu.Handle ;
      AppearanceMenu := PovEdit.AppearanceMenu.Handle ;
      StatusHandle := StatusForm.Handle ;
    end ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditGetHandles') ;
      Raise ;
    end ;
  end ;
end ;

procedure EditUpdateMenus (Editor : TOvcTextFileEditor) ; stdcall ; export ;
begin
  try
    PovEdit.FileMenuClick (PovEdit) ;
    PovEdit.Edit1Click (PovEdit) ;
    PovEdit.Search1Click (PovEdit) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditUpdateMenus') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditSelectEditor (Editor : TOvcTextFileEditor) : Boolean ; stdcall ;
var
  Col : Integer ;
  Line : LongInt ;
begin
  try
    Result := True ;
//  SetWindowPos (Editor.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOREDRAW) ;
    Editor.Show ;
    if Editor <> PovEdit.Editor then
      PovEdit.Editor.Hide ;
    PovEdit.Editor := Editor ;
    EditUpdateMenus (Editor) ;
    Line := Editor.GetCaretPosition (Col) ;
    PovEdit.EditorShowStatus (PovEdit, Line, Col) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSelectEditor') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditDispatch (Command : Integer) : Boolean ; stdcall ;
begin
  try
    Result := PovEdit.PopupMenu.DispatchCommand (Command) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditDispatch') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditGetEditor : TOvcTextFileEditor ; stdcall ;
begin
  Result := nil ;
  try
    Result := PovEdit.GetNextEditor ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditGetEditor') ;
      if ((E is EAccessViolation) or (E is EStackOverFlow)) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditReleaseEditor (Editor : TOvcTextFileEditor) : boolean ; stdcall ;
begin
  Result := False ;
  try
    Result := PovEdit.ReleaseEditor (Editor) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditReleaseEditor') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditGetTitle (Editor : TOvcTextFileEditor ; PTopLine : PLongInt ; PLine : PLongInt ; PCol : PInteger ; PModified : PInteger) : PChar ; stdcall ;
var
  Col : Integer ;
  Line : LongInt ;
begin
  try
    Line := Editor.GetCaretPosition (Col) ;
    Result := PChar (Editor.FileName) ;
    if PTopLine <> nil then
      PTopLine^ := Editor.TopLine ;
    if PLine <> nil then
      PLine^ := Line ;
    if PCol <> nil then
      PCol^ := Col ;
    if PModified <> nil then
      PModified^ := Integer (Editor.Modified) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditGetTitle') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function OpenFile (Editor : TOvcTextFileEditor ; FileName : PChar ; StoreInHistory : Boolean) : boolean ;
var
  OpenIn : TOvcTextFileEditor ;
begin
  Result := True ;
  OpenIn := PovEdit.FileIsLoaded (Editor, FileName) ;
  if OpenIn = nil then
  begin
    if FileExists (FileName) then
    begin
      Editor.FileName := FileName ;
      Editor.IsOpen := True ;
      if StoreInHistory then
        PovEdit.HistoryList.Add (FileName) ;
    end
    else
    begin
      Application.MessageBox (PChar ('The file ' + #$0D + '  ' + FileName + #$0D + 'does not exist and therefore cannot be opened'),
                              PChar ('POV-Ray Editor'),
                              MB_ICONEXCLAMATION) ;
      Result := False ;
    end ;
  end
  else
    Editor.Attach (OpenIn) ;
  if Result then
    PovEdit.UpdateTab ;
  PovEdit.UpdateHistory ;
end ;

function EditOpenFile (Editor : TOvcTextFileEditor ;
                       FileName : PChar ;
                       TopLine : LongInt ;
                       Line : LongInt ;
                       Col : Integer ;
                       StoreInHistory : Boolean) : boolean ; stdcall ;
begin
  try
    PovEdit.Editor := Editor ;
    Result := OpenFile (Editor, FileName, StoreInHistory) ;
    if Result then
    begin
      try
        Editor.TopLine := TopLine ;
        Editor.SetCaretPosition (Line, Col) ;
      except
        on EInvalidLineOrCol do ;
        on EInvalidLineOrPara do ;
      end ;
    end ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditOpenFile') ;
      Result := False ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditCanClose : Boolean ; stdcall ;
begin
  Result := True ;
  try
    Result := PovEdit.ProgramCloseQuery ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditCanClose') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditSetActive (Active : Boolean) ; stdcall ;
begin
  try
    PovEdit.SetMenuActive (Active) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSetActive') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditGetLine (Editor : TOvcTextFileEditor ; LineNumber : Integer ; Buffer : PChar ; BufLen : Integer) : Boolean ; stdcall ;
begin
  Result := False ;
  try
    if LineNumber > Editor.LineCount then
      exit ;
    Editor.GetLine (LineNumber, Buffer, BufLen) ;
    Result := True ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      // if I had the message concatenation here (i.e. 'EditGetLine : ' + E.Message),
      // the code would do VERY wierd things at run-time, *even if* no exception was raised.
      // hmmm ...
      DllShowMessage (E, 'EditGetLine') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditSeek (Editor : TOvcTextFileEditor ; From : Integer ; Offset : PInteger) : Integer ; stdcall ;
var
  Line : Integer ;
  Count : Integer ;
  CurrentOffset : Integer ;
  ThisLine : Integer ;
begin
  Result := 0 ;
  try
    Count := Editor.LineCount ;
    CurrentOffset := 0 ;
    for Line := 1 to Count do
    begin
      ThisLine := Editor.LineLength [Line] + 1 ;
      if CurrentOffset + ThisLine >= Offset^ then
      begin
        Result := Line ;
        Offset^ := Offset^ - CurrentOffset ;
        exit ;
      end
      else
        CurrentOffset := CurrentOffset + ThisLine ;
    end ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSeek') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditSaveFile ; stdcall ;
begin
  try
    PovEdit.SaveClick (PovEdit) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSaveFile') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditOpenInNew ; stdcall ;
begin
  try
    PovEdit.OpenInNewClick (PovEdit) ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSaveFile') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

procedure EditSaveSettings ; stdcall ;
begin
  try
    PovEdit.WriteSettings ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditSaveSettings') ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

function EditGetVersion (SizeOfRec : Integer ; EditPointer : PEditPointers) : Integer ; stdcall ; export ;
begin
  try
    Result := -1 ;
    if SizeOf (EditPointers) <> SizeOfRec then
      exit ;
    Result := 101 ;
    with EditPointer^ do
    begin
      Init := @EditInit ;
      Destroy := @EditDestroy ;
      Show := @EditShow ;
      SelectEditor := @EditSelectEditor ;
      CreateEditor := @EditCreateEditor ;
      GetHandles := @EditGetHandles ;
      UpdateMenus := @EditUpdateMenus ;
      Dispatch := @EditDispatch ;
      GetEditor := @EditGetEditor ;
      ReleaseEditor := @EditReleaseEditor ;
      GetTitle := @EditGetTitle ;
      CanClose := @EditCanClose ;
      SetActive := @EditSetActive ;
      OpenFile := @EditOpenFile ;
      GetLine := @EditGetLine ;
      Seek := @EditSeek ;
      SaveFile := @EditSaveFile ;
      OpenInNew := @EditOpenInNew ;
      SaveSettings := @EditSaveSettings ;
    end ;
  except
    on E : EInvalidOperation do ;
    on E : Exception do
    begin
      DllShowMessage (E, 'EditGetVersion') ;
      Result := -1 ;
      if (E is EAccessViolation) or (E is EStackOverFlow) then
        Raise ;
    end ;
  end ;
end ;

end.


