/*
    CaPriCe Forever - Amstrad CPC 464/664/6128 emulator
    Copyright (C) 2014-2018 by Frédéric Coste

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef TFormCodeExplorerH
#define TFormCodeExplorerH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.Grids.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.Dialogs.hpp>
#include <Vcl.Menus.hpp>
#include "TFormEditValue.h"
#include "..\Emulator\TEmulator.h"
#include "..\Settings\TSettings.h"
#include "..\..\Common\Z80DASM\z80dasm.h"


typedef void (*TCodeExplorerWriteFunction)(tNativeCPC* NativeCPC, tULong addr, tUChar val);


//---------------------------------------------------------------------------
class TFormCodeExplorer : public TForm
{
__published:	// Composants gérés par l'EDI
  TLabel *LabelTopAddress;
  TPanel *PanelFormatTopAddress;
  TPanel *PanelTopAddress;
  TTabControl *TabControlMemoryContent;
  TStringGrid *StringGridInstructions;
  TScrollBar *ScrollBarAddress;
  TOpenDialog *OpenDialogAssembler;
  TSaveDialog *SaveDialogAssembler;
  TPageControl *PageControlFeatures;
  TTabSheet *TabSheetPatch;
  TPanel *PanelPatchMachine;
  TTabSheet *TabSheetAssembler;
  TLabel *LabelCodeOrigin;
  TPanel *PanelFormatCodeOrigin;
  TPanel *PanelCodeOrigin;
  TLabel *LabelCodeSize;
  TPanel *PanelFormatCodeSize;
  TPanel *PanelCodeSize;
  TPopupMenu *PopupMenuAssembler;
  TMenuItem *AssemblerCopyMenu;
  TMenuItem *AssemblerClearMenu;
  TMenuItem *AssemblerPasteMenu;
  TMenuItem *AssemblerSelectAllMenu;
  TEdit *EditPatchAssembly;
  TPanel *PanelButtonRefresh;
  TPanel *PanelButtonRegPC;
  TPanel *PanelButtonPatchUpdate;
  TPanel *PanelButtonSetCodeOrigin;
  TPanel *PanelButtonGoToCodeOrigin;
  TPanel *PanelButtonPeek;
  TPanel *PanelButtonAssemblerUpdate;
  TPanel *PanelButtonAssemblerLoad;
  TPanel *PanelButtonAssemblerSave;
  TRichEdit *RichEditAssembler;
  TComboBox *ComboBoxAssemblerFilename;
  TLabel *LabelAssemblerDriveA;
  TPanel *PanelButtonAssemblerDriveASave;
  TLabel *LabelCodeLast;
  TPanel *PanelButtonSetCodeLast;
  TPanel *PanelFormatCodeLast;
  TPanel *PanelCodeLast;
  TPanel *PanelButtonGoToCodeLast;
  TPanel *PanelButtonAssemblerDriveALoad;
  TPanel *PanelButtonSetAddress1;
  TPanel *PanelAddress1;
  TPanel *PanelButtonGoToAddress1;
  TPanel *PanelButtonSetAddress2;
  TPanel *PanelAddress2;
  TPanel *PanelButtonGoToAddress2;
  TLabel *LabelIncludesDirectory;
  TLabel *LabelPredefines;
  TEdit *EditPredefines;
  TPanel *PanelCheckUsePredefines;
  TEdit *EditIncludesDirectory;
  TPanel *PanelButtonClear;
  TOpenDialog *OpenDialogIncludes;
  TGroupBox *GroupBoxBanks;
  TLabel *LabelBankWrite4000;
  TComboBox *ComboBoxRAMBanksBaseAddress;
  TLabel *LabelCommentRAMBaseAddress;
  TPanel *PanelBankWrite4000;
  TPanel *PanelBankWriteC000;
  TLabel *LabelBankWriteC000;
  TLabel *LabelBankWrite0000;
  TPanel *PanelBankWrite0000;
  TLabel *LabelBankWrite8000;
  TPanel *PanelBankWrite8000;
  TLabel *LabelRAMBanksBaseAddress;
  TComboBox *ComboBoxRAMBanksMapping;
  TLabel *LabelRAMBanksMapping;
  TLabel *LabelCommentOUTCommand;
  TPanel *PanelButtonGoToLine;
  TEdit *EditLine;
  TLabel *LabelLine;
  TPanel *PanelButtonGoToBank0;
  TPanel *PanelButtonGoToBank2;
  TPanel *PanelButtonGoToBank1;
  TPanel *PanelButtonGoToBank3;
  TTabSheet *TabSheetBASIC;
  TPanel *PanelButtonBasicRead;
  TRichEdit *RichEditBasic;
  TLabel *LabelBasicDriveA;
  TComboBox *ComboBoxBasicFilename;
  TPanel *PanelButtonBasicDriveALoad;
  TPanel *PanelButtonBasicDriveASave;
  TPanel *PanelButtonBasicGoTo;
  TPopupMenu *PopupMenuBASIC;
  TMenuItem *BASICSelectAllMenu;
  TMenuItem *BASICClearMenu;
  TMenuItem *BASICCopyMenu;
  TMenuItem *BASICPasteMenu;
	TPanel *PanelButtonAddBreakpoint;
  void __fastcall FormDestroy(TObject *Sender);
  void __fastcall FormShow(TObject *Sender);
  void __fastcall FormHide(TObject *Sender);
  void __fastcall FormResize(TObject *Sender);
  void __fastcall StringGridInstructionsDrawCell(TObject *Sender, int ACol, int ARow,
          TRect &Rect, TGridDrawState State);
  void __fastcall PanelTopAddressClick(TObject *Sender);
  void __fastcall ScrollBarAddressChange(TObject *Sender);
  void __fastcall PanelFormatTopAddressClick(TObject *Sender);
  void __fastcall StringGridInstructionsMouseWheelDown(TObject *Sender, TShiftState Shift,
          TPoint &MousePos, bool &Handled);
  void __fastcall StringGridInstructionsMouseWheelUp(TObject *Sender, TShiftState Shift,
          TPoint &MousePos, bool &Handled);
  void __fastcall StringGridInstructionsDblClick(TObject *Sender);
  void __fastcall PanelFormatCodeOriginClick(TObject *Sender);
  void __fastcall PanelCodeOriginClick(TObject *Sender);
  void __fastcall StringGridInstructionsClick(TObject *Sender);
  void __fastcall EditPatchAssemblyChange(TObject *Sender);
  void __fastcall TabControlMemoryContentDrawTab(TCustomTabControl *Control, int TabIndex,
          const TRect &Rect, bool Active);
  void __fastcall TabControlMemoryContentChange(TObject *Sender);
  void __fastcall PageControlFeaturesDrawTab(TCustomTabControl *Control, int TabIndex,
          const TRect &Rect, bool Active);
  void __fastcall PanelFormatCodeSizeClick(TObject *Sender);
  void __fastcall AssemblerClearMenuClick(TObject *Sender);
  void __fastcall AssemblerSelectAllMenuClick(TObject *Sender);
  void __fastcall AssemblerCopyMenuClick(TObject *Sender);
  void __fastcall AssemblerPasteMenuClick(TObject *Sender);
  void __fastcall PageControlFeaturesChange(TObject *Sender);
  void __fastcall StringGridInstructionsKeyDown(TObject *Sender, WORD &Key, TShiftState Shift);
  void __fastcall PanelButtonMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y);
  void __fastcall PanelButtonMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y);
  void __fastcall PanelButtonSetAddressClick(TObject *Sender);
  void __fastcall PanelAddressClick(TObject *Sender);
  void __fastcall PanelButtonGoToAddressClick(TObject *Sender);
  void __fastcall PanelButtonRefreshClick(TObject *Sender);
  void __fastcall PanelButtonRegPCClick(TObject *Sender);
  void __fastcall PanelButtonPatchUpdateClick(TObject *Sender);
  void __fastcall PanelButtonSetCodeOriginClick(TObject *Sender);
  void __fastcall PanelButtonGoToCodeOriginClick(TObject *Sender);
  void __fastcall PanelButtonPeekClick(TObject *Sender);
  void __fastcall PanelButtonAssemblerUpdateClick(TObject *Sender);
  void __fastcall PanelButtonAssemblerLoadClick(TObject *Sender);
  void __fastcall PanelButtonAssemblerSaveClick(TObject *Sender);
  void __fastcall RichEditAssemblerKeyDown(TObject *Sender, WORD &Key, TShiftState Shift);
  void __fastcall PanelButtonAssemblerDriveASaveClick(TObject *Sender);
  void __fastcall PanelButtonSetCodeLastClick(TObject *Sender);
  void __fastcall PanelFormatCodeLastClick(TObject *Sender);
  void __fastcall PanelCodeLastClick(TObject *Sender);
  void __fastcall PanelButtonGoToCodeLastClick(TObject *Sender);
  void __fastcall PanelButtonAssemblerDriveALoadClick(TObject *Sender);
  void __fastcall PanelCheckUsePredefinesClick(TObject *Sender);
  void __fastcall EditIncludesDirectoryChange(TObject *Sender);
  void __fastcall EditPredefinesChange(TObject *Sender);
  void __fastcall PanelButtonClearClick(TObject *Sender);
  void __fastcall EditIncludesDirectoryDblClick(TObject *Sender);
  void __fastcall ComboBoxRAMBanksBaseAddressChange(TObject *Sender);
  void __fastcall ComboBoxRAMBanksMappingChange(TObject *Sender);
  void __fastcall ComboBoxRAMBanksBaseAddressDrawItem(TWinControl *Control, int Index,
          TRect &Rect, TOwnerDrawState State);
  void __fastcall EditLineClick(TObject *Sender);
  void __fastcall PanelButtonGoToLineClick(TObject *Sender);
  void __fastcall RichEditAssemblerClick(TObject *Sender);
  void __fastcall RichEditAssemblerKeyUp(TObject *Sender, WORD &Key, TShiftState Shift);
  void __fastcall RichEditAssemblerChange(TObject *Sender);
  void __fastcall PanelButtonGoToBank0Click(TObject *Sender);
  void __fastcall PanelButtonGoToBank1Click(TObject *Sender);
  void __fastcall PanelButtonGoToBank2Click(TObject *Sender);
  void __fastcall PanelButtonGoToBank3Click(TObject *Sender);
  void __fastcall PanelButtonBasicReadClick(TObject *Sender);
  void __fastcall PanelButtonBasicGoToClick(TObject *Sender);
  void __fastcall BASICSelectAllMenuClick(TObject *Sender);
  void __fastcall BASICClearMenuClick(TObject *Sender);
  void __fastcall BASICCopyMenuClick(TObject *Sender);
  void __fastcall BASICPasteMenuClick(TObject *Sender);
  void __fastcall PanelButtonBasicDriveALoadClick(TObject *Sender);
	void __fastcall EditLineKeyPress(TObject *Sender, System::WideChar &Key);
	void __fastcall PanelButtonAddBreakpointClick(TObject *Sender);



private:	// Déclarations utilisateur
  //
  // Members
  //
  TEmulator* mEmulatorP;
  TSettings* mSettingsP;
  bool mPaused;
  tULong mTopAddress;
  tULong mMaxAddress;
  tLong mCodeOrigin;
  tLong mCodeLast;
	tLong mCodeSize;
  tULong mSelectedAddress;
	tULong mMemoryStartAddress;
  tULong mMemorySize;
  TZ80dasmParam mZ80dasmParam;
  TCodeExplorerWriteFunction mWriteFunction;
  AnsiString mAssemblerFilename;
  AnsiString mBasicFilename;
  TFormEditValue* mFormEditValue;
  tULong* mBASICLinesAddress;
  int mBASICLinesAddressCount;

  //
  // Methods
  //
  AnsiString __fastcall GetTitle(void);
  void __fastcall WMMove(TMessage &Message);
  inline void __fastcall SetEmulator(TEmulator* Value) { mEmulatorP=Value; };
  void __fastcall SetSettings(TSettings* Value);
  void __fastcall ShowAssemblerInstructions(void);
  void __fastcall ShowBASICMemory(void);
  void __fastcall UpdateInstructions(tNativeCPC* NativeCPC);
  void __fastcall UpdatePatch(tNativeCPC* NativeCPC);
  void __fastcall UpdateCatalogue(void);
  inline tULong __fastcall GetTopAddress(void) { return mTopAddress; };
  void __fastcall SetTopAddress(tULong Value);
  inline tLong __fastcall GetCodeOrigin(void) { return mCodeOrigin; };
  void __fastcall SetCodeOrigin(tLong Value);
  inline tLong __fastcall GetCodeLast(void) { return mCodeLast; };
  void __fastcall SetCodeLast(tLong Value);
  inline tLong __fastcall GetCodeSize(void) { return mCodeSize; };
  void __fastcall SetCodeSize(tLong Value);
  void __fastcall SetMemoryIndex(int Value);
  void __fastcall OnDiskEvent(tDrive* DriveP);
  bool __fastcall OnCPCEvent(tULong Condition, tNativeCPC* NativeCPC);
  void __fastcall UpdateBanks(void);
  AnsiString __fastcall BuildBankComment(tULong Address);
  tULong __fastcall DecodeBasicLine(tNativeCPC* NativeCPC, tULong Address, AnsiString& BasicLine);
  AnsiString& __fastcall AddBasicInstruction(AnsiString& BasicLine, AnsiString Instruction, tUChar NextToken);
  AnsiString& __fastcall AddBasicInstructionAddon(AnsiString& BasicLine, AnsiString Instruction,
            tUChar PrevToken, tUChar NextToken);
  void __fastcall DropFile(TWMDropFiles &Message); // drag & drop handler

  //
  // Private Properties
  //
  __property AnsiString Title = { read=GetTitle };
  __property tULong TopAddress = { read=GetTopAddress, write=SetTopAddress };
  __property tLong CodeOrigin = { read=GetCodeOrigin, write=SetCodeOrigin };
  __property tLong CodeLast = { read=GetCodeLast, write=SetCodeLast };
  __property tLong CodeSize = { read=GetCodeSize, write=SetCodeSize };
  __property int MemoryIndex = { write=SetMemoryIndex };

public:		// Déclarations utilisateur
  //
  // Public Properties
  //
  __property TEmulator* Emulator = { write=SetEmulator };
  __property TSettings* Settings = { write=SetSettings };

  //
  // API
  //
  __fastcall TFormCodeExplorer(TComponent* Owner);

#pragma option push -vi-
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_MOVE, TMessage, WMMove);
  MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, DropFile);
END_MESSAGE_MAP(TForm)
#pragma option pop
};
//---------------------------------------------------------------------------
extern PACKAGE TFormCodeExplorer *FormCodeExplorer;
//---------------------------------------------------------------------------
#endif
