unit Mdiform;
{ =======================================================================
  WinWCP Master MDI form (c) John Dempster, 1996-97 All Rights Reserved
  V1.3 20/3/97 CED 1401 support added (tested on micro1401)
  V1.3b 3/4/97 About box now reads Interface type on start-up
               pCLAMP multi-channel files now imported with correct dt
               -10412 error now fixed for N.I. boards
  V1.4 23/4/97 Support for CED 1902 added
  V1.5 20/5/97 Support for Digidata 1200 added
  4/6/97 ... Caption now correctly updated when New file created
  V1.5a 9/6/97 ...Append menu option added
  V1.6 10/6/97 ... Export to Axon ABF file added
  V1.6a 12/6/97 ... LEAK records now included in subtracted file when
                    in FILE MODE leak subtraction mode.
                    COPY DATA Buffer overflow GPI (REPLAY.PAS) fixed
  V1.6b 16/6/97 ... Cursor readings in View Records can be saved to log file
  V1.6c 25/6/97 ... Seal test now has 3 pulse options
        27/6/97 ... Seal Test AUTOSCALE and DISPLAYSCALE now in INI file
  V1.6d 27/6/97 ... Seal test baseline now fixed when AutoScale is unchecked
  V1.6e 8/7/97 ... Seal Test scaling now takes amplifier gain into account
  V1.6f 16/7/97 ... Default Outputs Dialog now indicates whether it is
                    active or not.
                    Seal Test always autoscaled, first time after program
                    started
  V1.7 25/8/97 ... Import from CED data files added (Convert.pas)
  V1.7a 31/8/97 ... Key shortcuts now available for setting record type
        1/9/97 ... Append now updates number of records correctly
  V1.7b 8/9/97 ... Event detector pre-trigger % now variable
                   Delete rejected records now works
                   Ctrl-R now toggles rejected record check box
  V1.7c 10/9/97 ... Active record in View records module (replay.pas)
                    now only displayed once.
                    Number of variables in X-Y displays now increased
                    to 6000 (measure.pas, curvefit.pas)
                    Histograms now stored in clipboard as Bin.Mid,Y pairs
  V1.7d 1/12/97 ... Event detection now works with standard 1401 (rec.pas)
                    CED error message text now returned (CED1401.pas)
  V1.8 14/12/97 ... Waveform generation now accurate to 0.1 ms
                    Averaging function limited of 16000 points
                    Copy Data GPF fixed by reducing size of text buffer to
                    30000
                    10-90% rise time now based upon 10%-90% (peak-baseline)
                    rather than 10%-90% peak+ - peak-
  V1.8a 6/1/97 ...  INI file can now be disabled with /NI command line
                    parameter. This allows program to be run from read-only
                    directory on a file server. Log file also disabled in
                    these circumstance.
  V1.8b 20/1/98 ... Seal Test now has free run option which allows monitoring
                    of input channels without voltage pulse generation/triggering
  V1.8c 24/2/98 ... EPC curve fitting function now works
  V1.9 3/2/98 ... Export to ASCII, Integer and floating point now added
  V1.9a 5/3/98 ... DMA channels can now be disabled for N.I. boards (update)
                   Digidata I/O port can now be changed by users (bug fix)
  V1.9b 23/3/98 ... Curve fitting no longer crashes when fitting very large
                    records.
                    Large error pulse steps between seal test sweeps
                    with Digidata 1200 fixed.
                    (Bug in VDS_ProgramDMACHannel in VDS.PAS).
  V2.0 2/4/98 ...   Time interval over which rate of rise is calculated
                    can now be set by user. (measure.pas)
                    Cursor readout now shows both absolute and C1-C0 values
                    (replay.pas)
                    LabPC.pas corrected to prevent NIDAQ error messages
                    during voltage pulses
                    Numbers of data points in user-defined waveforms now
                    reduced automatically to fit available buffer space.
                    Recording intervals also adjusted if too long
  V2.0a 14/4/98 ... Bug in WavRun.pas which caused NIDAQ error -10411 when
                    voltage pulse >7secs long were produced now fixed.
  V2.0b 5/5/98 ... Size of array increased in SaveInitializationFile and
                    LoadInitializationFile to avoids Array Full error when
                    6 channels are used.
  V2.1 6/2/98 ... SealTest module modified to fix intermittent 0V glitches
                    between test pulses with Digidata 1200
                    Delete Records & Delete Rejected option fixed to
                    prevent Divide by Zero errors when further records
                    are acquired.
                    Test pulse width can now be set within range 0.1 ms - 1000ms
                    System no longer crashes on File/Exit when
                    Seal Test or Recording in progress
  V2.2 12/4/99 ... RecEdit can now change ADCVoltageRange settings for record
                   Residual SD added to list of variables in Curvfit.pas
  V2.3 31/5/99 ... Updated to support ABF V1.5 (Clampex V7)
  =======================================================================}

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, Menus, Global, FileIo, Shared, Replay, Zoom, Setup,
  Measure, Average, PrintRec, Rec, Wavgen, CurvFit, SimSyn,SimHH, SealTest,
  LeakSub, About, RecEdit,Log, QAnal, COnvert, DrvFun, labio, defset, ced1902  ;

type
  TMain = class(TForm)
    MainMenu: TMainMenu;
    File1: TMenuItem;
    Edit: TMenuItem;
    View: TMenuItem;
    Help1: TMenuItem;
    mnNew: TMenuItem;
    mnOpen: TMenuItem;
    Print1: TMenuItem;
    PrintSetup1: TMenuItem;
    Exit1: TMenuItem;
    OpenDialog: TOpenDialog;
    SaveDialog: TSaveDialog;
    ZoomIn: TMenuItem;
    ZoomOut: TMenuItem;
    AutoErase: TMenuItem;
    Setup: TMenuItem;
    mnCED1902: TMenuItem;
    Recording1: TMenuItem;
    Analysis: TMenuItem;
    WaveformMeasurements: TMenuItem;
    SignalAverager: TMenuItem;
    LeakCurrentSubtraction: TMenuItem;
    CurveFitting: TMenuItem;
    ShowRaw: TMenuItem;
    ShowAveraged: TMenuItem;
    ShowLeakSubtracted: TMenuItem;
    mnClose: TMenuItem;
    PrinterSetupDialog1: TPrinterSetupDialog;
    WaveformGenerator: TMenuItem;
    CopyData: TMenuItem;
    CopyImage: TMenuItem;
    Record1: TMenuItem;
    RecordToDisk: TMenuItem;
    SealTest: TMenuItem;
    Simulations1: TMenuItem;
    Synapse: TMenuItem;
    HHSimulation: TMenuItem;
    Import1: TMenuItem;
    Export1: TMenuItem;
    InsertRecord: TMenuItem;
    DeleteRecord: TMenuItem;
    AppendRecord: TMenuItem;
    CopyRecord: TMenuItem;
    DeleteRejected: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    Contents: TMenuItem;
    SearchforHelpon1: TMenuItem;
    HowtouseHelp1: TMenuItem;
    About: TMenuItem;
    EditRecord: TMenuItem;
    InspectLogFile: TMenuItem;
    mnQuantalContent: TMenuItem;
    Windows: TMenuItem;
    ShowView: TMenuItem;
    ShowMeasure: TMenuItem;
    ShowFit: TMenuItem;
    ShowRecord: TMenuItem;
    ShowSealTest: TMenuItem;
    mnDrivingFunction: TMenuItem;
    ShowDrivingFunction: TMenuItem;
    mnDefaultSettings: TMenuItem;
    Append: TMenuItem;
    mnShowHints: TMenuItem;
    procedure mnOpenClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure AutoEraseClick(Sender: TObject);
    procedure ZoomInClick(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure Recording1Click(Sender: TObject);
    procedure WaveformMeasurementsClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SignalAveragerClick(Sender: TObject);
    procedure ShowRawClick(Sender: TObject);
    procedure ShowAveragedClick(Sender: TObject);
    procedure ShowLeakSubtractedClick(Sender: TObject);
    procedure ZoomOutClick(Sender: TObject);
    procedure mnCloseClick(Sender: TObject);
    procedure Print1Click(Sender: TObject);
    procedure PrintSetup1Click(Sender: TObject);
    procedure RecordToDiskClick(Sender: TObject);
    procedure mnNewClick(Sender: TObject);
    procedure WaveformGeneratorClick(Sender: TObject);
    procedure CopyDataClick(Sender: TObject);
    procedure CurveFittingClick(Sender: TObject);
    procedure SynapseClick(Sender: TObject);
    procedure HHSimulationClick(Sender: TObject);
    procedure SealTestClick(Sender: TObject);
    procedure LeakCurrentSubtractionClick(Sender: TObject);
    procedure CopyRecordClick(Sender: TObject);
    procedure AddRecordClick(Sender: TObject);
    procedure DeleteRecordClick(Sender: TObject);
    procedure AboutClick(Sender: TObject);
    procedure EditRecordClick(Sender: TObject);
    procedure InspectLogFileClick(Sender: TObject);
    procedure mnQuantalContentClick(Sender: TObject);
    procedure Import1Click(Sender: TObject);
    procedure CopyImageClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ShowViewClick(Sender: TObject);
    procedure ShowRecordClick(Sender: TObject);
    procedure ShowSealTestClick(Sender: TObject);
    procedure ShowMeasureClick(Sender: TObject);
    procedure ShowFitClick(Sender: TObject);
    procedure mnDrivingFunctionClick(Sender: TObject);
    procedure ShowDrivingFunctionClick(Sender: TObject);
    procedure mnDefaultSettingsClick(Sender: TObject);
    procedure mnCED1902Click(Sender: TObject);
    procedure ContentsClick(Sender: TObject);
    procedure SearchforHelpon1Click(Sender: TObject);
    procedure HowtouseHelp1Click(Sender: TObject);
    procedure AppendClick(Sender: TObject);
    procedure Export1Click(Sender: TObject);
    procedure DeleteRejectedClick(Sender: TObject);
    procedure mnShowHintsClick(Sender: TObject);
  private
    { Private declarations }
    procedure LoadDataFiles( FileName : string ) ;
    function OpenAssociateFile( var FileHeader : TFileHeader ;
                                const FileName : string ;
                                const FileExtension : string ) : boolean ;
    procedure UpdateFileHeaderBlocks ;
    procedure CloseAllDataFiles ;
  public
    { Public declarations }
    MeasureChild : TMeasureFrm ;
    ReplayChild : TReplayFrm ;
    ReplayChildExists : Boolean ;
    RecordChild : TRecordFrm ;
    SealTestChild : TSealTestFrm ;
    DrvFunChild : TDrvFunFrm ;
    QuantChild : TQuantFrm ;
    FitChild : TFitFrm ;
    LogChild : TLogFrm ;
    EditChild : TEditFrm ;


    procedure SetCopyMenu( EnableCopyData, EnableCopyImage : boolean ) ;
    procedure UpdateWindows ;
    procedure SetMenus ;
    procedure ClearTicksInWindowsMenu ;
    end;

var
  Main: TMain;


implementation

{$R *.DFM}

uses expform ;

procedure TMain.FormCreate(Sender: TObject);
{ ---------------------------------------------------------------
  Initialize global program settings and load last data file used
  ---------------------------------------------------------------}
const
     ClipboardFormatName : PChar = 'Strathclyde WCP Record' ;
var
   ch,i : Integer ;
begin
      { Check command line parameters }
      Settings.NoINIFile := False ;
      ch := ParamCount ;
      for i := 0 to ParamCount do
          if (ParamStr(i) = '/NI') or (ParamStr(i) = '/ni') then
             Settings.NoINIFile := True ;

      { Get directory which contains WinWCP program }
      Settings.ProgDirectory := ExtractFilePath(ParamStr(0)) ;
      Settings.VProtDirectory := Settings.ProgDirectory + 'vprot\' ;

      { Create default set of record types }
      RecordTypes := TStringList.Create ;
      RecordTypes.Add( 'ALL' ) ;
      RecordTypes.Add( 'EVOK' ) ;
      RecordTypes.Add( 'MINI' ) ;
      RecordTypes.Add( 'FAIL' ) ;
      RecordTypes.Add( 'TEST' ) ;
      RecordTypes.Add( 'LEAK' ) ;

      { Create channel names list }
      ChannelNames := TStringList.Create ;

     { Default values for channels }

     RawFH.NumChannels := 1 ;
     RawFH.NumSamples := 512 ;
     RawFH.NumAnalysisBytesPerRecord := 512 ;
     RawFH.NumDataBytesPerRecord := RawFH.NumSamples*RawFH.NumChannels*2 ;
     RawFH.NumBytesPerRecord := RawFH.NumDataBytesPerRecord
                                + RawFH.NumAnalysisBytesPerRecord ;
     RawFH.NumBytesInHeader := 512 ;
     RawFH.ADCVoltageRange := 5. ;
     RawFH.NumZeroAvg := 20 ;
     RawFH.dt := 0.001 ;
     RawFH.Version := 6.1 ;
     for ch := 0 to ChannelLimit do begin
         Channel[ch].TimeZero := 1. ;
         Channel[ch].ADCScale := 1. ;
         Channel[ch].CursorIndex := 128 ;
         Channel[ch].ZeroIndex := 0 ;
         Channel[ch].Cursor0 := 0 ;
         Channel[ch].Cursor1 := RawFH.NumSamples div 2 ;
         { Zero levels fixed at hardware zero }
         Channel[ch].ADCZero := 0 ;
         Channel[ch].ADCZeroAt := -1 ;
         Channel[ch].ADCCalibrationFactor := 0.001 ;
         Channel[ch].ADCAmplifierGain := 1. ;
         Channel[ch].ADCUnits := 'mV' ;
         Channel[ch].ADCName := format('Ch.%d',[ch]);
         Channel[ch].color := clBlue ;
         Channel[ch].xMin := 0. ;
         Channel[ch].xMax := RawfH.NumSamples-1 ;
         Channel[ch].yMin := MinADCValue ;
         Channel[ch].yMax := MaxADCValue ;
         Channel[ch].InUse := True ;
         end ;

     { Initialise to no laboratory interface }
     Settings.LaboratoryInterface := 0 ;

     { Initial Digidata 1200 I/O port settings }
     Settings.DD1200IOPort := $320 ;
     Settings.DD1200IRQ := 10 ;
     Settings.DD1200DMA := 5 ;
     { Allow N.I. interface boards to use DMA channels }
     Settings.NIDisableDMA := False ;

     Settings.TriggerMode := 'F' ;
     Settings.EventDetector.Channel := 0 ;
     Settings.EventDetector.Threshold := 10. ;
     Settings.EventDetector.PreTrigger := 10. ;
     Settings.AutoErase := True ;

     AutoErase.checked := Settings.AutoErase ;

     Settings.NumRecordsRequired := 1 ;
     Settings.CutOffFrequency := 0. ;
     { Minimum interval for updating D/A converters when
       generating command voltage waveforms }
     Settings.MinDACInterval := 0.0001 ;

     Settings.TUnits := 'ms' ;
     Settings.TScale := SecsToMs ;
     Settings.TUnScale := MsToSecs ;

     { Name of command voltage protocol file in current use }
     Settings.VProgramFileName := '' ;

     { Divide factor that the patch/voltage clamp applies to its
       command voltage input. The D/A output voltage is thus scaled up
       by this factor }
     Settings.VCommand.DivideFactor := 1. ;
     Settings.VCommand.HoldingVoltage := 0. ;
     Settings.DigitalPort.Value := 0 ;
     Settings.UpdateOutputs := True ;

     { Default settings for seal test pulse }
     Settings.SealTest.Use := 1 ;
     Settings.SealTest.PulseHeight1 := 0.01 ;
     Settings.SealTest.HoldingVoltage1 := 0. ;
     Settings.SealTest.PulseHeight2 := 0.01 ;
     Settings.SealTest.HoldingVoltage2 := 0. ;
     Settings.SealTest.PulseHeight3 := 0.0 ;
     Settings.SealTest.HoldingVoltage3 := 0. ;

     Settings.SealTest.PulseWidth:= 0.05 ;
     Settings.SealTest.CurrentChannel := 0 ;
     Settings.SealTest.VoltageChannel := 1 ;
     Settings.SealTest.AutoScale := True ;
     Settings.SealTest.DisplayScale := 1 ;
     { Set flag indicating this is the first sweep, to force an autoscale }
     Settings.SealTest.FirstSweep := True ;
     { Set seal test Display limits }
     for ch := 0 to ChannelLimit do begin
         Settings.SealTest.yMin[ch] := MinADCValue ;
         Settings.SealTest.yMax[ch] := MaxADCValue ;
         end ;


     Settings.Plot.TopMargin := 5. ;
     Settings.Plot.LeftMargin := 5. ;
     Settings.Plot.BottomMargin := 5. ;
     Settings.Plot.RightMargin := 2.5 ;
     Settings.Plot.FontName := 'Arial' ;
     Settings.Plot.FontSize := 12 ;
     Settings.Plot.LineThickness := 2 ;
     Settings.Plot.MarkerSize := 5 ;
     Settings.Plot.ShowLines := True ;
     Settings.Plot.ShowMarkers := True ;


     { Bitmap size for images copied to clipboard }
     Settings.BitmapWidth := 600 ;
     Settings.BitmapHeight := 500 ;

     { Time taken to write one sector to hard disk }
     { Zero forces a write test to be made within wavgen module }
     Settings.SectorWriteTime := 0. ;

     Settings.DataDirectory := '' ;

     { Settings for record hard copy plots }
     Settings.TimeBarValue := -1. ;
     for ch := 0 to ChannelLimit do Settings.BarValue[ch] := -1. ;
     Settings.ShowLabels := True ;
     Settings.ShowZeroLevels := True ;

     Settings.CED1902.Input := 1 ;
     Settings.CED1902.Gain := 1 ;
     Settings.CED1902.GainValue := 1. ;
     Settings.CED1902.LPFilter := 0 ;
     Settings.CED1902.HPFilter := 0 ;
     Settings.CED1902.ACCoupled := 0 ;
     Settings.CED1902.NotchFilter := 0 ;
     Settings.CED1902.ComPort := 1 ;
     Settings.CED1902.DCOffset := 0 ;
     Settings.CED1902.InUse := False ;

     Settings.WavGenNoDisplay := False ; {Display waveform check box settings
                                          for Waveform Generator }

     { Set the file names and handles for all header blocks to null }
     RawFH.FileHandle := -1 ;
     RawFH.FileName := '' ;
     AvgFH.FileHandle := -1 ;
     AvgFH.FileName := '' ;
     LeakFH.FileHandle := -1 ;
     LeakFH.FileName := '' ;
     DrvFH.FileHandle := -1 ;
     DrvFH.FileName := '' ;


     { Clear child form flags }
     ReplayChildExists := False ;

     { Register clipboard format }
     CF_WCPFormat := RegisterClipBoardFormat( ClipBoardFormatName ) ;

     ShowAveraged.visible := false ;
     ShowLeakSubtracted.visible := false ;
     ShowRaw.visible := False ;

     SetMenus ;

     { Load initialization file to get name of last data file used }

     if not Settings.NoINIFile then
        LoadInitializationFile( Settings.ProgDirectory + 'WinWCP.ini' ) ;

     for ch := 0 to RawFH.NumChannels-1 do begin
         Channel[ch].xMin := 0. ;
         Channel[ch].xMax := RawfH.NumSamples-1 ;
         Channel[ch].Cursor1 := RawFH.NumSamples div 2 ;
         end ;

     { Open log file (contains log of program activity)
       (Note. Log file not used if no INI file in use}
     if not Settings.NoINIFile then begin
        OpenLogFile ;
        WriteToLogFile( 'WinWCP Started' ) ;
        end ;

     AutoErase.checked := Settings.AutoErase ;
     { Name of last used data file returned in fH.FileName }

     end;


procedure TMain.mnOpenClick(Sender: TObject);
{ -Menu item --------------------
  Open an existing .wcp data file
  -------------------------------}
var
   OldNumSamples : Integer ;
begin
     OpenDialog.options := [ofPathMustExist] ;
     OpenDialog.DefaultExt := 'WCP' ;
     if Settings.DataDirectory <> '' then
        OpenDialog.InitialDir := Settings.DataDirectory ;
     OpenDialog.Filter := ' WCP Files (*.WCP)|*.WCP';
     OpenDialog.Title := 'Open File ' ;

     if OpenDialog.execute then begin

        OldNumSamples := RawFH.NumSamples ;
        LoadDataFiles( OpenDialog.FileName ) ;
        WriteToLogFile( RawFH.FileName + ' opened' ) ;
        fH := RawFH ;

        { Save data directory }
        Settings.DataDirectory := ExtractFilePath( RawFH.FileName ) ;

        if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
        if not CurveFitting.enabled then FitChild.NewFile := True ;
        if not RecordToDisk.enabled then begin
           RecordChild.caption := 'Record ' + RawFH.FileName ;
           RecordChild.edStatus.Text := '' ;
           end ;
        if ReplayChildExists then ReplayChild.NewFile := True ;

        { Set display magnification to minimum }
        if fH.NumRecords > 0 then begin
           if not ReplayChildExists then ReplayChild := TReplayFrm.Create(Self) ;
           if OldNumSamples <> RawFH.NumSamples then ZoomOut.Click ;
           ShowRaw.Visible := True ;
           ShowRaw.Click ;
           end
        else ShowRaw.Visible := False ;
        SetMenus ; ;
        end ;
     end;


procedure TMain.LoadDataFiles( FileName : string ) ;
{ -------------------------------------------------
  Load .WCP and any associated .AVG,.SUB data files
  -------------------------------------------------}
var
   OldRawFH : TFileHeader ;
   ch : Integer ;
begin

     if FileExists( FileName ) then begin

        { Keep old file details ... just in case }
        OldRawFH := RawFH ;

        { Open raw data file }
        if RawFH.FileHandle >= 0 then FileClose( RawFH.FileHandle ) ;
        RawFH.Filename := FileName ;
        RawFH.FileHandle := FileOpen( RawFH.FileName, fmOpenReadWrite ) ;
        if RawFH.Filehandle >= 0 then begin
            ShowRaw.visible := True ;
            { Open averages file (if one exists)}
            ShowAveraged.visible := OpenAssociateFile(AvgFH,RawFH.FileName,'.avg') ;
            { Open a leak subtracted file (if one exists) }
            ShowLeakSubtracted.visible := OpenAssociateFile(LeakFH,RawFH.FileName,'.sub') ;
            { Open a driving function file (if one exists) }
            ShowDrivingFunction.visible := OpenAssociateFile(DrvFH,RawFH.FileName,'.drv') ;
            { Load the raw file details }
            GetHeader( RawFH ) ;
            { Make sure all channels are visible }
            for ch := 0 to RawFH.NumChannels-1 do Channel[ch].InUse := True ;
            end
        else begin
             MessageDlg( ' File Error ='+IntToStr(AvgFH.Filehandle),
                           mtWarning, [mbOK], 0 ) ;
             { Restore original file }
             RawFH := OldRawFH ;
             RawFH.FileHandle := FileOpen( RawFH.FileName, fmOpenReadWrite ) ;
             end ;

        end ;

     SetMenus ;
     end ;

function TMain.OpenAssociateFile( var FileHeader : TFileHeader ;
                                     const FileName : string ;
                                     const FileExtension : string ) : boolean ;
{ -------------------------------------
  Open an associated file (if it exists)
  -------------------------------------}
begin
     FileHeader.FileName := ReplaceFileEnding( FileName, FileExtension ) ;
     if FileExists( FileHeader.FileName ) then begin
        if FileHeader.FileHandle >= 0 then FileClose( FileHeader.FileHandle ) ;
        FileHeader.FileHandle := FileOpen( FileHeader.FileName, fmOpenReadWrite ) ;
        if FileHeader.Filehandle >= 0 then begin
           GetHeader( FileHeader ) ;
           Result := True ;
           end
        else begin
             MessageDlg( format('%s Error=%d',[FileHeader.FileName,
                         FileHeader.Filehandle]), mtWarning, [mbOK], 0 ) ;
             FileHeader.FileHandle := -1 ;
             Result := False ;
             end ;
        end
     else Result := False ;
     end ;


procedure TMain.AutoEraseClick(Sender: TObject);
{ --------------------------------------
  Turn View/Record autoerase mode on/off
  --------------------------------------}
begin
     AutoErase.checked := not AutoErase.checked ;
     Settings.AutoErase := AutoErase.checked ;
     if ReplayChildExists then ReplayChild.Refresh ;
     if not WaveformMeasurements.enabled then MeasureChild.Refresh ;
     if not CurveFitting.enabled then FitChild.Refresh ;
     end;


procedure TMain.ZoomInClick(Sender: TObject);
var
   i : Integer ;
begin
     ZoomFrm.ShowModal ;
     end;


procedure TMain.Exit1Click(Sender: TObject);
{ --------------------------------
  Save state and terminate program
  -------------------------------- }
begin
     close ;
     end;


procedure TMain.Recording1Click(Sender: TObject);
{ - Menu Item -------------------------------
  Record parameters set-up dialog (setup.pas)
  -------------------------------------------}
var
   i : Integer ;
begin
     SetUpDlg.ShowModal ;
     if SetupDlg.ModalResult = mrOK then ZoomFrm.ZoomOut ;
     end;


procedure TMain.WaveformMeasurementsClick(Sender: TObject);
{ - Menu Item ------------------------------------
  Create waveform measurements module (measure.pas)
  ------------------------------------------------}
begin
     MeasureChild := TMeasureFrm.Create(Self) ;
     end;


procedure TMain.CurveFittingClick(Sender: TObject);
{ - Menu Item -------------------------------
  Run waveform curve fitting module (fit.pas)
  -------------------------------------------}
begin
    FitChild := TFitFrm.Create(Self) ;
    end;


procedure TMain.FormDestroy(Sender: TObject);
begin
     RecordTypes.Free ;
     ChannelNames.Free ;
     end;

procedure TMain.SignalAveragerClick(Sender: TObject);
{ - Menu Item ----------------------------
  Run signal averager module (average.pas)
  ----------------------------------------}
begin
     if ((RawFH.NumSamples*RawFH.NumChannels)-1) <= High(TSingleArray) then
        AvgFrm := TAvgFrm.Create(Self)
     else MessageDlg( 'Record too large to average (limit=16000 samples)',
                           mtWarning, [mbOK], 0 ) ;

     end;


procedure TMain.ShowRawClick(Sender: TObject);
{ - Menu Item -------------------------
  Select original data file for viewing
  -------------------------------------}
begin
     fH := RawFH ;
     GetHeader(fH) ;
     ShowRaw.checked := True ;
     ShowAveraged.checked :=  False ;
     ShowDrivingFunction.checked := False ;
     ShowLeakSubtracted.checked := False ;
     mnDrivingFunction.enabled := true ;

     { If no replay form ... create one }
     if (RawfH.NumRecords > 0) and (not ReplayChildExists) then
        ReplayChild := TReplayFrm.Create(Self) ;

     if ReplayChildExists then ReplayChild.NewFile := True ;
     if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
     if not CurveFitting.enabled then FitChild.NewFile := True ;
     end;


procedure TMain.ShowAveragedClick(Sender: TObject);
{ - Menu Item ---------------------------
  Select averages record file for viewing
  ----------------------------------------}
begin
     fH := AvgFH ;
     GetHeader( fH) ;
     ShowAveraged.checked := True ;
     ShowRaw.checked :=  False ;
     ShowDrivingFunction.checked := False ;
     ShowLeakSubtracted.checked := False ;
     mnDrivingFunction.enabled := true ;

     { If no replay form ... create one }
     if (AvgfH.NumRecords > 0) and (not ReplayChildExists) then
        ReplayChild := TReplayFrm.Create(Self) ;

     if ReplayChildExists then ReplayChild.NewFile := True ;
     if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
     if not CurveFitting.enabled then FitChild.NewFile := True ;
     end;


procedure TMain.ShowLeakSubtractedClick(Sender: TObject);
{ - Menu Item -----------------------------------
  Select leak subtracted record file for viewing
  ----------------------------------------------}
begin
     fH := LeakFH ;
     GetHeader( fH) ;
     ShowAveraged.checked := False ;
     ShowRaw.checked :=  False ;
     ShowDrivingFunction.checked := False ;
     ShowLeakSubtracted.checked := True ;
     mnDrivingFunction.enabled := true ;

          { If no replay form ... create one }
     if (LeakfH.NumRecords > 0) and (not ReplayChildExists) then
        ReplayChild := TReplayFrm.Create(Self) ;

     if ReplayChildExists then ReplayChild.NewFile := True ;
     if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
     if not CurveFitting.enabled then FitChild.NewFile := True ;
     end;


procedure TMain.ShowDrivingFunctionClick(Sender: TObject);
{ - Menu Item -----------------------------------
  Select driving function records file for viewing
  ----------------------------------------------}
begin
     fH := DrvFH ;
     GetHeader( fH) ;
     ShowAveraged.checked := False ;
     ShowRaw.checked :=  False ;
     ShowLeakSubtracted.checked := False ;
     ShowDrivingFunction.checked := True ;
     mnDrivingFunction.enabled := false ;

          { If no replay form ... create one }
     if (DrvfH.NumRecords > 0) and (not ReplayChildExists) then
        ReplayChild := TReplayFrm.Create(Self) ;

     if ReplayChildExists then ReplayChild.NewFile := True ;
     if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
     if not CurveFitting.enabled then FitChild.NewFile := True ;
     end;


procedure TMain.ZoomOutClick(Sender: TObject);
{ - Menu Item ---------------------------------
  Set display channels to minimum magnification
  ---------------------------------------------}
begin
     ZoomFrm.ZoomOut ;
     end;


procedure TMain.mnCloseClick(Sender: TObject);
{ -------------------------
  Close all forms and files
  -------------------------}
var
   i : Integer ;
begin
     { Close all child windows }
     with Main do
          for i := 0 to MDIChildCount-1 do MDICHildren[i].Close ;

     { Make View menu options invisible }
     ShowAveraged.visible := false ;
     ShowLeakSubtracted.visible := false ;
     ShowRaw.visible := False ;

     { Close files }
     CloseAllDataFiles ;
     end ;


procedure TMain.Print1Click(Sender: TObject);
{ - Menu Item ----------------------------------------------------
  Print the record or graph displayed in the currently active form
  ----------------------------------------------------------------}
begin
     if ReplayChildExists then
          if ReplayChild.Active then ReplayChild.HardCopy := True ;
     if not WaveformMeasurements.enabled then
        if MeasureChild.Active then MeasureChild.PrintHardCopy := True ;
     if not CurveFitting.enabled then
        if FitChild.Active then FitChild.PrintHardCopy := True ;
     if not Main.mnQuantalContent.enabled then
        if QuantChild.Active then QuantChild.PrintResults ;

     end;


procedure TMain.PrintSetup1Click(Sender: TObject);
{ - Menu Item ------------------
  Standard printer setup dialog
  ------------------------------}
begin
     PrinterSetupDialog1.Execute ;
     end;


procedure TMain.RecordToDiskClick(Sender: TObject);
{ - Menu Item ------------
  Display recording window
  ------------------------}
begin
     if IsLabInterfaceAvailable(Settings.LaboratoryInterface) = true then
        RecordChild := TRecordFrm.Create(Self) ;
     end;


procedure TMain.mnNewClick(Sender: TObject);
{ - Menu Item --------
  Create new data file
  --------------------}
var
   ch : Integer ;
   TempFile : string ;
   ok : boolean ;
begin
     { Present user with standard Save File dialog box }
     SaveDialog.options := [ofOverwritePrompt,ofHideReadOnly,ofPathMustExist] ;
     SaveDialog.DefaultExt := 'WCP' ;
     SaveDialog.FileName := ExtractFileName( RawFH.FileName ) ;
     SaveDialog.Filter := ' WCP Files (*.WCP)|*.WCP' ;
     SaveDialog.Title := 'New Data File' ;

     if Settings.DataDirectory <> '' then
        SaveDialog.InitialDir := Settings.DataDirectory ;

     if SaveDialog.execute then begin

        { Save data directory }
        Settings.DataDirectory := ExtractFilePath( SaveDialog.FileName ) ;
        { Close Measurements, Replay & fitting modules }
        if not WaveformMeasurements.enabled then MeasureChild.Close ;
        if not CurveFitting.enabled then FitChild.Close ;
        if ReplayChildExists then ReplayChild.Close ;

        { Close files }
        CloseAllDataFiles ;

        ShowRaw.checked := False ;
        ShowAveraged.checked := False ;
        ShowAveraged.visible := False ;
        ShowLeakSubtracted.checked := False ;
        ShowLeakSubtracted.Visible := False ;

        { Open new and empty data file }
        RawFH.FileName := SaveDialog.FileName ;
        RawFH.FileName := ReplaceFileEnding( RawFH.FileName, '.wcp' ) ;
        RawFH.FileHandle := FileCreate( RawFH.FileName ) ;
        RawFH.NumRecords := 0 ;
        for ch := 0 to RawFH.NumChannels-1 do Channel[ch].InUse := True ;
        SaveHeader( RawFH ) ;
        { Update record window's caption }
        if not RecordToDisk.enabled then begin
           RecordChild.caption := 'Record ' + RawFH.FileName ;
           RecordChild.edStatus.Text := '' ;
           end ;

        { Delete averages file (if it exists) }
        TempFile := ReplaceFileEnding( RawFH.FileName, '.avg' ) ;
        if FileExists(TempFile) then ok := DeleteFile(TempFile) ;
        { Delete leak subtraction file (if it exists) }
        TempFile := ReplaceFileEnding( RawFH.FileName, '.sub' ) ;
        if FileExists(TempFile) then ok := DeleteFile(TempFile) ;

        { Re-load empty data file }
        LoadDataFiles( RawFH.FileName ) ;
        FH := RawFH ;

        WriteToLogFile( 'New file ' + RawFH.FileName ) ;
        end ;
     end ;


procedure TMain.WaveformGeneratorClick(Sender: TObject);
{ - Menu Item -------------------------------
  Edit a voltage-clamp command pulse waveform
  -------------------------------------------}
begin
     WavGenFrm := TWavGenFrm.Create(Self) ;
     end;


procedure TMain.SetMenus ;
{ ---------------------------
  Activate usable menu items
  --------------------------}
var
   ClipHandle : THandle ;
   OK : boolean ;
begin
     View.Enabled := False ;
     Analysis.Enabled := False ;
     Print1.Enabled := False ;
     Edit.Enabled := True ;
     Setup.Enabled := False ;
     Record1.Enabled := False ;
     mnClose.Enabled := False ;
     Export1.Enabled := False ;
     Simulations1.Enabled := False ;

     { Disable copy/insert record functions }
     CopyRecord.Enabled := False ;
     InsertRecord.Enabled := False ;
     AppendRecord.Enabled := False ;
     DeleteRecord.Enabled := False ;
     DeleteRejected.Enabled := False ;

     { Enable setup, recording and simulation ... if a data file is open }
     if RawFH.FileHandle >= 0 then begin
           { Allow these functions when a data file is open }
           Setup.Enabled := True ;
           Record1.Enabled := True ;
           mnClose.Enabled := True ;

           Simulations1.Enabled := True ;
           View.Enabled := True ;
           ShowRaw.Visible := False ;

           { Enable these functions when a data record is in the clipboard }
            OK := OpenClipboard( Handle ) ;
            ClipHandle := GetClipboardData( CF_WCPFormat ) ;
            if ClipHandle <> 0 then begin
               InsertRecord.Enabled := True ;
               AppendRecord.Enabled := True ;
               end ;
            OK := CloseClipboard ;

           { Enable these functions when file contains data records }
           if RawFH.NumRecords > 0 then begin
              Analysis.Enabled := True ;
              Print1.Enabled := True ;
              Export1.Enabled := True ;
              Edit.Enabled := True ;
              CopyRecord.Enabled := True ;
              DeleteRecord.Enabled := True ;
              DeleteRejected.Enabled := True ;
              ShowRaw.Visible := True ;

              { Enable display of averages (if they exist) }
              if (AvgFH.FileHandle > 0) and (AvgFH.NumRecords > 0) then
                 ShowAveraged.visible := True
              else ShowAveraged.visible := False ;
              { Enable display of leak subtracted records (if they exist) }
              if (LeakFH.FileHandle > 0) and (LeakFH.NumRecords > 0) then
                 ShowLeakSubtracted.visible := True
              else ShowLeakSubtracted.visible := False ;
              { Enable display of leak subtracted records (if they exist) }
              if (DrvFH.FileHandle > 0) and (DrvFH.NumRecords > 0) then
                 ShowDrivingFunction.visible := True
              else ShowDrivingFunction.visible := False ;
              end ;
           end ;

     end ;

procedure TMain.SetCopyMenu( EnableCopyData, EnableCopyImage : boolean ) ;
{ --------------------------------------------------
  Enable/disable copy data and copy image menu items
  --------------------------------------------------}
begin
     CopyData.enabled := EnableCopyData ;
     CopyImage.enabled := EnableCopyImage ;
     end ;


procedure TMain.CopyDataClick(Sender: TObject);
begin
     { Copy a signal record in ASCII format from the View Records module }
     if ReplayChildExists then
        if ReplayChild.Active then ReplayChild.CopyToClipBoardAsData := True ;
     if not WaveformMeasurements.enabled then
        if MeasureChild.Active then MeasureChild.CopyToClipboardAsData := True ;
     if not CurveFitting.enabled then
        if FitChild.Active then FitChild.CopyToClipboardAsData := True ;
     end ;


procedure TMain.SynapseClick(Sender: TObject);
{ ---------------------------------------
  Open synaptic current simulation module
  ---------------------------------------}
begin
     SynapseSim := TSynapseSim.Create(Self) ;
     end;


procedure TMain.HHSimulationClick(Sender: TObject);
{ ---------------------------------------
  Open Hodgkin-Huxley simulation module
  ---------------------------------------}
begin
     VClampSim := TVClampSim.Create(Self) ;
     end;

procedure TMain.SealTestClick(Sender: TObject);
begin
     if IsLabInterfaceAvailable(Settings.LaboratoryInterface) = true then
        SealTestChild := TSealTestFrm.Create(Self) ;
     end;


procedure TMain.LeakCurrentSubtractionClick(Sender: TObject);
{ - Menu Item ----------------------------
  Run leak subtraction module (leaksub.pas)
  ----------------------------------------}
begin
     LeakSubFrm := TLeakSubFrm.Create(Self) ;
     end;


procedure TMain.CopyRecordClick(Sender: TObject);
{ - Menu Item --------------------------------------------------
  Copy a signal record to the clipboard (in WCP internal format)
  --------------------------------------------------------------}
var
   OK : Boolean ;
   ch : Integer ;
   ClipRec : ^TWCPClipboardRecord ;
   ClipHandle,H : THandle ;
   BufPtr : Pointer ;
begin
     try
        { Create a WCP format clipboard data record
          with the currently displayed record }
        New( ClipRec ) ;
        ClipRec^.FileHdr := FH ;
        for ch := 0 to FH.NumChannels-1 do ClipRec^.Channel[ch] := Channel[ch] ;
        GetRecord(ClipRec^.FileHdr,ClipRec^.RecHdr,FH.RecordNum,ClipRec^.ADC) ;

        { Allocate and lock space on the global heap }
        ClipHandle := GlobalAlloc( GHND, Sizeof(ClipRec^) ) ;
        BufPtr := GlobalLock( ClipHandle ) ;
        { Copy the record to the heap }
        Move( ClipRec^, BufPtr^, Sizeof(ClipRec^) ) ;
        { Unlock the record and hand it over to the clipboard }
        OK := GlobalUnlock( ClipHandle ) ;
        OK := OpenClipboard( Handle ) ;
        OK := EmptyClipBoard ;
        H := SetClipboardData( CF_WCPFormat, ClipHandle ) ;
        OK := CloseClipboard ;
        SetMenus ;
     finally
            Dispose( ClipRec ) ;
            end ;
     end;


procedure TMain.AddRecordClick(Sender: TObject);
{ - Menu Item --------------------------------------------------
  Append a signal record from the to the end of the data file
  --------------------------------------------------------------}
var
   OK : Boolean ;
   ClipRec : ^TWCPClipboardRecord ;
   ClipHandle : THandle ;
   BufPtr : Pointer ;
   InsertAt,i : LongInt ;
   ch : Integer ;
   ScaleFrom,ScaleTo : single ;
begin
     try
        { Create a WCP format clipboard data record to hold the record }
        New( ClipRec ) ;

        { Open clipboard and try to get a handle for a data record
          in WCP internal format (ClipHandle<>0 if successful) }
        OK := OpenClipboard( Handle ) ;
        ClipHandle := GetClipboardData( CF_WCPFormat ) ;

        { If a record is available .... }
        if ClipHandle <> 0 then begin
           { Copy the record from the clipboard }
           BufPtr := GlobalLock( ClipHandle ) ;
           Move( BufPtr^, ClipRec^,  Sizeof(ClipRec^) ) ;
          { Unlock the clipboard handle and close the clipboard }
          OK := GlobalUnlock( ClipHandle ) ;
          OK := CloseClipboard ;

          { If the data file is empty,
            copy the channel settings from the clipboard record }
          if RawFH.NumRecords = 0 then begin
             for ch := 0 to ChannelLimit do Channel[ch] := ClipRec^.Channel[ch] ;
             end ;

          { Append or insert the record (if it is compatible) }
          if (FH.NumChannels = ClipRec^.FileHdr.NumChannels)
             and (FH.NumSamples = ClipRec^.FileHdr.NumSamples) then begin

             Inc(FH.NumRecords) ;

             if Sender = InsertRecord then begin
                { *** Insert record at current position in file *** }
                { Move all records above the current position up by 1 }
                for i := FH.NumRecords-1 downto FH.CurrentRecord do begin
                    GetRecord(FH,ClipRec^.RecHdr,i,ClipRec^.ADC) ;
                    PutRecord(FH,ClipRec^.RecHdr,i+1,ClipRec^.ADC) ;
                    end ;
                { Get the record from the clipboard again }
                OK := OpenClipboard( Handle ) ;
                ClipHandle := GetClipboardData( CF_WCPFormat ) ;
                BufPtr := GlobalLock( ClipHandle ) ;
                Move( BufPtr^, ClipRec^,  Sizeof(ClipRec^) ) ;
                OK := GlobalUnlock( ClipHandle ) ;
                OK := CloseClipboard ;
                if FH.NumRecords = 1 then FH.CurrentRecord := 1 ;
                InsertAt := FH.CurrentRecord ;
                end
             else begin
                { *** Append to end of file *** }
                InsertAt := FH.NumRecords
                end ;

             { Adjust for possible differences in channel calibration factors }
             for ch := 0 to FH.NumChannels-1 do begin
                 ScaleFrom := ClipRec^.Channel[ch].ADCCalibrationFactor *
                              ClipRec^.Channel[ch].ADCAmplifierGain ;
                 ScaleTo := Channel[ch].ADCCalibrationFactor *
                            Channel[ch].ADCAmplifierGain ;
                 ClipRec^.RecHdr.ADCVoltageRange[ch] :=
                     ClipRec^.RecHdr.ADCVoltageRange[ch] * (ScaleTo/ScaleFrom) ;
                 end ;
             { Copy record to file }
             PutRecord(FH,ClipRec^.RecHdr,InsertAt,ClipRec^.ADC) ;
             SaveHeader(FH) ;

             if FH.FileName = RawFH.FileName then RawFH := FH ;
             if FH.Filename = AvgFH.FileName then AvgFH := FH ;
             if FH.FileName = LeakFH.FileName then LeakFH := FH ;
             if FH.Filename = DrvFH.FileName then DrvFH := FH ;

             if (FH.NumRecords = 1) then begin
                 { If this is the first record of a raw data file after New File
                   enable menus and display the View window }
                 FH := RawFH ;
                 SetMenus ;
                 ShowRaw.click ;
                 end
             else begin
                  { Refresh any child windows that are open }
                  with Main do
                       for i := 0 to MDIChildCount-1 do MDICHildren[i].Refresh ;
                  end ;
             end
          else MessageDlg(
               ' Record not added. Size or no. channels incompatible',
               mtWarning, [mbOK], 0 ) ;
          end ;
          UpdateFileHeaderBlocks ;
     finally
            Dispose( ClipRec ) ;
            end ;
     end;


procedure TMain.DeleteRecordClick(Sender: TObject);
{ - Menu Item -----------------------------------------------
  Delete a signal record from the data file
  31/5/98 File header blocks updated when a record is deleted
  -----------------------------------------------------------}
var
   Rec : ^TWCPClipboardRecord ;
   i,iDelete : LongInt ;
   TempFH : TFileHeader ;
begin
  if MessageDlg( 'Delete record! Are you Sure? ', mtConfirmation,
        [mbYes,mbNo], 0 ) = mrYes then begin
     try
        New(Rec) ;
        { Create temporary file }
        TempFH := FH ;
        TempFH.FileName := ReplaceFileEnding( FH.FileName, '.tmp' ) ;
        TempFH.FileHandle := FileCreate( TempFH.FileName ) ;

       { Copy all records except the current one to the temp. file }
       TempFH.NumRecords := 0 ;
       iDelete := FH.RecordNum ;
       for i := 1 to FH.NumRecords do begin
           GetRecord(FH,Rec^.RecHdr,i,Rec^.ADC) ;
           if i <> iDelete then begin
              Inc(TempFH.NumRecords) ;
              PutRecord(TempFH,Rec^.RecHdr,TempFH.NumRecords,Rec^.ADC) ;
              end ;
           end ;
       SaveHeader( TempFH ) ;

       { Close temporary and original file }
       FileClose( TempFH.FileHandle) ;
       FileClose( FH.FileHandle ) ;
       { Delete original file }
       DeleteFile( FH.FileName ) ;
       { Rename temp. file }
       if not RenameFile( TempFH.FileName, FH.FileName ) then
          MessageDlg(
               ' Renaming of' + TempFH.FileName + ' failed',mtWarning, [mbOK], 0 ) ;
       { Re-open file }
       FH.FileHandle := FileOpen( FH.FileName, fmOpenReadWrite ) ;
       GetHeader( FH ) ;
       { Refresh child windows }

       { Update data file header (added 31/5/98) }
       UpdateFileHeaderBlocks ;

       with Main do
            for i := 0 to MDIChildCount-1 do MDICHildren[i].Refresh ;
     finally
            Dispose(Rec) ;
            end ;
     end;
  end ;


procedure TMain.AboutClick(Sender: TObject);
{ - Menu Item --------------------
  Display About window (about.pas)
  -------------------------------}
begin
     AboutDlg := TAboutDlg.Create(Self) ;
     AboutDlg.ShowModal ;
     end;


procedure TMain.UpdateWindows ;
{ -------------------------------------
  Update display windows with new data
  -------------------------------------}
begin
     if not ReplayChildExists then begin
        SetMenus ;
        ReplayChild := TReplayFrm.Create(Self) ;
        end ;
     ReplayChild.NewFile := True ;
     if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
     if not CurveFitting.enabled then FitChild.NewFile := True ;
     end ;


procedure TMain.UpdateFileHeaderBlocks ;
{ --------------------------------------------------------------------
  Update original copies of file header blocks when changed made to FH
  --------------------------------------------------------------------}
begin
       if FH.FileName = RawFH.FileName then RawFH := FH
       else if FH.FileName = AvgFH.FileName then AvgFH := FH
       else if FH.FileName = LeakFH.FileName then LeakFH := FH
       else if FH.FileName = DrvFH.FileName then DrvFH := FH ;
       end ;


procedure TMain.EditRecordClick(Sender: TObject);
{ - Menu Item ----------------------
  Display recording module (rec.pas)
  ---------------------------------}
begin
     EditChild := TEditFrm.Create(Self) ;
     end;


procedure TMain.InspectLogFileClick(Sender: TObject);
begin
     LogChild := TLogFrm.Create(Self) ;
     end;


procedure TMain.mnQuantalContentClick(Sender: TObject);
{ - Menu Item ----------------------------------
  Run quantal content analysis module (qanal.pas)
  ----------------------------------------------}
begin
     QuantChild := TQuantFrm.Create(Self) ;
     end;


procedure TMain.Import1Click(Sender: TObject);
{ - Menu Item --------------------------------
  Import records from a foreign data file type
  --------------------------------------------}
begin
     OpenDialog.options := [ofPathMustExist] ;
     OpenDialog.DefaultExt := 'DAT' ;
     OpenDialog.Filter :=
     ' Axon Files (*.DAT,*.ABF)|*.DAT;*.ABF|CED Files(*.DAT)|*.DAT|ASCII Files(*.txt)|*.txt';
     OpenDialog.Title := 'Import File ' ;
     if Settings.DataDirectory <> '' then
        OpenDialog.InitialDir := Settings.DataDirectory ;

     if OpenDialog.execute then begin

        Settings.DataDirectory := ExtractFilePath( OpenDialog.FileName ) ;

        { Detect what kind of data file it is and import using appropriate
          conversion procedure (See convert.pas module) }
        ImportFromDataFile(  OpenDialog.FileName ) ;

        WriteToLogFile( RawFH.FileName + ' opened' ) ;
        fH := RawFH ;

        if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
        if not CurveFitting.enabled then FitChild.NewFile := True ;
        if ReplayChildExists then ReplayChild.NewFile := True ;

        { Set display magnification to minimum }
        if fH.NumRecords > 0 then begin
           if not ReplayChildExists then ReplayChild := TReplayFrm.Create(Self) ;
           ZoomOut.Click ;
           ShowRaw.Visible := True ;
           ShowRaw.Click ;
           end
        else ShowRaw.Visible := False ;
        SetMenus ; ;
        end ;
     end;


procedure TMain.CopyImageClick(Sender: TObject);
begin
     { Copy a signal record in ASCII format from the View Records module }
     if ReplayChildExists then
        if ReplayChild.Active then ReplayChild.CopyToClipBoardAsImage := True ;
     if not WaveformMeasurements.enabled then
        if MeasureChild.Active then MeasureChild.CopyToClipboardAsImage := True ;
     if not CurveFitting.enabled then
        if FitChild.Active then FitChild.CopyToClipboardAsImage := True ;
     end ;


procedure TMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
     if MessageDlg( 'Exit Program! Are you Sure? ', mtConfirmation,
        [mbYes,mbNo], 0 ) = mrYes then CanClose := True
                                  else CanClose := False ;
     end;

procedure TMain.FormClose(Sender: TObject; var Action: TCloseAction);
{ ---------------------------------
  Tidy up when program is shut down
  ---------------------------------}
begin

       { Close recording and seal test windows to ensure that
         laboratory interface systems are shutdown (to avoid system crash }
       if (not SealTest.Enabled) then SealTestChild.Close ;
       if (not RecordToDisk.Enabled) then RecordChild.Close ;

        { Close data files }
        CloseAllDataFiles ;

        { Close log file }
        CloseLogFile ;

        { Save initialization file }
        if not Settings.NoINIFile then
           SaveInitializationFile( Settings.ProgDirectory + 'WinWCP.ini' ) ;
        CloseLaboratoryInterface ;
        end;



procedure TMain.ShowViewClick(Sender: TObject);
{ -- Menu item -------------------------
  Bring View Record module to the front
  -------------------------------------}
begin
     { If window is minimised restore to normal }
     if ReplayChild.WindowState = wsMinimized then ReplayChild.WindowState := wsNormal ;
     { Bring it to the front }
     ReplayChild.BringToFront ;
     end;


procedure TMain.ShowRecordClick(Sender: TObject);
{ -- Menu item -------------------------
  Bring Recording module to the front
  -------------------------------------}
begin
     { If window is minimised restore to normal }
     if RecordChild.WindowState = wsMinimized then RecordChild.WindowState := wsNormal ;
     { Bring it to the front }
     RecordChild.BringToFront ;
     end;


procedure TMain.ShowSealTestClick(Sender: TObject);
{ -- Menu item -------------------------
  Bring Seal testing module to the front
  -------------------------------------}
begin
     { If window is minimised restore to normal }
     if SealTestChild.WindowState = wsMinimized then SealTestChild.WindowState := wsNormal ;
     { Bring it to the front }
     SealTestChild.BringToFront ;
     end;


procedure TMain.ShowMeasureClick(Sender: TObject);
{ -- Menu item -------------------------
  Bring Measurements module to the front
  -------------------------------------}
begin
     { If window is minimised restore to normal }
     if MeasureChild.WindowState = wsMinimized then MeasureChild.WindowState := wsNormal ;
     { Bring it to the front }
     MeasureChild.BringToFront ;
     end;

procedure TMain.ShowFitClick(Sender: TObject);
{ -- Menu item -------------------------
  Bring Curve fitting module to the front
  -------------------------------------}
begin
     { If window is minimised restore to normal }
     if FitChild.WindowState = wsMinimized then FitChild.WindowState := wsNormal ;
     { Bring it to the front }
     FitChild.BringToFront ;
     end;


procedure TMain.ClearTicksInWindowsMenu ;
begin
     ShowView.checked := false ;
     ShowRecord.checked := false ;
     ShowSealTest.checked := false ;
     ShowMeasure.checked := false ;
     ShowFit.checked := false ;
     end ;

procedure TMain.mnDrivingFunctionClick(Sender: TObject);
{ - Menu Item ---------------------------------
  Driving function analysis module (drvfun.pas)
  ---------------------------------------------}
begin
     DrvFunChild := TDrvFunFrm.Create(Self) ;
     end;



procedure TMain.mnDefaultSettingsClick(Sender: TObject);
begin
     DefSetFrm := TDefSetFrm.Create(Self) ;
     end;

procedure TMain.mnCED1902Click(Sender: TObject);
begin
     CED1902Frm := TCED1902Frm.Create(Self) ;
     end;

procedure TMain.ContentsClick(Sender: TObject);
begin
     application.helpcommand( HELP_CONTENTS, 0 ) ;
     end;




procedure TMain.SearchforHelpon1Click(Sender: TObject);
begin
     application.helpcommand( HELP_PARTIALKEY, 0 ) ;

     end;


procedure TMain.HowtouseHelp1Click(Sender: TObject);
begin
     application.helpcommand( HELP_HELPONHELP, 0 ) ;
     end;


procedure TMain.AppendClick(Sender: TObject);
{ - Menu Item -------------------------------------------
  Append records from another WCP data file (convert.pas)
  -------------------------------------------------------}
begin
     OpenDialog.options := [ofPathMustExist] ;
     OpenDialog.DefaultExt := 'DAT' ;
     OpenDialog.Filter := ' WCP Files (*.WCP)|*.WCP';
     OpenDialog.Title := 'Append File ' ;
     if Settings.DataDirectory <> '' then
        OpenDialog.InitialDir := Settings.DataDirectory ;

     if OpenDialog.execute then begin

        Settings.DataDirectory := ExtractFilePath( OpenDialog.FileName ) ;

        AppendWCPFile( OpenDialog.FileName ) ;
        fH := RawFH ;

        if not WaveformMeasurements.enabled then MeasureChild.NewFile := True ;
        if not CurveFitting.enabled then FitChild.NewFile := True ;
        if ReplayChildExists then ReplayChild.NewFile := True ;

        { Set display magnification to minimum }
        if fH.NumRecords > 0 then begin
           if not ReplayChildExists then ReplayChild := TReplayFrm.Create(Self) ;
           ZoomOut.Click ;
           ShowRaw.Visible := True ;
           ShowRaw.Click ;
           end
        else ShowRaw.Visible := False ;
        SetMenus ;
        { Update file header blocks with changes made to FH }
        UpdateFileHeaderBlocks ;
        end ;
     end;



procedure TMain.Export1Click(Sender: TObject);
{ - Menu Item --------------------------------
  Export records to a foreign data file type
  --------------------------------------------}
begin
     SaveDialog.DefaultExt := 'DAT' ;
     SaveDialog.options := [ofOverwritePrompt,ofHideReadOnly,ofPathMustExist] ;
     SaveDialog.Filter :=
     'Axon Files (*.DAT,*.ABF)|*.DAT;*.ABF|' +
     'CED Files (*.DAT)|*.DAT|' +
     'Tab Text (*.TXT)|*.TXT|' +
     'Binary (*.DAT)|*.DAT|';
     SaveDialog.FileName := ReplaceFileEnding( RawFH.FileName, '.dat' ) ;
     SaveDialog.Title := 'Export File ' ;
     if Settings.DataDirectory <> '' then
        SaveDialog.InitialDir := Settings.DataDirectory ;

     if SaveDialog.execute then begin
        ExportFrm.ExportFileName := SaveDialog.FileName ;
        ExportFrm.ShowModal ;
        end ;
     end ;


procedure TMain.DeleteRejectedClick(Sender: TObject);
{ - Menu Item ------------------------------
  Delete rejected records from the data file
  ------------------------------------------}
var
   Rec : ^TWCPClipboardRecord ;
   i,iDelete : LongInt ;
   TempFH : TFileHeader ;
begin

  if MessageDlg( 'Delete rejected records! Are you Sure? ', mtConfirmation,
        [mbYes,mbNo], 0 ) = mrYes then begin
     try
        New(Rec) ;
        { Create temporary file }
        TempFH := FH ;
        TempFH.FileName := ReplaceFileEnding( FH.FileName, '.tmp' ) ;
        TempFH.FileHandle := FileCreate( TempFH.FileName ) ;

       { Copy all records except rejected one to the temp. file }
       TempFH.NumRecords := 0 ;
       iDelete := FH.RecordNum ;
       for i := 1 to FH.NumRecords do begin
           GetRecord(FH,Rec^.RecHdr,i,Rec^.ADC) ;
           if Rec^.RecHdr.Status = 'ACCEPTED' then begin
              Inc(TempFH.NumRecords) ;
              PutRecord(TempFH,Rec^.RecHdr,TempFH.NumRecords,Rec^.ADC) ;
              end ;
           end ;
       SaveHeader( TempFH ) ;

       { Close temporary and original file }
       FileClose( TempFH.FileHandle) ;
       FileClose( FH.FileHandle ) ;
       { Delete original file }
       DeleteFile( FH.FileName ) ;
       { Rename temp. file }
       if not RenameFile( TempFH.FileName, FH.FileName ) then
          MessageDlg(
               ' Renaming of' + TempFH.FileName + ' failed',mtWarning, [mbOK], 0 ) ;
       { Re-open file }
       FH.FileHandle := FileOpen( FH.FileName, fmOpenReadWrite ) ;
       GetHeader( FH ) ;

       { Update file header blocks with changes made to FH }
        UpdateFileHeaderBlocks ;

       { Refresh child windows }
       with Main do
            for i := 0 to MDIChildCount-1 do MDICHildren[i].Refresh ;
     finally
            Dispose(Rec) ;
            end ;
     end;
  end ;


procedure TMain.mnShowHintsClick(Sender: TObject);
{ --------------------
  Enable/Disable hints
  --------------------}
begin
     Application.ShowHint := not Application.ShowHint ;
     mnShowHints.Checked := Application.ShowHint ;
     end;

procedure TMain.CloseAllDataFiles ;
{ -------------------------
  Close all open data files
  -------------------------}
begin
     if  RawFH.FileHandle >= 0 then begin
         FileClose(RawFH.FileHandle) ;
         RawFH.FileHandle := - 1 ;
         end ;
     if  AvgFH.FileHandle >= 0 then begin
         FileClose(AvgFH.FileHandle) ;
         AvgFH.FileHandle := - 1 ;
         end ;
     if LeakFH.FileHandle >= 0 then begin
        FileClose(LeakFH.FileHandle) ;
        LeakFH.FileHandle := - 1 ;
        end ;
     if DrvFH.FileHandle >= 0 then begin
        FileClose(DrvFH.FileHandle) ;
        DrvFH.FileHandle := - 1 ;
        end ;
     end ;

end.


